DawnC commited on
Commit
bbd8dfa
1 Parent(s): 31c1299

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. scoring_calculation_system.py +593 -396
scoring_calculation_system.py CHANGED
@@ -1297,15 +1297,13 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1297
 
1298
  # def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1299
  # """
1300
- # 1. 條件間的相互影響
1301
- # 2. 動態權重調整
1302
- # 3. 更自然的評分機制
 
1303
  # """
1304
  # def evaluate_perfect_conditions():
1305
- # """
1306
- # 評估條件匹配度,考慮條件間的相互關係。
1307
- # 返回的不只是單純的匹配分數,而是綜合了各種條件互相影響後的結果。
1308
- # """
1309
  # perfect_matches = {
1310
  # 'size_match': 0,
1311
  # 'exercise_match': 0,
@@ -1313,8 +1311,81 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1313
  # 'living_condition_match': 0
1314
  # }
1315
 
1316
- # # 居住空間與體型匹配評估
1317
- # size_living_evaluation = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1318
  # 'apartment': {
1319
  # 'Small': 1.0,
1320
  # 'Medium': 0.4,
@@ -1324,118 +1395,91 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1324
  # 'house_small': {
1325
  # 'Small': 0.9,
1326
  # 'Medium': 1.0,
1327
- # 'Large': 0.6,
1328
- # 'Giant': 0.4
 
 
 
 
 
 
1329
  # }
1330
  # }
1331
 
1332
- # # 對於大房子,我們不使用固定的匹配矩陣,而是根據其他條件動態評估
1333
- # if user_prefs.living_space == 'house_large':
1334
- # # 大房子的評估更關注其他因素而不是體型限制
1335
- # perfect_matches['size_match'] = 0.8 # 基礎分數較高
1336
- # if breed_info['Size'] in ['Medium', 'Large']:
1337
- # perfect_matches['size_match'] = 0.9
1338
  # else:
1339
- # perfect_matches['size_match'] = size_living_evaluation.get(
1340
- # user_prefs.living_space, {}
1341
- # ).get(breed_info['Size'], 0.5)
1342
-
1343
- # # 運動需求匹配評估,考慮多個相關因素
1344
- # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1345
- # exercise_time = user_prefs.exercise_time
1346
-
1347
- # # 建立運動時間的基礎評估
1348
- # def evaluate_exercise_match():
1349
- # # 根據運動需求級別動態計算理想範圍
1350
- # exercise_ranges = {
1351
- # 'VERY HIGH': (120, 180),
1352
- # 'HIGH': (90, 150),
1353
- # 'MODERATE': (60, 120),
1354
- # 'LOW': (30, 90)
1355
- # }
1356
 
1357
- # # 獲取該品種的理想運動範圍
1358
- # ideal_range = exercise_ranges.get(exercise_needs, (60, 120))
1359
- # min_time, max_time = ideal_range
1360
-
1361
- # # 動態計算匹配度,避免硬性分界
1362
- # if min_time <= exercise_time <= max_time:
1363
- # base_score = 1.0
1364
- # else:
1365
- # # 計算與理想範圍的偏差程度
1366
- # if exercise_time < min_time:
1367
- # deviation = (min_time - exercise_time) / min_time
1368
- # else:
1369
- # deviation = (exercise_time - max_time) / max_time
1370
- # base_score = max(0.3, 1 - deviation)
1371
-
1372
- # return base_score
1373
-
1374
- # # 結合運動時間與其他條件
1375
- # exercise_base_score = evaluate_exercise_match()
1376
-
1377
- # # 考慮時間可用性的影響
1378
- # time_availability_impact = {
1379
- # 'limited': 0.7,
1380
- # 'moderate': 0.9,
1381
- # 'flexible': 1.0
1382
- # }
1383
-
1384
- # # 考慮使用者經驗對運動安排的影響
1385
- # experience_impact = {
1386
- # 'beginner': 0.8,
1387
- # 'intermediate': 0.9,
1388
- # 'advanced': 1.0
1389
- # }
1390
 
1391
- # # 計算最終運動匹配度
1392
- # exercise_modifiers = (
1393
- # time_availability_impact.get(user_prefs.time_availability, 0.9) *
1394
- # experience_impact.get(user_prefs.experience_level, 0.9)
1395
- # )
1396
-
1397
- # perfect_matches['exercise_match'] = exercise_base_score * exercise_modifiers
1398
-
1399
- # # 經驗匹配評估,考慮品種難度和其他因素
1400
  # care_level = breed_info.get('Care Level', 'MODERATE').upper()
1401
-
1402
- # # 基礎經驗匹配評估
1403
- # experience_base = {
1404
- # 'HIGH': {'beginner': 0.3, 'intermediate': 0.7, 'advanced': 1.0},
1405
- # 'MODERATE': {'beginner': 0.6, 'intermediate': 0.9, 'advanced': 1.0},
1406
- # 'LOW': {'beginner': 0.9, 'intermediate': 1.0, 'advanced': 0.9}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1407
  # }
1408
 
1409
- # experience_score = experience_base.get(care_level, experience_base['MODERATE']
1410
- # ).get(user_prefs.experience_level, 0.7)
1411
 
1412
- # # 調整經驗分數基於其他因素
1413
- # if user_prefs.has_children:
1414
- # experience_score *= 0.8 if user_prefs.experience_level == 'beginner' else 0.9
1415
-
 
 
 
1416
  # perfect_matches['experience_match'] = experience_score
1417
-
1418
  # # 生活條件整體評估
1419
  # living_score = 1.0
1420
 
1421
- # # 院子影響評估
1422
  # if breed_info.get('Exercise Needs', 'MODERATE').upper() in ['HIGH', 'VERY HIGH']:
1423
  # yard_impacts = {
1424
- # 'no_yard': 0.6,
1425
- # 'shared_yard': 0.8,
1426
  # 'private_yard': 1.0
1427
  # }
1428
- # living_score *= yard_impacts.get(user_prefs.yard_access, 0.8)
 
 
 
 
 
 
 
 
1429
 
1430
  # perfect_matches['living_condition_match'] = living_score
1431
 
1432
  # return perfect_matches
1433
 
1434
  # def calculate_weights():
1435
- # """
1436
- # 計算動態權重,根據條件的極端程度自動調整各項評分的重要性
1437
- # """
1438
- # # 基礎權重設定
1439
  # base_weights = {
1440
  # 'space': 0.20,
1441
  # 'exercise': 0.20,
@@ -1445,49 +1489,60 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1445
  # 'health': 0.10
1446
  # }
1447
 
1448
- # # 計算條件的極端程度
1449
- # def calculate_extremity():
1450
  # extremities = {}
1451
 
1452
- # # 運動時間極端度
1453
  # if user_prefs.exercise_time < 30:
1454
- # extremities['exercise'] = ('low', 0.8)
 
 
1455
  # elif user_prefs.exercise_time > 150:
1456
- # extremities['exercise'] = ('high', 0.8)
 
 
1457
  # else:
1458
- # extremities['exercise'] = ('normal', 0.3)
1459
 
1460
- # # 居住空間極端度
1461
  # if user_prefs.living_space == 'apartment':
1462
- # extremities['space'] = ('restrictive', 0.9)
1463
- # elif user_prefs.living_space == 'house_large':
1464
- # extremities['space'] = ('relaxed', 0.2)
1465
  # else:
1466
- # extremities['space'] = ('normal', 0.5)
1467
 
1468
  # return extremities
