DawnC commited on
Commit
7745d43
1 Parent(s): 47e2a7c

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. scoring_calculation_system.py +169 -183
scoring_calculation_system.py CHANGED
@@ -129,39 +129,37 @@ class UserPreferences:
129
 
130
  @staticmethod
131
  def calculate_breed_bonus(breed_info: dict, user_prefs: 'UserPreferences') -> float:
132
- """
133
- 計算品種額外加分,考慮多個維度但不包含家庭相容性評分
134
- """
135
  bonus = 0.0
136
  temperament = breed_info.get('Temperament', '').lower()
137
  description = breed_info.get('Description', '').lower()
138
 
139
- # 1. 壽命加分(最高0.05)
140
  try:
141
  lifespan = breed_info.get('Lifespan', '10-12 years')
142
  years = [int(x) for x in lifespan.split('-')[0].split()[0:1]]
143
- longevity_bonus = min(0.05, (max(years) - 10) * 0.01)
144
  bonus += longevity_bonus
145
  except:
146
  pass
147
 
148
- # 2. 性格特徵加分(最高0.15)
149
  positive_traits = {
150
- 'friendly': 0.05,
151
- 'gentle': 0.05,
152
- 'patient': 0.05,
153
- 'intelligent': 0.04,
154
- 'adaptable': 0.04,
155
- 'affectionate': 0.04,
156
- 'easy-going': 0.03,
157
- 'calm': 0.03
158
  }
159
 
160
- # 根據經驗等級調整負面特徵的懲罰程度
161
  experience_multiplier = {
162
  'beginner': 1.3,
163
- 'intermediate': 1.0,
164
- 'advanced': 0.8
165
  }.get(user_prefs.experience_level, 1.0)
166
 
167
  negative_traits = {
@@ -174,86 +172,63 @@ def calculate_breed_bonus(breed_info: dict, user_prefs: 'UserPreferences') -> fl
174
  }
175
 
176
  personality_score = sum(value for trait, value in positive_traits.items() if trait in temperament)
 
 
177
  personality_score += sum(value for trait, value in negative_traits.items() if trait in temperament)
178
- bonus += max(-0.15, min(0.15, personality_score))
179
 
180
- # 3. 適應性加分(最高0.1)
181
  adaptability_bonus = 0.0
182
  if breed_info.get('Size') == "Small" and user_prefs.living_space == "apartment":
183
- adaptability_bonus += 0.05
184
  if 'adaptable' in temperament or 'versatile' in temperament:
185
- adaptability_bonus += 0.05
186
 
187
- # 考慮更多環境適應因素
188
  if user_prefs.yard_access == "no_yard":
189
  if "needs space" in description or "requires yard" in description:
190
- adaptability_bonus -= 0.05
191
  elif user_prefs.yard_access == "private_yard":
192
  if "active" in description or "energetic" in description:
193
- adaptability_bonus += 0.03
194
 
195
- # 氣候適應性
196
- climate_terms = {
197
- 'cold': ['thick coat', 'winter', 'cold climate'],
198
- 'hot': ['short coat', 'warm climate', 'heat tolerant'],
199
- 'moderate': ['adaptable', 'all climate']
200
- }
201
- if any(term in description for term in climate_terms[user_prefs.climate]):
202
- adaptability_bonus += 0.02
203
-
204
- bonus += min(0.1, adaptability_bonus)
205
 
206
- # 4. 專門技能評估(最高0.1)
207
  skill_bonus = 0.0
208
- exercise_level = user_prefs.exercise_time / 60.0 # 轉換為小時
209
 
210
  special_abilities = {
211
- 'working': 0.03 if exercise_level >= 1.5 else 0.01,
212
- 'herding': 0.03 if exercise_level >= 1.5 else 0.01,
213
- 'hunting': 0.03 if exercise_level >= 1.5 else 0.01,
214
- 'tracking': 0.03 if exercise_level >= 1.0 else 0.02,
215
- 'agility': 0.02 if exercise_level >= 1.0 else 0.01,
216
- 'sporting': 0.02 if exercise_level >= 1.2 else 0.01 # 新增運動犬種考量
217
  }
218
 
219
  for ability, value in special_abilities.items():
220
  if ability in temperament.lower() or ability in description:
221
- # 根據使用者經驗和時間可用性調整技能加分
222
- time_multiplier = 1.2 if user_prefs.time_availability == 'flexible' else 0.8
223
  if user_prefs.experience_level == 'advanced':
224
- skill_bonus += value * 1.2 * time_multiplier
225
- elif user_prefs.experience_level == 'beginner':
226
- skill_bonus += value * 0.7 * time_multiplier
227
  else:
228
- skill_bonus += value * time_multiplier
229
 
230
- bonus += min(0.1, skill_bonus)
231
-
232
- # 5. 特殊需求評估(最高0.1/-0.15)
233
- special_needs_score = 0.0
 
 
234
 
235
- # 檢查特殊訓練需求
236
- if any(term in description for term in ['requires extensive training', 'needs firm training']):
237
- if user_prefs.experience_level == 'beginner':
238
- special_needs_score -= 0.08
239
- elif user_prefs.experience_level == 'intermediate':
240
- special_needs_score -= 0.04
241
-
242
- # 檢查社交需求
243
- if 'social needs' in description or 'requires companionship' in description:
244
- if user_prefs.time_availability == 'limited':
245
- special_needs_score -= 0.06
246
- elif user_prefs.time_availability == 'flexible':
247
- special_needs_score += 0.02
248
-
249
- # 檢查獨立性
250
- if 'independent' in temperament:
251
- if user_prefs.time_availability == 'limited':
252
- special_needs_score += 0.03
253
-
254
- bonus += max(-0.15, min(0.1, special_needs_score))
255
 
256
- return min(0.5, max(-0.25, bonus))
 
257
 
258
 
259
  @staticmethod
@@ -638,130 +613,99 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
638
  # final_score = max(0.2, min(1.0, score + temperament_adjustments))
639
  # return final_score
640
 
641
- def calculate_experience_score(care_level: str, user_experience: str, temperament: str, has_children: bool = False) -> float:
642
  """
643
- 計算使用者經驗與品種需求的匹配分數,加入了更嚴格的評估標準
644
  """
645
- # 即使是進階使用者也不應該完全無視品種難度
646
  base_scores = {
647
  "High": {
648
- "beginner": 0.12,
649
- "intermediate": 0.65,
650
- "advanced": 0.85
651
- },
652
- "Moderate": {
653
  "beginner": 0.35,
654
  "intermediate": 0.75,
655
- "advanced": 0.90
 
 
 
 
 
656
  },
657
  "Low": {
658
- "beginner": 0.65,
659
  "intermediate": 0.85,
660
- "advanced": 0.92
661
  }
662
  }
663
 
664
- # 取得基礎分數
665
  score = base_scores.get(care_level, base_scores["Moderate"])[user_experience]
666
 
667
- # 品種難度評估
668
- breed_difficulty_penalty = 0.0
669
- difficult_characteristics = {
670
- 'working': 0.08,
671
- 'guardian': 0.10,
672
- 'primitive': 0.12,
673
- 'independent': 0.08,
674
- 'strong-willed': 0.07
675
- }
676
-
677
- for trait, penalty in difficult_characteristics.items():
678
- if trait in temperament.lower():
679
- # 即使是進階使用者也會受到一定程度的懲罰
680
- if user_experience == "advanced":
681
- breed_difficulty_penalty += penalty * 0.4
682
- elif user_experience == "intermediate":
683
- breed_difficulty_penalty += penalty * 0.7
684
- else:
685
- breed_difficulty_penalty += penalty
686
-
687
- # 性格特徵評估
688
  temperament_lower = temperament.lower()
689
  temperament_adjustments = 0.0
690
 
691
- if user_experience == "beginner":
692
- difficult_traits = {
693
- 'stubborn': -0.15,
694
- 'independent': -0.12,
695
- 'dominant': -0.12,
696
- 'protective': -0.10,
697
- 'aloof': -0.08
698
- }
699
- easy_traits = {
700
- 'gentle': 0.08,
701
- 'friendly': 0.08,
702
- 'eager to please': 0.08,
703
- 'patient': 0.06
704
  }
705
 
706
- for trait, penalty in difficult_traits.items():
707
- if trait in temperament_lower:
708
- temperament_adjustments += penalty * 1.2
709
-
710
- for trait, bonus in easy_traits.items():
711
  if trait in temperament_lower:
712
- temperament_adjustments += bonus
713
 
714
  elif user_experience == "intermediate":
715
  moderate_traits = {
716
- 'intelligent': 0.04,
717
- 'athletic': 0.03,
718
- 'versatile': 0.03,
719
  'stubborn': -0.06,
720
- 'independent': -0.05
 
 
721
  }
722
 
723
  for trait, adjustment in moderate_traits.items():
724
  if trait in temperament_lower:
725
  temperament_adjustments += adjustment
726
-
727
- else: # advanced
728
- # 即使是進階使用者,某些特徵也應該被視為挑戰而非優勢
729
- advanced_traits = {
730
- 'stubborn': 0.02,
731
- 'independent': 0.02,
732
- 'intelligent': 0.04,
733
- 'protective': -0.02,
734
- 'strong-willed': -0.02
 
735
  }
736
 
737
- for trait, adjustment in advanced_traits.items():
738
  if trait in temperament_lower:
739
  temperament_adjustments += adjustment
740
-
741
- # 如果有小孩,增加額外的安全考量
742
- if has_children:
743
- safety_penalty = 0.0
744
- risky_traits = {
745
- 'protective': 0.05,
746
- 'territorial': 0.06,
747
- 'dominant': 0.07,
748
- 'aggressive': 0.10,
749
- 'strong-willed': 0.05
750
  }
751
 
752
- for trait, penalty in risky_traits.items():
753
- if trait in temperament_lower:
754
- # 即使是進階使用者,有小孩的情況下也要特別注意
755
- if user_experience == "advanced":
756
- safety_penalty += penalty * 0.7
757
- else:
758
- safety_penalty += penalty
759
-
760
- temperament_adjustments -= safety_penalty
761
-
762
- # 確保最終分數在合理範圍內,且有適當的上限
763
- final_score = score - breed_difficulty_penalty + temperament_adjustments
764
- return max(0.2, min(0.92, final_score))
765
 
766
  def calculate_health_score(breed_name: str) -> float:
767
  """計算品種健康分數"""
@@ -939,34 +883,76 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
939
  # 計算加權總分
940
  weighted_score = sum(score * weights[category] for category, score in scores.items())
941
 
942
- def amplify_score(score):
943
- """
944
- 優化分數放大函數,確保分數範圍合理且結果一致
945
- """
946
- # 基礎調整
947
- adjusted = (score - 0.35) * 1.8
948
 
949
- # 使用 3.2 次方使曲線更平滑
950
- amplified = pow(adjusted, 3.2) / 5.8 + score
951
 
952
- # 特別處理高分區間,確保不超過95%
953
- if amplified > 0.90:
954
- # 壓縮高分區間,確保最高到95%
955
- amplified = 0.90 + (amplified - 0.90) * 0.5
956
 
957
- # 確保最終分數在合理範圍內(0.55-0.95)
958
- final_score = max(0.55, min(0.95, amplified))
959
 
960
- # 四捨五入到小數點後第三位
961
- return round(final_score, 3)
962
 
963
- final_score = amplify_score(weighted_score)
 
 
 
 
964
 
965
- # 四捨五入所有分數
966
- scores = {k: round(v, 4) for k, v in scores.items()}
967
- scores['overall'] = round(final_score, 4)
968
 
969
- return scores
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
970
 
971
  except Exception as e:
972
  print(f"Error details: {str(e)}")
 
129
 
130
  @staticmethod
131
  def calculate_breed_bonus(breed_info: dict, user_prefs: 'UserPreferences') -> float:
132
+ """計算品種額外加分,強化進階使用者的評分"""
 
 
133
  bonus = 0.0
134
  temperament = breed_info.get('Temperament', '').lower()
135
  description = breed_info.get('Description', '').lower()
136
 
137
+ # 1. 壽命加分(最高0.08)- 提高上限
138
  try:
139
  lifespan = breed_info.get('Lifespan', '10-12 years')
140
  years = [int(x) for x in lifespan.split('-')[0].split()[0:1]]
141
+ longevity_bonus = min(0.08, (max(years) - 10) * 0.015) # 提高係數
142
  bonus += longevity_bonus
143
  except:
144
  pass
145
 
146
+ # 2. 性格特徵加分(最高0.20)- 提高上限
147
  positive_traits = {
148
+ 'friendly': 0.06,
149
+ 'gentle': 0.06,
150
+ 'patient': 0.06,
151
+ 'intelligent': 0.05,
152
+ 'adaptable': 0.05,
153
+ 'affectionate': 0.05,
154
+ 'easy-going': 0.04,
155
+ 'calm': 0.04
156
  }
157
 
158
+ # 根據經驗等級調整負面特徵的影響
159
  experience_multiplier = {
160
  'beginner': 1.3,
161
+ 'intermediate': 0.8,
162
+ 'advanced': 0.5 # 大幅降低進階使用者的負面特徵懲罰
163
  }.get(user_prefs.experience_level, 1.0)
164
 
165
  negative_traits = {
 
172
  }
173
 
174
  personality_score = sum(value for trait, value in positive_traits.items() if trait in temperament)
175
+ if user_prefs.experience_level == 'advanced':
176
+ personality_score *= 1.2 # 進階使用者得到更多正面特徵加分
177
  personality_score += sum(value for trait, value in negative_traits.items() if trait in temperament)
178
+ bonus += max(-0.15, min(0.20, personality_score))
179
 
180
+ # 3. 適應性加分(最高0.15)- 提高上限
181
  adaptability_bonus = 0.0
182
  if breed_info.get('Size') == "Small" and user_prefs.living_space == "apartment":
183
+ adaptability_bonus += 0.07
184
  if 'adaptable' in temperament or 'versatile' in temperament:
185
+ adaptability_bonus += 0.08
186
 
187
+ # 考慮環境適應因素
188
  if user_prefs.yard_access == "no_yard":
189
  if "needs space" in description or "requires yard" in description:
190
+ adaptability_bonus -= 0.05 * experience_multiplier # 根據經驗調整懲罰
191
  elif user_prefs.yard_access == "private_yard":
192
  if "active" in description or "energetic" in description:
193
+ adaptability_bonus += 0.05
194
 
195
+ bonus += min(0.15, adaptability_bonus)
 
 
 
 
 
 
 
 
 
196
 
197
+ # 4. 專門技能評估(最高0.15)- 提高上限和進階使用者加分
198
  skill_bonus = 0.0
199
+ exercise_level = user_prefs.exercise_time / 60.0
200
 
201
  special_abilities = {
202
+ 'working': 0.05 if exercise_level >= 1.5 else 0.02,
203
+ 'herding': 0.05 if exercise_level >= 1.5 else 0.02,
204
+ 'hunting': 0.05 if exercise_level >= 1.5 else 0.02,
205
+ 'tracking': 0.04 if exercise_level >= 1.0 else 0.02,
206
+ 'agility': 0.04 if exercise_level >= 1.0 else 0.02,
207
+ 'sporting': 0.04 if exercise_level >= 1.2 else 0.02
208
  }
209
 
210
  for ability, value in special_abilities.items():
211
  if ability in temperament.lower() or ability in description:
212
+ # 進階使用者在專門技能方面得到更多加分
 
213
  if user_prefs.experience_level == 'advanced':
214
+ skill_bonus += value * 1.5
215
+ elif user_prefs.experience_level == 'intermediate':
216
+ skill_bonus += value * 1.2
217
  else:
218
+ skill_bonus += value
219
 
220
+ # 根據時間可用性調整技能加分
221
+ time_multiplier = {
222
+ 'flexible': 1.2,
223
+ 'moderate': 1.0,
224
+ 'limited': 0.8
225
+ }.get(user_prefs.time_availability, 1.0)
226
 
227
+ skill_bonus *= time_multiplier
228
+ bonus += min(0.15, skill_bonus)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
 
230
+ # 最終分數範圍調整,提高上限
231
+ return min(0.6, max(-0.20, bonus))
232
 
233
 
234
  @staticmethod
 
613
  # final_score = max(0.2, min(1.0, score + temperament_adjustments))
614
  # return final_score
615
 
616
+ def calculate_experience_score(care_level: str, user_experience: str, temperament: str) -> float:
617
  """
618
+ 計算使用者經驗與品種需求的匹配分數,強化進階使用者的評分
619
  """
620
+ # 調整基礎分數矩陣,提高 advanced 的基本分數
621
  base_scores = {
622
  "High": {
 
 
 
 
 
623
  "beginner": 0.35,
624
  "intermediate": 0.75,
625
+ "advanced": 0.92 # 提高上限
626
+ },
627
+ "Moderate": {
628
+ "beginner": 0.45,
629
+ "intermediate": 0.82,
630
+ "advanced": 0.95
631
  },
632
  "Low": {
633
+ "beginner": 0.60,
634
  "intermediate": 0.85,
635
+ "advanced": 0.98
636
  }
637
  }
638
 
 
639
  score = base_scores.get(care_level, base_scores["Moderate"])[user_experience]
640
 
641
+ # 性格特徵評估
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
642
  temperament_lower = temperament.lower()
643
  temperament_adjustments = 0.0
644
 
645
+ if user_experience == "advanced":
646
+ # 進階使用者的特徵評估
647
+ advanced_traits = {
648
+ 'intelligent': 0.08, # 提高正面特徵加分
649
+ 'independent': 0.06,
650
+ 'strong-willed': 0.05,
651
+ 'energetic': 0.05,
652
+ 'protective': 0.04,
653
+ 'dominant': -0.02, # 降低負面特徵懲罰
654
+ 'stubborn': -0.02,
655
+ 'aggressive': -0.05
 
 
656
  }
657
 
658
+ for trait, adjustment in advanced_traits.items():
 
 
 
 
659
  if trait in temperament_lower:
660
+ temperament_adjustments += adjustment
661
 
662
  elif user_experience == "intermediate":
663
  moderate_traits = {
664
+ 'intelligent': 0.05,
665
+ 'adaptable': 0.04,
666
+ 'easy-going': 0.04,
667
  'stubborn': -0.06,
668
+ 'independent': -0.05,
669
+ 'dominant': -0.05,
670
+ 'aggressive': -0.08
671
  }
672
 
673
  for trait, adjustment in moderate_traits.items():
674
  if trait in temperament_lower:
675
  temperament_adjustments += adjustment
676
+
677
+ else: # beginner
678
+ beginner_traits = {
679
+ 'gentle': 0.05,
680
+ 'friendly': 0.05,
681
+ 'easy-going': 0.04,
682
+ 'stubborn': -0.10,
683
+ 'independent': -0.08,
684
+ 'dominant': -0.08,
685
+ 'aggressive': -0.12
686
  }
687
 
688
+ for trait, adjustment in beginner_traits.items():
689
  if trait in temperament_lower:
690
  temperament_adjustments += adjustment
