DawnC commited on
Commit
9e5eb14
1 Parent(s): 99a626d

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. scoring_calculation_system.py +724 -239
scoring_calculation_system.py CHANGED
@@ -419,104 +419,370 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
419
  raise KeyError("Size information missing")
420
 
421
 
422
- def calculate_space_score(size: str, living_space: str, has_yard: bool, exercise_needs: str) -> float:
423
- """
424
- 主要改進:
425
- 1. 更均衡的基礎分數分配
426
- 2. 更細緻的空間需求評估
427
- 3. 強化運動需求與空間的關聯性
428
- """
429
- # 重新設計基礎分數矩陣,降低普遍分數以增加區別度
430
- base_scores = {
431
- "Small": {
432
- "apartment": 0.90, # 降低滿分機會
433
- "house_small": 0.85, # 小型犬不應在大空間得到太高分數
434
- "house_large": 0.80 # 避免小型犬總是得到最高分
435
- },
436
- "Medium": {
437
- "apartment": 0.40, # 維持對公寓環境的限制
438
- "house_small": 0.80, # 適中的分數
439
- "house_large": 0.90 # 給予合理的獎勵
440
- },
441
- "Large": {
442
- "apartment": 0.10, # 加重對大型犬在公寓的限制
443
- "house_small": 0.60, # 中等適合度
444
- "house_large": 0.95 # 最適合的環境
445
- },
446
- "Giant": {
447
- "apartment": 0.10, # 更嚴格的限制
448
- "house_small": 0.45, # 顯著的空間限制
449
- "house_large": 0.95 # 最理想的配對
450
- }
451
- }
452
 
453
- # 取得基礎分數
454
- base_score = base_scores.get(size, base_scores["Medium"])[living_space]
455
 
456
- # 運動需求相關的調整更加動態
457
- exercise_adjustments = {
458
- "Very High": {
459
- "apartment": -0.25, # 加重在受限空間的懲罰
460
- "house_small": -0.15,
461
- "house_large": -0.05
462
- },
463
- "High": {
464
- "apartment": -0.20,
465
- "house_small": -0.10,
466
- "house_large": 0
467
- },
468
- "Moderate": {
469
- "apartment": -0.10,
470
- "house_small": -0.05,
471
- "house_large": 0
472
- },
473
- "Low": {
474
- "apartment": 0.05, # 低運動需求在小空間反而有優勢
475
- "house_small": 0,
476
- "house_large": -0.05 # 輕微降低評分,因為空間可能過大
477
- }
478
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
 
480
- # 根據空間類型獲取運動需求調整
481
- adjustment = exercise_adjustments.get(exercise_needs,
482
- exercise_adjustments["Moderate"])[living_space]
 
 
 
483
 
484
- # 院子效益根據品種大小和運動需求動態調整
485
- if has_yard:
486
- yard_bonus = {
487
- "Giant": 0.20,
488
- "Large": 0.15,
489
- "Medium": 0.10,
490
- "Small": 0.05
491
- }.get(size, 0.10)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
 
493
- # 運動需求會影響院子的重要性
494
- if exercise_needs in ["Very High", "High"]:
495
- yard_bonus *= 1.2
496
- elif exercise_needs == "Low":
497
- yard_bonus *= 0.8
 
498
 
499
- current_score = base_score + adjustment + yard_bonus
500
- else:
501
- current_score = base_score + adjustment
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
 
503
- # 確保分數在合理範圍內,但避免極端值
504
- return min(0.95, max(0.15, current_score))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
 
506
 
507
  def calculate_exercise_score(breed_needs: str, exercise_time: int, exercise_type: str) -> float:
508
  """
509
  精確評估品種運動需求與使用者運動條件的匹配度
510
 
511
- Parameters:
512
- breed_needs: 品種的運動需求等級
513
- exercise_time: 使用者能提供的運動時間(分鐘)
514
- exercise_type: 使用者偏好的運動類型
515
-
516
- Returns:
517
- float: -0.2 到 0.2 之間的匹配分數
518
  """
519
- # 定義更細緻的運動需求等級
520
  exercise_levels = {
521
  'VERY HIGH': {
522
  'min': 120,
@@ -524,7 +790,12 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
524
  'max': 180,
525
  'intensity': 'high',
526
  'sessions': 'multiple',
527
- 'preferred_types': ['active_training', 'intensive_exercise']
 
 
 
 
 
528
  },
529
  'HIGH': {
530
  'min': 90,
@@ -532,7 +803,12 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
532
  'max': 150,
533
  'intensity': 'moderate_high',
534
  'sessions': 'multiple',
535
- 'preferred_types': ['active_training', 'moderate_activity']
 
 
 
 
 
536
  },
537
  'MODERATE HIGH': {
538
  'min': 70,
@@ -540,7 +816,12 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
540
  'max': 120,
541
  'intensity': 'moderate',
542
  'sessions': 'flexible',
543
- 'preferred_types': ['moderate_activity', 'active_training']
 
 
 
 
 
544
  },
545
  'MODERATE': {
546
  'min': 45,
@@ -548,7 +829,12 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
548
  'max': 90,
549
  'intensity': 'moderate',
550
  'sessions': 'flexible',
551
- 'preferred_types': ['moderate_activity', 'light_walks']
 
 
 
 
 
552
  },
553
  'MODERATE LOW': {
554
  'min': 30,
@@ -556,7 +842,12 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
556
  'max': 70,
557
  'intensity': 'light_moderate',
558
  'sessions': 'flexible',
559
- 'preferred_types': ['light_walks', 'moderate_activity']
 
 
 
 
 
560
  },
561
  'LOW': {
562
  'min': 15,
@@ -564,37 +855,62 @@ def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences)
564
  'max': 45,
565
  'intensity': 'light',
566
  'sessions': 'single',
567
- 'preferred_types': ['light_walks']
 
 
 
 
 
568
  }
569
  }
570
-
571
- # 獲取品種的運動需求配置
572
  breed_level = exercise_levels.get(breed_needs.upper(), exercise_levels['MODERATE'])
573
 
574
- # 計算時間匹配度(使用更平滑的評分曲線)
575
- if exercise_time >= breed_level['ideal']:
576
- if exercise_time > breed_level['max']:
577
- # 運動時間過長,適度降分
578
- time_score = 0.15 - (0.08 * (exercise_time - breed_level['max']) / 30)
 
 
 
 
 
 
 