1469
 
1470
- # extremities = calculate_extremity()
1471
 
1472
- # # 根據極端程度調整權重
1473
  # weight_adjustments = {}
1474
 
1475
- # # 空間限制的權重調整
1476
- # if extremities['space'][0] == 'restrictive':
1477
  # weight_adjustments['space'] = 3.0
1478
- # weight_adjustments['noise'] = 2.0
1479
- # elif extremities['space'][0] == 'relaxed':
1480
- # weight_adjustments['space'] = 0.5
1481
- # weight_adjustments['exercise'] = 1.5
 
 
 
1482
 
1483
- # # 運動需求的權重調整
1484
- # if extremities['exercise'][0] in ['low', 'high']:
1485
- # weight_adjustments['exercise'] = 2.5
 
 
1486
 
1487
- # # 經驗需求的權重調整
1488
  # if user_prefs.experience_level == 'beginner':
 
 
1489
  # weight_adjustments['experience'] = 2.0
1490
-
1491
  # # 應用權重調整
1492
  # final_weights = base_weights.copy()
1493
  # for key, adjustment in weight_adjustments.items():
@@ -1496,31 +1551,38 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1496
  # return final_weights
1497
 
1498
  # def apply_special_case_adjustments(score):
1499
- # """
1500
- # 處理特殊情況,考慮條件組合產生的效果
1501
- # """
1502
- # # 評估條件組合的嚴重程度
1503
  # severity = 1.0
1504
 
1505
- # # 空間與運動組合評估
1506
  # if user_prefs.living_space == 'apartment':
1507
  # if breed_info.get('Exercise Needs', 'MODERATE').upper() == 'VERY HIGH':
 
 
1508
  # severity *= 0.6
1509
- # elif breed_info['Size'] in ['Large', 'Giant']:
1510
- # severity *= 0.7
1511
 
1512
- # # 經驗與品種難度組合評估
1513
  # if user_prefs.experience_level == 'beginner':
1514
  # if breed_info.get('Care Level') == 'HIGH':
1515
  # if user_prefs.has_children:
1516
- # severity *= 0.6
1517
  # else:
1518
- # severity *= 0.7
1519
 
1520
- # # 時間限制與需求組合評估
1521
  # if user_prefs.time_availability == 'limited':
1522
- # if breed_info.get('Exercise Needs').upper() in ['HIGH', 'VERY HIGH']:
1523
- # severity *= 0.8
 
 
 
 
 
 
 
 
1524
 
1525
  # return score * severity
1526
 
@@ -1537,18 +1599,20 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1537
  # # 計算基礎分數
1538
  # base_score = sum(scores[k] * normalized_weights[k] for k in scores.keys())
1539
 
1540
- # # 完美匹配獎勵
1541
  # perfect_bonus = 1.0
1542
- # perfect_bonus += 0.15 * perfect_conditions['size_match']
1543
- # perfect_bonus += 0.15 * perfect_conditions['exercise_match']
1544
- # perfect_bonus += 0.15 * perfect_conditions['experience_match']
1545
- # perfect_bonus += 0.05 * perfect_conditions['living_condition_match']
1546
 
1547
- # # 品種特性加成(使用原有的 calculate_breed_bonus 函數)
1548
  # breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1549
 
1550
- # # 計算最終分數並應用特殊情況調整
1551
- # final_score = (base_score * 0.8 + breed_bonus * 0.2) * perfect_bonus
 
 
1552
  # final_score = apply_special_case_adjustments(final_score)
1553
 
1554
  # return min(1.0, final_score)
@@ -1562,183 +1626,205 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1562
  4. 條件組合的嚴格評估
1563
  """
1564
  def evaluate_perfect_conditions():
1565
- """評估條件匹配度,特別強化運動類型與專業程度的評估"""
 
 
 
 
 
1566
  perfect_matches = {
1567
  'size_match': 0,
1568
  'exercise_match': 0,
1569
  'experience_match': 0,
1570
- 'living_condition_match': 0
 
1571
  }
1572
 
1573
- # 運動類型與需求的精確匹配
1574
- exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1575
- exercise_time = user_prefs.exercise_time
1576
- exercise_type = user_prefs.exercise_type
1577
-
1578
- # 定義品種的理想運動模式
1579
- breed_exercise_preferences = {
1580
- 'VERY HIGH': {
1581
- 'ideal_type': 'active_training',
1582
- 'acceptable_types': ['moderate_activity'],
1583
- 'time_ranges': {
1584
- 'ideal': (120, 180),
1585
- 'acceptable': (90, 200)
1586
- }
1587
- },
1588
- 'HIGH': {
1589
- 'ideal_type': 'moderate_activity',
1590
- 'acceptable_types': ['active_training', 'light_walks'],
1591
- 'time_ranges': {
1592
- 'ideal': (90, 150),
1593
- 'acceptable': (60, 180)
1594
- }
1595
- },
1596
- 'MODERATE': {
1597
- 'ideal_type': 'moderate_activity',
1598
- 'acceptable_types': ['light_walks', 'active_training'],
1599
- 'time_ranges': {
1600
- 'ideal': (45, 90),
1601
- 'acceptable': (30, 120)
1602
- }
1603
- },
1604
- 'LOW': {
1605
- 'ideal_type': 'light_walks',
1606
- 'acceptable_types': ['moderate_activity'],
1607
- 'time_ranges': {
1608
- 'ideal': (30, 60),
1609
- 'acceptable': (15, 90)
1610
  }
1611
  }
1612
- }
1613
-
1614
- # 計算運動匹配度
1615
- exercise_profile = breed_exercise_preferences.get(exercise_needs,
1616
- breed_exercise_preferences['MODERATE'])
1617
-
1618
- # 時間匹配度計算
1619
- time_ranges = exercise_profile['time_ranges']
1620
- if time_ranges['ideal'][0] <= exercise_time <= time_ranges['ideal'][1]:
1621
- time_score = 1.0
1622
- elif time_ranges['acceptable'][0] <= exercise_time <= time_ranges['acceptable'][1]:
1623
- # 計算與理想範圍的距離
1624
- if exercise_time < time_ranges['ideal'][0]:
1625
- deviation = (time_ranges['ideal'][0] - exercise_time) / time_ranges['ideal'][0]
 
 
1626
  else:
1627
- deviation = (exercise_time - time_ranges['ideal'][1]) / time_ranges['ideal'][1]
1628
- time_score = max(0.4, 1 - (deviation * 0.6))
1629
- else:
1630
- time_score = 0.3
1631
-
1632
- # 運動類型匹配度計算
1633
- if exercise_type == exercise_profile['ideal_type']:
1634
- type_score = 1.0
1635
- elif exercise_type in exercise_profile['acceptable_types']:
1636
- type_score = 0.7
1637
- else:
1638
- type_score = 0.4
1639
-
1640
- # 若運動時間過長但強度不足,額外降低分數
1641
- if exercise_time > time_ranges['acceptable'][1] and exercise_type != exercise_profile['ideal_type']:
1642
- type_score *= 0.7
 
 
 
 
 
1643
 
1644
- perfect_matches['exercise_match'] = (time_score * 0.6) + (type_score * 0.4)
1645
-
1646
- # 體型與空間的實際利用評估
1647
- space_utilization = {
1648
- 'apartment': {
1649
- 'Small': 1.0,
1650
- 'Medium': 0.4,
1651
- 'Large': 0.2,
1652
- 'Giant': 0.1
1653
- },
1654
- 'house_small': {
1655
- 'Small': 0.9,
1656
- 'Medium': 1.0,
1657
- 'Large': 0.5,
1658
- 'Giant': 0.3
1659
- },
1660
- 'house_large': {
1661
- 'Small': 0.7,
1662
- 'Medium': 0.9,
1663
- 'Large': 1.0,
1664
- 'Giant': 0.95
1665
  }
1666
- }
1667
-
1668
- # 增加活動空間需求評估
1669
- space_needs = 'high' if exercise_needs in ['VERY HIGH', 'HIGH'] else 'moderate'
1670
- if space_needs == 'high' and user_prefs.living_space != 'house_large':
1671
- space_score = space_utilization[user_prefs.living_space][breed_info['Size']] * 0.8
1672
- else:
1673
- space_score = space_utilization.get(user_prefs.living_space,
1674
- space_utilization['house_small'])[breed_info['Size']]
 
 
 
 
 
 
 
 
 
 
1675
 
1676
- perfect_matches['size_match'] = space_score
1677
-
1678
- # 經驗需求的專業評估
1679
- care_level = breed_info.get('Care Level', 'MODERATE').upper()
1680
- temperament = breed_info.get('Temperament', '').lower()
1681
-
1682
- # 定義進階特徵
1683
- advanced_traits = ['working', 'independent', 'dominant', 'protective']
1684
- advanced_trait_count = sum(1 for trait in advanced_traits if trait in temperament)
1685
-
1686
- # 經驗匹配度計算
1687
- experience_matrix = {
1688
- 'HIGH': {
1689
- 'beginner': 0.2, # 更嚴格的新手限制
1690
- 'intermediate': 0.6,
1691
- 'advanced': 1.0
1692
- },
1693
- 'MODERATE': {
1694
- 'beginner': 0.5,
1695
- 'intermediate': 0.9,
1696
- 'advanced': 0.95
1697
- },
1698
- 'LOW': {
1699
- 'beginner': 0.9,
1700
- 'intermediate': 0.85,
1701
- 'advanced': 0.8 # 對專家稍微降低簡單品種的分數
1702
  }
1703
- }
1704
-
1705
- experience_score = experience_matrix[care_level][user_prefs.experience_level]
1706
-
1707
- # 根據進階特徵調整分數
1708
- if advanced_trait_count > 0:
1709
- if user_prefs.experience_level == 'beginner':
1710
- experience_score *= (0.8 ** advanced_trait_count)
1711
- elif user_prefs.experience_level == 'advanced':
1712
- experience_score *= (1.1 ** min(advanced_trait_count, 2))
1713
-
1714
- perfect_matches['experience_match'] = experience_score
1715
-
1716
- # 生活條件整體評估
1717
- living_score = 1.0
1718
-
1719
- # 院子影響的嚴格評估
1720
- if breed_info.get('Exercise Needs', 'MODERATE').upper() in ['HIGH', 'VERY HIGH']:
1721
- yard_impacts = {
1722
- 'no_yard': 0.5, # 更嚴格的懲罰
1723
- 'shared_yard': 0.7,
1724
  'private_yard': 1.0
1725
  }
1726
- living_score *= yard_impacts.get(user_prefs.yard_access, 0.7)
 
 
 
 
 
 
 
1727
 
1728
- # 時間可用性評估
1729
- time_impacts = {
1730
- 'limited': 0.6, # 更嚴格的時間限制影響
1731
- 'moderate': 0.8,
1732
- 'flexible': 1.0
1733
- }
1734
- living_score *= time_impacts.get(user_prefs.time_availability, 0.8)
1735
-
1736
- perfect_matches['living_condition_match'] = living_score
1737
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1738
  return perfect_matches
1739
 
1740
  def calculate_weights():
1741
- """計算動態權重,強化條件極端情況的影響"""
 
 
 
 
 
 
1742
  base_weights = {
1743
  'space': 0.20,
1744
  'exercise': 0.20,
@@ -1748,102 +1834,211 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1748
  'health': 0.10
1749
  }
1750
 
1751
- # 計算條件極端度
1752
- def calculate_condition_extremity():
1753
  extremities = {}
1754
 
1755
- # 運動時間極端度評估
1756
- if user_prefs.exercise_time < 30:
1757
- extremities['exercise'] = ('very_low', 0.9)
1758
- elif user_prefs.exercise_time < 60:
1759
- extremities['exercise'] = ('low', 0.7)
1760
- elif user_prefs.exercise_time > 150:
1761
- extremities['exercise'] = ('very_high', 0.9)
1762
- elif user_prefs.exercise_time > 120:
1763
- extremities['exercise'] = ('high', 0.7)
1764
- else:
1765
- extremities['exercise'] = ('moderate', 0.3)
1766
-
1767
- # 空間限制極端度評估
1768
- if user_prefs.living_space == 'apartment':
1769
- extremities['space'] = ('very_restricted', 0.9)
1770
- elif user_prefs.living_space == 'house_small':
1771
- extremities['space'] = ('restricted', 0.6)
1772
- else:
1773
- extremities['space'] = ('spacious', 0.3)
1774
-
1775
- return extremities
1776
-
1777
- extremities = calculate_condition_extremity()
1778
-
1779
- # 權重調整
1780
- weight_adjustments = {}
1781
-
1782
- # 空間權重調整
1783
- if extremities['space'][0] == 'very_restricted':
1784
- weight_adjustments['space'] = 3.0
1785
- weight_adjustments['noise'] = 2.5
1786
- elif extremities['space'][0] == 'restricted':
1787
- weight_adjustments['space'] = 2.0
1788
- weight_adjustments['noise'] = 1.8
1789
- elif extremities['space'][0] == 'spacious':
1790
- weight_adjustments['space'] = 0.7 # 大空間時降低空間權重
1791
- weight_adjustments['exercise'] = 1.5 # 提升運動重要性
1792
-
1793
- # 運動需求權重調整
1794
- if extremities['exercise'][0] in ['very_low', 'very_high']:
1795
- weight_adjustments['exercise'] = 3.0
1796
- elif extremities['exercise'][0] in ['low', 'high']:
1797
- weight_adjustments['exercise'] = 2.0
1798
 
1799
- # 經驗需求權重調整
1800
- if user_prefs.experience_level == 'beginner':
1801
- weight_adjustments['experience'] = 2.5
1802
- elif user_prefs.experience_level == 'advanced':
1803
- weight_adjustments['experience'] = 2.0
1804
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1805
  # 應用權重調整
1806
  final_weights = base_weights.copy()
1807
  for key, adjustment in weight_adjustments.items():
1808
- final_weights[key] *= adjustment
1809
-
 
1810
  return final_weights
1811
 
1812
  def apply_special_case_adjustments(score):
1813
- """處理特殊情況,更嚴格的條件組合評估"""
1814
- severity = 1.0
1815
-
1816
- # 空間與運動組合的嚴格評估
1817
- if user_prefs.living_space == 'apartment':
1818
- if breed_info.get('Exercise Needs', 'MODERATE').upper() == 'VERY HIGH':
1819
- severity *= 0.5 # 更嚴重的懲罰
1820
- elif breed_info.get('Exercise Needs') == 'HIGH':
1821
- severity *= 0.6
1822
- if breed_info['Size'] in ['Large', 'Giant']:
1823
- severity *= 0.5
 
 
 
 
 
 
1824
 
1825
- # 經驗與品種難度組合的嚴格評估
1826
- if user_prefs.experience_level == 'beginner':
1827
- if breed_info.get('Care Level') == 'HIGH':
1828
- if user_prefs.has_children:
1829
- severity *= 0.5
1830
- else:
1831
- severity *= 0.6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1832
 
1833
- # 時間限制與需求組合的嚴格評估
1834
- if user_prefs.time_availability == 'limited':
1835
- if breed_info.get('Exercise Needs').upper() in ['VERY HIGH', 'HIGH']:
1836
- severity *= 0.6
1837
-
1838
- # 運動類型不匹配的懲罰
1839
- if user_prefs.exercise_time > 120:
1840
- exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1841
- if exercise_needs == 'LOW':
1842
- severity *= 0.7
1843
- elif exercise_needs == 'VERY HIGH' and user_prefs.exercise_type == 'light_walks':
1844
- severity *= 0.6
1845
-
1846
- return score * severity
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1847
 
1848
  # 評估完美匹配條件
1849
  perfect_conditions = evaluate_perfect_conditions()
@@ -1851,30 +2046,32 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1851
  # 計算動態權重
1852
  weights = calculate_weights()
1853
 
1854
- # 正規化權重
1855
  total_weight = sum(weights.values())
1856
  normalized_weights = {k: v/total_weight for k, v in weights.items()}
1857
 
1858
  # 計算基礎分數
1859
  base_score = sum(scores[k] * normalized_weights[k] for k in scores.keys())
1860
 
1861
- # 完美匹配獎勵計算(降低獎勵影響)
1862
  perfect_bonus = 1.0
1863
- perfect_bonus += 0.12 * perfect_conditions['size_match']
1864
- perfect_bonus += 0.12 * perfect_conditions['exercise_match']
1865
- perfect_bonus += 0.12 * perfect_conditions['experience_match']
1866
- perfect_bonus += 0.04 * perfect_conditions['living_condition_match']
 
1867
 
1868
- # 品種特性加成
1869
- breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1870
 
1871
- # 計算最終分數
1872
- final_score = (base_score * 0.85 + breed_bonus * 0.15) * perfect_bonus
1873
 
1874
  # 應用特殊情況調整
1875
- final_score = apply_special_case_adjustments(final_score)
1876
 
1877
- return min(1.0, final_score)
 
1878
 
1879
 
1880
  def amplify_score_extreme(score: float) -> float:
 
1297
 
1298
  # def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1299
  # """
1300
+ # 1. 運動類型與時間的精確匹配
1301
+ # 2. 進階使用者的專業需求
1302
+ # 3. 空間利用的實際效果
1303
+ # 4. 條件組合的嚴格評估
1304
  # """
1305
  # def evaluate_perfect_conditions():
1306
+ # """評估條件匹配度,特別強化運動類型與專業程度的評估"""
 
 
 
1307
  # perfect_matches = {
1308
  # 'size_match': 0,
1309
  # 'exercise_match': 0,
 
1311
  # 'living_condition_match': 0
1312
  # }
1313
 
1314
+ # # 運動類型與需求的精確匹配
1315
+ # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1316
+ # exercise_time = user_prefs.exercise_time
1317
+ # exercise_type = user_prefs.exercise_type
1318
+
1319
+ # # 定義品種的理想運動模式
1320
+ # breed_exercise_preferences = {
1321
+ # 'VERY HIGH': {
1322
+ # 'ideal_type': 'active_training',
1323
+ # 'acceptable_types': ['moderate_activity'],
1324
+ # 'time_ranges': {
1325
+ # 'ideal': (120, 180),
1326
+ # 'acceptable': (90, 200)
1327
+ # }
1328
+ # },
1329
+ # 'HIGH': {
1330
+ # 'ideal_type': 'moderate_activity',
1331
+ # 'acceptable_types': ['active_training', 'light_walks'],
1332
+ # 'time_ranges': {
1333
+ # 'ideal': (90, 150),
1334
+ # 'acceptable': (60, 180)
1335
+ # }
1336
+ # },
1337
+ # 'MODERATE': {
1338
+ # 'ideal_type': 'moderate_activity',
1339
+ # 'acceptable_types': ['light_walks', 'active_training'],
1340
+ # 'time_ranges': {
1341
+ # 'ideal': (45, 90),
1342
+ # 'acceptable': (30, 120)
1343
+ # }
1344
+ # },
1345
+ # 'LOW': {
1346
+ # 'ideal_type': 'light_walks',
1347
+ # 'acceptable_types': ['moderate_activity'],
1348
+ # 'time_ranges': {
1349
+ # 'ideal': (30, 60),
1350
+ # 'acceptable': (15, 90)
1351
+ # }
1352
+ # }
1353
+ # }
1354
+
1355
+ # # 計算運動匹配度
1356
+ # exercise_profile = breed_exercise_preferences.get(exercise_needs,
1357
+ # breed_exercise_preferences['MODERATE'])
1358
+
1359
+ # # 時間匹配度計算
1360
+ # time_ranges = exercise_profile['time_ranges']
1361
+ # if time_ranges['ideal'][0] <= exercise_time <= time_ranges['ideal'][1]:
1362
+ # time_score = 1.0
1363
+ # elif time_ranges['acceptable'][0] <= exercise_time <= time_ranges['acceptable'][1]:
1364
+ # # 計算與理想範圍的距離
1365
+ # if exercise_time < time_ranges['ideal'][0]:
1366
+ # deviation = (time_ranges['ideal'][0] - exercise_time) / time_ranges['ideal'][0]
1367
+ # else:
1368
+ # deviation = (exercise_time - time_ranges['ideal'][1]) / time_ranges['ideal'][1]
1369
+ # time_score = max(0.4, 1 - (deviation * 0.6))
1370
+ # else:
1371
+ # time_score = 0.3
1372
+
1373
+ # # 運動類型匹配度計算
1374
+ # if exercise_type == exercise_profile['ideal_type']:
1375
+ # type_score = 1.0
1376
+ # elif exercise_type in exercise_profile['acceptable_types']:
1377
+ # type_score = 0.7
1378
+ # else:
1379
+ # type_score = 0.4
1380
+
1381
+ # # 若運動時間過長但強度不足,額外降低分數
1382
+ # if exercise_time > time_ranges['acceptable'][1] and exercise_type != exercise_profile['ideal_type']:
1383
+ # type_score *= 0.7
1384
+
1385
+ # perfect_matches['exercise_match'] = (time_score * 0.6) + (type_score * 0.4)
1386
+
1387
+ # # 體型與空間的實際利用評估
1388
+ # space_utilization = {
1389
  # 'apartment': {
1390
  # 'Small': 1.0,
1391
  # 'Medium': 0.4,
 
1395
  # 'house_small': {
1396
  # 'Small': 0.9,
1397
  # 'Medium': 1.0,
1398
+ # 'Large': 0.5,
1399
+ # 'Giant': 0.3
1400
+ # },
1401
+ # 'house_large': {
1402
+ # 'Small': 0.7,
1403
+ # 'Medium': 0.9,
1404
+ # 'Large': 1.0,
1405
+ # 'Giant': 0.95
1406
  # }
1407
  # }
1408
 
1409
+ # # 增加活動空間需求評估
1410
+ # space_needs = 'high' if exercise_needs in ['VERY HIGH', 'HIGH'] else 'moderate'
1411
+ # if space_needs == 'high' and user_prefs.living_space != 'house_large':
1412
+ # space_score = space_utilization[user_prefs.living_space][breed_info['Size']] * 0.8
 
 
1413
  # else:
1414
+ # space_score = space_utilization.get(user_prefs.living_space,
1415
+ # space_utilization['house_small'])[breed_info['Size']]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1416
 
1417
+ # perfect_matches['size_match'] = space_score
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1418
 
1419
+ # # 經驗需求的專業評估
 
 
 
 
 
 
 
 
1420
  # care_level = breed_info.get('Care Level', 'MODERATE').upper()
1421
+ # temperament = breed_info.get('Temperament', '').lower()
1422
+
1423
+ # # 定義進階特徵
1424
+ # advanced_traits = ['working', 'independent', 'dominant', 'protective']
1425
+ # advanced_trait_count = sum(1 for trait in advanced_traits if trait in temperament)
1426
+
1427
+ # # 經驗匹配度計算
1428
+ # experience_matrix = {
1429
+ # 'HIGH': {
1430
+ # 'beginner': 0.2, # 更嚴格的新手限制
1431
+ # 'intermediate': 0.6,
1432
+ # 'advanced': 1.0
1433
+ # },
1434
+ # 'MODERATE': {
1435
+ # 'beginner': 0.5,
1436
+ # 'intermediate': 0.9,
1437
+ # 'advanced': 0.95
1438
+ # },
1439
+ # 'LOW': {
1440
+ # 'beginner': 0.9,
1441
+ # 'intermediate': 0.85,
1442
+ # 'advanced': 0.8 # 對專家稍微降低簡單品種的分數
1443
+ # }
1444
  # }
1445
 
1446
+ # experience_score = experience_matrix[care_level][user_prefs.experience_level]
 
1447
 
1448
+ # # 根據進階特徵調整分數
1449
+ # if advanced_trait_count > 0:
1450
+ # if user_prefs.experience_level == 'beginner':
1451
+ # experience_score *= (0.8 ** advanced_trait_count)
1452
+ # elif user_prefs.experience_level == 'advanced':
1453
+ # experience_score *= (1.1 ** min(advanced_trait_count, 2))
1454
+
1455
  # perfect_matches['experience_match'] = experience_score
1456
+
1457
  # # 生活條件整體評估
1458
  # living_score = 1.0
1459
 
1460
+ # # 院子影響的嚴格評估
1461
  # if breed_info.get('Exercise Needs', 'MODERATE').upper() in ['HIGH', 'VERY HIGH']:
1462
  # yard_impacts = {
1463
+ # 'no_yard': 0.5, # 更嚴格的懲罰
1464
+ # 'shared_yard': 0.7,
1465
  # 'private_yard': 1.0
1466
  # }
1467
+ # living_score *= yard_impacts.get(user_prefs.yard_access, 0.7)
1468
+
1469
+ # # 時間可用性評估
1470
+ # time_impacts = {
1471
+ # 'limited': 0.6, # 更嚴格的時間限制影響
1472
+ # 'moderate': 0.8,
1473
+ # 'flexible': 1.0
1474
+ # }
1475
+ # living_score *= time_impacts.get(user_prefs.time_availability, 0.8)
1476
 
1477
  # perfect_matches['living_condition_match'] = living_score
1478
 
1479
  # return perfect_matches
1480
 
1481
  # def calculate_weights():
1482
+ # """計算動態權重,強化條件極端情況的影響"""
 
 
 
1483
  # base_weights = {
1484
  # 'space': 0.20,
1485
  # 'exercise': 0.20,
 
1489
  # 'health': 0.10
1490
  # }
1491
 
1492
+ # # 計算條件極端度
1493
+ # def calculate_condition_extremity():
1494
  # extremities = {}
1495
 
1496
+ # # 運動時間極端度評估
1497
  # if user_prefs.exercise_time < 30:
1498
+ # extremities['exercise'] = ('very_low', 0.9)
1499
+ # elif user_prefs.exercise_time < 60:
1500
+ # extremities['exercise'] = ('low', 0.7)
1501
  # elif user_prefs.exercise_time > 150:
1502
+ # extremities['exercise'] = ('very_high', 0.9)
1503
+ # elif user_prefs.exercise_time > 120:
1504
+ # extremities['exercise'] = ('high', 0.7)
1505
  # else:
1506
+ # extremities['exercise'] = ('moderate', 0.3)
1507
 
1508
+ # # 空間限制極端度評估
1509
  # if user_prefs.living_space == 'apartment':
1510
+ # extremities['space'] = ('very_restricted', 0.9)
1511
+ # elif user_prefs.living_space == 'house_small':
1512
+ # extremities['space'] = ('restricted', 0.6)
1513
  # else:
1514
+ # extremities['space'] = ('spacious', 0.3)
1515
 
1516
  # return extremities
1517
 
1518
+ # extremities = calculate_condition_extremity()
1519
 
1520
+ # # 權重調整
1521
  # weight_adjustments = {}
1522
 
1523
+ # # 空間權重調整
1524
+ # if extremities['space'][0] == 'very_restricted':
1525
  # weight_adjustments['space'] = 3.0
1526
+ # weight_adjustments['noise'] = 2.5
1527
+ # elif extremities['space'][0] == 'restricted':
1528
+ # weight_adjustments['space'] = 2.0
1529
+ # weight_adjustments['noise'] = 1.8
1530
+ # elif extremities['space'][0] == 'spacious':
1531
+ # weight_adjustments['space'] = 0.7 # 大空間時降低空間權重
1532
+ # weight_adjustments['exercise'] = 1.5 # 提升運動重要性
1533
 
1534
+ # # 運動需求權重調整
1535
+ # if extremities['exercise'][0] in ['very_low', 'very_high']:
1536
+ # weight_adjustments['exercise'] = 3.0
1537
+ # elif extremities['exercise'][0] in ['low', 'high']:
1538
+ # weight_adjustments['exercise'] = 2.0
1539
 
1540
+ # # 經驗需求權重調整
1541
  # if user_prefs.experience_level == 'beginner':
1542
+ # weight_adjustments['experience'] = 2.5
1543
+ # elif user_prefs.experience_level == 'advanced':
1544
  # weight_adjustments['experience'] = 2.0
1545
+
1546
  # # 應用權重調整
1547
  # final_weights = base_weights.copy()
1548
  # for key, adjustment in weight_adjustments.items():
 
1551
  # return final_weights
1552
 
1553
  # def apply_special_case_adjustments(score):
1554
+ # """處理特殊情況,更嚴格的條件組合評估"""
 
 
 
1555
  # severity = 1.0
1556
 
1557
+ # # 空間與運動組合的嚴格評估
1558
  # if user_prefs.living_space == 'apartment':
1559
  # if breed_info.get('Exercise Needs', 'MODERATE').upper() == 'VERY HIGH':
1560
+ # severity *= 0.5 # 更嚴重的懲罰
1561
+ # elif breed_info.get('Exercise Needs') == 'HIGH':
1562
  # severity *= 0.6
1563
+ # if breed_info['Size'] in ['Large', 'Giant']:
1564
+ # severity *= 0.5
1565
 
1566
+ # # 經驗與品種難度組合的嚴格評估
1567
  # if user_prefs.experience_level == 'beginner':
1568
  # if breed_info.get('Care Level') == 'HIGH':
1569
  # if user_prefs.has_children:
1570
+ # severity *= 0.5
1571
  # else:
1572
+ # severity *= 0.6
1573
 
1574
+ # # 時間限制與需求組合的嚴格評估
1575
  # if user_prefs.time_availability == 'limited':
1576
+ # if breed_info.get('Exercise Needs').upper() in ['VERY HIGH', 'HIGH']:
1577
+ # severity *= 0.6
1578
+
1579
+ # # 運動類型不匹配的懲罰
1580
+ # if user_prefs.exercise_time > 120:
1581
+ # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1582
+ # if exercise_needs == 'LOW':
1583
+ # severity *= 0.7
1584
+ # elif exercise_needs == 'VERY HIGH' and user_prefs.exercise_type == 'light_walks':
1585
+ # severity *= 0.6
1586
 
1587
  # return score * severity
1588
 
 
1599
  # # 計算基礎分數
1600
  # base_score = sum(scores[k] * normalized_weights[k] for k in scores.keys())
1601
 
1602
+ # # 完美匹配獎勵計算(降低獎勵影響)
1603
  # perfect_bonus = 1.0
1604
+ # perfect_bonus += 0.12 * perfect_conditions['size_match']
1605
+ # perfect_bonus += 0.12 * perfect_conditions['exercise_match']
1606
+ # perfect_bonus += 0.12 * perfect_conditions['experience_match']
1607
+ # perfect_bonus += 0.04 * perfect_conditions['living_condition_match']
1608
 
1609
+ # # 品種特性加成
1610
  # breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1611
 
1612
+ # # 計算最終分數
1613
+ # final_score = (base_score * 0.85 + breed_bonus * 0.15) * perfect_bonus
1614
+
1615
+ # # 應用特殊情況調整
1616
  # final_score = apply_special_case_adjustments(final_score)
1617
 
1618
  # return min(1.0, final_score)
 
1626
  4. 條件組合的嚴格評估
1627
  """
1628
  def evaluate_perfect_conditions():
1629
+ """
1630
+ 評估條件匹配度,特別強化:
1631
+ 1. 運動類型與時間的綜合評估
1632
+ 2. 專業技能需求評估
1633
+ 3. ���種特性評估
1634
+ """
1635
  perfect_matches = {
1636
  'size_match': 0,
1637
  'exercise_match': 0,
1638
  'experience_match': 0,
1639
+ 'living_condition_match': 0,
1640
+ 'breed_trait_match': 0 # 新增品種特性匹配度
1641
  }
1642
 
1643
+ # 第一部分:運動需求評估
1644
+ def evaluate_exercise_compatibility():
1645
+ exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1646
+ exercise_time = user_prefs.exercise_time
1647
+ exercise_type = user_prefs.exercise_type
1648
+ temperament = breed_info.get('Temperament', '').lower()
1649
+
1650
+ # 定義品種運動特性
1651
+ exercise_patterns = {
1652
+ 'sprint_type': { # 短跑型,如 Whippet
1653
+ 'keywords': ['fast', 'speed', 'agile', 'sprint'],
1654
+ 'ideal_time': (30, 90),
1655
+ 'ideal_type': 'active_training',
1656
+ 'time_penalties': {
1657
+ 'over': 0.7, # 運動時間過長的懲罰
1658
+ 'under': 0.6 # 運動時間不足的懲罰
1659
+ }
1660
+ },
1661
+ 'endurance_type': { # 耐力型,如 Border Collie
1662
+ 'keywords': ['herding', 'working', 'energetic', 'tireless'],
1663
+ 'ideal_time': (90, 180),
1664
+ 'ideal_type': 'moderate_activity',
1665
+ 'time_penalties': {
1666
+ 'over': 0.9, # 耐力型對超時較寬容
1667
+ 'under': 0.5 # 但對運動不足較敏感
1668
+ }
1669
+ },
1670
+ 'moderate_type': { # 一般型
1671
+ 'keywords': ['playful', 'active', 'friendly'],
1672
+ 'ideal_time': (60, 120),
1673
+ 'ideal_type': 'moderate_activity',
1674
+ 'time_penalties': {
1675
+ 'over': 0.8,
1676
+ 'under': 0.7
1677
+ }
 
 
1678
  }
1679
  }
1680
+
1681
+ # 判斷品種的運動類型
1682
+ breed_type = 'moderate_type' # 預設值
1683
+ for pattern_type, pattern in exercise_patterns.items():
1684
+ if any(keyword in temperament for keyword in pattern['keywords']):
1685
+ breed_type = pattern_type
1686
+ break
1687
+
1688
+ pattern = exercise_patterns[breed_type]
1689
+ min_time, max_time = pattern['ideal_time']
1690
+
1691
+ # 計算時間匹配度
1692
+ if min_time <= exercise_time <= max_time:
1693
+ time_score = 1.0
1694
+ elif exercise_time < min_time:
1695
+ time_score = pattern['time_penalties']['under']
1696
  else:
1697
+ time_score = pattern['time_penalties']['over']
1698
+
1699
+ # 運動類型匹配度
1700
+ type_scores = {
1701
+ 'light_walks': 0.7,
1702
+ 'moderate_activity': 0.9,
1703
+ 'active_training': 1.0
1704
+ }
1705
+ type_score = type_scores.get(exercise_type, 0.7)
1706
+
1707
+ # 特殊情況處理
1708
+ if breed_type == 'sprint_type' and exercise_time > 120:
1709
+ if exercise_type != 'active_training':
1710
+ type_score *= 0.6 # 衝刺型品種不適合長時間中低強度運動
1711
+
1712
+ return (time_score * 0.6) + (type_score * 0.4)
1713
+
1714
+ # 第二部分:專業技能需求評估
1715
+ def evaluate_expertise_requirements():
1716
+ care_level = breed_info.get('Care Level', 'MODERATE').upper()
1717
+ temperament = breed_info.get('Temperament', '').lower()
1718
 
1719
+ # 定義專業技能要求
1720
+ expertise_requirements = {
1721
+ 'training_complexity': {
1722
+ 'HIGH': {'beginner': 0.3, 'intermediate': 0.7, 'advanced': 1.0},
1723
+ 'MODERATE': {'beginner': 0.6, 'intermediate': 0.9, 'advanced': 1.0},
1724
+ 'LOW': {'beginner': 0.9, 'intermediate': 0.95, 'advanced': 0.9}
1725
+ },
1726
+ 'special_traits': {
1727
+ 'working': 0.2, # 工作犬需要額外技能
1728
+ 'herding': 0.2, # 牧羊犬需要特殊訓練
1729
+ 'intelligent': 0.15,# 高智商犬種需要心智刺激
1730
+ 'independent': 0.15,# 獨立性強的需要特殊處理
1731
+ 'protective': 0.1 # 護衛犬需要適當訓練
1732
+ }
 
 
 
 
 
 
 
1733
  }
1734
+
1735
+ # 基礎分數
1736
+ base_score = expertise_requirements['training_complexity'][care_level][user_prefs.experience_level]
1737
+
1738
+ # 特殊特徵評估
1739
+ trait_penalty = 0
1740
+ for trait, penalty in expertise_requirements['special_traits'].items():
1741
+ if trait in temperament:
1742
+ if user_prefs.experience_level == 'beginner':
1743
+ trait_penalty += penalty
1744
+ elif user_prefs.experience_level == 'advanced':
1745
+ trait_penalty -= penalty * 0.5 # 專家反而因應對特殊特徵而加分
1746
+
1747
+ return max(0.2, min(1.0, base_score - trait_penalty))
1748
+
1749
+ # 第三部分:生活環境評估
1750
+ def evaluate_living_conditions():
1751
+ size = breed_info['Size']
1752
+ exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1753
 
1754
+ # 空間需求矩陣
1755
+ space_requirements = {
1756
+ 'apartment': {
1757
+ 'Small': 1.0, 'Medium': 0.4, 'Large': 0.2, 'Giant': 0.1
1758
+ },
1759
+ 'house_small': {
1760
+ 'Small': 0.9, 'Medium': 1.0, 'Large': 0.5, 'Giant': 0.3
1761
+ },
1762
+ 'house_large': {
1763
+ 'Small': 0.8, 'Medium': 0.9, 'Large': 1.0, 'Giant': 1.0
1764
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1765
  }
1766
+
1767
+ # 基礎空間分數
1768
+ space_score = space_requirements.get(user_prefs.living_space,
1769
+ space_requirements['house_small'])[size]
1770
+
1771
+ # 活動空間需求調整
1772
+ if exercise_needs in ['HIGH', 'VERY HIGH']:
1773
+ if user_prefs.living_space != 'house_large':
1774
+ space_score *= 0.8
1775
+
1776
+ # 院子可用性評估
1777
+ yard_scores = {
1778
+ 'no_yard': 0.7,
1779
+ 'shared_yard': 0.85,
 
 
 
 
 
 
 
1780
  'private_yard': 1.0
1781
  }
1782
+ space_score *= yard_scores.get(user_prefs.yard_access, 0.8)
1783
+
1784
+ return space_score
1785
+
1786
+ # 第四部分:品種特性評估(新增)
1787
+ def evaluate_breed_traits():
1788
+ temperament = breed_info.get('Temperament', '').lower()
1789
+ description = breed_info.get('Description', '').lower()
1790
 
1791
+ trait_scores = []
1792
+
1793
+ # 評估性格特徵
1794
+ if user_prefs.has_children:
1795
+ if 'good with children' in description:
1796
+ trait_scores.append(1.0)
1797
+ elif 'patient' in temperament or 'gentle' in temperament:
1798
+ trait_scores.append(0.8)
1799
+ else:
1800
+ trait_scores.append(0.5)
1801
+
1802
+ # 評估適應性
1803
+ adaptability_keywords = ['adaptable', 'versatile', 'flexible']
1804
+ if any(keyword in temperament for keyword in adaptability_keywords):
1805
+ trait_scores.append(1.0)
1806
+ else:
1807
+ trait_scores.append(0.7)
1808
+
1809
+ return sum(trait_scores) / len(trait_scores) if trait_scores else 0.7
1810
+
1811
+ # 計算各項匹配分數
1812
+ perfect_matches['exercise_match'] = evaluate_exercise_compatibility()
1813
+ perfect_matches['experience_match'] = evaluate_expertise_requirements()
1814
+ perfect_matches['living_condition_match'] = evaluate_living_conditions()
1815
+ perfect_matches['size_match'] = evaluate_living_conditions() # 共用生活環境評估
1816
+ perfect_matches['breed_trait_match'] = evaluate_breed_traits()
1817
+
1818
  return perfect_matches
1819
 
1820
  def calculate_weights():
1821
+ """
1822
+ 計算動態權重,特別關注:
1823
+ 1. 條件極端度對權重的影響
1824
+ 2. 多重條件組合的權重調整
1825
+ 3. 品種特性對權重分配的影響
1826
+ """
1827
+ # 基礎權重設定
1828
  base_weights = {
1829
  'space': 0.20,
1830
  'exercise': 0.20,
 
1834
  'health': 0.10
1835
  }
1836
 
1837
+ def analyze_condition_extremity():
1838
+ """評估各條件的極端程度及其影響"""
1839
  extremities = {}
1840
 
1841
+ # 運動時間極端度分析
1842
+ def analyze_exercise_extremity():
1843
+ if user_prefs.exercise_time <= 30:
1844
+ return ('extremely_low', 0.9)
1845
+ elif user_prefs.exercise_time <= 60:
1846
+ return ('low', 0.7)
1847
+ elif user_prefs.exercise_time >= 180:
1848
+ return ('extremely_high', 0.9)
1849
+ elif user_prefs.exercise_time >= 120:
1850
+ return ('high', 0.7)
1851
+ return ('moderate', 0.4)
1852
+
1853
+ # 空間限制極端度分析
1854
+ def analyze_space_extremity():
1855
+ space_extremity = {
1856
+ 'apartment': ('highly_restricted', 0.9),
1857
+ 'house_small': ('restricted', 0.6),
1858
+ 'house_large': ('spacious', 0.4)
1859
+ }
1860
+ return space_extremity.get(user_prefs.living_space, ('moderate', 0.5))
1861
+
1862
+ # 經驗水平極端度分析
1863
+ def analyze_experience_extremity():
1864
+ experience_extremity = {
1865
+ 'beginner': ('low', 0.8),
1866
+ 'intermediate': ('moderate', 0.5),
1867
+ 'advanced': ('high', 0.7)
1868
+ }
1869
+ return experience_extremity.get(user_prefs.experience_level, ('moderate', 0.5))
1870
+
1871
+ # 整合各項極端度評估
1872
+ extremities['exercise'] = analyze_exercise_extremity()
1873
+ extremities['space'] = analyze_space_extremity()
1874
+ extremities['experience'] = analyze_experience_extremity()
 
 
 
 
 
 
 
 
 
1875
 
1876
+ return extremities
1877
+
1878
+ def calculate_weight_adjustments(extremities):
1879
+ """根據條件極端度計算權重調整"""
1880
+ adjustments = {}
1881
 
1882
+ # 空間權重調整邏輯
1883
+ if extremities['space'][0] == 'highly_restricted':
1884
+ adjustments['space'] = 2.5
1885
+ adjustments['noise'] = 2.0
1886
+ elif extremities['space'][0] == 'restricted':
1887
+ adjustments['space'] = 1.8
1888
+ adjustments['noise'] = 1.5
1889
+ elif extremities['space'][0] == 'spacious':
1890
+ adjustments['space'] = 0.8 # 降低空間權重
1891
+ adjustments['exercise'] = 1.4 # 提升運動重要性
1892
+
1893
+ # 運動需求權重調整
1894
+ if extremities['exercise'][0] in ['extremely_low', 'extremely_high']:
1895
+ adjustments['exercise'] = 2.5
1896
+ elif extremities['exercise'][0] in ['low', 'high']:
1897
+ adjustments['exercise'] = 1.8
1898
+
1899
+ # 經驗需求權重調整
1900
+ if extremities['experience'][0] == 'low':
1901
+ adjustments['experience'] = 2.2
1902
+ if breed_info.get('Care Level') == 'HIGH':
1903
+ adjustments['experience'] = 2.5
1904
+ elif extremities['experience'][0] == 'high':
1905
+ adjustments['experience'] = 1.8
1906
+
1907
+ # 綜合條件影響
1908
+ def adjust_for_combinations():
1909
+ # 公寓 + 高運動需求
1910
+ if (extremities['space'][0] == 'highly_restricted' and
1911
+ extremities['exercise'][0] in ['high', 'extremely_high']):
1912
+ adjustments['space'] = adjustments.get('space', 1.0) * 1.3
1913
+ adjustments['exercise'] = adjustments.get('exercise', 1.0) * 1.3
1914
+
1915
+ # 新手 + 大空間 + 高運動量
1916
+ if (extremities['experience'][0] == 'low' and
1917
+ extremities['space'][0] == 'spacious' and
1918
+ extremities['exercise'][0] in ['high', 'extremely_high']):
1919
+ adjustments['experience'] = adjustments.get('experience', 1.0) * 1.4
1920
+
1921
+ # 空間充足時降低其權重
1922
+ if extremities['space'][0] == 'spacious':
1923
+ for key in ['grooming', 'health', 'noise']:
1924
+ if key not in adjustments:
1925
+ adjustments[key] = 1.2
1926
+
1927
+ adjust_for_combinations()
1928
+ return adjustments
1929
+
1930
+ # 獲取條件極端度
1931
+ extremities = analyze_condition_extremity()
1932
+
1933
+ # 計算權重調整
1934
+ weight_adjustments = calculate_weight_adjustments(extremities)
1935
+
1936
  # 應用權重調整
1937
  final_weights = base_weights.copy()
1938
  for key, adjustment in weight_adjustments.items():
1939
+ if key in final_weights:
1940
+ final_weights[key] *= adjustment
1941
+
1942
  return final_weights
1943
 
1944
  def apply_special_case_adjustments(score):
1945
+ """
1946
+ 處理特殊情況的分數調整,著重:
1947
+ 1. 條件組合的協同效應
1948
+ 2. 品種特性的特殊要求
1949
+ 3. 極端情況的嚴格處理
1950
+ """
1951
+ severity_multiplier = 1.0
1952
+
1953
+ def evaluate_spatial_exercise_combination():
1954
+ """評估空間與運動需求的組合影響"""
1955
+ multiplier = 1.0
1956
+
1957
+ if user_prefs.living_space == 'apartment':
1958
+ if breed_info.get('Exercise Needs', 'MODERATE').upper() == 'VERY HIGH':
1959
+ multiplier *= 0.5
1960
+ elif breed_info.get('Exercise Needs') == 'HIGH':
1961
+ multiplier *= 0.6
1962
 
1963
+ # 大型犬在公寓的額外懲罰
1964
+ if breed_info['Size'] in ['Large', 'Giant']:
1965
+ multiplier *= 0.5
1966
+
1967
+ return multiplier
1968
+
1969
+ def evaluate_experience_combination():
1970
+ """評估經驗需求的複合影響"""
1971
+ multiplier = 1.0
1972
+ temperament = breed_info.get('Temperament', '').lower()
1973
+ care_level = breed_info.get('Care Level', 'MODERATE')
1974
+
1975
+ # 新手飼主的特殊考量
1976
+ if user_prefs.experience_level == 'beginner':
1977
+ # 高難度品種的嚴格限制
1978
+ if care_level == 'HIGH':
1979
+ if user_prefs.has_children:
1980
+ multiplier *= 0.5
1981
+ else:
1982
+ multiplier *= 0.6
1983
+
1984
+ # 特殊性格特徵的影響
1985
+ challenging_traits = ['independent', 'dominant', 'protective', 'strong-willed']
1986
+ trait_count = sum(1 for trait in challenging_traits if trait in temperament)
1987
+ if trait_count > 0:
1988
+ multiplier *= (0.8 ** trait_count)
1989
 
1990
+ # 進階飼主的特殊考量
1991
+ elif user_prefs.experience_level == 'advanced':
1992
+ if care_level == 'LOW' and breed_info.get('Exercise Needs') == 'LOW':
1993
+ multiplier *= 0.9 # 對專家來說可能過於簡單
1994
+
1995
+ return multiplier
1996
+
1997
+ def evaluate_breed_specific_requirements():
1998
+ """評估品種特定的要求"""
1999
+ multiplier = 1.0
2000
+ exercise_time = user_prefs.exercise_time
2001
+ exercise_type = user_prefs.exercise_type
2002
+
2003
+ # 特定品種的運動模式評估
2004
+ if 'sprint' in breed_info.get('Temperament', '').lower():
2005
+ if exercise_time > 120 and exercise_type != 'active_training':
2006
+ multiplier *= 0.7 # 衝刺型品種不適合長時間中低強度運動
2007
+
2008
+ # 工作犬種的特殊需求
2009
+ if any(trait in breed_info.get('Temperament', '').lower()
2010
+ for trait in ['working', 'herding']):
2011
+ if exercise_time < 90 or exercise_type == 'light_walks':
2012
+ multiplier *= 0.7
2013
+
2014
+ return multiplier
2015
+
2016
+ def evaluate_environmental_impact():
2017
+ """評估環境因素的影響"""
2018
+ multiplier = 1.0
2019
+
2020
+ # 時間限制的影響
2021
+ if user_prefs.time_availability == 'limited':
2022
+ if breed_info.get('Exercise Needs').upper() in ['VERY HIGH', 'HIGH']:
2023
+ multiplier *= 0.7
2024
+
2025
+ # 噪音敏感度的影響
2026
+ if user_prefs.noise_tolerance == 'low':
2027
+ if breed_info.get('Breed') in breed_noise_info:
2028
+ if breed_noise_info[breed_info['Breed']]['noise_level'].lower() == 'high':
2029
+ multiplier *= 0.6
2030
+
2031
+ return multiplier
2032
+
2033
+ # 整合所有特殊情況的評估
2034
+ severity_multiplier *= evaluate_spatial_exercise_combination()
2035
+ severity_multiplier *= evaluate_experience_combination()
2036
+ severity_multiplier *= evaluate_breed_specific_requirements()
2037
+ severity_multiplier *= evaluate_environmental_impact()
2038
+
2039
+ # 確保最終分數在合理範圍內
2040
+ final_score = score * severity_multiplier
2041
+ return max(0.2, min(1.0, final_score))
2042
 
2043
  # 評估完美匹配條件
2044
  perfect_conditions = evaluate_perfect_conditions()
 
2046
  # 計算動態權重
2047
  weights = calculate_weights()
2048
 
2049
+ # 正規化權重確保總和為1
2050
  total_weight = sum(weights.values())
2051
  normalized_weights = {k: v/total_weight for k, v in weights.items()}
2052
 
2053
  # 計算基礎分數
2054
  base_score = sum(scores[k] * normalized_weights[k] for k in scores.keys())
2055
 
2056
+ # 計算完美匹配獎勵(降低獎勵影響以避免過高分數)
2057
  perfect_bonus = 1.0
2058
+ perfect_bonus += 0.10 * perfect_conditions['size_match'] # 降低單項獎勵
2059
+ perfect_bonus += 0.10 * perfect_conditions['exercise_match']
2060
+ perfect_bonus += 0.10 * perfect_conditions['experience_match']
2061
+ perfect_bonus += 0.05 * perfect_conditions['living_condition_match']
2062
+ perfect_bonus += 0.05 * perfect_conditions['breed_trait_match'] # 新增品種特性獎勵
2063
 
2064
+ # 計算品種特性加成(使用更嚴格的係數)
2065
+ breed_bonus = calculate_breed_bonus(breed_info, user_prefs) * 0.15 # 降低品種加成的影響
2066
 
2067
+ # 計算初步分數
2068
+ initial_score = (base_score * 0.85 + breed_bonus * 0.15) * perfect_bonus
2069
 
2070
  # 應用特殊情況調整
2071
+ final_score = apply_special_case_adjustments(initial_score)
2072
 
2073
+ # 確保最終分數在有效範圍內
2074
+ return min(1.0, max(0.3, final_score))
2075
 
2076
 
2077
  def amplify_score_extreme(score: float) -> float: