Spaces:
Running
Running
Update scoring_calculation_system.py
Browse files- scoring_calculation_system.py +222 -57
scoring_calculation_system.py
CHANGED
@@ -1161,53 +1161,205 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
|
|
1161 |
return min(0.2, adaptability_score)
|
1162 |
|
1163 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1164 |
def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
|
1165 |
-
"""
|
1166 |
-
|
1167 |
-
通過更細緻的特徵評估和動態權重調整,自然產生分數差異
|
1168 |
-
"""
|
1169 |
-
# 評估關鍵特徵的匹配度,使用更極端的調整係數
|
1170 |
def evaluate_key_features():
|
1171 |
-
# 空間適配性評估
|
1172 |
space_multiplier = 1.0
|
1173 |
if user_prefs.living_space == 'apartment':
|
1174 |
if breed_info['Size'] == 'Giant':
|
1175 |
-
space_multiplier = 0.
|
1176 |
elif breed_info['Size'] == 'Large':
|
1177 |
-
space_multiplier = 0.
|
|
|
|
|
1178 |
elif breed_info['Size'] == 'Small':
|
1179 |
-
space_multiplier = 1.
|
1180 |
-
|
1181 |
-
# 運動需求評估
|
1182 |
exercise_multiplier = 1.0
|
1183 |
exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
|
|
|
|
|
|
|
|
|
1184 |
if exercise_needs == 'VERY HIGH':
|
1185 |
-
if user_prefs.exercise_time <
|
1186 |
-
exercise_multiplier = 0.
|
1187 |
elif user_prefs.exercise_time > 150:
|
1188 |
-
exercise_multiplier = 1.
|
1189 |
-
elif exercise_needs == '
|
1190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1191 |
|
1192 |
return space_multiplier, exercise_multiplier
|
1193 |
|
1194 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1195 |
def evaluate_experience():
|
1196 |
exp_multiplier = 1.0
|
1197 |
care_level = breed_info.get('Care Level', 'MODERATE')
|
1198 |
|
1199 |
if care_level == 'High':
|
1200 |
if user_prefs.experience_level == 'beginner':
|
1201 |
-
exp_multiplier = 0.
|
1202 |
elif user_prefs.experience_level == 'advanced':
|
1203 |
-
exp_multiplier = 1.
|
1204 |
elif care_level == 'Low':
|
1205 |
if user_prefs.experience_level == 'advanced':
|
1206 |
-
exp_multiplier = 0.
|
1207 |
|
1208 |
return exp_multiplier
|
1209 |
|
1210 |
-
#
|
1211 |
space_mult, exercise_mult = evaluate_key_features()
|
1212 |
exp_mult = evaluate_experience()
|
1213 |
|
@@ -1217,77 +1369,90 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
|
|
1217 |
'exercise': scores['exercise'] * exercise_mult,
|
1218 |
'experience': scores['experience'] * exp_mult,
|
1219 |
'grooming': scores['grooming'],
|
1220 |
-
'health': scores['health'],
|
1221 |
'noise': scores['noise']
|
1222 |
}
|
1223 |
|
1224 |
-
#
|
1225 |
weights = {
|
1226 |
-
'space': 0.
|
1227 |
-
'exercise': 0.
|
1228 |
-
'experience': 0.
|
1229 |
'grooming': 0.15,
|
1230 |
'health': 0.10,
|
1231 |
'noise': 0.10
|
1232 |
}
|
1233 |
|
1234 |
-
#
|
1235 |
if user_prefs.has_children:
|
1236 |
if user_prefs.children_age == 'toddler':
|
1237 |
-
weights['noise'] *=
|
1238 |
-
weights['experience'] *= 1.
|
1239 |
-
|
|
|
|
|
|
|
|
|
1240 |
if user_prefs.living_space == 'apartment':
|
1241 |
-
weights['space'] *= 1.
|
1242 |
-
weights['noise'] *= 1.
|
1243 |
|
1244 |
# 運動時間極端情況
|
1245 |
if user_prefs.exercise_time < 30:
|
1246 |
-
weights['exercise'] *=
|
1247 |
elif user_prefs.exercise_time > 150:
|
1248 |
-
weights['exercise'] *= 1.
|
1249 |
|
1250 |
# 正規化權重
|
1251 |
total_weight = sum(weights.values())
|
1252 |
normalized_weights = {k: v/total_weight for k, v in weights.items()}
|
1253 |
|
1254 |
-
#
|
1255 |
-
|
1256 |
-
|
1257 |
# 品種特性加成
|
1258 |
breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
|
1259 |
|
1260 |
-
#
|
1261 |
-
|
|
|
|
|
|
|
|
|
1262 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1263 |
|
1264 |
def amplify_score_extreme(score: float) -> float:
|
1265 |
"""
|
1266 |
-
|
1267 |
|
1268 |
-
|
1269 |
-
- 極差匹配 (0.0-0.2) ->
|
1270 |
-
- 較差匹配 (0.2-0.4) ->
|
1271 |
-
- 中等匹配 (0.4-0.6) ->
|
1272 |
-
- 良好匹配 (0.6-0.8) ->
|
1273 |
-
- 優秀匹配 (0.8-
|
|
|
1274 |
"""
|
1275 |
if score < 0.2:
|
1276 |
-
|
1277 |
-
return 0.50 + (score / 0.2) * 0.10
|
1278 |
elif score < 0.4:
|
1279 |
-
# 較差匹配:緩慢增長
|
1280 |
position = (score - 0.2) / 0.2
|
1281 |
-
return 0.
|
1282 |
elif score < 0.6:
|
1283 |
-
# 中等匹配:較大的分數增長
|
1284 |
position = (score - 0.4) / 0.2
|
1285 |
-
return 0.
|
1286 |
elif score < 0.8:
|
1287 |
-
# 良好匹配:快速增長
|
1288 |
position = (score - 0.6) / 0.2
|
1289 |
-
return 0.
|
|
|
|
|
|
|
1290 |
else:
|
1291 |
-
|
1292 |
-
|
1293 |
-
return 0.90 + position * 0.08
|
|
|
1161 |
return min(0.2, adaptability_score)
|
1162 |
|
1163 |
|
1164 |
+
# def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
|
1165 |
+
# """
|
1166 |
+
# 改進的品種相容性評分系統
|
1167 |
+
# 通過更細緻的特徵評估和動態權重調整,自然產生分數差異
|
1168 |
+
# """
|
1169 |
+
# # 評估關鍵特徵的匹配度,使用更極端的調整係數
|
1170 |
+
# def evaluate_key_features():
|
1171 |
+
# # 空間適配性評估
|
1172 |
+
# space_multiplier = 1.0
|
1173 |
+
# if user_prefs.living_space == 'apartment':
|
1174 |
+
# if breed_info['Size'] == 'Giant':
|
1175 |
+
# space_multiplier = 0.3 # 嚴重不適合
|
1176 |
+
# elif breed_info['Size'] == 'Large':
|
1177 |
+
# space_multiplier = 0.4 # 明顯不適合
|
1178 |
+
# elif breed_info['Size'] == 'Small':
|
1179 |
+
# space_multiplier = 1.4 # 明顯優勢
|
1180 |
+
|
1181 |
+
# # 運動需求評估
|
1182 |
+
# exercise_multiplier = 1.0
|
1183 |
+
# exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
|
1184 |
+
# if exercise_needs == 'VERY HIGH':
|
1185 |
+
# if user_prefs.exercise_time < 60:
|
1186 |
+
# exercise_multiplier = 0.3 # 嚴重不足
|
1187 |
+
# elif user_prefs.exercise_time > 150:
|
1188 |
+
# exercise_multiplier = 1.5 # 完美匹配
|
1189 |
+
# elif exercise_needs == 'LOW' and user_prefs.exercise_time > 150:
|
1190 |
+
# exercise_multiplier = 0.5 # 運動過度
|
1191 |
+
|
1192 |
+
# return space_multiplier, exercise_multiplier
|
1193 |
+
|
1194 |
+
# # 計算經驗匹配度
|
1195 |
+
# def evaluate_experience():
|
1196 |
+
# exp_multiplier = 1.0
|
1197 |
+
# care_level = breed_info.get('Care Level', 'MODERATE')
|
1198 |
+
|
1199 |
+
# if care_level == 'High':
|
1200 |
+
# if user_prefs.experience_level == 'beginner':
|
1201 |
+
# exp_multiplier = 0.4
|
1202 |
+
# elif user_prefs.experience_level == 'advanced':
|
1203 |
+
# exp_multiplier = 1.3
|
1204 |
+
# elif care_level == 'Low':
|
1205 |
+
# if user_prefs.experience_level == 'advanced':
|
1206 |
+
# exp_multiplier = 0.9 # 略微降低評分,因為可能不夠有挑戰性
|
1207 |
+
|
1208 |
+
# return exp_multiplier
|
1209 |
+
|
1210 |
+
# # 取得特徵調整係數
|
1211 |
+
# space_mult, exercise_mult = evaluate_key_features()
|
1212 |
+
# exp_mult = evaluate_experience()
|
1213 |
+
|
1214 |
+
# # 調整基礎分數
|
1215 |
+
# adjusted_scores = {
|
1216 |
+
# 'space': scores['space'] * space_mult,
|
1217 |
+
# 'exercise': scores['exercise'] * exercise_mult,
|
1218 |
+
# 'experience': scores['experience'] * exp_mult,
|
1219 |
+
# 'grooming': scores['grooming'],
|
1220 |
+
# 'health': scores['health'],
|
1221 |
+
# 'noise': scores['noise']
|
1222 |
+
# }
|
1223 |
+
|
1224 |
+
# # 計算加權平均,關鍵特徵佔更大權重
|
1225 |
+
# weights = {
|
1226 |
+
# 'space': 0.35,
|
1227 |
+
# 'exercise': 0.30,
|
1228 |
+
# 'experience': 0.20,
|
1229 |
+
# 'grooming': 0.15,
|
1230 |
+
# 'health': 0.10,
|
1231 |
+
# 'noise': 0.10
|
1232 |
+
# }
|
1233 |
+
|
1234 |
+
# # 動態調整權重
|
1235 |
+
# if user_prefs.has_children:
|
1236 |
+
# if user_prefs.children_age == 'toddler':
|
1237 |
+
# weights['noise'] *= 1.5 # 幼童對噪音更敏感
|
1238 |
+
# weights['experience'] *= 1.3 # 需要更有經驗的飼主
|
1239 |
+
|
1240 |
+
# if user_prefs.living_space == 'apartment':
|
1241 |
+
# weights['space'] *= 1.4 # 公寓空間限制更重要
|
1242 |
+
# weights['noise'] *= 1.3 # 噪音問題更重要
|
1243 |
+
|
1244 |
+
# # 運動時間極端情況
|
1245 |
+
# if user_prefs.exercise_time < 30:
|
1246 |
+
# weights['exercise'] *= 1.5 # 運動時間極少時加重權重
|
1247 |
+
# elif user_prefs.exercise_time > 150:
|
1248 |
+
# weights['exercise'] *= 1.3 # 運動時間充足時略微加重
|
1249 |
+
|
1250 |
+
# # 正規化權重
|
1251 |
+
# total_weight = sum(weights.values())
|
1252 |
+
# normalized_weights = {k: v/total_weight for k, v in weights.items()}
|
1253 |
+
|
1254 |
+
# # 計算最終分數
|
1255 |
+
# final_score = sum(adjusted_scores[k] * normalized_weights[k] for k in scores.keys())
|
1256 |
+
|
1257 |
+
# # 品種特性加成
|
1258 |
+
# breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
|
1259 |
+
|
1260 |
+
# # 整合最終分數,保持在0-1範圍內
|
1261 |
+
# return min(1.0, max(0.0, (final_score * 0.85) + (breed_bonus * 0.15)))
|
1262 |
+
|
1263 |
+
|
1264 |
+
# def amplify_score_extreme(score: float) -> float:
|
1265 |
+
# """
|
1266 |
+
# 改進的分數轉換函數,提供更大的分數區間和更明顯的差異
|
1267 |
+
|
1268 |
+
# 轉換邏輯:
|
1269 |
+
# - 極差匹配 (0.0-0.2) -> 50-60%
|
1270 |
+
# - 較差匹配 (0.2-0.4) -> 60-70%
|
1271 |
+
# - 中等匹配 (0.4-0.6) -> 70-82%
|
1272 |
+
# - 良好匹配 (0.6-0.8) -> 82-90%
|
1273 |
+
# - 優秀匹配 (0.8-1.0) -> 90-98%
|
1274 |
+
# """
|
1275 |
+
# if score < 0.2:
|
1276 |
+
# # 極差匹配:更低的起始分數
|
1277 |
+
# return 0.50 + (score / 0.2) * 0.10
|
1278 |
+
# elif score < 0.4:
|
1279 |
+
# # 較差匹配:緩慢增長
|
1280 |
+
# position = (score - 0.2) / 0.2
|
1281 |
+
# return 0.60 + position * 0.10
|
1282 |
+
# elif score < 0.6:
|
1283 |
+
# # 中等匹配:較大的分數增長
|
1284 |
+
# position = (score - 0.4) / 0.2
|
1285 |
+
# return 0.70 + position * 0.12
|
1286 |
+
# elif score < 0.8:
|
1287 |
+
# # 良好匹配:快速增長
|
1288 |
+
# position = (score - 0.6) / 0.2
|
1289 |
+
# return 0.82 + position * 0.08
|
1290 |
+
# else:
|
1291 |
+
# # 優秀匹配:達到更高分數
|
1292 |
+
# position = (score - 0.8) / 0.2
|
1293 |
+
# return 0.90 + position * 0.08
|
1294 |
+
|
1295 |
+
|
1296 |
def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
|
1297 |
+
"""改進的品種相容性評分系統"""
|
1298 |
+
|
|
|
|
|
|
|
1299 |
def evaluate_key_features():
|
1300 |
+
# 空間適配性評估 - 更極端的調整
|
1301 |
space_multiplier = 1.0
|
1302 |
if user_prefs.living_space == 'apartment':
|
1303 |
if breed_info['Size'] == 'Giant':
|
1304 |
+
space_multiplier = 0.2 # 更嚴重的懲罰
|
1305 |
elif breed_info['Size'] == 'Large':
|
1306 |
+
space_multiplier = 0.3
|
1307 |
+
elif breed_info['Size'] == 'Medium':
|
1308 |
+
space_multiplier = 0.7
|
1309 |
elif breed_info['Size'] == 'Small':
|
1310 |
+
space_multiplier = 1.6 # 更大的獎勵
|
1311 |
+
|
1312 |
+
# 運動需求評估 - 更細緻的匹配
|
1313 |
exercise_multiplier = 1.0
|
1314 |
exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
|
1315 |
+
|
1316 |
+
# 運動時間差異計算
|
1317 |
+
time_diff_ratio = abs(user_prefs.exercise_time - get_ideal_exercise_time(exercise_needs)) / 60.0
|
1318 |
+
|
1319 |
if exercise_needs == 'VERY HIGH':
|
1320 |
+
if user_prefs.exercise_time < 90:
|
1321 |
+
exercise_multiplier = max(0.2, 1.0 - time_diff_ratio)
|
1322 |
elif user_prefs.exercise_time > 150:
|
1323 |
+
exercise_multiplier = min(2.0, 1.0 + time_diff_ratio/2)
|
1324 |
+
elif exercise_needs == 'HIGH':
|
1325 |
+
if user_prefs.exercise_time < 60:
|
1326 |
+
exercise_multiplier = max(0.3, 1.0 - time_diff_ratio)
|
1327 |
+
elif user_prefs.exercise_time > 120:
|
1328 |
+
exercise_multiplier = min(1.8, 1.0 + time_diff_ratio/2)
|
1329 |
+
elif exercise_needs == 'LOW':
|
1330 |
+
if user_prefs.exercise_time > 120:
|
1331 |
+
exercise_multiplier = max(0.4, 1.0 - time_diff_ratio/2)
|
1332 |
|
1333 |
return space_multiplier, exercise_multiplier
|
1334 |
|
1335 |
+
def get_ideal_exercise_time(exercise_needs: str) -> int:
|
1336 |
+
"""獲取理想運動時間"""
|
1337 |
+
return {
|
1338 |
+
'VERY HIGH': 150,
|
1339 |
+
'HIGH': 120,
|
1340 |
+
'MODERATE HIGH': 90,
|
1341 |
+
'MODERATE': 60,
|
1342 |
+
'MODERATE LOW': 45,
|
1343 |
+
'LOW': 30
|
1344 |
+
}.get(exercise_needs, 60)
|
1345 |
+
|
1346 |
+
# 經驗匹配度評估 - 更強的影響力
|
1347 |
def evaluate_experience():
|
1348 |
exp_multiplier = 1.0
|
1349 |
care_level = breed_info.get('Care Level', 'MODERATE')
|
1350 |
|
1351 |
if care_level == 'High':
|
1352 |
if user_prefs.experience_level == 'beginner':
|
1353 |
+
exp_multiplier = 0.3 # 更嚴重的懲罰
|
1354 |
elif user_prefs.experience_level == 'advanced':
|
1355 |
+
exp_multiplier = 1.5 # 更大的獎勵
|
1356 |
elif care_level == 'Low':
|
1357 |
if user_prefs.experience_level == 'advanced':
|
1358 |
+
exp_multiplier = 0.8
|
1359 |
|
1360 |
return exp_multiplier
|
1361 |
|
1362 |
+
# 計算調整係數
|
1363 |
space_mult, exercise_mult = evaluate_key_features()
|
1364 |
exp_mult = evaluate_experience()
|
1365 |
|
|
|
1369 |
'exercise': scores['exercise'] * exercise_mult,
|
1370 |
'experience': scores['experience'] * exp_mult,
|
1371 |
'grooming': scores['grooming'],
|
1372 |
+
'health': scores['health'] * (1.5 if user_prefs.health_sensitivity == 'high' else 1.0),
|
1373 |
'noise': scores['noise']
|
1374 |
}
|
1375 |
|
1376 |
+
# 基礎權重
|
1377 |
weights = {
|
1378 |
+
'space': 0.25,
|
1379 |
+
'exercise': 0.25,
|
1380 |
+
'experience': 0.15,
|
1381 |
'grooming': 0.15,
|
1382 |
'health': 0.10,
|
1383 |
'noise': 0.10
|
1384 |
}
|
1385 |
|
1386 |
+
# 動態權重調整 - 更強的條件反應
|
1387 |
if user_prefs.has_children:
|
1388 |
if user_prefs.children_age == 'toddler':
|
1389 |
+
weights['noise'] *= 2.0 # 更強的噪音影響
|
1390 |
+
weights['experience'] *= 1.5
|
1391 |
+
weights['health'] *= 1.3
|
1392 |
+
elif user_prefs.children_age == 'school_age':
|
1393 |
+
weights['noise'] *= 1.5
|
1394 |
+
weights['experience'] *= 1.3
|
1395 |
+
|
1396 |
if user_prefs.living_space == 'apartment':
|
1397 |
+
weights['space'] *= 1.8 # 更強的空間限制
|
1398 |
+
weights['noise'] *= 1.6
|
1399 |
|
1400 |
# 運動時間極端情況
|
1401 |
if user_prefs.exercise_time < 30:
|
1402 |
+
weights['exercise'] *= 2.0
|
1403 |
elif user_prefs.exercise_time > 150:
|
1404 |
+
weights['exercise'] *= 1.5
|
1405 |
|
1406 |
# 正規化權重
|
1407 |
total_weight = sum(weights.values())
|
1408 |
normalized_weights = {k: v/total_weight for k, v in weights.items()}
|
1409 |
|
1410 |
+
# 計算基礎分數
|
1411 |
+
base_score = sum(adjusted_scores[k] * normalized_weights[k] for k in scores.keys())
|
1412 |
+
|
1413 |
# 品種特性加成
|
1414 |
breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
|
1415 |
|
1416 |
+
# 動態整合係數
|
1417 |
+
bonus_weight = min(0.25, max(0.15, breed_bonus)) # 讓優秀特性有更大影響
|
1418 |
+
|
1419 |
+
# 完美匹配加成
|
1420 |
+
if all(score >= 0.8 for score in adjusted_scores.values()):
|
1421 |
+
base_score *= 1.2
|
1422 |
|
1423 |
+
# 極端不匹配懲罰
|
1424 |
+
if any(score <= 0.3 for score in adjusted_scores.values()):
|
1425 |
+
base_score *= 0.6
|
1426 |
+
|
1427 |
+
return min(1.0, max(0.0, (base_score * (1.0 - bonus_weight)) + (breed_bonus * bonus_weight)))
|
1428 |
+
|
1429 |
|
1430 |
def amplify_score_extreme(score: float) -> float:
|
1431 |
"""
|
1432 |
+
改進的分數轉換函數,提供更動態的分數範圍
|
1433 |
|
1434 |
+
動態轉換邏輯:
|
1435 |
+
- 極差匹配 (0.0-0.2) -> 45-58%
|
1436 |
+
- 較差匹配 (0.2-0.4) -> 58-72%
|
1437 |
+
- 中等匹配 (0.4-0.6) -> 72-85%
|
1438 |
+
- 良好匹配 (0.6-0.8) -> 85-92%
|
1439 |
+
- 優秀匹配 (0.8-0.9) -> 92-96%
|
1440 |
+
- 完美匹配 (0.9-1.0) -> 96-99%
|
1441 |
"""
|
1442 |
if score < 0.2:
|
1443 |
+
return 0.45 + (score / 0.2) * 0.13
|
|
|
1444 |
elif score < 0.4:
|
|
|
1445 |
position = (score - 0.2) / 0.2
|
1446 |
+
return 0.58 + position * 0.14
|
1447 |
elif score < 0.6:
|
|
|
1448 |
position = (score - 0.4) / 0.2
|
1449 |
+
return 0.72 + position * 0.13
|
1450 |
elif score < 0.8:
|
|
|
1451 |
position = (score - 0.6) / 0.2
|
1452 |
+
return 0.85 + position * 0.07
|
1453 |
+
elif score < 0.9:
|
1454 |
+
position = (score - 0.8) / 0.1
|
1455 |
+
return 0.92 + position * 0.04
|
1456 |
else:
|
1457 |
+
position = (score - 0.9) / 0.1
|
1458 |
+
return 0.96 + position * 0.03
|
|