579
  else:
580
- time_score = 0.15
581
- elif exercise_time >= breed_level['min']:
582
- # 在最小需求和理想需求之間,線性計算分數
583
- time_ratio = (exercise_time - breed_level['min']) / (breed_level['ideal'] - breed_level['min'])
584
- time_score = 0.05 + (time_ratio * 0.10)
585
- else:
586
- # 運動時間不足,根據差距程度扣分
587
- time_ratio = max(0, exercise_time / breed_level['min'])
588
- time_score = -0.20 * (1 - time_ratio)
589
-
590
  # 運動類型匹配度評估
591
- type_score = 0.0
592
- if exercise_type in breed_level['preferred_types']:
593
- type_score = 0.05
594
- if exercise_type == breed_level['preferred_types'][0]:
595
- type_score = 0.08 # 最佳匹配類型給予更高分數
 
 
 
 
 
 
 
 
 
 
 
 
 
 
596
 
597
- return max(-0.2, min(0.2, time_score + type_score))
 
 
 
 
 
 
598
 
599
 
600
  def calculate_grooming_score(breed_needs: str, user_commitment: str, breed_size: str) -> float:
@@ -1293,166 +1609,335 @@ def calculate_environmental_fit(breed_info: dict, user_prefs: UserPreferences) -
1293
  # return 0.90 + position * 0.08
1294
 
1295
 
1296
- def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1297
- """改進的品種相容性評分系統"""
1298
 
1299
- def evaluate_key_features():
1300
- # 空間適配性評估 - 更極端的調整
1301
- space_multiplier = 1.0
1302
- if user_prefs.living_space == 'apartment':
1303
- if breed_info['Size'] == 'Giant':
1304
- space_multiplier = 0.2 # 更嚴重的懲罰
1305
- elif breed_info['Size'] == 'Large':
1306
- space_multiplier = 0.3
1307
- elif breed_info['Size'] == 'Medium':
1308
- space_multiplier = 0.7
1309
- elif breed_info['Size'] == 'Small':
1310
- space_multiplier = 1.6 # 更大的獎勵
1311
 
1312
- # 運動需求評估 - 更細緻的匹配
1313
- exercise_multiplier = 1.0
1314
- exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1315
 
1316
- # 運動時間差異計算
1317
- time_diff_ratio = abs(user_prefs.exercise_time - get_ideal_exercise_time(exercise_needs)) / 60.0
1318
 
1319
- if exercise_needs == 'VERY HIGH':
1320
- if user_prefs.exercise_time < 90:
1321
- exercise_multiplier = max(0.2, 1.0 - time_diff_ratio)
1322
- elif user_prefs.exercise_time > 150:
1323
- exercise_multiplier = min(2.0, 1.0 + time_diff_ratio/2)
1324
- elif exercise_needs == 'HIGH':
1325
- if user_prefs.exercise_time < 60:
1326
- exercise_multiplier = max(0.3, 1.0 - time_diff_ratio)
1327
- elif user_prefs.exercise_time > 120:
1328
- exercise_multiplier = min(1.8, 1.0 + time_diff_ratio/2)
1329
- elif exercise_needs == 'LOW':
1330
- if user_prefs.exercise_time > 120:
1331
- exercise_multiplier = max(0.4, 1.0 - time_diff_ratio/2)
1332
-
1333
- return space_multiplier, exercise_multiplier
1334
-
1335
- def get_ideal_exercise_time(exercise_needs: str) -> int:
1336
- """獲取理想運動時間"""
1337
- return {
1338
- 'VERY HIGH': 150,
1339
- 'HIGH': 120,
1340
- 'MODERATE HIGH': 90,
1341
- 'MODERATE': 60,
1342
- 'MODERATE LOW': 45,
1343
- 'LOW': 30
1344
- }.get(exercise_needs, 60)
1345
-
1346
- # 經驗匹配度評估 - 更強的影響力
1347
- def evaluate_experience():
1348
- exp_multiplier = 1.0
1349
- care_level = breed_info.get('Care Level', 'MODERATE')
1350
 
1351
- if care_level == 'High':
1352
- if user_prefs.experience_level == 'beginner':
1353
- exp_multiplier = 0.3 # 更嚴重的懲罰
1354
- elif user_prefs.experience_level == 'advanced':
1355
- exp_multiplier = 1.5 # 更大的獎勵
1356
- elif care_level == 'Low':
1357
- if user_prefs.experience_level == 'advanced':
1358
- exp_multiplier = 0.8
1359
 
1360
- return exp_multiplier
1361
-
1362
- # 計算調整係數
1363
- space_mult, exercise_mult = evaluate_key_features()
1364
- exp_mult = evaluate_experience()
1365
-
1366
- # 調整基礎分數
1367
- adjusted_scores = {
1368
- 'space': scores['space'] * space_mult,
1369
- 'exercise': scores['exercise'] * exercise_mult,
1370
- 'experience': scores['experience'] * exp_mult,
1371
- 'grooming': scores['grooming'],
1372
- 'health': scores['health'] * (1.5 if user_prefs.health_sensitivity == 'high' else 1.0),
1373
- 'noise': scores['noise']
1374
- }
1375
 
1376
- # 基礎權重
1377
- weights = {
1378
- 'space': 0.25,
1379
- 'exercise': 0.25,
1380
- 'experience': 0.15,
1381
- 'grooming': 0.15,
1382
- 'health': 0.10,
1383
- 'noise': 0.10
1384
- }
1385
 
1386
- # 動態權重調整 - 更強的條件反應
1387
- if user_prefs.has_children:
1388
- if user_prefs.children_age == 'toddler':
1389
- weights['noise'] *= 2.0 # 更強的噪音影響
1390
- weights['experience'] *= 1.5
1391
- weights['health'] *= 1.3
1392
- elif user_prefs.children_age == 'school_age':
1393
- weights['noise'] *= 1.5
1394
- weights['experience'] *= 1.3
1395
 
1396
- if user_prefs.living_space == 'apartment':
1397
- weights['space'] *= 1.8 # 更強的空間限制
1398
- weights['noise'] *= 1.6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1399
 