691
+
692
+ # 特殊能力評估 - 對進階使用者加分
693
+ if user_experience == "advanced":
694
+ special_abilities = {
695
+ 'working': 0.04,
696
+ 'hunting': 0.04,
697
+ 'herding': 0.04,
698
+ 'guard': 0.03,
699
+ 'agility': 0.03
 
700
  }
701
 
702
+ for ability, bonus in special_abilities.items():
703
+ if ability in temperament_lower:
704
+ temperament_adjustments += bonus
705
+
706
+ # 確保最終分數在合理範圍內
707
+ final_score = max(0.3, min(0.98, score + temperament_adjustments))
708
+ return final_score
 
 
 
 
 
 
709
 
710
  def calculate_health_score(breed_name: str) -> float:
711
  """計算品種健康分數"""
 
883
  # 計算加權總分
884
  weighted_score = sum(score * weights[category] for category, score in scores.items())
885
 
886
+ # def amplify_score(score):
887
+ # """
888
+ # 優化分數放大函數,確保分數範圍合理且結果一致
889
+ # """
890
+ # # 基礎調整
891
+ # adjusted = (score - 0.35) * 1.8
892
 
893
+ # # 使用 3.2 次方使曲線更平滑
894
+ # amplified = pow(adjusted, 3.2) / 5.8 + score
895
 
896
+ # # 特別處理高分區間,確保不超過95%
897
+ # if amplified > 0.90:
898
+ # # 壓縮高分區間,確保最高到95%
899
+ # amplified = 0.90 + (amplified - 0.90) * 0.5
900
 
901
+ # # 確保最終分數在合理範圍內(0.55-0.95)
902
+ # final_score = max(0.55, min(0.95, amplified))
903
 
904
+ # # 四捨五入到小數點後第三位
905
+ # return round(final_score, 3)
906
 
907
+ # final_score = amplify_score(weighted_score)
908
+
909
+ # # 四捨五入所有分數
910
+ # scores = {k: round(v, 4) for k, v in scores.items()}
911
+ # scores['overall'] = round(final_score, 4)
912
 
913
+ # return scores
 
 
914
 
915
+ def amplify_score(score):
916
+ """
917
+ 優化分數放大函數,確保更合理的分數分布和品種間的差異
918
+
919
+ 1. 調整基礎計算係數,使分數差異更明顯
920
+ 2. 重新設計高分區間的處理
921
+ 3. 確保進階使用者能獲得更高分數
922
+ 4. 維持適當的分數下限
923
+ """
924
+ # 第一階段:基礎調整
925
+ # 降低基礎調整係數,使分數變化更平滑
926
+ adjusted = (score - 0.30) * 1.5
927
+
928
+ # 第二階段:非線性轉換
929
+ # 使用較小的指數,讓分數差異更明顯
930
+ amplified = pow(adjusted, 2.8) / 4.2 + score
931
+
932
+ # 第三階段:分數區間處理
933
+ if amplified > 0.85:
934
+ # 高分區間的處理更細緻
935
+ extra = (amplified - 0.85)
936
+ amplified = 0.85 + extra * 0.6
937
+ elif amplified < 0.65:
938
+ # 低分區間給予適當提升
939
+ boost = (0.65 - amplified) * 0.3
940
+ amplified += boost
941
+
942
+ # 第四階段:確保分數在合理範圍內
943
+ # 提高最低分數,降低最高分數
944
+ final_score = max(0.60, min(0.92, amplified))
945
+
946
+ # 第五階段:微調
947
+ # 讓分數更容易落在中間區間
948
+ if 0.75 <= final_score <= 0.85:
949
+ variance = (random.random() - 0.5) * 0.02
950
+ final_score += variance
951
+
952
+ # 確保最終分數在絕對範圍內
953
+ final_score = max(0.60, min(0.92, final_score))
954
+
955
+ return round(final_score, 3)
956
 
957
  except Exception as e:
958
  print(f"Error details: {str(e)}")