DawnC commited on
Commit
b9a579d
1 Parent(s): b25319f

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. scoring_calculation_system.py +349 -297
scoring_calculation_system.py CHANGED
@@ -1294,110 +1294,143 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1294
 
1295
  return min(0.2, adaptability_score)
1296
 
 
1297
  # def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1298
  # """
1299
- # 重構的品種相容性評分系統
1300
- # 目標:實現更大的分數差異和更高的頂部分數,更精確的條件匹配
 
 
 
1301
  # """
1302
  # def evaluate_perfect_conditions():
1303
- # """評估完美條件匹配度,允許部分匹配"""
1304
  # perfect_matches = {
1305
  # 'size_match': 0,
1306
  # 'exercise_match': 0,
1307
  # 'experience_match': 0,
1308
- # 'general_match': False
1309
  # }
1310
 
1311
- # # 體型與空間匹配更細緻化
1312
- # if user_prefs.living_space == 'apartment':
1313
- # if breed_info['Size'] == 'Small':
1314
- # perfect_matches['size_match'] = 1.0
1315
- # elif breed_info['Size'] == 'Medium':
1316
- # perfect_matches['size_match'] = 0.5
1317
- # else:
1318
- # perfect_matches['size_match'] = 0
1319
- # elif user_prefs.living_space == 'house_small':
1320
- # if breed_info['Size'] in ['Small', 'Medium']:
1321
- # perfect_matches['size_match'] = 1.0
1322
- # elif breed_info['Size'] == 'Large':
1323
- # perfect_matches['size_match'] = 0.6
1324
- # else:
1325
- # perfect_matches['size_match'] = 0.3
1326
- # elif user_prefs.living_space == 'house_large':
1327
- # if breed_info['Size'] in ['Medium', 'Large']:
1328
- # perfect_matches['size_match'] = 1.0
1329
- # elif breed_info['Size'] == 'Small':
1330
- # perfect_matches['size_match'] = 0.7
1331
- # else:
1332
- # perfect_matches['size_match'] = 0.8
1333
-
1334
- # # 運動需求匹配更精確
1335
  # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1336
  # exercise_time = user_prefs.exercise_time
 
1337
 
1338
- # if exercise_needs == 'VERY HIGH':
1339
- # if exercise_time >= 150:
1340
- # perfect_matches['exercise_match'] = 1.0
1341
- # elif exercise_time >= 120:
1342
- # perfect_matches['exercise_match'] = 0.7
1343
- # elif exercise_time >= 90:
1344
- # perfect_matches['exercise_match'] = 0.4
1345
- # else:
1346
- # perfect_matches['exercise_match'] = 0
1347
- # elif exercise_needs == 'HIGH':
1348
- # if 120 <= exercise_time <= 150:
1349
- # perfect_matches['exercise_match'] = 1.0
1350
- # elif exercise_time >= 90:
1351
- # perfect_matches['exercise_match'] = 0.8
1352
- # elif exercise_time >= 60:
1353
- # perfect_matches['exercise_match'] = 0.5
1354
- # else:
1355
- # perfect_matches['exercise_match'] = 0.2
1356
- # elif exercise_needs == 'MODERATE':
1357
- # if 60 <= exercise_time <= 120:
1358
- # perfect_matches['exercise_match'] = 1.0
1359
- # elif exercise_time > 120:
1360
- # perfect_matches['exercise_match'] = 0.8
1361
- # else:
1362
- # perfect_matches['exercise_match'] = 0.6
1363
- # elif exercise_needs == 'LOW':
1364
- # if 30 <= exercise_time <= 90:
1365
- # perfect_matches['exercise_match'] = 1.0
1366
- # elif exercise_time > 90:
1367
- # perfect_matches['exercise_match'] = 0.7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1368
  # else:
1369
- # perfect_matches['exercise_match'] = 0.5
1370
 
1371
- # # 經驗匹配更細緻
1372
- # care_level = breed_info.get('Care Level', 'MODERATE')
1373
- # if care_level == 'High':
1374
- # if user_prefs.experience_level == 'advanced':
1375
- # perfect_matches['experience_match'] = 1.0
1376
- # elif user_prefs.experience_level == 'intermediate':
1377
- # perfect_matches['experience_match'] = 0.6
1378
- # else:
1379
- # perfect_matches['experience_match'] = 0.2
1380
- # elif care_level == 'Moderate':
1381
- # if user_prefs.experience_level == 'advanced':
1382
- # perfect_matches['experience_match'] = 0.9
1383
- # elif user_prefs.experience_level == 'intermediate':
1384
- # perfect_matches['experience_match'] = 1.0
1385
- # else:
1386
- # perfect_matches['experience_match'] = 0.7
1387
- # elif care_level == 'Low':
1388
- # if user_prefs.experience_level == 'beginner':
1389
- # perfect_matches['experience_match'] = 1.0
1390
- # else:
1391
- # perfect_matches['experience_match'] = 0.9
1392
-
1393
- # # 一般條件匹配
1394
- # if all(score >= 0.85 for score in scores.values()):
1395
- # perfect_matches['general_match'] = True
1396
-
1397
  # return perfect_matches
1398
 
1399
  # def calculate_weights():
1400
- # """計算更動態的權重"""
1401
  # base_weights = {
1402
  # 'space': 0.20,
1403
  # 'exercise': 0.20,
@@ -1407,22 +1440,16 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1407
  # 'noise': 0.10
1408
  # }
1409
 
1410
- # # 極端條件權重調整
1411
  # multipliers = {}
1412
 
1413
- # # 經驗權重更細緻的調整
1414
- # if user_prefs.experience_level == 'beginner':
1415
- # if breed_info.get('Care Level') == 'High':
1416
- # multipliers['experience'] = 3.5
1417
- # else:
1418
- # multipliers['experience'] = 3.0
1419
- # elif user_prefs.experience_level == 'advanced':
1420
- # if breed_info.get('Care Level') == 'High':
1421
- # multipliers['experience'] = 2.8
1422
- # else:
1423
- # multipliers['experience'] = 2.5
1424
-
1425
- # # 運動需求更細緻的調整
1426
  # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1427
  # if exercise_needs == 'VERY HIGH':
1428
  # if user_prefs.exercise_time < 90:
@@ -1432,40 +1459,62 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1432
  # elif user_prefs.exercise_time < 30:
1433
  # multipliers['exercise'] = 3.5
1434
 
1435
- # # 空間限制權重調整
1436
- # if user_prefs.living_space == 'apartment':
1437
- # multipliers['space'] = 2.5
1438
- # multipliers['noise'] = 2.0
1439
-
 
 
1440
  # # 噪音敏感度調整
1441
  # if user_prefs.noise_tolerance == 'low':
1442
- # multipliers['noise'] = multipliers.get('noise', 1.0) * 2.5
 
 
 
 
1443
 
1444
- # # 應用乘數
1445
  # for key, multiplier in multipliers.items():
1446
  # base_weights[key] *= multiplier
1447
 
1448
  # return base_weights
1449
 
1450
  # def apply_special_case_adjustments(score):
1451
- # """處理特殊情況"""
1452
- # # 新手不適合的特殊情況
1453
  # if user_prefs.experience_level == 'beginner':
1454
- # if (breed_info.get('Care Level') == 'High' and
1455
- # breed_info.get('Exercise Needs') == 'VERY HIGH'):
1456
- # score *= 0.7
1457
-
1458
- # # 運動時間極端不匹配的情況
 
 
1459
  # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1460
  # if exercise_needs == 'VERY HIGH' and user_prefs.exercise_time < 60:
1461
- # score *= 0.6
1462
-
1463
- # # 噪音敏感度極端情況
1464
- # if (user_prefs.noise_tolerance == 'low' and
1465
- # breed_info.get('Breed') in breed_noise_info and
1466
- # breed_noise_info[breed_info['Breed']]['noise_level'].lower() == 'high'):
1467
- # score *= 0.7
1468
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1469
  # return score
1470
 
1471
  # # 評估完美匹配條件
@@ -1481,19 +1530,18 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1481
  # # 計算基礎分數
1482
  # base_score = sum(scores[k] * normalized_weights[k] for k in scores.keys())
1483
 
1484
- # # 完美匹配獎勵更動態
1485
  # perfect_bonus = 1.0
1486
- # perfect_bonus += 0.2 * perfect_conditions['size_match']
1487
- # perfect_bonus += 0.2 * perfect_conditions['exercise_match']
1488
- # perfect_bonus += 0.2 * perfect_conditions['experience_match']
1489
- # if perfect_conditions['general_match']:
1490
- # perfect_bonus += 0.2
1491
-
1492
  # # 品種特性加成
1493
- # breed_bonus = calculate_breed_bonus(breed_info, user_prefs) * 1.5
1494
 
1495
  # # 計算最終分數
1496
- # final_score = (base_score * 0.7 + breed_bonus * 0.3) * perfect_bonus
1497
 
1498
  # # 應用特殊情況調整
1499
  # final_score = apply_special_case_adjustments(final_score)
@@ -1503,14 +1551,15 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1503
 
1504
  def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1505
  """
1506
- 優化後的品種相容性評分系統
1507
- 主要改進:
1508
- 1. 更精確的條件匹配度評估
1509
- 2. 更動態的權重分配
1510
- 3. 更嚴格的特殊情況處理
1511
  """
1512
  def evaluate_perfect_conditions():
1513
- """評估完美條件匹配度,重點優化不同條件組合的評估邏輯"""
 
 
 
1514
  perfect_matches = {
1515
  'size_match': 0,
1516
  'exercise_match': 0,
@@ -1518,210 +1567,216 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1518
  'living_condition_match': 0
1519
  }
1520
 
1521
- # 體型與居住空間匹配評估
1522
- size_living_matrix = {
1523
  'apartment': {
1524
  'Small': 1.0,
1525
  'Medium': 0.4,
1526
- 'Large': 0.1,
1527
- 'Giant': 0.05
1528
  },
1529
  'house_small': {
1530
  'Small': 0.9,
1531
  'Medium': 1.0,
1532
- 'Large': 0.5,
1533
- 'Giant': 0.3
1534
- },
1535
- 'house_large': {
1536
- 'Small': 0.7,
1537
- 'Medium': 0.9,
1538
- 'Large': 1.0,
1539
- 'Giant': 0.9
1540
  }
1541
  }
1542
- perfect_matches['size_match'] = size_living_matrix.get(user_prefs.living_space, {}).get(breed_info['Size'], 0.5)
1543
 
1544
- # 運動需求匹配評估
 
 
 
 
 
 
 
 
 
 
 
1545
  exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1546
  exercise_time = user_prefs.exercise_time
1547
- exercise_type = user_prefs.exercise_type
1548
-
1549
- # 建立運動時間範圍對照表
1550
- exercise_ranges = {
1551
- 'VERY HIGH': {'ideal': (150, 180), 'acceptable': (120, 200)},
1552
- 'HIGH': {'ideal': (120, 150), 'acceptable': (90, 180)},
1553
- 'MODERATE': {'ideal': (60, 120), 'acceptable': (45, 150)},
1554
- 'LOW': {'ideal': (30, 60), 'acceptable': (20, 90)}
1555
- }
1556
 
1557
- # 評估運動時間匹配度
1558
- breed_range = exercise_ranges.get(exercise_needs, exercise_ranges['MODERATE'])
1559
- if breed_range['ideal'][0] <= exercise_time <= breed_range['ideal'][1]:
1560
- time_match = 1.0
1561
- elif breed_range['acceptable'][0] <= exercise_time <= breed_range['acceptable'][1]:
1562
- time_match = 0.7
1563
- else:
1564
- time_match = 0.3
1565
-
1566
- # 運動類型匹配評估
1567
- exercise_type_matrix = {
1568
- 'VERY HIGH': {
1569
- 'light_walks': 0.2,
1570
- 'moderate_activity': 0.5,
1571
- 'active_training': 1.0
1572
- },
1573
- 'HIGH': {
1574
- 'light_walks': 0.3,
1575
- 'moderate_activity': 0.8,
1576
- 'active_training': 1.0
1577
- },
1578
- 'MODERATE': {
1579
- 'light_walks': 0.7,
1580
- 'moderate_activity': 1.0,
1581
- 'active_training': 0.8
1582
- },
1583
- 'LOW': {
1584
- 'light_walks': 1.0,
1585
- 'moderate_activity': 0.7,
1586
- 'active_training': 0.4
1587
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1588
  }
1589
 
1590
- type_match = exercise_type_matrix.get(exercise_needs, {}).get(exercise_type, 0.5)
1591
- perfect_matches['exercise_match'] = (time_match * 0.7) + (type_match * 0.3)
 
 
 
 
1592
 
1593
- # 經驗匹配度評估
 
 
 
 
 
 
 
 
1594
  care_level = breed_info.get('Care Level', 'MODERATE').upper()
1595
- experience_matrix = {
1596
- 'HIGH': {
1597
- 'beginner': 0.1,
1598
- 'intermediate': 0.6,
1599
- 'advanced': 1.0
1600
- },
1601
- 'MODERATE': {
1602
- 'beginner': 0.5,
1603
- 'intermediate': 1.0,
1604
- 'advanced': 0.9
1605
- },
1606
- 'LOW': {
1607
- 'beginner': 1.0,
1608
- 'intermediate': 0.9,
1609
- 'advanced': 0.8
1610
- }
1611
  }
1612
- perfect_matches['experience_match'] = experience_matrix.get(care_level, {}).get(user_prefs.experience_level, 0.5)
1613
 
1614
- # 生活條件整體匹配評估
1615
- living_factors = []
1616
 
1617
- # 院子可用性評估
 
 
 
 
 
 
 
 
 
1618
  if breed_info.get('Exercise Needs', 'MODERATE').upper() in ['HIGH', 'VERY HIGH']:
1619
- if user_prefs.yard_access == 'no_yard':
1620
- living_factors.append(0.3)
1621
- elif user_prefs.yard_access == 'shared_yard':
1622
- living_factors.append(0.7)
1623
- else:
1624
- living_factors.append(1.0)
1625
-
1626
- # 時間可用性評估
1627
- time_availability_scores = {
1628
- 'limited': 0.4,
1629
- 'moderate': 0.7,
1630
- 'flexible': 1.0
1631
- }
1632
- living_factors.append(time_availability_scores.get(user_prefs.time_availability, 0.7))
1633
 
1634
- perfect_matches['living_condition_match'] = sum(living_factors) / len(living_factors) if living_factors else 0.5
1635
 
1636
  return perfect_matches
1637
 
1638
  def calculate_weights():
1639
- """計算動態權重,根據使用者條件調整各項評分的重要性"""
 
 
 
1640
  base_weights = {
1641
  'space': 0.20,
1642
  'exercise': 0.20,
1643
  'experience': 0.20,
1644
  'grooming': 0.15,
1645
- 'health': 0.15,
1646
- 'noise': 0.10
1647
  }
1648
 
1649
- multipliers = {}
1650
-
1651
- # 居住空間權重調整
1652
- if user_prefs.living_space == 'apartment':
1653
- multipliers['space'] = 3.0
1654
- multipliers['noise'] = 2.5
1655
- if breed_info['Size'] in ['Large', 'Giant']:
1656
- multipliers['space'] = 4.0
1657
-
1658
- # 運動需求權重調整
1659
- exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1660
- if exercise_needs == 'VERY HIGH':
1661
- if user_prefs.exercise_time < 90:
1662
- multipliers['exercise'] = 4.0
1663
- elif user_prefs.exercise_time > 150:
1664
- multipliers['exercise'] = 3.0
1665
- elif user_prefs.exercise_time < 30:
1666
- multipliers['exercise'] = 3.5
1667
 
1668
- # 經驗需求權重調整
1669
- if user_prefs.experience_level == 'beginner':
1670
- if breed_info.get('Care Level', 'MODERATE').upper() == 'HIGH':
1671
- multipliers['experience'] = 4.0
 
1672
  else:
1673
- multipliers['experience'] = 3.0
1674
 
1675
- # 噪音敏感度調整
1676
- if user_prefs.noise_tolerance == 'low':
1677
- multipliers['noise'] = multipliers.get('noise', 1.0) * 3.0
 
 
 
 
 
 
1678
 
1679
- # 有小孩的情況特別注重經驗需求
1680
- if user_prefs.has_children and user_prefs.children_age == 'toddler':
1681
- multipliers['experience'] = multipliers.get('experience', 1.0) * 2.0
 
 
 
 
 
 
 
 
 
 
 
 
 
1682
 
 
 
 
 
1683
  # 應用權重調整
1684
- for key, multiplier in multipliers.items():
1685
- base_weights[key] *= multiplier
 
1686
 
1687
- return base_weights
1688
 
1689
  def apply_special_case_adjustments(score):
1690
- """處理特殊情況,給予更嚴格的分數調整"""
1691
- # 極端不匹配情況的嚴格懲罰
 
 
 
 
 
 
 
 
 
 
 
 
1692
  if user_prefs.experience_level == 'beginner':
1693
  if breed_info.get('Care Level') == 'HIGH':
1694
- if breed_info.get('Exercise Needs') == 'VERY HIGH':
1695
- score *= 0.4
1696
  else:
1697
- score *= 0.6
1698
 
1699
- # 運動需求極端不匹配
1700
- exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1701
- if exercise_needs == 'VERY HIGH' and user_prefs.exercise_time < 60:
1702
- score *= 0.4
1703
- elif exercise_needs == 'LOW' and user_prefs.exercise_time > 150:
1704
- score *= 0.5
1705
-
1706
- # 居住空間極端不匹配
1707
- if user_prefs.living_space == 'apartment':
1708
- if breed_info['Size'] == 'Giant':
1709
- score *= 0.3
1710
- elif breed_info['Size'] == 'Large':
1711
- score *= 0.5
1712
-
1713
- # 噪音敏感度極端不匹配
1714
- if user_prefs.noise_tolerance == 'low':
1715
- if breed_info.get('Breed') in breed_noise_info:
1716
- if breed_noise_info[breed_info['Breed']]['noise_level'].lower() == 'high':
1717
- score *= 0.4
1718
-
1719
- # 時間限制的影響
1720
  if user_prefs.time_availability == 'limited':
1721
  if breed_info.get('Exercise Needs').upper() in ['HIGH', 'VERY HIGH']:
1722
- score *= 0.6
1723
 
1724
- return score
1725
 
1726
  # 評估完美匹配條件
1727
  perfect_conditions = evaluate_perfect_conditions()
@@ -1736,20 +1791,18 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1736
  # 計算基礎分數
1737
  base_score = sum(scores[k] * normalized_weights[k] for k in scores.keys())
1738
 
1739
- # 完美匹配獎勵計算
1740
  perfect_bonus = 1.0
1741
  perfect_bonus += 0.15 * perfect_conditions['size_match']
1742
  perfect_bonus += 0.15 * perfect_conditions['exercise_match']
1743
  perfect_bonus += 0.15 * perfect_conditions['experience_match']
1744
  perfect_bonus += 0.05 * perfect_conditions['living_condition_match']
1745
 
1746
- # 品種特性加成
1747
- breed_bonus = calculate_breed_bonus(breed_info, user_prefs) * 1.2
1748
 
1749
- # 計算最終分數
1750
  final_score = (base_score * 0.8 + breed_bonus * 0.2) * perfect_bonus
1751
-
1752
- # 應用特殊情況調整
1753
  final_score = apply_special_case_adjustments(final_score)
1754
 
1755
  return min(1.0, final_score)
@@ -1757,7 +1810,6 @@ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreference
1757
 
1758
  def amplify_score_extreme(score: float) -> float:
1759
  """
1760
- 改進的分數轉換函數:實現更高的頂部分數
1761
  - 完美匹配可達到95-99%
1762
  - 優秀匹配在90-95%
1763
  - 良好匹配在85-90%
 
1294
 
1295
  return min(0.2, adaptability_score)
1296
 
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,
1311
  # 'experience_match': 0,
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,
 
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:
 
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
  # # 評估完美匹配條件
 
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)
 
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
  'living_condition_match': 0
1568
  }
1569
 
1570
+ # 居住空間與體型匹配評估
1571
+ size_living_evaluation = {
1572
  'apartment': {
1573
  'Small': 1.0,
1574
  'Medium': 0.4,
1575
+ 'Large': 0.2,
1576
+ 'Giant': 0.1
1577
  },
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,
1696
  'experience': 0.20,
1697
  'grooming': 0.15,
1698
+ 'noise': 0.15,
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():
1748
+ final_weights[key] *= adjustment
1749
 
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
 
1781
  # 評估完美匹配條件
1782
  perfect_conditions = evaluate_perfect_conditions()
 
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)
 
1810
 
1811
  def amplify_score_extreme(score: float) -> float:
1812
  """
 
1813
  - 完美匹配可達到95-99%
1814
  - 優秀匹配在90-95%
1815
  - 良好匹配在85-90%