DawnC commited on
Commit
dddd3ac
1 Parent(s): baf67fd

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. scoring_calculation_system.py +207 -87
scoring_calculation_system.py CHANGED
@@ -143,6 +143,7 @@ def calculate_breed_bonus(breed_info: dict, user_prefs: UserPreferences) -> floa
143
  """
144
  bonus = 0.0
145
  temperament = breed_info.get('Temperament', '').lower()
 
146
 
147
  # 壽命評估 - 重新設計以反映更實際的考量
148
  try:
@@ -206,6 +207,47 @@ def calculate_breed_bonus(breed_info: dict, user_prefs: UserPreferences) -> floa
206
 
207
  bonus += max(-0.25, min(0.25, personality_score))
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  # 適應性評估 - 根據具體環境給予更細緻的評分
210
  adaptability_bonus = 0.0
211
  if breed_info.get('Size') == "Small" and user_prefs.living_space == "apartment":
@@ -779,8 +821,20 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
779
  return min(0.95, max(0.15, current_score))
780
 
781
 
782
- # def calculate_exercise_score(breed_needs: str, user_time: int) -> float:
783
- # """運動需求計算"""
 
 
 
 
 
 
 
 
 
 
 
 
784
  # exercise_needs = {
785
  # 'VERY HIGH': {'min': 120, 'ideal': 150, 'max': 180},
786
  # 'HIGH': {'min': 90, 'ideal': 120, 'max': 150},
@@ -791,57 +845,115 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
791
 
792
  # breed_need = exercise_needs.get(breed_needs.strip().upper(), exercise_needs['MODERATE'])
793
 
794
- # # 計算匹配度
795
- # if user_time >= breed_need['ideal']:
796
- # if user_time > breed_need['max']:
797
- # return 0.9 # 稍微降分,因為可能過度運動
798
- # return 1.0
799
- # elif user_time >= breed_need['min']:
800
- # return 0.8 + (user_time - breed_need['min']) / (breed_need['ideal'] - breed_need['min']) * 0.2
 
 
 
801
  # else:
802
- # return max(0.3, 0.8 * (user_time / breed_need['min']))
 
 
 
 
803
 
804
 
805
- def calculate_exercise_score(breed_needs: str, exercise_time: int) -> float:
806
  """
807
- 優化的運動需求評分系統
808
 
809
  Parameters:
810
- breed_needs: str - 品種的運動需求等級
811
- exercise_time: int - 使用者可提供的運動時間(分鐘)
 
812
 
813
- 改進:
814
- 1. 更細緻的運動需求評估
815
- 2. 更合理的時間匹配計算
816
- 3. 避免極端評分
817
  """
818
- # 基礎運動需求評估
819
- exercise_needs = {
820
- 'VERY HIGH': {'min': 120, 'ideal': 150, 'max': 180},
821
- 'HIGH': {'min': 90, 'ideal': 120, 'max': 150},
822
- 'MODERATE': {'min': 45, 'ideal': 60, 'max': 90},
823
- 'LOW': {'min': 20, 'ideal': 30, 'max': 45},
824
- 'VARIES': {'min': 30, 'ideal': 60, 'max': 90}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
825
  }
826
 
827
- breed_need = exercise_needs.get(breed_needs.strip().upper(), exercise_needs['MODERATE'])
 
828
 
829
- # 基礎時間匹配度計算
830
- if exercise_time >= breed_need['ideal']:
831
- if exercise_time > breed_need['max']:
832
- # 運動時間過長,稍微降低分數
833
- time_score = 0.9
834
  else:
835
- time_score = 1.0
836
- elif exercise_time >= breed_need['min']:
837
  # 在最小需求和理想需求之間,線性計算分數
838
- time_score = 0.7 + (exercise_time - breed_need['min']) / (breed_need['ideal'] - breed_need['min']) * 0.3
 
839
  else:
840
- # 運動時間不足,但仍根據比例給予分數
841
- time_score = max(0.3, 0.7 * (exercise_time / breed_need['min']))
 
 
 
 
 
 
 
 
842
 
843
- # 確保分數在合理範圍內
844
- return min(1.0, max(0.3, time_score))
845
 
846
 
847
  def calculate_grooming_score(breed_needs: str, user_commitment: str, breed_size: str) -> float:
@@ -1462,67 +1574,75 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1462
  return min(0.2, adaptability_score)
1463
 
1464
 
1465
- def calculate_final_weighted_score(
1466
- scores: dict,
1467
- user_prefs: UserPreferences,
1468
- breed_info: dict,
1469
- adaptability_bonus: float
1470
- ) -> float:
1471
  """
1472
- 優化的最終分數計算系統,強化條件變化的影響力
 
1473
  """
1474
- # 基礎權重 - 更極端的差異
1475
- base_weights = {
1476
- 'space': 0.35, # 極度重視空間匹配
1477
- 'exercise': 0.25, # 重視運動需求
1478
  'grooming': 0.15,
1479
  'experience': 0.15,
1480
- 'health': 0.07,
1481
- 'noise': 0.03
1482
  }
1483
-
1484
- # 條件特殊化評分
1485
- special_conditions = 0.0
1486
 
1487
- # 極端條件判定
 
 
 
 
 
 
 
 
1488
  if user_prefs.living_space == 'apartment':
1489
- if breed_info['Size'] == 'Large':
1490
- special_conditions -= 0.35 # 大型犬在公寓極度不適合
1491
- elif breed_info['Size'] == 'Small':
1492
- special_conditions += 0.15 # 小型犬在公寓加分
1493
-
1494
- # 運動需求極端匹配
1495
- exercise_needs = breed_info.get('Exercise_Needs', 'MODERATE').upper()
1496
- if user_prefs.exercise_time > 120: # 高運動量
1497
- if exercise_needs in ['VERY HIGH', 'HIGH']:
1498
- special_conditions += 0.20
1499
- elif exercise_needs == 'LOW':
1500
- special_conditions -= 0.25
1501
- elif user_prefs.exercise_time < 45: # 低運動量
1502
- if exercise_needs in ['VERY HIGH', 'HIGH']:
1503
- special_conditions -= 0.25
1504
- elif exercise_needs == 'LOW':
1505
- special_conditions += 0.15
1506
-
1507
- # 經驗等級極端匹配
1508
  if user_prefs.experience_level == 'beginner':
1509
- if breed_info.get('Care_Level') == 'HIGH':
1510
- special_conditions -= 0.30
1511
- elif user_prefs.experience_level == 'advanced':
1512
- if breed_info.get('Care_Level') == 'LOW':
1513
- special_conditions -= 0.20
 
 
 
 
 
 
 
 
1514
 
1515
- # 計算加權基礎分數
1516
- weighted_base = sum(score * base_weights[category] for category, score in scores.items())
 
 
 
 
 
 
 
 
 
 
 
 
1517
 
1518
- # 品種特性加成
1519
  breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1520
 
1521
- # 最終分數計算
1522
- raw_score = (weighted_base * 0.65) + (breed_bonus * 0.20) + (adaptability_bonus * 0.10) + (special_conditions * 0.05)
1523
-
1524
- # 分數轉換 - 使用S型曲線
1525
- return amplify_score_extreme(raw_score)
1526
 
1527
 
1528
  def amplify_score_extreme(score: float) -> float:
 
143
  """
144
  bonus = 0.0
145
  temperament = breed_info.get('Temperament', '').lower()
146
+ description = breed_info.get('Description', '').lower()
147
 
148
  # 壽命評估 - 重新設計以反映更實際的考量
149
  try:
 
207
 
208
  bonus += max(-0.25, min(0.25, personality_score))
209
 
210
+ exercise_match = calculate_exercise_match(
211
+ breed_info.get('Exercise_Needs', 'MODERATE'),
212
+ user_prefs.exercise_time,
213
+ user_prefs.exercise_type
214
+ )
215
+ bonus += exercise_match
216
+
217
+ # 運動類型特性評估
218
+ exercise_traits = {
219
+ 'active_training': {
220
+ 'athletic': 0.10,
221
+ 'energetic': 0.08,
222
+ 'working': 0.08,
223
+ 'intelligent': 0.06
224
+ },
225
+ 'moderate_activity': {
226
+ 'adaptable': 0.08,
227
+ 'balanced': 0.06,
228
+ 'versatile': 0.06,
229
+ 'steady': 0.04
230
+ },
231
+ 'light_walks': {
232
+ 'calm': 0.08,
233
+ 'gentle': 0.06,
234
+ 'easy-going': 0.06,
235
+ 'patient': 0.04
236
+ }
237
+ }
238
+
239
+ # 計算運動類型特性匹配度
240
+ if user_prefs.exercise_type in exercise_traits:
241
+ trait_score = 0
242
+ matched_traits = 0
243
+ for trait, value in exercise_traits[user_prefs.exercise_type].items():
244
+ if trait in temperament:
245
+ trait_score += value
246
+ matched_traits += 1
247
+ if matched_traits > 0:
248
+ bonus += min(0.15, trait_score * (1 + (matched_traits - 1) * 0.1))
249
+
250
+
251
  # 適應性評估 - 根據具體環境給予更細緻的評分
252
  adaptability_bonus = 0.0
253
  if breed_info.get('Size') == "Small" and user_prefs.living_space == "apartment":
 
821
  return min(0.95, max(0.15, current_score))
822
 
823
 
824
+ # def calculate_exercise_score(breed_needs: str, exercise_time: int) -> float:
825
+ # """
826
+ # 優化的運動需求評分系統
827
+
828
+ # Parameters:
829
+ # breed_needs: str - 品種的運動需求等級
830
+ # exercise_time: int - 使用者可提供的運動時間(分鐘)
831
+
832
+ # 改進:
833
+ # 1. 更細緻的運動需求評估
834
+ # 2. 更合理的時間匹配計算
835
+ # 3. 避免極端評分
836
+ # """
837
+ # # 基礎運動需求評估
838
  # exercise_needs = {
839
  # 'VERY HIGH': {'min': 120, 'ideal': 150, 'max': 180},
840
  # 'HIGH': {'min': 90, 'ideal': 120, 'max': 150},
 
845
 
846
  # breed_need = exercise_needs.get(breed_needs.strip().upper(), exercise_needs['MODERATE'])
847
 
848
+ # # 基礎時間匹配度計算
849
+ # if exercise_time >= breed_need['ideal']:
850
+ # if exercise_time > breed_need['max']:
851
+ # # 運動時間過長,稍微降低分數
852
+ # time_score = 0.9
853
+ # else:
854
+ # time_score = 1.0
855
+ # elif exercise_time >= breed_need['min']:
856
+ # # 在最小需求和理想需求之間,線性計算分數
857
+ # time_score = 0.7 + (exercise_time - breed_need['min']) / (breed_need['ideal'] - breed_need['min']) * 0.3
858
  # else:
859
+ # # 運動時間不足,但仍根據比例給予分數
860
+ # time_score = max(0.3, 0.7 * (exercise_time / breed_need['min']))
861
+
862
+ # # 確保分數在合理範圍內
863
+ # return min(1.0, max(0.3, time_score))
864
 
865
 
866
+ def calculate_exercise_match(breed_needs: str, exercise_time: int, exercise_type: str) -> float:
867
  """
868
+ 精確評估品種運動需求與使用者運動條件的匹配度
869
 
870
  Parameters:
871
+ breed_needs: 品種的運動���求等級
872
+ exercise_time: 使用者能提供的運動時間(分鐘)
873
+ exercise_type: 使用者偏好的運動類型
874
 
875
+ Returns:
876
+ float: -0.2 到 0.2 之間的匹配分數
 
 
877
  """
878
+ # 定義更細緻的運動需求等級
879
+ exercise_levels = {
880
+ 'VERY HIGH': {
881
+ 'min': 120,
882
+ 'ideal': 150,
883
+ 'max': 180,
884
+ 'intensity': 'high',
885
+ 'sessions': 'multiple',
886
+ 'preferred_types': ['active_training', 'intensive_exercise']
887
+ },
888
+ 'HIGH': {
889
+ 'min': 90,
890
+ 'ideal': 120,
891
+ 'max': 150,
892
+ 'intensity': 'moderate_high',
893
+ 'sessions': 'multiple',
894
+ 'preferred_types': ['active_training', 'moderate_activity']
895
+ },
896
+ 'MODERATE HIGH': {
897
+ 'min': 70,
898
+ 'ideal': 90,
899
+ 'max': 120,
900
+ 'intensity': 'moderate',
901
+ 'sessions': 'flexible',
902
+ 'preferred_types': ['moderate_activity', 'active_training']
903
+ },
904
+ 'MODERATE': {
905
+ 'min': 45,
906
+ 'ideal': 60,
907
+ 'max': 90,
908
+ 'intensity': 'moderate',
909
+ 'sessions': 'flexible',
910
+ 'preferred_types': ['moderate_activity', 'light_walks']
911
+ },
912
+ 'MODERATE LOW': {
913
+ 'min': 30,
914
+ 'ideal': 45,
915
+ 'max': 70,
916
+ 'intensity': 'light_moderate',
917
+ 'sessions': 'flexible',
918
+ 'preferred_types': ['light_walks', 'moderate_activity']
919
+ },
920
+ 'LOW': {
921
+ 'min': 15,
922
+ 'ideal': 30,
923
+ 'max': 45,
924
+ 'intensity': 'light',
925
+ 'sessions': 'single',
926
+ 'preferred_types': ['light_walks']
927
+ }
928
  }
929
 
930
+ # 獲取品種的運動需求配置
931
+ breed_level = exercise_levels.get(breed_needs.upper(), exercise_levels['MODERATE'])
932
 
933
+ # 計算時間匹配度(使用更平滑的評分曲線)
934
+ if exercise_time >= breed_level['ideal']:
935
+ if exercise_time > breed_level['max']:
936
+ # 運動時間過長,適度降分
937
+ time_score = 0.15 - (0.05 * (exercise_time - breed_level['max']) / 30)
938
  else:
939
+ time_score = 0.15
940
+ elif exercise_time >= breed_level['min']:
941
  # 在最小需求和理想需求之間,線性計算分數
942
+ time_ratio = (exercise_time - breed_level['min']) / (breed_level['ideal'] - breed_level['min'])
943
+ time_score = 0.05 + (time_ratio * 0.10)
944
  else:
945
+ # 運動時間不足,根據差距程度扣分
946
+ time_ratio = max(0, exercise_time / breed_level['min'])
947
+ time_score = -0.15 * (1 - time_ratio)
948
+
949
+ # 運動類型匹配度評估
950
+ type_score = 0.0
951
+ if exercise_type in breed_level['preferred_types']:
952
+ type_score = 0.05
953
+ if exercise_type == breed_level['preferred_types'][0]:
954
+ type_score = 0.08 # 最佳匹配類型給予更高分數
955
 
956
+ return max(-0.2, min(0.2, time_score + type_score))
 
957
 
958
 
959
  def calculate_grooming_score(breed_needs: str, user_commitment: str, breed_size: str) -> float:
 
1574
  return min(0.2, adaptability_score)
1575
 
1576
 
1577
+ def calculate_dynamic_weights(user_prefs: UserPreferences, breed_info: dict) -> dict:
 
 
 
 
 
1578
  """
1579
+ 根據使用者條件動態計算權重
1580
+ 這個系統會根據具體情況調整各個評分項目的重要性
1581
  """
1582
+ weights = {
1583
+ 'space': 0.25, # 降低基礎空間權重
1584
+ 'exercise': 0.20,
 
1585
  'grooming': 0.15,
1586
  'experience': 0.15,
1587
+ 'health': 0.15,
1588
+ 'noise': 0.10
1589
  }
 
 
 
1590
 
1591
+ # 運動時間對權重的影響
1592
+ if user_prefs.exercise_time > 150:
1593
+ weights['exercise'] *= 1.4
1594
+ weights['space'] *= 0.8
1595
+ elif user_prefs.exercise_time < 30:
1596
+ weights['exercise'] *= 0.8
1597
+ weights['health'] *= 1.2
1598
+
1599
+ # 居住環境對權重的影響
1600
  if user_prefs.living_space == 'apartment':
1601
+ weights['noise'] *= 1.3
1602
+ weights['space'] *= 1.2
1603
+ elif user_prefs.living_space == 'house_large':
1604
+ weights['exercise'] *= 1.2
1605
+ weights['space'] *= 0.8
1606
+
1607
+ # 經驗等級對權重的影響
 
 
 
 
 
 
 
 
 
 
 
 
1608
  if user_prefs.experience_level == 'beginner':
1609
+ weights['experience'] *= 1.3
1610
+ weights['health'] *= 1.2
1611
+
1612
+ # 有孩童時的權重調整
1613
+ if user_prefs.has_children:
1614
+ if user_prefs.children_age == 'toddler':
1615
+ weights['temperament'] = 0.20 # 新增性格權重
1616
+ weights['space'] *= 0.8
1617
+
1618
+ # 重新正規化權重
1619
+ total = sum(weights.values())
1620
+ return {k: v/total for k, v in weights.items()}
1621
+
1622
 
1623
+ def calculate_final_weighted_score(
1624
+ scores: dict,
1625
+ user_prefs: UserPreferences,
1626
+ breed_info: dict,
1627
+ adaptability_bonus: float
1628
+ ) -> float:
1629
+ """
1630
+ 整合動態權重的最終分數計算系統
1631
+ """
1632
+ # 第一步:計算動態權重
1633
+ weights = calculate_dynamic_weights(user_prefs, breed_info) # 內部函數
1634
+
1635
+ # 第二步:計算基礎加權分數
1636
+ weighted_base = sum(score * weights[category] for category, score in scores.items())
1637
 
1638
+ # 第三步:計算品種特性加成
1639
  breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1640
 
1641
+ # 第四步:最終分數計算
1642
+ final_score = (weighted_base * 0.70) + (breed_bonus * 0.20) + (adaptability_bonus * 0.10)
1643
+
1644
+ # 第五步:分數轉換
1645
+ return amplify_score_extreme(final_score)
1646
 
1647
 
1648
  def amplify_score_extreme(score: float) -> float: