DawnC commited on
Commit
14daade
1 Parent(s): 8501045

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. scoring_calculation_system.py +132 -122
scoring_calculation_system.py CHANGED
@@ -1487,58 +1487,6 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
1487
  print(traceback.format_exc())
1488
  return {k: 0.6 for k in ['space', 'exercise', 'grooming', 'experience', 'health', 'noise', 'overall']}
1489
 
1490
- def check_critical_matches(scores: dict, user_prefs: UserPreferences) -> dict:
1491
- """評估是否存在極端不適配的情況"""
1492
- critical_issues = {
1493
- 'has_critical': False,
1494
- 'reasons': []
1495
- }
1496
-
1497
- # 檢查極端不適配情況
1498
- if scores['space'] < 0.3:
1499
- critical_issues['has_critical'] = True
1500
- critical_issues['reasons'].append('space_incompatible')
1501
-
1502
- if scores['noise'] < 0.3 and user_prefs.living_space == 'apartment':
1503
- critical_issues['has_critical'] = True
1504
- critical_issues['reasons'].append('noise_incompatible')
1505
-
1506
- if scores['experience'] < 0.3 and user_prefs.experience_level == 'beginner':
1507
- critical_issues['has_critical'] = True
1508
- critical_issues['reasons'].append('too_challenging')
1509
-
1510
- return critical_issues
1511
-
1512
- def apply_critical_penalty(scores: dict, critical_issues: dict) -> dict:
1513
- """
1514
- 當發現關鍵不適配時,調整分數
1515
-
1516
- 首先計算基礎整體分數,然後根據不同的關鍵問題應用懲罰係數
1517
- """
1518
- penalized_scores = scores.copy()
1519
- penalty_factor = 0.6 # 基礎懲罰因子
1520
-
1521
- # 先計算基礎整體分數(使用簡單平均)
1522
- base_overall = sum(scores.values()) / len(scores)
1523
- penalized_scores['overall'] = base_overall
1524
-
1525
- # 根據不同的關鍵問題應用懲罰
1526
- for reason in critical_issues['reasons']:
1527
- if reason == 'space_incompatible':
1528
- penalized_scores['overall'] *= penalty_factor
1529
- penalized_scores['space'] *= penalty_factor
1530
- elif reason == 'noise_incompatible':
1531
- penalized_scores['overall'] *= penalty_factor
1532
- penalized_scores['noise'] *= penalty_factor
1533
- elif reason == 'too_challenging':
1534
- penalized_scores['overall'] *= penalty_factor
1535
- penalized_scores['experience'] *= penalty_factor
1536
-
1537
- # 確保所有分數都在有效範圍內
1538
- for key in penalized_scores:
1539
- penalized_scores[key] = max(0.1, min(1.0, penalized_scores[key]))
1540
-
1541
- return penalized_scores
1542
 
1543
  def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -> float:
1544
  """計算品種與環境的適應性加成"""
@@ -1563,92 +1511,154 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1563
  return min(0.2, adaptability_score)
1564
 
1565
 
1566
- def calculate_dynamic_weights(user_prefs: UserPreferences, breed_info: dict) -> dict:
 
 
 
 
1567
  """
1568
- 根據使用者條件動態計算權重
1569
- 這個系統會根據具體情況調整各個評分項目的重要性
 
 
 
 
 
 
1570
  """
1571
- weights = {
1572
- 'space': 0.25, # 降低基礎空間權重
1573
- 'exercise': 0.20,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1574
  'grooming': 0.15,
1575
- 'experience': 0.15,
1576
- 'health': 0.15,
1577
  'noise': 0.10
1578
  }
1579
-
1580
- # 運動時間對權重的影響
1581
- if user_prefs.exercise_time > 150:
1582
- weights['exercise'] *= 1.4
1583
- weights['space'] *= 0.8
1584
- elif user_prefs.exercise_time < 30:
1585
- weights['exercise'] *= 0.8
1586
- weights['health'] *= 1.2
1587
 
1588
- # 居住環境對權重的影響
1589
- if user_prefs.living_space == 'apartment':
1590
- weights['noise'] *= 1.3
1591
- weights['space'] *= 1.2
1592
- elif user_prefs.living_space == 'house_large':
1593
- weights['exercise'] *= 1.2
1594
- weights['space'] *= 0.8
1595
 
1596
- # 經驗等級對權重的影響
1597
- if user_prefs.experience_level == 'beginner':
1598
- weights['experience'] *= 1.3
1599
- weights['health'] *= 1.2
1600
-
1601
- # 有孩童時的權重調整
1602
- if user_prefs.has_children:
1603
- if user_prefs.children_age == 'toddler':
1604
- weights['temperament'] = 0.20 # 新增性格權重
1605
- weights['space'] *= 0.8
1606
-
1607
  # 重新正規化權重
1608
- total = sum(weights.values())
1609
- return {k: v/total for k, v in weights.items()}
1610
 
 
 
 
 
 
 
 
 
 
 
 
 
1611
 
1612
- def calculate_final_weighted_score(
1613
- scores: dict,
1614
- user_prefs: UserPreferences,
1615
- breed_info: dict,
1616
- adaptability_bonus: float
1617
- ) -> float:
1618
- """
1619
- 整合動態權重的最終分數計算系統
1620
- """
1621
- # 第一步:計算動態權重
1622
- weights = calculate_dynamic_weights(user_prefs, breed_info) # 內部函數
1623
-
1624
- # 第二步:計算基礎加權分數
1625
- weighted_base = sum(score * weights[category] for category, score in scores.items())
1626
-
1627
- # 第三步:計算品種特性加成
1628
  breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1629
-
1630
- # 第四步:最終分數計算
1631
- final_score = (weighted_base * 0.70) + (breed_bonus * 0.20) + (adaptability_bonus * 0.10)
1632
-
1633
- # 第五步:分數轉換
 
 
1634
  return amplify_score_extreme(final_score)
1635
 
1636
 
1637
  def amplify_score_extreme(score: float) -> float:
1638
  """
1639
- 使用S型曲線進行分數轉換,加大差異
 
 
 
 
 
 
 
1640
  """
1641
- # 基礎範圍
1642
- base_min = 0.65
1643
- base_max = 0.95
1644
-
1645
- # 正規化
1646
- normalized = (score - 0.5) / 0.5
1647
-
1648
- # S型曲線轉換
1649
- sigmoid = 1 / (1 + math.exp(-normalized * 4))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1650
 
1651
- # 映射到目標範圍
1652
- final = base_min + (base_max - base_min) * sigmoid
 
 
 
 
 
 
 
 
 
 
 
 
1653
 
1654
- return round(min(base_max, max(base_min, final)), 4)
 
 
1487
  print(traceback.format_exc())
1488
  return {k: 0.6 for k in ['space', 'exercise', 'grooming', 'experience', 'health', 'noise', 'overall']}
1489
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1490
 
1491
  def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -> float:
1492
  """計算品種與環境的適應性加成"""
 
1511
  return min(0.2, adaptability_score)
1512
 
1513
 
1514
+ def calculate_breed_compatibility_score(
1515
+ scores: dict,
1516
+ user_prefs: UserPreferences,
1517
+ breed_info: dict
1518
+ ) -> float:
1519
  """
1520
+ 整合的品種相容性評分系統
1521
+
1522
+ 這個函數整合了:
1523
+ 1. 關鍵參數評估
1524
+ 2. 動態權重計算
1525
+ 3. 環境適應性評估
1526
+ 4. 品種特性加成
1527
+ 5. 最終分數計算和轉換
1528
  """
1529
+ # 1. 首先檢查關鍵不適配情況
1530
+ critical_params = {
1531
+ 'space': {
1532
+ 'threshold': 0.3,
1533
+ 'conditions': lambda: True, # 永遠檢查
1534
+ 'penalty': 0.3 # 極低分數
1535
+ },
1536
+ 'noise': {
1537
+ 'threshold': 0.3,
1538
+ 'conditions': lambda p: p.living_space == 'apartment',
1539
+ 'penalty': 0.4
1540
+ },
1541
+ 'experience': {
1542
+ 'threshold': 0.3,
1543
+ 'conditions': lambda p: p.experience_level == 'beginner',
1544
+ 'penalty': 0.4
1545
+ }
1546
+ }
1547
+
1548
+ # 檢查關鍵參數
1549
+ for param, config in critical_params.items():
1550
+ if scores[param] < config['threshold'] and config['conditions'](user_prefs):
1551
+ return config['penalty']
1552
+
1553
+ # 2. 計算基礎權重
1554
+ base_weights = {
1555
+ 'space': 0.35,
1556
+ 'exercise': 0.30,
1557
+ 'experience': 0.20,
1558
  'grooming': 0.15,
1559
+ 'health': 0.10,
 
1560
  'noise': 0.10
1561
  }
1562
+
1563
+ # 3. 根據具體情況調整權重
1564
+ adjusted_weights = {}
1565
+ for param, weight in base_weights.items():
1566
+ multiplier = 1.0
 
 
 
1567
 
1568
+ # 根據具體條件調整權重
1569
+ if param == 'space' and user_prefs.living_space == 'apartment':
1570
+ multiplier *= 1.2
1571
+ elif param == 'exercise' and user_prefs.exercise_time > 150:
1572
+ multiplier *= 1.4
1573
+ # ... 其他調整條件
 
1574
 
1575
+ adjusted_weights[param] = weight * multiplier
1576
+
 
 
 
 
 
 
 
 
 
1577
  # 重新正規化權重
1578
+ total_weight = sum(adjusted_weights.values())
1579
+ normalized_weights = {k: v/total_weight for k, v in adjusted_weights.items()}
1580
 
1581
+ # 4. 計算加權基礎分數
1582
+ base_score = 0
1583
+ for param, weight in normalized_weights.items():
1584
+ score = scores[param]
1585
+
1586
+ # 非線性調整
1587
+ if score > 0.8:
1588
+ score = min(1.0, score * 1.2)
1589
+ elif score < 0.6:
1590
+ score = score * 0.8
1591
+
1592
+ base_score += score * weight
1593
 
1594
+ # 5. 計算環境適應性加成
1595
+ adaptability_bonus = calculate_environmental_fit(breed_info, user_prefs)
1596
+
1597
+ # 6. 計算品種特性加成
 
 
 
 
 
 
 
 
 
 
 
 
1598
  breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1599
+
1600
+ # 7. 整合最終分數
1601
+ final_score = (base_score * 0.70) +
1602
+ (breed_bonus * 0.20) +
1603
+ (adaptability_bonus * 0.10)
1604
+
1605
+ # 8. 轉換和限制分數範圍
1606
  return amplify_score_extreme(final_score)
1607
 
1608
 
1609
  def amplify_score_extreme(score: float) -> float:
1610
  """
1611
+ 1. 擴大分數範圍至 0.3-0.95
1612
+ 2. 使用分段函數處理不同分數區間
1613
+ 3. 加強極端值的影響
1614
+
1615
+ Args:
1616
+ score: 原始分數 (0-1 範圍)
1617
+ Returns:
1618
+ 放大後的分數 (0.3-0.95 範圍)
1619
  """
1620
+ # 定義分數區間的轉換參數
1621
+ ranges = {
1622
+ 'poor': {
1623
+ 'range': (0, 0.4),
1624
+ 'out_min': 0.3,
1625
+ 'out_max': 0.5,
1626
+ 'amplification': 1.2 # 加強低分懲罰
1627
+ },
1628
+ 'mediocre': {
1629
+ 'range': (0.4, 0.6),
1630
+ 'out_min': 0.5,
1631
+ 'out_max': 0.7,
1632
+ 'amplification': 1.0 # 中等分數保持線性
1633
+ },
1634
+ 'good': {
1635
+ 'range': (0.6, 0.8),
1636
+ 'out_min': 0.7,
1637
+ 'out_max': 0.85,
1638
+ 'amplification': 1.1 # 稍微獎勵好分數
1639
+ },
1640
+ 'excellent': {
1641
+ 'range': (0.8, 1.0),
1642
+ 'out_min': 0.85,
1643
+ 'out_max': 0.95,
1644
+ 'amplification': 1.3 # 強力獎勵優秀分數
1645
+ }
1646
+ }
1647
 
1648
+ # 找出分數所屬區間
1649
+ for range_name, config in ranges.items():
1650
+ range_min, range_max = config['range']
1651
+ if range_min <= score <= range_max:
1652
+ # 計算在當前區間的相對位置
1653
+ range_position = (score - range_min) / (range_max - range_min)
1654
+
1655
+ # 應用放大係數
1656
+ range_position = min(1.0, range_position * config['amplification'])
1657
+
1658
+ # 轉換到輸出範圍
1659
+ amplified = config['out_min'] + (config['out_max'] - config['out_min']) * range_position
1660
+
1661
+ return round(max(0.3, min(0.95, amplified)), 4)
1662
 
1663
+ # 如果分數超出範圍,返回最近的有效值
1664
+ return 0.3 if score < 0 else 0.95