1400
- # 運動時間極端情況
1401
- if user_prefs.exercise_time < 30:
1402
- weights['exercise'] *= 2.0
1403
- elif user_prefs.exercise_time > 150:
1404
- weights['exercise'] *= 1.5
1405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1406
  # 正規化權重
1407
  total_weight = sum(weights.values())
1408
  normalized_weights = {k: v/total_weight for k, v in weights.items()}
1409
-
1410
- # 計算基礎分數
1411
- base_score = sum(adjusted_scores[k] * normalized_weights[k] for k in scores.keys())
 
 
 
 
 
1412
 
1413
  # 品種特性加成
1414
  breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1415
 
1416
- # 動態整合係數
1417
- bonus_weight = min(0.25, max(0.15, breed_bonus)) # 讓優秀特性有更大影響
 
 
 
1418
 
1419
  # 完美匹配加成
1420
- if all(score >= 0.8 for score in adjusted_scores.values()):
1421
- base_score *= 1.2
1422
 
1423
- # 極端不匹配懲罰
1424
- if any(score <= 0.3 for score in adjusted_scores.values()):
1425
- base_score *= 0.6
1426
-
1427
- return min(1.0, max(0.0, (base_score * (1.0 - bonus_weight)) + (breed_bonus * bonus_weight)))
 
 
1428
 
1429
 
1430
  def amplify_score_extreme(score: float) -> float:
1431
  """
1432
- 改進的分數轉換函數,提供更動態的分數範圍
1433
-
1434
- 動態轉換邏輯:
1435
- - 極差匹配 (0.0-0.2) -> 45-58%
1436
- - 較差匹配 (0.2-0.4) -> 58-72%
1437
- - 中等匹配 (0.4-0.6) -> 72-85%
1438
- - 良好匹配 (0.6-0.8) -> 85-92%
1439
- - 優秀匹配 (0.8-0.9) -> 92-96%
1440
- - 完美匹配 (0.9-1.0) -> 96-99%
1441
  """
 
 
 
 
 
1442
  if score < 0.2:
1443
- return 0.45 + (score / 0.2) * 0.13
 
 
 
 
 
1444
  elif score < 0.4:
 
 
 
1445
  position = (score - 0.2) / 0.2
1446
- return 0.58 + position * 0.14
 
1447
  elif score < 0.6:
 
 
 
1448
  position = (score - 0.4) / 0.2
1449
- return 0.72 + position * 0.13
 
1450
  elif score < 0.8:
 
 
 
1451
  position = (score - 0.6) / 0.2
1452
- return 0.85 + position * 0.07
 
1453
  elif score < 0.9:
 
 
 
1454
  position = (score - 0.8) / 0.1
1455
- return 0.92 + position * 0.04
 
1456
  else:
 
 
 
1457
  position = (score - 0.9) / 0.1
1458
- return 0.96 + position * 0.03
 
419
  raise KeyError("Size information missing")
420
 
421
 
422
+ # def calculate_space_score(size: str, living_space: str, has_yard: bool, exercise_needs: str) -> float:
423
+ # """
424
+ # 主要改進:
425
+ # 1. 更均衡的基礎分數分配
426
+ # 2. 更細緻的空間需求評估
427
+ # 3. 強化運動需求與空間的關聯性
428
+ # """
429
+ # # 重新設計基礎分數矩陣,降低普遍分數以增加區別度
430
+ # base_scores = {
431
+ # "Small": {
432
+ # "apartment": 0.90, # 降低滿分機會
433
+ # "house_small": 0.85, # 小型犬不應在大空間得到太高分數
434
+ # "house_large": 0.80 # 避免小型犬總是得到最高分
435
+ # },
436
+ # "Medium": {
437
+ # "apartment": 0.40, # 維持對公寓環境的限制
438
+ # "house_small": 0.80, # 適中的分數
439
+ # "house_large": 0.90 # 給予合理的獎勵
440
+ # },
441
+ # "Large": {
442
+ # "apartment": 0.10, # 加重對大型犬在公寓的限制
443
+ # "house_small": 0.60, # 中等適合度
444
+ # "house_large": 0.95 # 最適合的環境
445
+ # },
446
+ # "Giant": {
447
+ # "apartment": 0.10, # 更嚴格的限制
448
+ # "house_small": 0.45, # 顯著的空間限制
449
+ # "house_large": 0.95 # 最理想的配對
450
+ # }
451
+ # }
452
 
453
+ # # 取得基礎分數
454
+ # base_score = base_scores.get(size, base_scores["Medium"])[living_space]
455
 
456
+ # # 運動需求相關的調整更加動態
457
+ # exercise_adjustments = {
458
+ # "Very High": {
459
+ # "apartment": -0.25, # 加重在受限空間的懲罰
460
+ # "house_small": -0.15,
461
+ # "house_large": -0.05
462
+ # },
463
+ # "High": {
464
+ # "apartment": -0.20,
465
+ # "house_small": -0.10,
466
+ # "house_large": 0
467
+ # },
468
+ # "Moderate": {
469
+ # "apartment": -0.10,
470
+ # "house_small": -0.05,
471
+ # "house_large": 0
472
+ # },
473
+ # "Low": {
474
+ # "apartment": 0.05, # 低運動需求在小空間反而有優勢
475
+ # "house_small": 0,
476
+ # "house_large": -0.05 # 輕微降低評分,因為空間可能過大
477
+ # }
478
+ # }
479
+
480
+ # # 根據空間類型獲取運動需求調整
481
+ # adjustment = exercise_adjustments.get(exercise_needs,
482
+ # exercise_adjustments["Moderate"])[living_space]
483
+
484
+ # # 院子效益根據品種大小和運動需求動態調整
485
+ # if has_yard:
486
+ # yard_bonus = {
487
+ # "Giant": 0.20,
488
+ # "Large": 0.15,
489
+ # "Medium": 0.10,
490
+ # "Small": 0.05
491
+ # }.get(size, 0.10)
492
+
493
+ # # 運動需求會影響院子的重要性
494
+ # if exercise_needs in ["Very High", "High"]:
495
+ # yard_bonus *= 1.2
496
+ # elif exercise_needs == "Low":
497
+ # yard_bonus *= 0.8
498
+
499
+ # current_score = base_score + adjustment + yard_bonus
500
+ # else:
501
+ # current_score = base_score + adjustment
502
+
503
+ # # 確保分數在合理範圍內,但避免極端值
504
+ # return min(0.95, max(0.15, current_score))
505
+
506
+
507
+ # def calculate_exercise_score(breed_needs: str, exercise_time: int, exercise_type: str) -> float:
508
+ # """
509
+ # 精確評估品種運動需求與使用者運動條件的匹配度
510
+
511
+ # Parameters:
512
+ # breed_needs: 品種的運動需求等級
513
+ # exercise_time: 使用者能提供的運動時間(分鐘)
514
+ # exercise_type: 使用者偏好的運動類型
515
+
516
+ # Returns:
517
+ # float: -0.2 到 0.2 之間的匹配分數
518
+ # """
519
+ # # 定義更細緻的運動需求等級
520
+ # exercise_levels = {
521
+ # 'VERY HIGH': {
522
+ # 'min': 120,
523
+ # 'ideal': 150,
524
+ # 'max': 180,
525
+ # 'intensity': 'high',
526
+ # 'sessions': 'multiple',
527
+ # 'preferred_types': ['active_training', 'intensive_exercise']
528
+ # },
529
+ # 'HIGH': {
530
+ # 'min': 90,
531
+ # 'ideal': 120,
532
+ # 'max': 150,
533
+ # 'intensity': 'moderate_high',
534
+ # 'sessions': 'multiple',
535
+ # 'preferred_types': ['active_training', 'moderate_activity']
536
+ # },
537
+ # 'MODERATE HIGH': {
538
+ # 'min': 70,
539
+ # 'ideal': 90,
540
+ # 'max': 120,
541
+ # 'intensity': 'moderate',
542
+ # 'sessions': 'flexible',
543
+ # 'preferred_types': ['moderate_activity', 'active_training']
544
+ # },
545
+ # 'MODERATE': {
546
+ # 'min': 45,
547
+ # 'ideal': 60,
548
+ # 'max': 90,
549
+ # 'intensity': 'moderate',
550
+ # 'sessions': 'flexible',
551
+ # 'preferred_types': ['moderate_activity', 'light_walks']
552
+ # },
553
+ # 'MODERATE LOW': {
554
+ # 'min': 30,
555
+ # 'ideal': 45,
556
+ # 'max': 70,
557
+ # 'intensity': 'light_moderate',
558
+ # 'sessions': 'flexible',
559
+ # 'preferred_types': ['light_walks', 'moderate_activity']
560
+ # },
561
+ # 'LOW': {
562
+ # 'min': 15,
563
+ # 'ideal': 30,
564
+ # 'max': 45,
565
+ # 'intensity': 'light',
566
+ # 'sessions': 'single',
567
+ # 'preferred_types': ['light_walks']
568
+ # }
569
+ # }
570
+
571
+ # # 獲取品種的運動需求配置
572
+ # breed_level = exercise_levels.get(breed_needs.upper(), exercise_levels['MODERATE'])
573
+
574
+ # # 計算時間匹配度(使用更平滑的評分曲線)
575
+ # if exercise_time >= breed_level['ideal']:
576
+ # if exercise_time > breed_level['max']:
577
+ # # 運動時間過長,適度降分
578
+ # time_score = 0.15 - (0.08 * (exercise_time - breed_level['max']) / 30)
579
+ # else:
580
+ # time_score = 0.15
581
+ # elif exercise_time >= breed_level['min']:
582
+ # # 在最小需求和理想需求之間,線性計算分數
583
+ # time_ratio = (exercise_time - breed_level['min']) / (breed_level['ideal'] - breed_level['min'])
584
+ # time_score = 0.05 + (time_ratio * 0.10)
585
+ # else:
586
+ # # 運動時間不足,根據差距程度扣分
587
+ # time_ratio = max(0, exercise_time / breed_level['min'])
588
+ # time_score = -0.20 * (1 - time_ratio)
589
 
590
+ # # 運動類型匹配度評估
591
+ # type_score = 0.0
592
+ # if exercise_type in breed_level['preferred_types']:
593
+ # type_score = 0.05
594
+ # if exercise_type == breed_level['preferred_types'][0]:
595
+ # type_score = 0.08 # 最佳匹配類型給予更高分數
596
 
597
+ # return max(-0.2, min(0.2, time_score + type_score))
598
+
599
+
600
+ def calculate_space_score(size: str, living_space: str, has_yard: bool, exercise_needs: str) -> float:
601
+ """
602
+ 改進的空間評分系統,提供更細緻的居住環境評估
603
+
604
+ 改進重點:
605
+ 1. 更動態的基礎分數矩陣
606
+ 2. 強化空間品質評估
607
+ 3. 增加極端情況處理
608
+ 4. 考慮不同空間組合的協同效應
609
+ """
610
+ def get_base_score():
611
+ # 基礎分數矩陣 - 更極端的分數分配
612
+ base_matrix = {
613
+ "Small": {
614
+ "apartment": {
615
+ "no_yard": 0.85, # 小型犬在公寓仍然適合
616
+ "shared_yard": 0.90, # 共享院子提供額外活動空間
617
+ "private_yard": 0.95 # 私人院子最理想
618
+ },
619
+ "house_small": {
620
+ "no_yard": 0.80,
621
+ "shared_yard": 0.85,
622
+ "private_yard": 0.90
623
+ },
624
+ "house_large": {
625
+ "no_yard": 0.75,
626
+ "shared_yard": 0.80,
627
+ "private_yard": 0.85
628
+ }
629
+ },
630
+ "Medium": {
631
+ "apartment": {
632
+ "no_yard": 0.35, # 中型犬在公寓較受限
633
+ "shared_yard": 0.45,
634
+ "private_yard": 0.55
635
+ },
636
+ "house_small": {
637
+ "no_yard": 0.75,
638
+ "shared_yard": 0.85,
639
+ "private_yard": 0.90
640
+ },
641
+ "house_large": {
642
+ "no_yard": 0.85,
643
+ "shared_yard": 0.90,
644
+ "private_yard": 0.95
645
+ }
646
+ },
647
+ "Large": {
648
+ "apartment": {
649
+ "no_yard": 0.15, # 大型犬在公寓極不適合
650
+ "shared_yard": 0.25,
651
+ "private_yard": 0.35
652
+ },
653
+ "house_small": {
654
+ "no_yard": 0.55,
655
+ "shared_yard": 0.65,
656
+ "private_yard": 0.75
657
+ },
658
+ "house_large": {
659
+ "no_yard": 0.85,
660
+ "shared_yard": 0.90,
661
+ "private_yard": 1.0
662
+ }
663
+ },
664
+ "Giant": {
665
+ "apartment": {
666
+ "no_yard": 0.10, # 巨型犬在公寓基本不適合
667
+ "shared_yard": 0.20,
668
+ "private_yard": 0.30
669
+ },
670
+ "house_small": {
671
+ "no_yard": 0.40,
672
+ "shared_yard": 0.50,
673
+ "private_yard": 0.60
674
+ },
675
+ "house_large": {
676
+ "no_yard": 0.80,
677
+ "shared_yard": 0.90,
678
+ "private_yard": 1.0
679
+ }
680
+ }
681
+ }
682
+
683
+ yard_type = "private_yard" if has_yard else "no_yard"
684
+ return base_matrix.get(size, base_matrix["Medium"])[living_space][yard_type]
685
+
686
+ def calculate_exercise_adjustment():
687
+ # 運動需求對空間評分的影響
688
+ exercise_impact = {
689
+ "Very High": {
690
+ "apartment": -0.30, # 高運動需求在公寓環境更受限
691
+ "house_small": -0.15,
692
+ "house_large": -0.05
693
+ },
694
+ "High": {
695
+ "apartment": -0.25,
696
+ "house_small": -0.10,
697
+ "house_large": 0
698
+ },
699
+ "Moderate": {
700
+ "apartment": -0.15,
701
+ "house_small": -0.05,
702
+ "house_large": 0
703
+ },
704
+ "Low": {
705
+ "apartment": 0.10, # 低運動需求反而適合小空間
706
+ "house_small": 0.05,
707
+ "house_large": 0
708
+ }
709
+ }
710
 
711
+ return exercise_impact.get(exercise_needs, exercise_impact["Moderate"])[living_space]
712
+
713
+ def calculate_yard_bonus():
714
+ # 院子效益評估更加細緻
715
+ if not has_yard:
716
+ return 0
717
 
718
+ yard_benefits = {
719
+ "Giant": {
720
+ "Very High": 0.25,
721
+ "High": 0.20,
722
+ "Moderate": 0.15,
723
+ "Low": 0.10
724
+ },
725
+ "Large": {
726
+ "Very High": 0.20,
727
+ "High": 0.15,
728
+ "Moderate": 0.10,
729
+ "Low": 0.05
730
+ },
731
+ "Medium": {
732
+ "Very High": 0.15,
733
+ "High": 0.10,
734
+ "Moderate": 0.08,
735
+ "Low": 0.05
736
+ },
737
+ "Small": {
738
+ "Very High": 0.10,
739
+ "High": 0.08,
740
+ "Moderate": 0.05,
741
+ "Low": 0.03
742
+ }
743
+ }
744
 
745
+ size_benefits = yard_benefits.get(size, yard_benefits["Medium"])
746
+ return size_benefits.get(exercise_needs, size_benefits["Moderate"])
747
+
748
+ def apply_extreme_case_adjustments(score):
749
+ # 處理極端情況
750
+ if size == "Giant" and living_space == "apartment":
751
+ return score * 0.5 # 巨型犬在公寓給予更嚴重的懲罰
752
+
753
+ if size == "Large" and living_space == "apartment" and exercise_needs == "Very High":
754
+ return score * 0.6 # 高運動需求的大型犬在公寓更不適合
755
+
756
+ if size == "Small" and living_space == "house_large" and exercise_needs == "Low":
757
+ return score * 0.9 # 低運動需求的小型犬在大房子可能過於寬敞
758
+
759
+ return score
760
+
761
+ # 計算最終分數
762
+ base_score = get_base_score()
763
+ exercise_adj = calculate_exercise_adjustment()
764
+ yard_bonus = calculate_yard_bonus()
765
+
766
+ # 整合所有評分因素
767
+ initial_score = base_score + exercise_adj + yard_bonus
768
+
769
+ # 應用極端情況調整
770
+ final_score = apply_extreme_case_adjustments(initial_score)
771
+
772
+ # 確保分數在有效範圍內,但允許更極端的結果
773
+ return max(0.05, min(1.0, final_score))
774
 
775
 
776
  def calculate_exercise_score(breed_needs: str, exercise_time: int, exercise_type: str) -> float:
777
  """
778
  精確評估品種運動需求與使用者運動條件的匹配度
779
 
780
+ 改進重點:
781
+ 1. 擴大分數範圍到 0.1-1.0
782
+ 2. 加強運動類型影響
783
+ 3. 考慮運動強度與時間的綜合效果
784
+ 4. 更細緻的時間匹配評估
 
 
785
  """
 
786
  exercise_levels = {
787
  'VERY HIGH': {
788
  'min': 120,
 
790
  'max': 180,
791
  'intensity': 'high',
792
  'sessions': 'multiple',
793
+ 'preferred_types': ['active_training', 'intensive_exercise'],
794
+ 'type_weights': {
795
+ 'active_training': 1.0,
796
+ 'moderate_activity': 0.6,
797
+ 'light_walks': 0.3
798
+ }
799
  },
800
  'HIGH': {
801
  'min': 90,
 
803
  'max': 150,
804
  'intensity': 'moderate_high',
805
  'sessions': 'multiple',
806
+ 'preferred_types': ['active_training', 'moderate_activity'],
807
+ 'type_weights': {
808
+ 'active_training': 0.9,
809
+ 'moderate_activity': 0.8,
810
+ 'light_walks': 0.4
811
+ }
812
  },
813
  'MODERATE HIGH': {
814
  'min': 70,
 
816
  'max': 120,
817
  'intensity': 'moderate',
818
  'sessions': 'flexible',
819
+ 'preferred_types': ['moderate_activity', 'active_training'],
820
+ 'type_weights': {
821
+ 'active_training': 0.8,
822
+ 'moderate_activity': 0.9,
823
+ 'light_walks': 0.5
824
+ }
825
  },
826
  'MODERATE': {
827
  'min': 45,
 
829
  'max': 90,
830
  'intensity': 'moderate',
831
  'sessions': 'flexible',
832
+ 'preferred_types': ['moderate_activity', 'light_walks'],
833
+ 'type_weights': {
834
+ 'active_training': 0.7,
835
+ 'moderate_activity': 1.0,
836
+ 'light_walks': 0.8
837
+ }
838
  },
839
  'MODERATE LOW': {
840
  'min': 30,
 
842
  'max': 70,
843
  'intensity': 'light_moderate',
844
  'sessions': 'flexible',
845
+ 'preferred_types': ['light_walks', 'moderate_activity'],
846
+ 'type_weights': {
847
+ 'active_training': 0.6,
848
+ 'moderate_activity': 0.9,
849
+ 'light_walks': 1.0
850
+ }
851
  },
852
  'LOW': {
853
  'min': 15,
 
855
  'max': 45,
856
  'intensity': 'light',
857
  'sessions': 'single',
858
+ 'preferred_types': ['light_walks'],
859
+ 'type_weights': {
860
+ 'active_training': 0.5,
861
+ 'moderate_activity': 0.8,
862
+ 'light_walks': 1.0
863
+ }
864
  }
865
  }
866
+
 
867
  breed_level = exercise_levels.get(breed_needs.upper(), exercise_levels['MODERATE'])
868
 
869
+ # 時間匹配度評估(基礎分數)
870
+ def calculate_time_score():
871
+ if exercise_time >= breed_level['ideal']:
872
+ if exercise_time > breed_level['max']:
873
+ # 超出最大值的懲罰更明顯
874
+ excess = (exercise_time - breed_level['max']) / 30
875
+ return max(0.4, 1.0 - (excess * 0.2))
876
+ return 1.0 # 理想範圍內給予滿分
877
+ elif exercise_time >= breed_level['min']:
878
+ # 在最小值和理想值之間使用更陡峭的曲線
879
+ progress = (exercise_time - breed_level['min']) / (breed_level['ideal'] - breed_level['min'])
880
+ return 0.5 + (progress * 0.5)
881
  else:
882
+ # 低於最小值時給予更嚴厲的懲罰
883
+ deficit_ratio = exercise_time / breed_level['min']
884
+ return max(0.1, deficit_ratio * 0.5)
885
+
 
 
 
 
 
 
886
  # 運動類型匹配度評估
887
+ def calculate_type_score():
888
+ type_weight = breed_level['type_weights'].get(exercise_type, 0.5)
889
+
890
+ # 根據運動需求等級調整類型權重
891
+ if breed_needs.upper() in ['VERY HIGH', 'HIGH']:
892
+ if exercise_type == 'light_walks':
893
+ type_weight *= 0.5 # 高需求品種做輕度運動的懲罰
894
+ elif breed_needs.upper() == 'LOW':
895
+ if exercise_type == 'active_training':
896
+ type_weight *= 0.7 # 低需求品種做高強度運動的輕微懲罰
897
+
898
+ return type_weight
899
+
900
+ # 計算最終分數
901
+ time_score = calculate_time_score()
902
+ type_score = calculate_type_score()
903
+
904
+ # 綜合評分,運動時間佔70%,類型佔30%
905
+ final_score = (time_score * 0.7) + (type_score * 0.3)
906
 
907
+ # 特殊情況調整
908
+ if exercise_time < breed_level['min'] * 0.5: # 運動時間嚴重不足
909
+ final_score *= 0.5
910
+ elif exercise_time > breed_level['max'] * 1.5: # 運動時間過多
911
+ final_score *= 0.7
912
+
913
+ return max(0.1, min(1.0, final_score))
914
 
915
 
916
  def calculate_grooming_score(breed_needs: str, user_commitment: str, breed_size: str) -> float:
 
1609
  # return 0.90 + position * 0.08
1610
 
1611
 
1612
+ # def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1613
+ # """改進的品種相容性評分系統"""
1614
 
1615
+ # def evaluate_key_features():
1616
+ # # 空間適配性評估 - 更極端的調整
1617
+ # space_multiplier = 1.0
1618
+ # if user_prefs.living_space == 'apartment':
1619
+ # if breed_info['Size'] == 'Giant':
1620
+ # space_multiplier = 0.2 # 更嚴重的懲罰
1621
+ # elif breed_info['Size'] == 'Large':
1622
+ # space_multiplier = 0.3
1623
+ # elif breed_info['Size'] == 'Medium':
1624
+ # space_multiplier = 0.7
1625
+ # elif breed_info['Size'] == 'Small':
1626
+ # space_multiplier = 1.6 # 更大的獎勵
1627
 
1628
+ # # 運動需求評估 - 更細緻的匹配
1629
+ # exercise_multiplier = 1.0
1630
+ # exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1631
 
1632
+ # # 運動時間差異計算
1633
+ # time_diff_ratio = abs(user_prefs.exercise_time - get_ideal_exercise_time(exercise_needs)) / 60.0
1634
 
1635
+ # if exercise_needs == 'VERY HIGH':
1636
+ # if user_prefs.exercise_time < 90:
1637
+ # exercise_multiplier = max(0.2, 1.0 - time_diff_ratio)
1638
+ # elif user_prefs.exercise_time > 150:
1639
+ # exercise_multiplier = min(2.0, 1.0 + time_diff_ratio/2)
1640
+ # elif exercise_needs == 'HIGH':
1641
+ # if user_prefs.exercise_time < 60:
1642
+ # exercise_multiplier = max(0.3, 1.0 - time_diff_ratio)
1643
+ # elif user_prefs.exercise_time > 120:
1644
+ # exercise_multiplier = min(1.8, 1.0 + time_diff_ratio/2)
1645
+ # elif exercise_needs == 'LOW':
1646
+ # if user_prefs.exercise_time > 120:
1647
+ # exercise_multiplier = max(0.4, 1.0 - time_diff_ratio/2)
1648
+
1649
+ # return space_multiplier, exercise_multiplier
1650
+
1651
+ # def get_ideal_exercise_time(exercise_needs: str) -> int:
1652
+ # """獲取理想運動時間"""
1653
+ # return {
1654
+ # 'VERY HIGH': 150,
1655
+ # 'HIGH': 120,
1656
+ # 'MODERATE HIGH': 90,
1657
+ # 'MODERATE': 60,
1658
+ # 'MODERATE LOW': 45,
1659
+ # 'LOW': 30
1660
+ # }.get(exercise_needs, 60)
1661
+
1662
+ # # 經驗匹配度評估 - 更強的影響力
1663
+ # def evaluate_experience():
1664
+ # exp_multiplier = 1.0
1665
+ # care_level = breed_info.get('Care Level', 'MODERATE')
1666
 
1667
+ # if care_level == 'High':
1668
+ # if user_prefs.experience_level == 'beginner':
1669
+ # exp_multiplier = 0.3 # 更嚴重的懲罰
1670
+ # elif user_prefs.experience_level == 'advanced':
1671
+ # exp_multiplier = 1.5 # 更大的獎勵
1672
+ # elif care_level == 'Low':
1673
+ # if user_prefs.experience_level == 'advanced':
1674
+ # exp_multiplier = 0.8
1675
 
1676
+ # return exp_multiplier
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1677
 
1678
+ # # 計算調整係數
1679
+ # space_mult, exercise_mult = evaluate_key_features()
1680
+ # exp_mult = evaluate_experience()
 
 
 
 
 
 
1681
 
1682
+ # # 調整基礎分數
1683
+ # adjusted_scores = {
1684
+ # 'space': scores['space'] * space_mult,
1685
+ # 'exercise': scores['exercise'] * exercise_mult,
1686
+ # 'experience': scores['experience'] * exp_mult,
1687
+ # 'grooming': scores['grooming'],
1688
+ # 'health': scores['health'] * (1.5 if user_prefs.health_sensitivity == 'high' else 1.0),
1689
+ # 'noise': scores['noise']
1690
+ # }
1691
 
1692
+ # # 基礎權重
1693
+ # weights = {
1694
+ # 'space': 0.25,
1695
+ # 'exercise': 0.25,
1696
+ # 'experience': 0.15,
1697
+ # 'grooming': 0.15,
1698
+ # 'health': 0.10,
1699
+ # 'noise': 0.10
1700
+ # }
1701
+
1702
+ # # 動態權重調整 - 更強的條件反應
1703
+ # if user_prefs.has_children:
1704
+ # if user_prefs.children_age == 'toddler':
1705
+ # weights['noise'] *= 2.0 # 更強的噪音影響
1706
+ # weights['experience'] *= 1.5
1707
+ # weights['health'] *= 1.3
1708
+ # elif user_prefs.children_age == 'school_age':
1709
+ # weights['noise'] *= 1.5
1710
+ # weights['experience'] *= 1.3
1711
+
1712
+ # if user_prefs.living_space == 'apartment':
1713
+ # weights['space'] *= 1.8 # 更強的空間限制
1714
+ # weights['noise'] *= 1.6
1715
+
1716
+ # # 運動時間極端情況
1717
+ # if user_prefs.exercise_time < 30:
1718
+ # weights['exercise'] *= 2.0
1719
+ # elif user_prefs.exercise_time > 150:
1720
+ # weights['exercise'] *= 1.5
1721
+
1722
+ # # 正規化權重
1723
+ # total_weight = sum(weights.values())
1724
+ # normalized_weights = {k: v/total_weight for k, v in weights.items()}
1725
+
1726
+ # # 計算基礎分數
1727
+ # base_score = sum(adjusted_scores[k] * normalized_weights[k] for k in scores.keys())
1728
+
1729
+ # # 品種特性加成
1730
+ # breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1731
+
1732
+ # # 動態整合係數
1733
+ # bonus_weight = min(0.25, max(0.15, breed_bonus)) # 讓優秀特性有更大影響
1734
+
1735
+ # # 完美匹配加成
1736
+ # if all(score >= 0.8 for score in adjusted_scores.values()):
1737
+ # base_score *= 1.2
1738
+
1739
+ # # 極端不匹配懲罰
1740
+ # if any(score <= 0.3 for score in adjusted_scores.values()):
1741
+ # base_score *= 0.6
1742
+
1743
+ # return min(1.0, max(0.0, (base_score * (1.0 - bonus_weight)) + (breed_bonus * bonus_weight)))
1744
 
 
 
 
 
 
1745
 
1746
+ # def amplify_score_extreme(score: float) -> float:
1747
+ # """
1748
+ # 改進的分數轉換函數,提供更動態的分數範圍
1749
+
1750
+ # 動態轉換邏輯:
1751
+ # - 極差匹配 (0.0-0.2) -> 45-58%
1752
+ # - 較差匹配 (0.2-0.4) -> 58-72%
1753
+ # - 中等匹配 (0.4-0.6) -> 72-85%
1754
+ # - 良好匹配 (0.6-0.8) -> 85-92%
1755
+ # - 優秀匹配 (0.8-0.9) -> 92-96%
1756
+ # - 完美匹配 (0.9-1.0) -> 96-99%
1757
+ # """
1758
+ # if score < 0.2:
1759
+ # return 0.45 + (score / 0.2) * 0.13
1760
+ # elif score < 0.4:
1761
+ # position = (score - 0.2) / 0.2
1762
+ # return 0.58 + position * 0.14
1763
+ # elif score < 0.6:
1764
+ # position = (score - 0.4) / 0.2
1765
+ # return 0.72 + position * 0.13
1766
+ # elif score < 0.8:
1767
+ # position = (score - 0.6) / 0.2
1768
+ # return 0.85 + position * 0.07
1769
+ # elif score < 0.9:
1770
+ # position = (score - 0.8) / 0.1
1771
+ # return 0.92 + position * 0.04
1772
+ # else:
1773
+ # position = (score - 0.9) / 0.1
1774
+ # return 0.96 + position * 0.03
1775
+
1776
+
1777
+ def calculate_breed_compatibility_score(scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
1778
+ """
1779
+ 改進的品種相容性評分系統,提供更動態和精確的評分
1780
+
1781
+ 主要改進:
1782
+ 1. 更動態的權重系統
1783
+ 2. 更強的極端情況處理
1784
+ 3. 更精確的品種特性評估
1785
+ """
1786
+ def evaluate_condition_extremity():
1787
+ """評估使用者條件的極端程度"""
1788
+ extremity_count = 0
1789
+
1790
+ # 空間條件極端性
1791
+ if user_prefs.living_space == 'apartment' and breed_info['Size'] in ['Large', 'Giant']:
1792
+ extremity_count += 2
1793
+ elif user_prefs.living_space == 'house_large' and breed_info['Size'] == 'Small':
1794
+ extremity_count += 1
1795
+
1796
+ # 運動需求極端性
1797
+ exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
1798
+ if exercise_needs == 'VERY HIGH' and user_prefs.exercise_time < 60:
1799
+ extremity_count += 2
1800
+ elif exercise_needs == 'LOW' and user_prefs.exercise_time > 150:
1801
+ extremity_count += 1
1802
+
1803
+ # 經驗等級極端性
1804
+ care_level = breed_info.get('Care Level', 'MODERATE')
1805
+ if care_level == 'High' and user_prefs.experience_level == 'beginner':
1806
+ extremity_count += 2
1807
+
1808
+ return extremity_count
1809
+
1810
+ def calculate_dynamic_weights():
1811
+ """計算動態權重"""
1812
+ # 基礎權重
1813
+ weights = {
1814
+ 'space': 0.20,
1815
+ 'exercise': 0.20,
1816
+ 'experience': 0.15,
1817
+ 'grooming': 0.15,
1818
+ 'health': 0.15,
1819
+ 'noise': 0.15
1820
+ }
1821
+
1822
+ # 根據生活環境調整權重
1823
+ if user_prefs.living_space == 'apartment':
1824
+ weights['space'] *= 2.0
1825
+ weights['noise'] *= 1.8
1826
+
1827
+ # 根據家庭情況調整
1828
+ if user_prefs.has_children:
1829
+ if user_prefs.children_age == 'toddler':
1830
+ weights['noise'] *= 2.0
1831
+ weights['experience'] *= 1.8
1832
+ weights['health'] *= 1.5
1833
+ elif user_prefs.children_age == 'school_age':
1834
+ weights['noise'] *= 1.5
1835
+ weights['experience'] *= 1.3
1836
+
1837
+ # 根據運動時間調整
1838
+ if user_prefs.exercise_time < 30:
1839
+ weights['exercise'] *= 2.5
1840
+ elif user_prefs.exercise_time > 150:
1841
+ weights['exercise'] *= 2.0
1842
+
1843
+ # 根據健康敏感度調整
1844
+ if user_prefs.health_sensitivity == 'high':
1845
+ weights['health'] *= 1.8
1846
+
1847
+ return weights
1848
+
1849
+ # 計算條件極端程度
1850
+ extremity_level = evaluate_condition_extremity()
1851
+
1852
+ # 計算動態權重
1853
+ weights = calculate_dynamic_weights()
1854
+
1855
  # 正規化權重
1856
  total_weight = sum(weights.values())
1857
  normalized_weights = {k: v/total_weight for k, v in weights.items()}
1858
+
1859
+ # 計算加權分數
1860
+ weighted_scores = {
1861
+ k: scores[k] * normalized_weights[k] for k in scores.keys()
1862
+ }
1863
+
1864
+ # 基礎分數
1865
+ base_score = sum(weighted_scores.values())
1866
 
1867
  # 品種特性加成
1868
  breed_bonus = calculate_breed_bonus(breed_info, user_prefs)
1869
 
1870
+ # 根據極端程度調整最終分數
1871
+ if extremity_level >= 3:
1872
+ base_score *= 0.6 # 多個極端條件的嚴重懲罰
1873
+ elif extremity_level >= 2:
1874
+ base_score *= 0.8 # 較少極端條件的適度懲罰
1875
 
1876
  # 完美匹配加成
1877
+ if all(score >= 0.8 for score in scores.values()):
1878
+ base_score *= 1.3
1879
 
1880
+ # 品種特性影響力隨匹配度增加
1881
+ bonus_weight = min(0.35, max(0.15, breed_bonus))
1882
+
1883
+ # 最終分數計算
1884
+ final_score = (base_score * (1.0 - bonus_weight)) + (breed_bonus * bonus_weight)
1885
+
1886
+ return min(1.0, max(0.0, final_score))
1887
 
1888
 
1889
  def amplify_score_extreme(score: float) -> float:
1890
  """
1891
+ 改進的分數轉換函數,提供更合理的分數分布
1892
+
1893
+ 特點:
1894
+ 1. 更大的分數範圍
1895
+ 2. 更平滑的轉換曲線
1896
+ 3. 更準確的極端情況處理
 
 
 
1897
  """
1898
+ def sigmoid_transform(x: float, steepness: float = 10) -> float:
1899
+ """使用 sigmoid 函數實現更平滑的轉換"""
1900
+ import math
1901
+ return 1 / (1 + math.exp(-steepness * (x - 0.5)))
1902
+
1903
  if score < 0.2:
1904
+ # 極差匹配:使用更低的起始分數
1905
+ base = 0.40
1906
+ range_score = 0.15
1907
+ position = score / 0.2
1908
+ return base + (sigmoid_transform(position) * range_score)
1909
+
1910
  elif score < 0.4:
1911
+ # 較差匹配:緩慢增長
1912
+ base = 0.55
1913
+ range_score = 0.15
1914
  position = (score - 0.2) / 0.2
1915
+ return base + (sigmoid_transform(position) * range_score)
1916
+
1917
  elif score < 0.6:
1918
+ # 中等匹配:較大增長
1919
+ base = 0.70
1920
+ range_score = 0.15
1921
  position = (score - 0.4) / 0.2
1922
+ return base + (sigmoid_transform(position) * range_score)
1923
+
1924
  elif score < 0.8:
1925
+ # 良好匹配:快速增長
1926
+ base = 0.85
1927
+ range_score = 0.10
1928
  position = (score - 0.6) / 0.2
1929
+ return base + (sigmoid_transform(position) * range_score)
1930
+
1931
  elif score < 0.9:
1932
+ # 優秀匹配:接近最高分
1933
+ base = 0.95
1934
+ range_score = 0.03
1935
  position = (score - 0.8) / 0.1
1936
+ return base + (sigmoid_transform(position) * range_score)
1937
+
1938
  else:
1939
+ # 完美匹配:可能達到最高分
1940
+ base = 0.98
1941
+ range_score = 0.02
1942
  position = (score - 0.9) / 0.1
1943
+ return base + (sigmoid_transform(position) * range_score)