DawnC commited on
Commit
b89b477
1 Parent(s): e1ee9f9

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. scoring_calculation_system.py +185 -241
scoring_calculation_system.py CHANGED
@@ -1073,258 +1073,202 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
1073
 
1074
  # 1. 計算基礎分數
1075
  try:
1076
- space_score = calculate_space_score(
1077
- breed_info['Size'],
1078
- user_prefs.living_space,
1079
- user_prefs.space_for_play,
1080
- breed_info.get('Exercise Needs', 'Moderate')
1081
- )
1082
- print(f"空間分數計算結果: {space_score}")
1083
- except Exception as e:
1084
- print(f"空間分數計算錯誤: {str(e)}")
1085
- raise
1086
-
1087
- try:
1088
- exercise_score = calculate_exercise_score(
1089
- breed_info.get('Exercise Needs', 'Moderate'),
1090
- user_prefs.exercise_time
1091
- )
1092
- print(f"運動分數計算結果: {exercise_score}")
1093
- except Exception as e:
1094
- print(f"運動分數計算錯誤: {str(e)}")
1095
- raise
1096
-
1097
- try:
1098
- grooming_score = calculate_grooming_score(
1099
- breed_info.get('Grooming Needs', 'Moderate'),
1100
- user_prefs.grooming_commitment.lower(),
1101
- breed_info['Size']
1102
- )
1103
- print(f"美容分數計算結果: {grooming_score}")
1104
- except Exception as e:
1105
- print(f"美容分數計算錯誤: {str(e)}")
1106
- raise
1107
-
1108
- try:
1109
- experience_score = calculate_experience_score(
1110
- breed_info.get('Care Level', 'Moderate'),
1111
- user_prefs.experience_level,
1112
- breed_info.get('Temperament', '')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1113
  )
1114
- print(f"經驗分數計算結果: {experience_score}")
1115
- except Exception as e:
1116
- print(f"經驗分數計算錯誤: {str(e)}")
1117
- raise
1118
-
1119
- try:
1120
- # 修正:加入 user_prefs 參數
1121
- health_score = calculate_health_score(breed_info.get('Breed', ''), user_prefs)
1122
- print(f"健康分數計算結果: {health_score}")
1123
  except Exception as e:
1124
- print(f"健康分數計算錯誤: {str(e)}")
1125
- raise
 
 
 
 
1126
 
1127
- try:
1128
- noise_score = calculate_noise_score(
1129
- breed_info.get('Breed', ''),
1130
- user_prefs
1131
- )
1132
- print(f"噪音分數計算結果: {noise_score}")
1133
- except Exception as e:
1134
- print(f"噪音分數計算錯誤: {str(e)}")
1135
- raise
1136
 
1137
- # 整合所有分數到字典中
1138
- scores = {
1139
- 'space': space_score,
1140
- 'exercise': exercise_score,
1141
- 'grooming': grooming_score,
1142
- 'experience': experience_score,
1143
- 'health': health_score,
1144
- 'noise': noise_score
1145
- }
 
 
 
1146
 
1147
- print("\n=== 所有基礎分數 ===")
1148
- for category, score in scores.items():
1149
- print(f"{category}: {score}")
1150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1151
 
1152
- # 首先處理極端情況
1153
- def check_critical_issues(scores: dict, breed_info: dict) -> float:
1154
- """
1155
- 檢查關鍵問題並計算懲罰係數
1156
- """
1157
- penalty = 1.0
1158
-
1159
- # 檢查經驗分數 - 如果太低表示品種太難駕馭
1160
- if scores['experience'] < 0.3:
1161
- penalty *= 0.8
1162
-
1163
- # 檢查空間分數 - 特別是對公寓的情況
1164
- if user_prefs.living_space == 'apartment' and scores['space'] < 0.4:
1165
- penalty *= 0.85
 
1166
 
1167
- # 檢查健康分數 - 健康問題是重要考量
1168
- if scores['health'] < 0.4:
1169
- penalty *= 0.9
1170
-
1171
- return penalty
1172
 
1173
- # # 計算權重和加權分數
1174
- # def calculate_weighted_score(scores: dict) -> float:
1175
- # """
1176
- # 使用動態權重計算加權分數
1177
- # """
1178
- # base_weights = {
1179
- # 'space': 0.28,
1180
- # 'exercise': 0.18,
1181
- # 'grooming': 0.12,
1182
- # 'experience': 0.22,
1183
- # 'health': 0.12,
1184
- # 'noise': 0.08
1185
- # }
1186
-
1187
- # # 根據居住環境調整權重
1188
- # if user_prefs.living_space == 'apartment':
1189
- # base_weights['space'] *= 1.2
1190
- # base_weights['noise'] *= 1.2
1191
-
1192
- # # 根據經驗等級調整權重
1193
- # if user_prefs.experience_level == 'beginner':
1194
- # base_weights['experience'] *= 1.3
1195
-
1196
- # # 重新正規化權重
1197
- # total_weight = sum(base_weights.values())
1198
- # weights = {k: v/total_weight for k, v in base_weights.items()}
1199
-
1200
- # # 計算加權分數
1201
- # return sum(score * weights[category] for category, score in scores.items())
1202
 
1203
- def calculate_weighted_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1204
- """
1205
- 計算加權分數的函數
1206
-
1207
- Parameters:
1208
- scores: dict - 包含各項評分的字典
1209
- user_prefs: UserPreferences - 使用者偏好設定
1210
- breed_info: dict - 品種資訊
1211
-
1212
- Returns:
1213
- float: 加權後的最終分數
1214
- """
1215
- # 基礎權重設定
1216
- base_weights = {
1217
- 'space': 0.25,
1218
- 'exercise': 0.20,
1219
- 'grooming': 0.15,
1220
- 'experience': 0.18,
1221
- 'health': 0.12,
1222
- 'noise': 0.10
1223
- }
1224
-
1225
- # 根據使用者經驗調整權重
1226
- if user_prefs.experience_level == 'beginner':
1227
- base_weights['experience'] *= 1.2
1228
- base_weights['health'] *= 1.1
1229
- base_weights['grooming'] *= 0.9
1230
- elif user_prefs.experience_level == 'advanced':
1231
- base_weights['exercise'] *= 1.2
1232
- base_weights['experience'] *= 0.8
1233
-
1234
- # 根據居住環境調整權重
1235
- if user_prefs.living_space == 'apartment':
1236
- base_weights['noise'] *= 1.3
1237
- base_weights['space'] *= 1.2
1238
- elif user_prefs.living_space == 'house_large':
1239
- base_weights['exercise'] *= 1.2
1240
- base_weights['space'] *= 0.9
1241
-
1242
- # 有孩童時的權重調整
1243
- if user_prefs.has_children:
1244
- base_weights['noise'] *= 1.2
1245
- base_weights['health'] *= 1.1
1246
-
1247
- # 重新正規化權重
1248
- total_weight = sum(base_weights.values())
1249
- weights = {k: v/total_weight for k, v in base_weights.items()}
1250
-
1251
- # 計算加權分數
1252
- weighted_score = sum(score * weights[category] for category, score in scores.items())
1253
-
1254
- # 計算品種特性加成
1255
- breed_bonus = calculate_breed_characteristic_bonus(breed_info, user_prefs)
1256
-
1257
- # 混合基礎分數和特性加成
1258
- final_score = (weighted_score * 0.85) + (breed_bonus * 0.15)
1259
-
1260
- return min(0.95, max(0.55, final_score))
1261
-
1262
- def calculate_breed_characteristic_bonus(breed_info: dict, user_prefs: UserPreferences) -> float:
1263
- """
1264
- 計算品種特性加成,增加品種多樣性
1265
- """
1266
- bonus = 0.0
1267
- temperament = breed_info.get('Temperament', '').lower()
1268
- description = breed_info.get('Description', '').lower()
1269
-
1270
- # 品種類型加成
1271
- breed_types = {
1272
- 'working': {'keywords': ['working', 'guard', 'protection'], 'bonus': 0.05},
1273
- 'companion': {'keywords': ['companion', 'friendly', 'affectionate'], 'bonus': 0.05},
1274
- 'sporting': {'keywords': ['hunting', 'sporting', 'athletic'], 'bonus': 0.05},
1275
- 'herding': {'keywords': ['herding', 'shepherd', 'cattle'], 'bonus': 0.05}
1276
- }
1277
-
1278
- # 根據使用場景給予特定加成
1279
- for breed_type, info in breed_types.items():
1280
- if any(keyword in description or keyword in temperament for keyword in info['keywords']):
1281
- if user_prefs.has_children and breed_type == 'companion':
1282
- bonus += info['bonus'] * 1.5
1283
- elif user_prefs.exercise_type == 'active_training' and breed_type in ['working', 'sporting']:
1284
- bonus += info['bonus'] * 1.3
1285
- else:
1286
- bonus += info['bonus']
1287
-
1288
- # 特殊加成(增加多樣性)
1289
- if 'rare' in description or 'unique' in description:
1290
- bonus += 0.03
1291
- if 'independent' in temperament and user_prefs.experience_level == 'advanced':
1292
- bonus += 0.04
1293
-
1294
- return min(0.15, bonus) # 限制最大加成
1295
-
1296
 
1297
- # 計算最終分數
1298
- def calculate_final_score(base_score: float, penalty: float) -> float:
1299
- """
1300
- 計算並調整最終分數,確保合理的分數分布
1301
- """
1302
- # 應用懲罰係數
1303
- adjusted_score = base_score * penalty
1304
-
1305
- # 將分數映射到期望的範圍(0.55-0.95)
1306
- mapped_score = 0.55 + (adjusted_score * 0.4)
1307
-
1308
- # 確保分數在合理範圍內
1309
- final = max(0.55, min(0.95, mapped_score))
1310
-
1311
- return round(final, 4)
1312
 
1313
- # 執行計算流程
1314
- penalty = check_critical_issues(scores, breed_info)
1315
- weighted_score = calculate_weighted_score(scores, user_prefs, breed_info)
1316
- final_score = calculate_final_score(weighted_score, penalty)
1317
 
1318
- # 準備返回結果
1319
- scores = {k: round(v, 4) for k, v in scores.items()}
1320
- scores['overall'] = final_score
1321
-
1322
- return scores
1323
 
1324
- except Exception as e:
1325
- print(f"\n!!!!! 發生嚴重錯誤 !!!!!")
1326
- print(f"錯誤類型: {type(e).__name__}")
1327
- print(f"錯誤訊息: {str(e)}")
1328
- print(f"完整錯誤追蹤:")
1329
- print(traceback.format_exc())
1330
- return {k: 0.6 for k in ['space', 'exercise', 'grooming', 'experience', 'health', 'noise', 'overall']}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1073
 
1074
  # 1. 計算基礎分數
1075
  try:
1076
+ print("\n=== 開始計算品種相容性分數 ===")
1077
+ print(f"處理品種: {breed_info.get('Breed', 'Unknown')}")
1078
+ print(f"品種信息: {breed_info}")
1079
+ print(f"使用者偏好: {vars(user_prefs)}")
1080
+
1081
+ # 計算所有基礎分數並整合到字典中
1082
+ scores = {
1083
+ 'space': calculate_space_score(
1084
+ breed_info['Size'],
1085
+ user_prefs.living_space,
1086
+ user_prefs.yard_access != 'no_yard',
1087
+ breed_info.get('Exercise Needs', 'Moderate')
1088
+ ),
1089
+ 'exercise': calculate_exercise_score(
1090
+ breed_info.get('Exercise Needs', 'Moderate'),
1091
+ user_prefs.exercise_time
1092
+ ),
1093
+ 'grooming': calculate_grooming_score(
1094
+ breed_info.get('Grooming Needs', 'Moderate'),
1095
+ user_prefs.grooming_commitment.lower(),
1096
+ breed_info['Size']
1097
+ ),
1098
+ 'experience': calculate_experience_score(
1099
+ breed_info.get('Care Level', 'Moderate'),
1100
+ user_prefs.experience_level,
1101
+ breed_info.get('Temperament', '')
1102
+ ),
1103
+ 'health': calculate_health_score(
1104
+ breed_info.get('Breed', ''),
1105
+ user_prefs
1106
+ ),
1107
+ 'noise': calculate_noise_score(
1108
+ breed_info.get('Breed', ''),
1109
+ user_prefs
1110
+ )
1111
+ }
1112
+
1113
+ # 檢查關鍵不適配情況
1114
+ critical_issues = check_critical_matches(scores, user_prefs)
1115
+ if critical_issues['has_critical']:
1116
+ return apply_critical_penalty(scores, critical_issues)
1117
+
1118
+ # 計算環境適應性加成
1119
+ adaptability_bonus = calculate_environmental_fit(breed_info, user_prefs)
1120
+
1121
+ # 計算最終加權分數
1122
+ final_score = calculate_final_weighted_score(
1123
+ scores=scores,
1124
+ user_prefs=user_prefs,
1125
+ breed_info=breed_info,
1126
+ adaptability_bonus=adaptability_bonus
1127
  )
1128
+
1129
+ # 更新最終結果
1130
+ scores.update({
1131
+ 'overall': final_score,
1132
+ 'adaptability_bonus': adaptability_bonus
1133
+ })
1134
+
1135
+ return scores
1136
+
1137
  except Exception as e:
1138
+ print(f"\n!!!!! 發生嚴重錯誤 !!!!!")
1139
+ print(f"錯誤類型: {type(e).__name__}")
1140
+ print(f"錯誤訊息: {str(e)}")
1141
+ print(f"完整錯誤追蹤:")
1142
+ print(traceback.format_exc())
1143
+ return {k: 0.6 for k in ['space', 'exercise', 'grooming', 'experience', 'health', 'noise', 'overall']}
1144
 
1145
+ def check_critical_matches(scores: dict, user_prefs: UserPreferences) -> dict:
1146
+ """評估是否存在極端不適配的情況"""
1147
+ critical_issues = {
1148
+ 'has_critical': False,
1149
+ 'reasons': []
1150
+ }
 
 
 
1151
 
1152
+ # 檢查極端不適配情況
1153
+ if scores['space'] < 0.3:
1154
+ critical_issues['has_critical'] = True
1155
+ critical_issues['reasons'].append('space_incompatible')
1156
+
1157
+ if scores['noise'] < 0.3 and user_prefs.living_space == 'apartment':
1158
+ critical_issues['has_critical'] = True
1159
+ critical_issues['reasons'].append('noise_incompatible')
1160
+
1161
+ if scores['experience'] < 0.3 and user_prefs.experience_level == 'beginner':
1162
+ critical_issues['has_critical'] = True
1163
+ critical_issues['reasons'].append('too_challenging')
1164
 
1165
+ return critical_issues
 
 
1166
 
1167
+ def apply_critical_penalty(scores: dict, critical_issues: dict) -> dict:
1168
+ """當發現關鍵不適配時,調整分數"""
1169
+ penalized_scores = scores.copy()
1170
+ penalty_factor = 0.6
1171
+
1172
+ for reason in critical_issues['reasons']:
1173
+ if reason == 'space_incompatible':
1174
+ penalized_scores['overall'] *= penalty_factor
1175
+ penalized_scores['space'] *= penalty_factor
1176
+ elif reason == 'noise_incompatible':
1177
+ penalized_scores['overall'] *= penalty_factor
1178
+ penalized_scores['noise'] *= penalty_factor
1179
+ elif reason == 'too_challenging':
1180
+ penalized_scores['overall'] *= penalty_factor
1181
+ penalized_scores['experience'] *= penalty_factor
1182
+
1183
+ return penalized_scores
1184
 
1185
+ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -> float:
1186
+ """計算品種與環境的適應性加成"""
1187
+ adaptability_score = 0.0
1188
+ description = breed_info.get('Description', '').lower()
1189
+ temperament = breed_info.get('Temperament', '').lower()
1190
+
1191
+ # 環境適應性評估
1192
+ if user_prefs.living_space == 'apartment':
1193
+ if 'adaptable' in temperament or 'apartment' in description:
1194
+ adaptability_score += 0.1
1195
+ if breed_info.get('Size') == 'Small':
1196
+ adaptability_score += 0.05
1197
+ elif user_prefs.living_space == 'house_large':
1198
+ if 'active' in temperament or 'energetic' in description:
1199
+ adaptability_score += 0.1
1200
 
1201
+ # 氣候適應性
1202
+ if user_prefs.climate in description or user_prefs.climate in temperament:
1203
+ adaptability_score += 0.05
1204
+
1205
+ return min(0.2, adaptability_score)
1206
 
1207
+ def calculate_final_weighted_score(scores: dict, user_prefs: UserPreferences,
1208
+ breed_info: dict, adaptability_bonus: float) -> float:
1209
+ """計算最終加權分數"""
1210
+ base_weights = {
1211
+ 'space': 0.25,
1212
+ 'exercise': 0.20,
1213
+ 'grooming': 0.15,
1214
+ 'experience': 0.18,
1215
+ 'health': 0.12,
1216
+ 'noise': 0.10
1217
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1218
 
1219
+ # 根據居住環境動態調整權重
1220
+ if user_prefs.living_space == 'apartment':
1221
+ base_weights['space'] *= 1.4
1222
+ base_weights['noise'] *= 1.3
1223
+ base_weights['exercise'] *= 0.8
1224
+ elif user_prefs.living_space == 'house_large':
1225
+ base_weights['exercise'] *= 1.3
1226
+ base_weights['space'] *= 0.9
1227
+ base_weights['noise'] *= 0.8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1228
 
1229
+ # 根據經驗等級調整權重
1230
+ if user_prefs.experience_level == 'beginner':
1231
+ base_weights['experience'] *= 1.5
1232
+ base_weights['health'] *= 1.2
1233
+ elif user_prefs.experience_level == 'advanced':
1234
+ base_weights['exercise'] *= 1.2
1235
+ base_weights['experience'] *= 0.8
 
 
 
 
 
 
 
 
1236
 
1237
+ # 有孩童時的特殊調整
1238
+ if user_prefs.has_children:
1239
+ base_weights['noise'] *= 1.3
1240
+ base_weights['health'] *= 1.2
1241
 
1242
+ # 重新正規化權重
1243
+ total_weight = sum(base_weights.values())
1244
+ weights = {k: v/total_weight for k, v in base_weights.items()}
 
 
1245
 
1246
+ # 計算基礎加權分數
1247
+ weighted_base = sum(score * weights[category] for category, score in scores.items())
1248
+
1249
+ # 品種特性加成
1250
+ breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1251
+
1252
+ # 計算最終分數
1253
+ final_score = (weighted_base * 0.75) + (breed_bonus * 0.15) + (adaptability_bonus * 0.10)
1254
+
1255
+ # 擴大分數範圍
1256
+ amplified_score = amplify_score_range(final_score)
1257
+
1258
+ return round(amplified_score, 4)
1259
+
1260
+ def amplify_score_range(score: float) -> float:
1261
+ """擴大分數範圍,使差異更明顯"""
1262
+ min_score = 0.45
1263
+ max_score = 0.95
1264
+
1265
+ # 正規化到 0-1 範圍
1266
+ normalized = (score - 0.5) / 0.5
1267
+
1268
+ # 非線性轉換
1269
+ amplified = math.pow(abs(normalized), 1.5) * math.copysign(1, normalized)
1270
+
1271
+ # 映射回目標範圍
1272
+ final = min_score + (max_score - min_score) * ((amplified + 1) / 2)
1273
+
1274
+ return min(max_score, max(min_score, final))