DawnC commited on
Commit
d6a4bd7
1 Parent(s): e1ccf49

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. scoring_calculation_system.py +270 -77
scoring_calculation_system.py CHANGED
@@ -222,17 +222,26 @@ def calculate_family_safety_score(breed_info: dict, children_age: str) -> float:
222
 
223
  # 基礎安全分數(根據體型)
224
  base_safety_scores = {
225
- "Small": 0.85,
226
- "Medium": 0.75,
227
- "Large": 0.65,
228
- "Giant": 0.55
229
  }
230
- safety_score = base_safety_scores.get(size, 0.70)
231
 
232
- # 年齡相關的調整
233
  age_factors = {
234
  'toddler': {
235
- 'base_modifier': -0.15,
 
 
 
 
 
 
 
 
 
236
  'size_penalty': {
237
  "Small": -0.05,
238
  "Medium": -0.10,
@@ -240,53 +249,34 @@ def calculate_family_safety_score(breed_info: dict, children_age: str) -> float:
240
  "Giant": -0.25
241
  }
242
  },
243
- 'school_age': {
244
- 'base_modifier': -0.08,
245
  'size_penalty': {
246
  "Small": -0.02,
247
  "Medium": -0.05,
248
  "Large": -0.10,
249
  "Giant": -0.15
250
  }
251
- },
252
- 'teenager': {
253
- 'base_modifier': -0.05,
254
- 'size_penalty': {
255
- "Small": 0,
256
- "Medium": -0.02,
257
- "Large": -0.05,
258
- "Giant": -0.08
259
- }
260
  }
261
  }
262
 
263
- # 應用年齡相關調整
264
- age_adjustment = age_factors.get(children_age, age_factors['school_age'])
265
- safety_score += age_adjustment['base_modifier']
266
- safety_score += age_adjustment['size_penalty'].get(size, -0.10)
267
-
268
- # 正面特徵評估
269
- positive_traits = {
270
- 'gentle': 0.10,
271
- 'patient': 0.10,
272
- 'good with children': 0.15,
273
- 'friendly': 0.08,
274
- 'calm': 0.08,
275
- 'tolerant': 0.08,
276
- 'playful': 0.05
277
- }
278
-
279
- # 危險特徵評估(更嚴格的懲罰)
280
  dangerous_traits = {
281
- 'aggressive': -0.25,
282
- 'territorial': -0.20,
283
- 'protective': -0.15,
284
- 'nervous': -0.15,
285
- 'dominant': -0.15,
286
- 'strong-willed': -0.12,
287
- 'independent': -0.10,
288
- 'energetic': -0.08
289
  }
 
 
 
 
 
 
290
 
291
  # 計算特徵分數
292
  for trait, bonus in positive_traits.items():
@@ -403,6 +393,113 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
403
  return base_score
404
 
405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  def calculate_experience_score(care_level: str, user_experience: str, temperament: str) -> float:
407
  """
408
  計算使用者經驗與品種需求的匹配分數
@@ -494,16 +591,26 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
494
  else: # advanced
495
  # 資深玩家能夠應對挑戰性特徵
496
  advanced_traits = {
497
- 'stubborn': 0.04, # 反轉為優勢
498
- 'independent': 0.04, # 反轉為優勢
499
- 'intelligent': 0.05, # 獎勵聰明
500
- 'protective': 0.04, # 獎勵保護性
501
- 'strong-willed': 0.03 # 獎勵強勢
 
 
 
502
  }
503
 
504
  for trait, bonus in advanced_traits.items():
505
  if trait in temperament_lower:
506
- temperament_adjustments += bonus
 
 
 
 
 
 
 
507
 
508
  # 確保最終分數在合理範圍內
509
  final_score = max(0.2, min(1.0, score + temperament_adjustments))
@@ -627,6 +734,75 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
627
 
628
  return max(0.2, min(1.0, final_score))
629
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
630
  # 計算所有基礎分數
631
  scores = {
632
  'space': calculate_space_score(
@@ -652,48 +828,65 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
652
  'health': calculate_health_score(breed_info.get('Breed', '')),
653
  'noise': calculate_noise_score(breed_info.get('Breed', ''), user_prefs.noise_tolerance)
654
  }
655
-
656
-
657
- # 優化權重配置
658
- weights = {
659
- 'space': 0.28,
660
- 'exercise': 0.18,
661
- 'grooming': 0.12,
662
- 'experience': 0.22,
663
- 'health': 0.12,
664
- 'noise': 0.08
 
 
 
 
 
 
665
  }
666
-
 
 
 
 
 
 
 
 
 
667
  # 計算加權總分
668
  weighted_score = sum(score * weights[category] for category, score in scores.items())
669
-
 
 
 
 
670
  def amplify_score(score):
671
  """
