DawnC commited on
Commit
3f53841
1 Parent(s): b9a579d

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. scoring_calculation_system.py +377 -308
scoring_calculation_system.py CHANGED
@@ -1297,14 +1297,15 @@ 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
- # 優化後的品種相容性評分系統
1301
- # 主要改進:
1302
- # 1. 更精確的條件匹配度評估
1303
- # 2. 更動態的權重分配
1304
- # 3. 更嚴格的特殊情況處理
1305
  # """
1306
  # def evaluate_perfect_conditions():
1307
- # """評估完美條件匹配度,重點優化不同條件組合的評估邏輯"""
 
 
 
1308
  # perfect_matches = {
1309
  # 'size_match': 0,
1310
  # 'exercise_match': 0,
@@ -1312,210 +1313,216 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1312
  # 'living_condition_match': 0
1313
  # }
1314
 
1315
- # # 體型與居住空間匹配評估
1316
- # size_living_matrix = {
1317
  # 'apartment': {
1318
  # 'Small': 1.0,
1319
  # 'Medium': 0.4,
1320
- # 'Large': 0.1,
1321
- # 'Giant': 0.05
1322
  # },
1323
  # 'house_small': {
1324
  # 'Small': 0.9,
1325
  # 'Medium': 1.0,
1326
- # 'Large': 0.5,
1327
- # 'Giant': 0.3
1328
- # },
1329
- # 'house_large': {
1330
- # 'Small': 0.7,
1331
- # 'Medium': 0.9,
1332
- # 'Large': 1.0,
1333
- # 'Giant': 0.9
1334
  # }
1335
  # }
1336
- # perfect_matches['size_match'] = size_living_matrix.get(user_prefs.living_space, {}).get(breed_info['Size'], 0.5)
1337
 
1338
- # # 運動需求匹配評估
 
 
 
 
 
 
 
 
 
 
 
1339
  # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1340
  # exercise_time = user_prefs.exercise_time
1341
- # exercise_type = user_prefs.exercise_type
1342
-
1343
- # # 建立運動時間範圍對照表
1344
- # exercise_ranges = {
1345
- # 'VERY HIGH': {'ideal': (150, 180), 'acceptable': (120, 200)},
1346
- # 'HIGH': {'ideal': (120, 150), 'acceptable': (90, 180)},
1347
- # 'MODERATE': {'ideal': (60, 120), 'acceptable': (45, 150)},
1348
- # 'LOW': {'ideal': (30, 60), 'acceptable': (20, 90)}
1349
- # }
1350
 
1351
- # # 評估運動時間匹配度
1352
- # breed_range = exercise_ranges.get(exercise_needs, exercise_ranges['MODERATE'])
1353
- # if breed_range['ideal'][0] <= exercise_time <= breed_range['ideal'][1]:
1354
- # time_match = 1.0
1355
- # elif breed_range['acceptable'][0] <= exercise_time <= breed_range['acceptable'][1]:
1356
- # time_match = 0.7
1357
- # else:
1358
- # time_match = 0.3
1359
-
1360
- # # 運動類型匹配評估
1361
- # exercise_type_matrix = {
1362
- # 'VERY HIGH': {
1363
- # 'light_walks': 0.2,
1364
- # 'moderate_activity': 0.5,
1365
- # 'active_training': 1.0
1366
- # },
1367
- # 'HIGH': {
1368
- # 'light_walks': 0.3,
1369
- # 'moderate_activity': 0.8,
1370
- # 'active_training': 1.0
1371
- # },
1372
- # 'MODERATE': {
1373
- # 'light_walks': 0.7,
1374
- # 'moderate_activity': 1.0,
1375
- # 'active_training': 0.8
1376
- # },
1377
- # 'LOW': {
1378
- # 'light_walks': 1.0,
1379
- # 'moderate_activity': 0.7,
1380
- # 'active_training': 0.4
1381
  # }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1382
  # }
1383
 
1384
- # type_match = exercise_type_matrix.get(exercise_needs, {}).get(exercise_type, 0.5)
1385
- # perfect_matches['exercise_match'] = (time_match * 0.7) + (type_match * 0.3)
 
 
 
 
1386
 
1387
- # # 經驗匹配度評估
 
 
 
 
 
 
 
 
1388
  # care_level = breed_info.get('Care Level', 'MODERATE').upper()
1389
- # experience_matrix = {
1390
- # 'HIGH': {
1391
- # 'beginner': 0.1,
1392
- # 'intermediate': 0.6,
1393
- # 'advanced': 1.0
1394
- # },
1395
- # 'MODERATE': {
1396
- # 'beginner': 0.5,
1397
- # 'intermediate': 1.0,
1398
- # 'advanced': 0.9
1399
- # },
1400
- # 'LOW': {
1401
- # 'beginner': 1.0,
1402
- # 'intermediate': 0.9,
1403
- # 'advanced': 0.8
1404
- # }
1405
  # }
1406
- # perfect_matches['experience_match'] = experience_matrix.get(care_level, {}).get(user_prefs.experience_level, 0.5)
1407
 
1408
- # # 生活條件整體匹配評估
1409
- # living_factors = []
1410
 
1411
- # # 院子可用性評估
 
 
 
 
 
 
 
 
 
1412
  # if breed_info.get('Exercise Needs', 'MODERATE').upper() in ['HIGH', 'VERY HIGH']:
1413
- # if user_prefs.yard_access == 'no_yard':
1414
- # living_factors.append(0.3)
1415
- # elif user_prefs.yard_access == 'shared_yard':
1416
- # living_factors.append(0.7)
1417
- # else:
1418
- # living_factors.append(1.0)
1419
-
1420
- # # 時間可用性評估
1421
- # time_availability_scores = {
1422
- # 'limited': 0.4,
1423
- # 'moderate': 0.7,
1424
- # 'flexible': 1.0
1425
- # }
1426
- # living_factors.append(time_availability_scores.get(user_prefs.time_availability, 0.7))
1427
 
1428
- # perfect_matches['living_condition_match'] = sum(living_factors) / len(living_factors) if living_factors else 0.5
1429
 
1430
  # return perfect_matches
1431
 
1432
  # def calculate_weights():
1433
- # """計算動態權重,根據使用者條件調整各項評分的重要性"""
 
 
 
1434
  # base_weights = {
1435
  # 'space': 0.20,
1436
  # 'exercise': 0.20,
1437
  # 'experience': 0.20,
1438
  # 'grooming': 0.15,
1439
- # 'health': 0.15,
1440
- # 'noise': 0.10
1441
  # }
1442
 
1443
- # multipliers = {}
1444
-
1445
- # # 居住空間權重調整
1446
- # if user_prefs.living_space == 'apartment':
1447
- # multipliers['space'] = 3.0
1448
- # multipliers['noise'] = 2.5
1449
- # if breed_info['Size'] in ['Large', 'Giant']:
1450
- # multipliers['space'] = 4.0
1451
-
1452
- # # 運動需求權重調整
1453
- # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1454
- # if exercise_needs == 'VERY HIGH':
1455
- # if user_prefs.exercise_time < 90:
1456
- # multipliers['exercise'] = 4.0
1457
- # elif user_prefs.exercise_time > 150:
1458
- # multipliers['exercise'] = 3.0
1459
- # elif user_prefs.exercise_time < 30:
1460
- # multipliers['exercise'] = 3.5
1461
 
1462
- # # 經驗需求權重調整
1463
- # if user_prefs.experience_level == 'beginner':
1464
- # if breed_info.get('Care Level', 'MODERATE').upper() == 'HIGH':
1465
- # multipliers['experience'] = 4.0
 
1466
  # else:
1467
- # multipliers['experience'] = 3.0
1468
 
1469
- # # 噪音敏感度調整
1470
- # if user_prefs.noise_tolerance == 'low':
1471
- # multipliers['noise'] = multipliers.get('noise', 1.0) * 3.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1472
 
1473
- # # 有小孩的情況特別注重經驗需求
1474
- # if user_prefs.has_children and user_prefs.children_age == 'toddler':
1475
- # multipliers['experience'] = multipliers.get('experience', 1.0) * 2.0
1476
 
 
 
 
 
1477
  # # 應用權重調整
1478
- # for key, multiplier in multipliers.items():
1479
- # base_weights[key] *= multiplier
 
1480
 
1481
- # return base_weights
1482
 
1483
  # def apply_special_case_adjustments(score):
1484
- # """處理特殊情況,給予更嚴格的分數調整"""
1485
- # # 極端不匹配情況的嚴格懲罰
 
 
 
 
 
 
 
 
 
 
 
 
1486
  # if user_prefs.experience_level == 'beginner':
1487
  # if breed_info.get('Care Level') == 'HIGH':
1488
- # if breed_info.get('Exercise Needs') == 'VERY HIGH':
1489
- # score *= 0.4
1490
  # else:
1491
- # score *= 0.6
1492
-
1493
- # # 運動需求極端不匹配
1494
- # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1495
- # if exercise_needs == 'VERY HIGH' and user_prefs.exercise_time < 60:
1496
- # score *= 0.4
1497
- # elif exercise_needs == 'LOW' and user_prefs.exercise_time > 150:
1498
- # score *= 0.5
1499
-
1500
- # # 居住空間極端不匹配
1501
- # if user_prefs.living_space == 'apartment':
1502
- # if breed_info['Size'] == 'Giant':
1503
- # score *= 0.3
1504
- # elif breed_info['Size'] == 'Large':
1505
- # score *= 0.5
1506
-
1507
- # # 噪音敏感度極端不匹配
1508
- # if user_prefs.noise_tolerance == 'low':
1509
- # if breed_info.get('Breed') in breed_noise_info:
1510
- # if breed_noise_info[breed_info['Breed']]['noise_level'].lower() == 'high':
1511
- # score *= 0.4
1512
 
1513
- # # 時間限制的影響
1514
  # if user_prefs.time_availability == 'limited':
1515
  # if breed_info.get('Exercise Needs').upper() in ['HIGH', 'VERY HIGH']:
1516
- # score *= 0.6
1517
 
1518
- # return score
1519
 
1520
  # # 評估完美匹配條件
1521
  # perfect_conditions = evaluate_perfect_conditions()
@@ -1530,20 +1537,18 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1530
  # # 計算基礎分數
1531
  # base_score = sum(scores[k] * normalized_weights[k] for k in scores.keys())
1532
 
1533
- # # 完美匹配獎勵計算
1534
  # perfect_bonus = 1.0
1535
  # perfect_bonus += 0.15 * perfect_conditions['size_match']
1536
  # perfect_bonus += 0.15 * perfect_conditions['exercise_match']
1537
  # perfect_bonus += 0.15 * perfect_conditions['experience_match']
1538
  # perfect_bonus += 0.05 * perfect_conditions['living_condition_match']
1539
 
1540
- # # 品種特性加成
1541
- # breed_bonus = calculate_breed_bonus(breed_info, user_prefs) * 1.2
1542
 
1543
- # # 計算最終分數
1544
  # final_score = (base_score * 0.8 + breed_bonus * 0.2) * perfect_bonus
1545
-
1546
- # # 應用特殊情況調整
1547
  # final_score = apply_special_case_adjustments(final_score)
1548
 
1549
  # return min(1.0, final_score)
@@ -1551,15 +1556,13 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1551
 
1552
  def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1553
  """
1554
- 1. 條件間的相互影響
1555
- 2. 動態權重調整
1556
- 3. 更自然的評分機制
 
1557
  """
1558
  def evaluate_perfect_conditions():
1559
- """
1560
- 評估條件匹配度,考慮條件間的相互關係。
1561
- 返回的不只是單純的匹配分數,而是綜合了各種條件互相影響後的結果。
1562
- """
1563
  perfect_matches = {
1564
  'size_match': 0,
1565
  'exercise_match': 0,
@@ -1567,8 +1570,81 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1567
  'living_condition_match': 0
1568
  }
1569
 
1570
- # 居住空間與體型匹配評估
1571
- size_living_evaluation = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1572
  'apartment': {
1573
  'Small': 1.0,
1574
  'Medium': 0.4,
@@ -1578,118 +1654,91 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1578
  'house_small': {
1579
  'Small': 0.9,
1580
  'Medium': 1.0,
1581
- 'Large': 0.6,
1582
- 'Giant': 0.4
 
 
 
 
 
 
1583
  }
1584
  }
1585
 
1586
- # 對於大房子,我們不使用固定的匹配矩陣,而是根據其他條件動態評估
1587
- if user_prefs.living_space == 'house_large':
1588
- # 大房子的評估更關注其他因素而不是體型限制
1589
- perfect_matches['size_match'] = 0.8 # 基礎分數較高
1590
- if breed_info['Size'] in ['Medium', 'Large']:
1591
- perfect_matches['size_match'] = 0.9
1592
  else:
1593
- perfect_matches['size_match'] = size_living_evaluation.get(
1594
- user_prefs.living_space, {}
1595
- ).get(breed_info['Size'], 0.5)
1596
-
1597
- # 運動需求匹配評估,考慮多個相關因素
1598
- exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1599
- exercise_time = user_prefs.exercise_time
1600
-
1601
- # 建立運動時間的基礎評估
1602
- def evaluate_exercise_match():
1603
- # 根據運動需求級別動態計算理想範圍
1604
- exercise_ranges = {
1605
- 'VERY HIGH': (120, 180),
1606
- 'HIGH': (90, 150),
1607
- 'MODERATE': (60, 120),
1608
- 'LOW': (30, 90)
1609
- }
1610
-
1611
- # 獲取該品種的理想運動範圍
1612
- ideal_range = exercise_ranges.get(exercise_needs, (60, 120))
1613
- min_time, max_time = ideal_range
1614
 
1615
- # 動態計算匹配度,避免硬性分界
1616
- if min_time <= exercise_time <= max_time:
1617
- base_score = 1.0
1618
- else:
1619
- # 計算與理想範圍的偏差程度
1620
- if exercise_time < min_time:
1621
- deviation = (min_time - exercise_time) / min_time
1622
- else:
1623
- deviation = (exercise_time - max_time) / max_time
1624
- base_score = max(0.3, 1 - deviation)
1625
-
1626
- return base_score
1627
-
1628
- # 結合運動時間與其他條件
1629
- exercise_base_score = evaluate_exercise_match()
1630
-
1631
- # 考慮時間可用性的影響
1632
- time_availability_impact = {
1633
- 'limited': 0.7,
1634
- 'moderate': 0.9,
1635
- 'flexible': 1.0
1636
- }
1637
-
1638
- # 考慮使用者經驗對運動安排的影響
1639
- experience_impact = {
1640
- 'beginner': 0.8,
1641
- 'intermediate': 0.9,
1642
- 'advanced': 1.0
1643
- }
1644
 
1645
- # 計算最終運動匹配度
1646
- exercise_modifiers = (
1647
- time_availability_impact.get(user_prefs.time_availability, 0.9) *
1648
- experience_impact.get(user_prefs.experience_level, 0.9)
1649
- )
1650
-
1651
- perfect_matches['exercise_match'] = exercise_base_score * exercise_modifiers
1652
-
1653
- # 經驗匹配評估,考慮品種難度和其他因素
1654
  care_level = breed_info.get('Care Level', 'MODERATE').upper()
1655
-
1656
- # 基礎經驗匹配評估
1657
- experience_base = {
1658
- 'HIGH': {'beginner': 0.3, 'intermediate': 0.7, 'advanced': 1.0},
1659
- 'MODERATE': {'beginner': 0.6, 'intermediate': 0.9, 'advanced': 1.0},
1660
- 'LOW': {'beginner': 0.9, 'intermediate': 1.0, 'advanced': 0.9}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1661
  }
1662
 
1663
- experience_score = experience_base.get(care_level, experience_base['MODERATE']
1664
- ).get(user_prefs.experience_level, 0.7)
1665
 
1666
- # 調整經驗分數基於其他因素
1667
- if user_prefs.has_children:
1668
- experience_score *= 0.8 if user_prefs.experience_level == 'beginner' else 0.9
1669
-
 
 
 
1670
  perfect_matches['experience_match'] = experience_score
1671
-
1672
  # 生活條件整體評估
1673
  living_score = 1.0
1674
 
1675
- # 院子影響評估
1676
  if breed_info.get('Exercise Needs', 'MODERATE').upper() in ['HIGH', 'VERY HIGH']:
1677
  yard_impacts = {
1678
- 'no_yard': 0.6,
1679
- 'shared_yard': 0.8,
1680
  'private_yard': 1.0
1681
  }
1682
- living_score *= yard_impacts.get(user_prefs.yard_access, 0.8)
 
 
 
 
 
 
 
 
1683
 
1684
  perfect_matches['living_condition_match'] = living_score
1685
 
1686
  return perfect_matches
1687
 
1688
  def calculate_weights():
1689
- """
1690
- 計算動態權重,根據條件的極端程度自動調整各項評分的重要性
1691
- """
1692
- # 基礎權重設定
1693
  base_weights = {
1694
  'space': 0.20,
1695
  'exercise': 0.20,
@@ -1699,49 +1748,60 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1699
  'health': 0.10
1700
  }
1701
 
1702
- # 計算條件的極端程度
1703
- def calculate_extremity():
1704
  extremities = {}
1705
 
1706
- # 運動時間極端度
1707
  if user_prefs.exercise_time < 30:
1708
- extremities['exercise'] = ('low', 0.8)
 
 
1709
  elif user_prefs.exercise_time > 150:
1710
- extremities['exercise'] = ('high', 0.8)
 
 
1711
  else:
1712
- extremities['exercise'] = ('normal', 0.3)
1713
 
1714
- # 居住空間極端度
1715
  if user_prefs.living_space == 'apartment':
1716
- extremities['space'] = ('restrictive', 0.9)
1717
- elif user_prefs.living_space == 'house_large':
1718
- extremities['space'] = ('relaxed', 0.2)
1719
  else:
1720
- extremities['space'] = ('normal', 0.5)
1721
 
1722
  return extremities
1723
 
1724
- extremities = calculate_extremity()
1725
 
1726
- # 根據極端程度調整權重
1727
  weight_adjustments = {}
1728
 
1729
- # 空間限制的權重調整
1730
- if extremities['space'][0] == 'restrictive':
1731
  weight_adjustments['space'] = 3.0
1732
- weight_adjustments['noise'] = 2.0
1733
- elif extremities['space'][0] == 'relaxed':
1734
- weight_adjustments['space'] = 0.5
1735
- weight_adjustments['exercise'] = 1.5
 
 
 
1736
 
1737
- # 運動需求的權重調整
1738
- if extremities['exercise'][0] in ['low', 'high']:
1739
- weight_adjustments['exercise'] = 2.5
 
 
1740
 
1741
- # 經驗需求的權重調整
1742
  if user_prefs.experience_level == 'beginner':
 
 
1743
  weight_adjustments['experience'] = 2.0
1744
-
1745
  # 應用權重調整
1746
  final_weights = base_weights.copy()
1747
  for key, adjustment in weight_adjustments.items():
@@ -1750,31 +1810,38 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1750
  return final_weights
1751
 
1752
  def apply_special_case_adjustments(score):
1753
- """
1754
- 處理特殊情況,考慮條件組合產生的效果
1755
- """
1756
- # 評估條件組合的嚴重程度
1757
  severity = 1.0
1758
 
1759
- # 空間與運動組合評估
1760
  if user_prefs.living_space == 'apartment':
1761
  if breed_info.get('Exercise Needs', 'MODERATE').upper() == 'VERY HIGH':
 
 
1762
  severity *= 0.6
1763
- elif breed_info['Size'] in ['Large', 'Giant']:
1764
- severity *= 0.7
1765
 
1766
- # 經驗與品種難度組合評估
1767
  if user_prefs.experience_level == 'beginner':
1768
  if breed_info.get('Care Level') == 'HIGH':
1769
  if user_prefs.has_children:
1770
- severity *= 0.6
1771
  else:
1772
- severity *= 0.7
1773
 
1774
- # 時間限制與需求組合評估
1775
  if user_prefs.time_availability == 'limited':
1776
- if breed_info.get('Exercise Needs').upper() in ['HIGH', 'VERY HIGH']:
1777
- severity *= 0.8
 
 
 
 
 
 
 
 
1778
 
1779
  return score * severity
1780
 
@@ -1791,18 +1858,20 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1791
  # 計算基礎分數
1792
  base_score = sum(scores[k] * normalized_weights[k] for k in scores.keys())
1793
 
1794
- # 完美匹配獎勵
1795
  perfect_bonus = 1.0
1796
- perfect_bonus += 0.15 * perfect_conditions['size_match']
1797
- perfect_bonus += 0.15 * perfect_conditions['exercise_match']
1798
- perfect_bonus += 0.15 * perfect_conditions['experience_match']
1799
- perfect_bonus += 0.05 * perfect_conditions['living_condition_match']
1800
 
1801
- # 品種特性加成(使用原有的 calculate_breed_bonus 函數)
1802
  breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1803
 
1804
- # 計算最終分數並應用特殊情況調整
1805
- final_score = (base_score * 0.8 + breed_bonus * 0.2) * perfect_bonus
 
 
1806
  final_score = apply_special_case_adjustments(final_score)
1807
 
1808
  return min(1.0, final_score)
 
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
  # 'living_condition_match': 0
1314
  # }
1315
 
1316
+ # # 居住空間與體型匹配評估
1317
+ # size_living_evaluation = {
1318
  # 'apartment': {
1319
  # 'Small': 1.0,
1320
  # 'Medium': 0.4,
1321
+ # 'Large': 0.2,
1322
+ # 'Giant': 0.1
1323
  # },
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,
1442
  # 'experience': 0.20,
1443
  # 'grooming': 0.15,
1444
+ # 'noise': 0.15,
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():
1494
+ # final_weights[key] *= adjustment
1495
 
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
 
1527
  # # 評估完美匹配條件
1528
  # perfect_conditions = evaluate_perfect_conditions()
 
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)
 
1556
 
1557
  def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1558
  """
1559
+ 1. 運動類型與時間的精確匹配
1560
+ 2. 進階使用者的專業需求
1561
+ 3. 空間利用的實際效果
1562
+ 4. 條件組合的嚴格評估
1563
  """
1564
  def evaluate_perfect_conditions():
1565
+ """評估條件匹配度,特別強化運動類型與專業程度的評估"""
 
 
 
1566
  perfect_matches = {
1567
  'size_match': 0,
1568
  'exercise_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,
 
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
  '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():
 
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
 
 
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)