Skip to content

Commit 76acc35

Browse files
committed
Merge branch 'develop' of https://github.com/pirogramming/Moodico into main-test
2 parents d0342f8 + 49748f9 commit 76acc35

18 files changed

Lines changed: 1389 additions & 184 deletions

File tree

moodico/moodtest/color_analyzer.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import json
2+
import random
3+
import math
4+
import logging
5+
logger = logging.getLogger(__name__)
6+
7+
def product_result_by_mood(mood):
8+
try:
9+
mood_zones_path = 'static/data/mood_zones.json'
10+
products_path = 'static/data/all_products_hex_update_tempk=4_2_1_1.json'
11+
12+
with open(mood_zones_path, 'r', encoding='utf-8') as f:
13+
mood_zones = json.load(f)
14+
15+
with open(products_path, 'r', encoding='utf-8') as f:
16+
all_products = json.load(f)
17+
18+
zone = mood_zones[mood]['area']
19+
zone_left = zone['left']
20+
zone_top = zone['top']
21+
zone_right = zone_left + zone['width']
22+
zone_bottom = zone_top + zone['height']
23+
24+
filtered_results = []
25+
for product in all_products:
26+
# LAB -> coords 변환 로직
27+
coords = calculate_coordinates_from_lab(product['lab_l'], product['lab_a'], product['lab_b'])
28+
29+
if (zone_left <= coords['warmCool'] <= zone_right and
30+
zone_top <= coords['lightDeep'] <= zone_bottom):
31+
filtered_results.append(product)
32+
33+
return filtered_results
34+
35+
except Exception as e:
36+
logger.error(f"제품 필터링 중 에러 발생: {e}")
37+
return []
38+
39+
# 무드필터링 된 제품을 받아서 랜덤으로 최대 3개 반환하는 함수
40+
# 우선은 랜덤으로 구현하였으나, 로직 수정 가능
41+
def get_random_products(filtered_products):
42+
product_count = len(filtered_products)
43+
if product_count > 3:
44+
return random.sample(filtered_products, 3)
45+
else:
46+
return filtered_products
47+
48+
# color_analyzer.js의 calculateCoordinatesFromLAB(l, a, b)와 동일한 역할의 함수
49+
def sigmoid(x):
50+
return 1 / (1 + math.exp(-x))
51+
def enhance_contrast(value):
52+
return (1 - math.cos(value * math.pi)) / 2
53+
def calculate_coordinates_from_lab(l, a, b):
54+
l_star = l
55+
a_star = a
56+
b_star = b
57+
58+
warm_cool_score = (a_star * 0.5) + (b_star * 1.0)
59+
60+
# sigmoid를 활용한 비선형 매핑 - warmCool
61+
spread_wc_factor = 35
62+
scaled_wc_score = (warm_cool_score - 35) / spread_wc_factor
63+
sigmoid_wc_middle_value = sigmoid(scaled_wc_score)
64+
sigmoid_wc_value = enhance_contrast(sigmoid_wc_middle_value) + 0.03
65+
66+
# 선형 매핑 간격 조정 - lightDeep
67+
scale = 1.1
68+
offset = -7
69+
light_score = (l_star * scale) + offset
70+
71+
light_score = max(0, min(100, light_score))
72+
73+
warm_cool = sigmoid_wc_value * 100
74+
light_deep = 100 - light_score
75+
76+
return {'warmCool': warm_cool, 'lightDeep': light_deep}

moodico/moodtest/views.py

Lines changed: 194 additions & 112 deletions
Large diffs are not rendered by default.

moodico/products/views.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from django.views.decorators.http import require_http_methods
99
from django.views.decorators.csrf import csrf_exempt
1010

11-
from moodico.products.models import ProductLike
1211
from moodico.products.models import ProductLike, ProductRating, ProductRatingImage
1312
from django.db import models
1413
import logging
@@ -104,7 +103,42 @@ def crawled_product_detail(request, crawled_id):
104103
</html>
105104
""")
106105

107-
return render(request, 'products/crawled_detail.html', {'product': product})
106+
# 해당 제품의 리뷰 정보 가져오기
107+
from moodico.users.utils import get_user_from_request
108+
user = get_user_from_request(request)
109+
110+
# 제품 ID로 리뷰 찾기 (crawled_id 사용)
111+
user_review = None
112+
if user:
113+
try:
114+
user_review = ProductRating.objects.get(
115+
user=user,
116+
product_id=crawled_id
117+
)
118+
except ProductRating.DoesNotExist:
119+
pass
120+
121+
# 제품의 모든 리뷰 가져오기
122+
all_reviews = ProductRating.objects.filter(product_id=crawled_id).order_by('-created_at')
123+
124+
# 평균 별점과 평가 개수 계산
125+
total_ratings = all_reviews.count()
126+
if total_ratings > 0:
127+
total_score = sum(review.rating for review in all_reviews)
128+
average_rating = round(total_score / total_ratings, 1)
129+
else:
130+
average_rating = 0.0
131+
132+
context = {
133+
'product': product,
134+
'user_review': user_review,
135+
'all_reviews': all_reviews,
136+
'user': user,
137+
'total_ratings': total_ratings,
138+
'average_rating': average_rating,
139+
}
140+
141+
return render(request, 'products/crawled_detail.html', context)
108142

109143
except Exception as e:
110144
logger.error(f"크롤링된 제품 상세 정보 로드 실패: {e}")

moodico/users/utils.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
from django.shortcuts import redirect
22
from functools import wraps
3+
from django.contrib.auth.models import User
34

45
def login_or_kakao_required(view_func):
56
@wraps(view_func)
67
def _wrapped_view(request, *args, **kwargs):
78
if request.user.is_authenticated or request.session.get("nickname"):
89
return view_func(request, *args, **kwargs)
910
return redirect('login')
10-
return _wrapped_view
11+
return _wrapped_view
12+
13+
def get_user_from_request(request):
14+
"""요청에서 사용자 정보를 가져오는 함수"""
15+
if request.user.is_authenticated:
16+
return request.user
17+
elif request.session.get("nickname"):
18+
# 카카오 로그인 사용자의 경우 User 객체가 없을 수 있음
19+
return None
20+
return None

moodico/users/views.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from django.http import HttpRequest
66
from django.conf import settings
77
from django.views.decorators.http import require_http_methods
8-
from moodico.products.models import ProductLike
8+
from moodico.products.models import ProductLike, ProductRating
99
from .utils import login_or_kakao_required
1010
from moodico.users.models import UserProfile
1111
from moodico.products.views import get_liked_products_color_info
@@ -145,7 +145,11 @@ def profile(request):
145145
user_mood = user_profile.mood_result if user_profile.mood_result else "정보 없음"
146146
except UserProfile.DoesNotExist:
147147
user_mood = "정보 없음"
148+
148149
liked_products = ProductLike.objects.filter(user=request.user).order_by('-created_at')
150+
151+
# 사용자가 작성한 리뷰들 가져오기
152+
user_reviews = ProductRating.objects.filter(user=request.user).order_by('-created_at')
149153

150154
# 찜한 제품들의 색상 및 URL 정보 가져오기
151155
liked_products_colors = get_liked_products_color_info(liked_products)
@@ -155,6 +159,7 @@ def profile(request):
155159
'user_mood': user_mood,
156160
'liked_products': liked_products,
157161
'liked_products_colors': liked_products_colors,
162+
'user_reviews': user_reviews,
158163
}
159164

160165
return render(request, 'users/profile.html', context)

static/css/moodtest/mood_result.css

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@
327327
}
328328

329329
.product-card {
330+
position: relative;
330331
background: white;
331332
border-radius: 15px;
332333
padding: 16px;
@@ -347,7 +348,6 @@
347348

348349
.product-image {
349350
width: 100%;
350-
height: 120px;
351351
object-fit: cover;
352352
border-radius: 10px;
353353
margin-bottom: 12px;
@@ -379,16 +379,20 @@
379379
}
380380

381381
.purchase-btn {
382+
display: block;
383+
width: 100%;
382384
padding: 8px 12px;
383385
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
384-
color: white;
385386
border: none;
386387
border-radius: 8px;
387-
font-size: 13px;
388-
font-weight: 600;
389388
cursor: pointer;
390389
transition: all 0.3s;
391-
width: 100%;
390+
color: white;
391+
font-size: 13px;
392+
font-weight: 600;
393+
text-align: center;
394+
text-decoration: none;
395+
box-sizing: border-box;
392396
}
393397

394398
.purchase-btn:hover {

0 commit comments

Comments
 (0)