PawMatchAI / score_integration_manager.py
DawnC's picture
Update score_integration_manager.py
7466dd7 verified
import math
import traceback
from typing import Dict, Any, List
from dataclasses import dataclass
@dataclass
class UserPreferences:
"""使用者偏好設定的資料結構"""
living_space: str # "apartment", "house_small", "house_large"
yard_access: str # "no_yard", "shared_yard", "private_yard"
exercise_time: int # minutes per day
exercise_type: str # "light_walks", "moderate_activity", "active_training"
grooming_commitment: str # "low", "medium", "high"
experience_level: str # "beginner", "intermediate", "advanced"
time_availability: str # "limited", "moderate", "flexible"
has_children: bool
children_age: str # "toddler", "school_age", "teenager"
noise_tolerance: str # "low", "medium", "high"
space_for_play: bool
other_pets: bool
climate: str # "cold", "moderate", "hot"
health_sensitivity: str = "medium"
barking_acceptance: str = None
size_preference: str = "no_preference" # "no_preference", "small", "medium", "large", "giant"
training_commitment: str = "medium" # "low", "medium", "high" - 訓練投入程度
living_environment: str = "ground_floor" # "ground_floor", "with_elevator", "walk_up" - 居住環境細節
def __post_init__(self):
if self.barking_acceptance is None:
self.barking_acceptance = self.noise_tolerance
class ScoreIntegrationManager:
"""
評分整合管理器類別
負責動態權重計算、評分整合和條件互動評估
"""
def __init__(self):
"""初始化評分整合管理器"""
pass
def apply_size_filter(self, breed_score: float, user_preference: str, breed_size: str) -> float:
"""
強過濾機制,基於用戶的體型偏好過濾品種
Parameters:
breed_score (float): 原始品種評分
user_preference (str): 用戶偏好的體型
breed_size (str): 品種的實際體型
Returns:
float: 過濾後的評分,如果體型不符合會返回 0
"""
if user_preference == "no_preference":
return breed_score
# 標準化 size 字串以進行比較
breed_size = breed_size.lower().strip()
user_preference = user_preference.lower().strip()
# 特殊處理 "varies" 的情況
if breed_size == "varies":
return breed_score * 0.5 # 給予一個折扣係數,因為不確定性
# 如果用戶有明確體型偏好但品種不符合,返回 0
if user_preference != breed_size:
return 0
return breed_score
def calculate_breed_compatibility_score(self, scores: dict, user_prefs: UserPreferences, breed_info: dict) -> float:
"""
計算品種相容性總分,完整實現原始版本的複雜邏輯:
1. 運動類型與時間的精確匹配
2. 進階使用者的專業需求
3. 空間利用的實際效果
4. 條件組合的嚴格評估
"""
def evaluate_perfect_conditions():
"""
評估條件匹配度,特別強化:
1. 運動類型與時間的綜合評估
2. 專業技能需求評估
3. 品種特性評估
"""
perfect_matches = {
'size_match': 0,
'exercise_match': 0,
'experience_match': 0,
'living_condition_match': 0,
'breed_trait_match': 0 # 新增品種特性匹配度
}
# 第一部分:運動需求評估
def evaluate_exercise_compatibility():
"""
評估運動需求的匹配度,特別關注:
1. 時間與強度的合理搭配
2. 不同品種的運動特性
3. 運動類型的適配性
這個函數就像是一個體育教練,需要根據每個"運動員"(狗品種)的特點,
為他們制定合適的訓練計劃。
"""
exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
exercise_time = user_prefs.exercise_time
exercise_type = user_prefs.exercise_type
temperament = breed_info.get('Temperament', '').lower()
description = breed_info.get('Description', '').lower()
# 定義更精確的品種運動特性
breed_exercise_patterns = {
'sprint_type': { # 短跑型犬種,如 Whippet, Saluki
'identifiers': ['fast', 'speed', 'sprint', 'racing', 'coursing', 'sight hound'],
'ideal_exercise': {
'active_training': 1.0, # 完美匹配高強度訓練
'moderate_activity': 0.5, # 持續運動不是最佳選擇
'light_walks': 0.3 # 輕度運動效果很差
},
'time_ranges': {
'ideal': (30, 60), # 最適合的運動時間範圍
'acceptable': (20, 90), # 可以接受的時間範圍
'penalty_start': 90 # 開始給予懲罰的時間點
},
'penalty_rate': 0.8 # 超出範圍時的懲罰係數
},
'endurance_type': { # 耐力型犬種,如 Border Collie
'identifiers': ['herding', 'working', 'tireless', 'energetic', 'stamina', 'athletic'],
'ideal_exercise': {
'active_training': 0.9, # 高強度訓練很好
'moderate_activity': 1.0, # 持續運動是最佳選擇
'light_walks': 0.4 # 輕度運動不足
},
'time_ranges': {
'ideal': (90, 180), # 需要較長的運動時間
'acceptable': (60, 180),
'penalty_start': 60 # 運動時間過短會受罰
},
'penalty_rate': 0.7
},
'moderate_type': { # 一般活動型犬種,如 Labrador
'identifiers': ['friendly', 'playful', 'adaptable', 'versatile', 'companion'],
'ideal_exercise': {
'active_training': 0.8,
'moderate_activity': 1.0,
'light_walks': 0.6
},
'time_ranges': {
'ideal': (60, 120),
'acceptable': (45, 150),
'penalty_start': 150
},
'penalty_rate': 0.6
}
}
def determine_breed_type():
"""改進品種運動類型的判斷,更精確識別工作犬"""
# 優先檢查特殊運動類型的標識符
for breed_type, pattern in breed_exercise_patterns.items():
if any(identifier in temperament or identifier in description
for identifier in pattern['identifiers']):
return breed_type
# 改進:根據運動需求和工作犬特徵進行更細緻的判斷
if (exercise_needs in ['VERY HIGH', 'HIGH'] or
any(trait in temperament.lower() for trait in
['herding', 'working', 'intelligent', 'athletic', 'tireless'])):
if user_prefs.experience_level == 'advanced':
return 'endurance_type' # 優先判定為耐力型
elif exercise_needs == 'LOW':
return 'moderate_type'
return 'moderate_type'
def calculate_time_match(pattern):
"""
計算運動時間的匹配度。
這就像在判斷運動時間是否符合訓練計劃。
"""
ideal_min, ideal_max = pattern['time_ranges']['ideal']
accept_min, accept_max = pattern['time_ranges']['acceptable']
penalty_start = pattern['time_ranges']['penalty_start']
# 在理想範圍內
if ideal_min <= exercise_time <= ideal_max:
return 1.0
# 超出可接受範圍的嚴格懲罰
elif exercise_time < accept_min:
deficit = accept_min - exercise_time
return max(0.2, 1 - (deficit / accept_min) * 1.2)
elif exercise_time > accept_max:
excess = exercise_time - penalty_start
penalty = min(0.8, (excess / penalty_start) * pattern['penalty_rate'])
return max(0.2, 1 - penalty)
# 在可接受範圍但不在理想範圍
else:
if exercise_time < ideal_min:
progress = (exercise_time - accept_min) / (ideal_min - accept_min)
return 0.6 + (0.4 * progress)
else:
remaining = (accept_max - exercise_time) / (accept_max - ideal_max)
return 0.6 + (0.4 * remaining)
def apply_special_adjustments(time_score, type_score, breed_type, pattern):
"""
處理特殊情況,確保運動方式真正符合品種需求。
特別加強:
1. 短跑型犬種的長時間運動懲罰
2. 耐力型犬種的獎勵機制
3. 運動類型匹配的重要性
"""
# 短跑型品種的特殊處理
if breed_type == 'sprint_type':
if exercise_time > pattern['time_ranges']['penalty_start']:
# 加重長時間運動的懲罰
penalty_factor = min(0.8, (exercise_time - pattern['time_ranges']['penalty_start']) / 60)
time_score *= max(0.3, 1 - penalty_factor) # 最低降到0.3
# 運動類型不適合時的額外懲罰
if exercise_type != 'active_training':
type_score *= 0.3 # 更嚴重的懲罰
# 耐力型品種的特殊處理
elif breed_type == 'endurance_type':
if exercise_time < pattern['time_ranges']['penalty_start']:
time_score *= 0.5 # 維持運動不足的懲罰
elif exercise_time >= 150: # 新增:高運動量獎勵
if exercise_type in ['active_training', 'moderate_activity']:
time_bonus = min(0.3, (exercise_time - 150) / 150)
time_score = min(1.0, time_score * (1 + time_bonus))
type_score = min(1.0, type_score * 1.2)
# 運動強度不足的懲罰
if exercise_type == 'light_walks':
if exercise_time > 90:
type_score *= 0.4 # 加重懲罰
else:
type_score *= 0.5
return time_score, type_score
# 執行評估流程
breed_type = determine_breed_type()
pattern = breed_exercise_patterns[breed_type]
# 計算基礎分數
time_score = calculate_time_match(pattern)
type_score = pattern['ideal_exercise'].get(exercise_type, 0.5)
# 應用特殊調整
time_score, type_score = apply_special_adjustments(time_score, type_score, breed_type, pattern)
# 根據品種類型決定最終權重
if breed_type == 'sprint_type':
if exercise_time > pattern['time_ranges']['penalty_start']:
# 超時時更重視運動類型的匹配度
return (time_score * 0.3) + (type_score * 0.7)
else:
return (time_score * 0.5) + (type_score * 0.5)
elif breed_type == 'endurance_type':
if exercise_time < pattern['time_ranges']['penalty_start']:
# 時間不足時更重視時間因素
return (time_score * 0.7) + (type_score * 0.3)
else:
return (time_score * 0.6) + (type_score * 0.4)
else:
return (time_score * 0.5) + (type_score * 0.5)
# 第二部分:專業技能需求評估
def evaluate_expertise_requirements():
care_level = breed_info.get('Care Level', 'MODERATE').upper()
temperament = breed_info.get('Temperament', '').lower()
# 定義專業技能要求
expertise_requirements = {
'training_complexity': {
'VERY HIGH': {'beginner': 0.2, 'intermediate': 0.5, 'advanced': 0.9},
'HIGH': {'beginner': 0.3, 'intermediate': 0.7, 'advanced': 1.0},
'MODERATE': {'beginner': 0.6, 'intermediate': 0.9, 'advanced': 1.0},
'LOW': {'beginner': 0.9, 'intermediate': 0.95, 'advanced': 0.9}
},
'special_traits': {
'working': 0.2, # 工作犬需要額外技能
'herding': 0.2, # 牧羊犬需要特殊訓練
'intelligent': 0.15,# 高智商犬種需要心智刺激
'independent': 0.15,# 獨立性強的需要特殊處理
'protective': 0.1 # 護衛犬需要適當訓練
}
}
# 基礎分數
base_score = expertise_requirements['training_complexity'][care_level][user_prefs.experience_level]
# 特殊特徵評估
trait_penalty = 0
for trait, penalty in expertise_requirements['special_traits'].items():
if trait in temperament:
if user_prefs.experience_level == 'beginner':
trait_penalty += penalty
elif user_prefs.experience_level == 'advanced':
trait_penalty -= penalty * 0.5 # 專家反而因應對特殊特徵而加分
return max(0.2, min(1.0, base_score - trait_penalty))
def evaluate_living_conditions() -> float:
"""
評估生活環境適配性,特別加強:
1. 降低對大型犬的過度懲罰
2. 增加品種特性評估
3. 提升對適應性的重視度
"""
size = breed_info['Size']
exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
temperament = breed_info.get('Temperament', '').lower()
description = breed_info.get('Description', '').lower()
# 降低對大型犬的懲罰
space_requirements = {
'apartment': {
'Small': 1.0,
'Medium': 0.8,
'Large': 0.7,
'Giant': 0.6,
'Varies': 0.8
},
'house_small': {
'Small': 0.9,
'Medium': 1.0,
'Large': 0.8,
'Giant': 0.7,
'Varies': 1.0
},
'house_large': {
'Small': 0.8,
'Medium': 0.9,
'Large': 1.0,
'Giant': 1.0,
'Varies': 0.9
}
}
# 基礎空間分數
space_score = space_requirements.get(
user_prefs.living_space,
space_requirements['house_small']
)[size]
# 品種適應性評估
adaptability_bonus = 0
adaptable_traits = ['adaptable', 'calm', 'quiet', 'gentle', 'laid-back']
challenging_traits = ['hyperactive', 'restless', 'requires space']
# 計算適應性加分
if user_prefs.living_space == 'apartment':
for trait in adaptable_traits:
if trait in temperament or trait in description:
adaptability_bonus += 0.1
# 特別處理大型犬的適應性
if size in ['Large', 'Giant']:
apartment_friendly_traits = ['calm', 'gentle', 'quiet']
matched_traits = sum(1 for trait in apartment_friendly_traits
if trait in temperament or trait in description)
if matched_traits > 0:
adaptability_bonus += 0.15 * matched_traits
# 活動空間需求調整,更寬容的評估
if exercise_needs in ['HIGH', 'VERY HIGH']:
if user_prefs.living_space != 'house_large':
space_score *= 0.9 # 從0.8提升到0.9,降低懲罰
# 院子可用性評估,提供更合理的獎勵
yard_scores = {
'no_yard': 0.85, # 從0.7提升到0.85
'shared_yard': 0.92, # 從0.85提升到0.92
'private_yard': 1.0
}
yard_multiplier = yard_scores.get(user_prefs.yard_access, 0.85)
# 根據體型調整院子重要性
if size in ['Large', 'Giant']:
yard_importance = 1.2
elif size == 'Medium':
yard_importance = 1.1
else:
yard_importance = 1.0
# 計算最終分數
final_score = space_score * (1 + adaptability_bonus)
# 應用院子影響
if user_prefs.yard_access != 'no_yard':
yard_bonus = (yard_multiplier - 1) * yard_importance
final_score = min(1.0, final_score + yard_bonus)
# 確保分數在合理範圍內,但提供更高的基礎分數
return max(0.4, min(1.0, final_score))
# 第四部分:品種特性評估
def evaluate_breed_traits():
temperament = breed_info.get('Temperament', '').lower()
description = breed_info.get('Description', '').lower()
trait_scores = []
# 評估性格特徵
if user_prefs.has_children:
if 'good with children' in description:
trait_scores.append(1.0)
elif 'patient' in temperament or 'gentle' in temperament:
trait_scores.append(0.8)
else:
trait_scores.append(0.5)
# 評估適應性
adaptability_keywords = ['adaptable', 'versatile', 'flexible']
if any(keyword in temperament for keyword in adaptability_keywords):
trait_scores.append(1.0)
else:
trait_scores.append(0.7)
return sum(trait_scores) / len(trait_scores) if trait_scores else 0.7
# 計算各項匹配分數
perfect_matches['exercise_match'] = evaluate_exercise_compatibility()
perfect_matches['experience_match'] = evaluate_expertise_requirements()
perfect_matches['living_condition_match'] = evaluate_living_conditions()
perfect_matches['size_match'] = evaluate_living_conditions() # 共用生活環境評估
perfect_matches['breed_trait_match'] = evaluate_breed_traits()
return perfect_matches
def calculate_weights() -> dict:
"""
動態計算評分權重,特別關注:
1. 極端情況的權重調整
2. 使用者條件的協同效應
3. 品種特性的影響
Returns:
dict: 包含各評分項目權重的字典
"""
# 定義基礎權重 - 提供更合理的起始分配
base_weights = {
'space': 0.25, # 提升空間權重,因為這是最基本的需求
'exercise': 0.25, # 運動需求同樣重要
'experience': 0.20, # 保持經驗的重要性
'grooming': 0.10, # 稍微降低美容需求的權重
'noise': 0.10, # 維持噪音評估的權重
'health': 0.10 # 維持健康評估的權重
}
def analyze_condition_extremity() -> dict:
"""
評估使用者條件的極端程度,這影響權重的動態調整。
根據條件的極端程度返回相應的調整建議。
"""
extremities = {}
# 運動時間評估 - 更細緻的分級
if user_prefs.exercise_time <= 30:
extremities['exercise'] = ('extremely_low', 0.8)
elif user_prefs.exercise_time <= 60:
extremities['exercise'] = ('low', 0.6)
elif user_prefs.exercise_time >= 180:
extremities['exercise'] = ('extremely_high', 0.8)
elif user_prefs.exercise_time >= 120:
extremities['exercise'] = ('high', 0.6)
else:
extremities['exercise'] = ('moderate', 0.3)
# 空間限制評估 - 更合理的空間評估
space_extremity = {
'apartment': ('restricted', 0.7), # 從0.9降低到0.7,減少限制
'house_small': ('moderate', 0.5),
'house_large': ('spacious', 0.3)
}
extremities['space'] = space_extremity.get(user_prefs.living_space, ('moderate', 0.5))
# 經驗水平評估 - 保持原有的評估邏輯
experience_extremity = {
'beginner': ('low', 0.7),
'intermediate': ('moderate', 0.4),
'advanced': ('high', 0.6)
}
extremities['experience'] = experience_extremity.get(user_prefs.experience_level, ('moderate', 0.5))
return extremities
def calculate_weight_adjustments(extremities: dict) -> dict:
"""
根據極端程度計算權重調整,特別注意條件組合的影響。
"""
adjustments = {}
temperament = breed_info.get('Temperament', '').lower()
is_working_dog = any(trait in temperament
for trait in ['herding', 'working', 'intelligent', 'tireless'])
# 空間權重調整
if extremities['space'][0] == 'restricted':
if extremities['exercise'][0] in ['high', 'extremely_high']:
adjustments['space'] = 1.3
adjustments['exercise'] = 2.3
else:
adjustments['space'] = 1.6
adjustments['noise'] = 1.5
# 運動需求權重調整
if extremities['exercise'][0] in ['extremely_high', 'extremely_low']:
base_adjustment = 2.0
if extremities['exercise'][0] == 'extremely_high':
if is_working_dog:
base_adjustment = 2.3
adjustments['exercise'] = base_adjustment
# 經驗需求權重調整
if extremities['experience'][0] == 'low':
adjustments['experience'] = 1.8
if breed_info.get('Care Level') == 'HIGH':
adjustments['experience'] = 2.0
elif extremities['experience'][0] == 'high':
if is_working_dog:
adjustments['experience'] = 1.8 # 從2.5降低到1.8
# 特殊組合的處理
def adjust_for_combinations():
if (extremities['space'][0] == 'restricted' and
extremities['exercise'][0] in ['high', 'extremely_high']):
# 適度降低極端組合的影響
adjustments['space'] = adjustments.get('space', 1.0) * 1.2
adjustments['exercise'] = adjustments.get('exercise', 1.0) * 1.2
# 理想組合的獎勵
if (extremities['experience'][0] == 'high' and
extremities['space'][0] == 'spacious' and
extremities['exercise'][0] in ['high', 'extremely_high'] and
is_working_dog):
adjustments['exercise'] = adjustments.get('exercise', 1.0) * 1.3
adjustments['experience'] = adjustments.get('experience', 1.0) * 1.3
adjust_for_combinations()
return adjustments
# 獲取條件極端度
extremities = analyze_condition_extremity()
# 計算權重調整
weight_adjustments = calculate_weight_adjustments(extremities)
# 應用權重調整,確保總和為1
final_weights = base_weights.copy()
for key, adjustment in weight_adjustments.items():
if key in final_weights:
final_weights[key] *= adjustment
# 正規化權重
total_weight = sum(final_weights.values())
normalized_weights = {k: v/total_weight for k, v in final_weights.items()}
return normalized_weights
def calculate_base_score(scores: dict, weights: dict) -> float:
"""
計算基礎評分分數,採用更靈活的評分機制。
這個函數使用了改進後的評分邏輯,主要關注:
1. 降低關鍵指標的最低門檻,使系統更包容
2. 引入非線性評分曲線,讓分數分布更合理
3. 優化多重條件失敗的處理方式
4. 加強對品種特性的考慮
Parameters:
scores: 包含各項評分的字典
weights: 包含各項權重的字典
Returns:
float: 0.2到1.0之間的基礎分數
"""
# 重新定義關鍵指標閾值,提供更寬容的評分標準
critical_thresholds = {
'space': 0.35,
'exercise': 0.35,
'experience': 0.5,
'noise': 0.5
}
# 評估關鍵指標失敗情況
def evaluate_critical_failures() -> list:
"""
評估關鍵指標的失敗情況,但採用更寬容的標準。
根據品種特性動態調整失敗判定。
"""
failures = []
temperament = breed_info.get('Temperament', '').lower()
for metric, threshold in critical_thresholds.items():
if scores[metric] < threshold:
# 特殊情況處理:適應性強的品種可以有更低的空間要求
if metric == 'space' and any(trait in temperament
for trait in ['adaptable', 'calm', 'apartment']):
if scores[metric] >= threshold - 0.1:
continue
# 運動需求的特殊處理
elif metric == 'exercise':
exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
if exercise_needs == 'LOW' and scores[metric] >= threshold - 0.1:
continue
failures.append((metric, scores[metric]))
return failures
# 計算基礎分數
def calculate_weighted_score() -> float:
"""
計算加權分數,使用非線性函數使分數分布更合理。
"""
weighted_scores = []
for key, score in scores.items():
if key in weights:
# 使用sigmoid函數使分數曲線更平滑
adjusted_score = 1 / (1 + math.exp(-10 * (score - 0.5)))
weighted_scores.append(adjusted_score * weights[key])
return sum(weighted_scores)
# 處理臨界失敗情況
critical_failures = evaluate_critical_failures()
base_score = calculate_weighted_score()
if critical_failures:
# 分離空間和運動相關的懲罰
space_exercise_penalty = 0
other_penalty = 0
for metric, score in critical_failures:
if metric in ['space', 'exercise']:
# 降低空間和運動失敗的懲罰程度
penalty = (critical_thresholds[metric] - score) * 0.08
space_exercise_penalty += penalty
else:
# 其他失敗的懲罰保持較高
penalty = (critical_thresholds[metric] - score) * 0.20
other_penalty += penalty
# 計算總懲罰,但使用更溫和的方式
total_penalty = (space_exercise_penalty + other_penalty) / 2
base_score *= (1 - total_penalty)
# 多重失敗的處理更寬容
if len(critical_failures) > 1:
# 從0.98提升到0.99,降低多重失敗的疊加懲罰
base_score *= (0.99 ** (len(critical_failures) - 1))
# 品種特性加分
def apply_breed_bonus() -> float:
"""
根據品種特性提供額外加分,
特別是對於在特定環境下表現良好的品種。
"""
bonus = 0
temperament = breed_info.get('Temperament', '').lower()
description = breed_info.get('Description', '').lower()
# 適應性加分
adaptability_traits = ['adaptable', 'versatile', 'easy-going']
if any(trait in temperament for trait in adaptability_traits):
bonus += 0.05
# 公寓適應性加分
if user_prefs.living_space == 'apartment':
apartment_traits = ['calm', 'quiet', 'good for apartments']
if any(trait in temperament or trait in description for trait in apartment_traits):
bonus += 0.05
return min(0.1, bonus) # 限制最大加分
# 應用品種特性加分
breed_bonus = apply_breed_bonus()
base_score = min(1.0, base_score * (1 + breed_bonus))
# 確保最終分數在合理範圍內
return max(0.2, min(1.0, base_score))
def evaluate_condition_interactions(scores: dict) -> float:
"""評估不同條件間的相互影響,更寬容地處理極端組合"""
interaction_penalty = 1.0
# 只保留最基本的經驗相關評估
if user_prefs.experience_level == 'beginner':
if breed_info.get('Care Level') == 'HIGH':
interaction_penalty *= 0.95
# 運動時間與類型的基本互動也降低懲罰程度
exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
if exercise_needs == 'VERY HIGH' and user_prefs.exercise_type == 'light_walks':
interaction_penalty *= 0.95
return interaction_penalty
def calculate_adjusted_perfect_bonus(perfect_conditions: dict) -> float:
"""計算完美匹配獎勵,但更注重條件的整體表現"""
bonus = 1.0
# 降低單項獎勵的影響力
bonus += 0.06 * perfect_conditions['size_match']
bonus += 0.06 * perfect_conditions['exercise_match']
bonus += 0.06 * perfect_conditions['experience_match']
bonus += 0.03 * perfect_conditions['living_condition_match']
# 如果有任何條件表現不佳,降低整體獎勵
low_scores = [score for score in perfect_conditions.values() if score < 0.6]
if low_scores:
bonus *= (0.85 ** len(low_scores))
# 確保獎勵不會過高
return min(1.25, bonus)
def apply_breed_specific_adjustments(score: float) -> float:
"""根據品種特性進行最終調整"""
# 檢查是否存在極端不匹配的情況
exercise_mismatch = False
size_mismatch = False
experience_mismatch = False
# 運動需求極端不匹配
if breed_info.get('Exercise Needs', 'MODERATE').upper() == 'VERY HIGH':
if user_prefs.exercise_time < 90 or user_prefs.exercise_type == 'light_walks':
exercise_mismatch = True
# 體型與空間極端不匹配
if user_prefs.living_space == 'apartment' and breed_info['Size'] in ['Large', 'Giant']:
size_mismatch = True
# 經驗需求極端不匹配
if user_prefs.experience_level == 'beginner' and breed_info.get('Care Level') == 'HIGH':
experience_mismatch = True
# 根據不匹配的數量進行懲罰
mismatch_count = sum([exercise_mismatch, size_mismatch, experience_mismatch])
if mismatch_count > 0:
score *= (0.8 ** mismatch_count)
return score
# 計算動態權重
weights = calculate_weights()
# 正規化權重
total_weight = sum(weights.values())
normalized_weights = {k: v/total_weight for k, v in weights.items()}
# 計算基礎分數
base_score = calculate_base_score(scores, normalized_weights)
# 評估條件互動
interaction_multiplier = evaluate_condition_interactions(scores)
# 計算完美匹配獎勵
perfect_conditions = evaluate_perfect_conditions()
perfect_bonus = calculate_adjusted_perfect_bonus(perfect_conditions)
# 計算初步分數
preliminary_score = base_score * interaction_multiplier * perfect_bonus
# 應用品種特定調整
final_score = apply_breed_specific_adjustments(preliminary_score)
# 確保分數在合理範圍內,並降低最高可能分數
max_possible_score = 0.96 # 降低最高可能分數
min_possible_score = 0.3
return min(max_possible_score, max(min_possible_score, final_score))
def calculate_environmental_fit(self, breed_info: dict, user_prefs: UserPreferences) -> float:
"""
計算品種與環境的適應性加成
Args:
breed_info: 品種資訊
user_prefs: 使用者偏好
Returns:
float: 環境適應性加成分數
"""
adaptability_score = 0.0
description = breed_info.get('Description', '').lower()
temperament = breed_info.get('Temperament', '').lower()
# 環境適應性評估
if user_prefs.living_space == 'apartment':
if 'adaptable' in temperament or 'apartment' in description:
adaptability_score += 0.1
if breed_info.get('Size') == 'Small':
adaptability_score += 0.05
elif user_prefs.living_space == 'house_large':
if 'active' in temperament or 'energetic' in description:
adaptability_score += 0.1
# 氣候適應性
if user_prefs.climate in description or user_prefs.climate in temperament:
adaptability_score += 0.05
return min(0.2, adaptability_score)