672
- 優化分數放大函數,確保分數範圍合理且結果一致
673
  """
674
- # 基礎調整
675
- adjusted = (score - 0.35) * 1.8
676
 
677
- # 使用 3.2 次方使曲線更平滑
678
- amplified = pow(adjusted, 3.2) / 5.8 + score
679
 
680
- # 特別處理高分區間,確保不超過95%
681
- if amplified > 0.90:
682
- # 壓縮高分區間,確保最高到95%
683
- amplified = 0.90 + (amplified - 0.90) * 0.5
684
 
685
- # 確保最終分數在合理範圍內(0.55-0.95)
686
- final_score = max(0.55, min(0.95, amplified))
687
 
688
- # 四捨五入到小數點後第三位
689
  return round(final_score, 3)
690
 
691
- final_score = amplify_score(weighted_score)
692
-
693
- # 四捨五入所有分數
 
694
  scores = {k: round(v, 4) for k, v in scores.items()}
695
  scores['overall'] = round(final_score, 4)
696
-
697
  return scores
698
 
699
  except Exception as e:
 
222
 
223
  # 基礎安全分數(根據體型)
224
  base_safety_scores = {
225
+ "Small": 0.80, # 從 0.85 降至 0.80
226
+ "Medium": 0.65, # 從 0.75 降至 0.65
227
+ "Large": 0.50, # 從 0.65 降至 0.50
228
+ "Giant": 0.40 # 從 0.55 降至 0.40
229
  }
230
+ safety_score = base_safety_scores.get(size, 0.60)
231
 
232
+ # 加強年齡相關的調整力度
233
  age_factors = {
234
  'toddler': {
235
+ 'base_modifier': -0.25, # 從 -0.15 降至 -0.25
236
+ 'size_penalty': {
237
+ "Small": -0.10, # 從 -0.05 降至 -0.10
238
+ "Medium": -0.20, # 從 -0.10 降至 -0.20
239
+ "Large": -0.30, # 從 -0.20 降至 -0.30
240
+ "Giant": -0.35 # 從 -0.25 降至 -0.35
241
+ }
242
+ },
243
+ 'school_age': {
244
+ 'base_modifier': -0.15, # 從 -0.08 降至 -0.15
245
  'size_penalty': {
246
  "Small": -0.05,
247
  "Medium": -0.10,
 
249
  "Giant": -0.25
250
  }
251
  },
252
+ 'teenager': {
253
+ 'base_modifier': -0.08, # 從 -0.05 降至 -0.08
254
  'size_penalty': {
255
  "Small": -0.02,
256
  "Medium": -0.05,
257
  "Large": -0.10,
258
  "Giant": -0.15
259
  }
 
 
 
 
 
 
 
 
 
260
  }
261
  }
262
 
263
+ # 加強對危險特徵的評估
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  dangerous_traits = {
265
+ 'aggressive': -0.35, # 從 -0.25 加重到 -0.35
266
+ 'territorial': -0.30, # 從 -0.20 加重到 -0.30
267
+ 'protective': -0.25, # 從 -0.15 加重到 -0.25
268
+ 'nervous': -0.25, # 從 -0.15 加重到 -0.25
269
+ 'dominant': -0.20, # 從 -0.15 加重到 -0.20
270
+ 'strong-willed': -0.18, # 從 -0.12 加重到 -0.18
271
+ 'independent': -0.15, # 從 -0.10 加重到 -0.15
272
+ 'energetic': -0.12 # 從 -0.08 加重到 -0.12
273
  }
274
+
275
+ # 特殊風險評估加重
276
+ if 'history of' in breed_info.get('Description', '').lower():
277
+ safety_score -= 0.25 # 從 -0.15 加重到 -0.25
278
+ if 'requires experienced' in breed_info.get('Description', '').lower():
279
+ safety_score -= 0.20 # 從 -0.10 加重到 -0.20
280
 
281
  # 計算特徵分數
282
  for trait, bonus in positive_traits.items():
 
393
  return base_score
394
 
395
 
396
+ # def calculate_experience_score(care_level: str, user_experience: str, temperament: str) -> float:
397
+ # """
398
+ # 計算使用者經驗與品種需求的匹配分數
399
+
400
+ # 參數說明:
401
+ # care_level: 品種的照顧難度 ("High", "Moderate", "Low")
402
+ # user_experience: 使用者經驗等級 ("beginner", "intermediate", "advanced")
403
+ # temperament: 品種的性格特徵描述
404
+
405
+ # 返回:
406
+ # float: 0.2-1.0 之間的匹配分數
407
+ # """
408
+ # # 基礎分數矩陣 - 更大的分數差異來反映經驗重要性
409
+ # base_scores = {
410
+ # "High": {
411
+ # "beginner": 0.12, # 降低起始分,反映高難度品種對新手的挑戰
412
+ # "intermediate": 0.65, # 中級玩家可以應付,但仍有改善空間
413
+ # "advanced": 1.0 # 資深者能完全勝任
414
+ # },
415
+ # "Moderate": {
416
+ # "beginner": 0.35, # 適中難度對新手來說仍具挑戰
417
+ # "intermediate": 0.82, # 中級玩家有很好的勝任能力
418
+ # "advanced": 1.0 # 資深者完全勝任
419
+ # },
420
+ # "Low": {
421
+ # "beginner": 0.72, # 低難度品種適合新手
422
+ # "intermediate": 0.92, # 中級玩家幾乎完全勝任
423
+ # "advanced": 1.0 # 資深者完全勝任
424
+ # }
425
+ # }
426
+
427
+ # # 取得基礎分數
428
+ # score = base_scores.get(care_level, base_scores["Moderate"])[user_experience]
429
+
430
+ # # 性格特徵評估 - 根據經驗等級調整權重
431
+ # temperament_lower = temperament.lower()
432
+ # temperament_adjustments = 0.0
433
+
434
+ # if user_experience == "beginner":
435
+ # # 新手不適合的特徵 - 更嚴格的懲罰
436
+ # difficult_traits = {
437
+ # 'stubborn': -0.15, # 加重固執的懲罰
438
+ # 'independent': -0.12, # 加重獨立性的懲罰
439
+ # 'dominant': -0.12, # 加重支配性的懲罰
440
+ # 'strong-willed': -0.10, # 加重強勢的懲罰
441
+ # 'protective': -0.08, # 加重保護性的懲罰
442
+ # 'aloof': -0.08, # 加重冷漠的懲罰
443
+ # 'energetic': -0.06 # 輕微懲罰高能量
444
+ # }
445
+
446
+ # # 新手友善的特徵 - 提供更多獎勵
447
+ # easy_traits = {
448
+ # 'gentle': 0.08, # 增加溫和的獎勵
449
+ # 'friendly': 0.08, # 增加友善的獎勵
450
+ # 'eager to please': 0.08, # 增加順從的獎勵
451
+ # 'patient': 0.06, # 獎勵耐心
452
+ # 'adaptable': 0.06, # 獎勵適應性
453
+ # 'calm': 0.05 # 獎勵冷靜
454
+ # }
455
+
456
+ # # 計算特徵調整
457
+ # for trait, penalty in difficult_traits.items():
458
+ # if trait in temperament_lower:
459
+ # temperament_adjustments += penalty * 1.2 # 加重新手的懲罰
460
+
461
+ # for trait, bonus in easy_traits.items():
462
+ # if trait in temperament_lower:
463
+ # temperament_adjustments += bonus
464
+
465
+ # # 品種特殊調整
466
+ # if any(term in temperament_lower for term in ['terrier', 'working', 'guard']):
467
+ # temperament_adjustments -= 0.12 # 加重對特定類型品種的懲罰
468
+
469
+ # elif user_experience == "intermediate":
470
+ # # 中級玩家的調整更加平衡
471
+ # moderate_traits = {
472
+ # 'intelligent': 0.05, # 獎勵聰明
473
+ # 'athletic': 0.04, # 獎勵運動能力
474
+ # 'versatile': 0.04, # 獎勵多功能性
475
+ # 'stubborn': -0.06, # 輕微懲罰固執
476
+ # 'independent': -0.05, # 輕微懲罰獨立性
477
+ # 'protective': -0.04 # 輕微懲罰保護性
478
+ # }
479
+
480
+ # for trait, adjustment in moderate_traits.items():
481
+ # if trait in temperament_lower:
482
+ # temperament_adjustments += adjustment
483
+
484
+ # else: # advanced
485
+ # # 資深玩家能夠應對挑戰性特徵
486
+ # advanced_traits = {
487
+ # 'stubborn': 0.04, # 反轉為優勢
488
+ # 'independent': 0.04, # 反轉為優勢
489
+ # 'intelligent': 0.05, # 獎勵聰明
490
+ # 'protective': 0.04, # 獎勵保護性
491
+ # 'strong-willed': 0.03 # 獎勵強勢
492
+ # }
493
+
494
+ # for trait, bonus in advanced_traits.items():
495
+ # if trait in temperament_lower:
496
+ # temperament_adjustments += bonus
497
+
498
+ # # 確保最終分數在合理範圍內
499
+ # final_score = max(0.2, min(1.0, score + temperament_adjustments))
500
+ # return final_score
501
+
502
+
503
  def calculate_experience_score(care_level: str, user_experience: str, temperament: str) -> float:
504
  """
505
  計算使用者經驗與品種需求的匹配分數
 
591
  else: # advanced
592
  # 資深玩家能夠應對挑戰性特徵
593
  advanced_traits = {
594
+ 'stubborn': 0.02, # 降低加分幅度
595
+ 'independent': 0.02,
596
+ 'intelligent': 0.05,
597
+ 'protective': 0.02,
598
+ 'strong-willed': 0.02,
599
+ 'aggressive': -0.04, # 新增負面特徵
600
+ 'nervous': -0.03,
601
+ 'dominant': -0.02
602
  }
603
 
604
  for trait, bonus in advanced_traits.items():
605
  if trait in temperament_lower:
606
+ # 加入條件評估
607
+ if bonus > 0: # 正面特徵
608
+ # 限制正面特徵的累積加分不超過0.15
609
+ if temperament_adjustments + bonus <= 0.15:
610
+ temperament_adjustments += bonus
611
+ else: # 負面特徵
612
+ # 負面特徵一定要計算
613
+ temperament_adjustments += bonus
614
 
615
  # 確保最終分數在合理範圍內
616
  final_score = max(0.2, min(1.0, score + temperament_adjustments))
 
734
 
735
  return max(0.2, min(1.0, final_score))
736
 
737
+ # # 計算所有基礎分數
738
+ # scores = {
739
+ # 'space': calculate_space_score(
740
+ # breed_info['Size'],
741
+ # user_prefs.living_space,
742
+ # user_prefs.space_for_play,
743
+ # breed_info.get('Exercise Needs', 'Moderate')
744
+ # ),
745
+ # 'exercise': calculate_exercise_score(
746
+ # breed_info.get('Exercise Needs', 'Moderate'),
747
+ # user_prefs.exercise_time
748
+ # ),
749
+ # 'grooming': calculate_grooming_score(
750
+ # breed_info.get('Grooming Needs', 'Moderate'),
751
+ # user_prefs.grooming_commitment.lower(),
752
+ # breed_info['Size']
753
+ # ),
754
+ # 'experience': calculate_experience_score(
755
+ # breed_info.get('Care Level', 'Moderate'),
756
+ # user_prefs.experience_level,
757
+ # breed_info.get('Temperament', '')
758
+ # ),
759
+ # 'health': calculate_health_score(breed_info.get('Breed', '')),
760
+ # 'noise': calculate_noise_score(breed_info.get('Breed', ''), user_prefs.noise_tolerance)
761
+ # }
762
+
763
+
764
+ # # 優化權重配置
765
+ # weights = {
766
+ # 'space': 0.28,
767
+ # 'exercise': 0.18,
768
+ # 'grooming': 0.12,
769
+ # 'experience': 0.22,
770
+ # 'health': 0.12,
771
+ # 'noise': 0.08
772
+ # }
773
+
774
+ # # 計算加權總分
775
+ # weighted_score = sum(score * weights[category] for category, score in scores.items())
776
+
777
+ # def amplify_score(score):
778
+ # """
779
+ # 優化分數放大函數,確保分數範圍合理且結果一致
780
+ # """
781
+ # # 基礎調整
782
+ # adjusted = (score - 0.35) * 1.8
783
+
784
+ # # 使用 3.2 次方使曲線更平滑
785
+ # amplified = pow(adjusted, 3.2) / 5.8 + score
786
+
787
+ # # 特別處理高分區間,確保不超過95%
788
+ # if amplified > 0.90:
789
+ # # 壓縮高分區間,確保最高到95%
790
+ # amplified = 0.90 + (amplified - 0.90) * 0.5
791
+
792
+ # # 確保最終分數在合理範圍內(0.55-0.95)
793
+ # final_score = max(0.55, min(0.95, amplified))
794
+
795
+ # # 四捨五入到小數點後第三位
796
+ # return round(final_score, 3)
797
+
798
+ # final_score = amplify_score(weighted_score)
799
+
800
+ # # 四捨五入所有分數
801
+ # scores = {k: round(v, 4) for k, v in scores.items()}
802
+ # scores['overall'] = round(final_score, 4)
803
+
804
+ # return scores
805
+
806
  # 計算所有基礎分數
807
  scores = {
808
  'space': calculate_space_score(
 
828
  'health': calculate_health_score(breed_info.get('Breed', '')),
829
  'noise': calculate_noise_score(breed_info.get('Breed', ''), user_prefs.noise_tolerance)
830
  }
831
+
832
+ # 如果有孩童,計算家庭安全分數
833
+ if user_prefs.has_children:
834
+ scores['family_safety'] = calculate_family_safety_score(breed_info, user_prefs.children_age)
835
+
836
+ # 計算品種額外加分
837
+ breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
838
+
839
+ # 調整權重配置
840
+ base_weights = {
841
+ 'space': 0.25, # 從 0.28 降低
842
+ 'exercise': 0.15, # 從 0.18 降低
843
+ 'grooming': 0.10, # 從 0.12 降低
844
+ 'experience': 0.20, # 從 0.22 降低
845
+ 'health': 0.10, # 從 0.12 降低
846
+ 'noise': 0.05 # 從 0.08 降低
847
  }
848
+
849
+ # 如果有孩童,加入家庭安全權重
850
+ if user_prefs.has_children:
851
+ base_weights['family_safety'] = 0.15 # 新增家庭安全權重
852
+ # 重新標準化其他權重
853
+ total = sum(base_weights.values())
854
+ weights = {k: v/total for k, v in base_weights.items()}
855
+ else:
856
+ weights = base_weights
857
+
858
  # 計算加權總分
859
  weighted_score = sum(score * weights[category] for category, score in scores.items())
860
+
861
+ # 加入品種加分的影響
862
+ # breed_bonus 的影響應該要在加權總分之後,但在最終放大之前
863
+ adjusted_score = weighted_score * (1 + breed_bonus) # breed_bonus 作為乘數效果
864
+
865
  def amplify_score(score):
866
  """
867
+ 優化分數放大函數,加入更強的差異化效果
868
  """
869
+ # 基礎調整 - 降低基準點使差異更明顯
870
+ adjusted = (score - 0.40) * 2.0 # 從 0.35 降至 0.40,乘數從 1.8 提高到 2.0
871
 
872
+ # 使用更高的指數使曲線更陡峭
873
+ amplified = pow(adjusted, 3.5) / 6.2 + score # 指數從 3.2 提高到 3.5
874
 
875
+ # 更嚴格的高分處理
876
+ if amplified > 0.85: # 從 0.90 降至 0.85
877
+ amplified = 0.85 + (amplified - 0.85) * 0.4 # 係數從 0.5 降至 0.4
 
878
 
879
+ # 調整分數範圍
880
+ final_score = max(0.60, min(0.95, amplified)) # 最低分從 0.55 提高到 0.60
881
 
 
882
  return round(final_score, 3)
883
 
884
+ # 計算最終分數
885
+ final_score = amplify_score(adjusted_score)
886
+
887
+ # 四捨五入所有分數並回傳
888
  scores = {k: round(v, 4) for k, v in scores.items()}
889
  scores['overall'] = round(final_score, 4)
 
890
  return scores
891
 
892
  except Exception as e: