Spaces:
Running
on
Zero
Running
on
Zero
Update scoring_calculation_system.py
Browse files- scoring_calculation_system.py +300 -50
scoring_calculation_system.py
CHANGED
|
@@ -285,81 +285,328 @@ def calculate_breed_bonus(breed_info: dict, user_prefs: UserPreferences) -> floa
|
|
| 285 |
return min(0.5, max(-0.35, bonus))
|
| 286 |
|
| 287 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 288 |
@staticmethod
|
| 289 |
def calculate_additional_factors(breed_info: dict, user_prefs: 'UserPreferences') -> dict:
|
| 290 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
factors = {
|
| 292 |
'versatility': 0.0, # 多功能性
|
| 293 |
'trainability': 0.0, # 可訓練度
|
| 294 |
'energy_level': 0.0, # 能量水平
|
| 295 |
'grooming_needs': 0.0, # 美容需求
|
| 296 |
'social_needs': 0.0, # 社交需求
|
| 297 |
-
'weather_adaptability': 0.0
|
|
|
|
|
|
|
| 298 |
}
|
| 299 |
|
| 300 |
temperament = breed_info.get('Temperament', '').lower()
|
|
|
|
| 301 |
size = breed_info.get('Size', 'Medium')
|
| 302 |
|
| 303 |
-
# 1. 多功能性評估
|
| 304 |
-
versatile_traits =
|
| 305 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
|
| 307 |
-
|
| 308 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
|
| 310 |
factors['versatility'] = min(1.0, trait_score + role_score)
|
| 311 |
|
| 312 |
-
# 2.
|
| 313 |
trainable_traits = {
|
| 314 |
'intelligent': 0.3,
|
| 315 |
'eager to please': 0.3,
|
| 316 |
'trainable': 0.2,
|
| 317 |
-
'quick learner': 0.2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
}
|
| 319 |
-
factors['trainability'] = min(1.0, sum(value for trait, value in trainable_traits.items()
|
| 320 |
-
if trait in temperament))
|
| 321 |
|
| 322 |
-
|
|
|
|
|
|
|
|
|
|
| 323 |
exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
|
| 324 |
energy_levels = {
|
| 325 |
-
'VERY HIGH':
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 330 |
}
|
| 331 |
-
factors['energy_level'] = energy_levels.get(exercise_needs, 0.6)
|
| 332 |
|
| 333 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 334 |
grooming_needs = breed_info.get('Grooming Needs', 'MODERATE').upper()
|
| 335 |
grooming_levels = {
|
| 336 |
'HIGH': 1.0,
|
| 337 |
'MODERATE': 0.6,
|
| 338 |
'LOW': 0.3
|
| 339 |
}
|
| 340 |
-
coat_penalty = 0.2 if any(term in breed_info.get('Description', '').lower()
|
| 341 |
-
for term in ['long coat', 'double coat']) else 0
|
| 342 |
-
factors['grooming_needs'] = min(1.0, grooming_levels.get(grooming_needs, 0.6) + coat_penalty)
|
| 343 |
|
| 344 |
-
#
|
| 345 |
-
|
| 346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 347 |
|
| 348 |
-
social_score = sum(0.25 for trait in social_traits if trait in temperament)
|
| 349 |
-
antisocial_score = sum(-0.2 for trait in antisocial_traits if trait in temperament)
|
| 350 |
factors['social_needs'] = min(1.0, max(0.0, social_score + antisocial_score))
|
| 351 |
|
| 352 |
-
# 6. 氣候適應性評估
|
| 353 |
-
|
| 354 |
-
'cold':
|
| 355 |
-
|
| 356 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
}
|
| 358 |
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
return factors
|
| 364 |
|
| 365 |
|
|
@@ -1217,12 +1464,12 @@ def calculate_final_weighted_score(scores: dict, user_prefs: UserPreferences,
|
|
| 1217 |
breed_info: dict, adaptability_bonus: float) -> float:
|
| 1218 |
"""計算最終加權分數"""
|
| 1219 |
base_weights = {
|
| 1220 |
-
'space': 0.
|
| 1221 |
-
'exercise': 0.
|
| 1222 |
'grooming': 0.15,
|
| 1223 |
-
'experience': 0.
|
| 1224 |
-
'health': 0.
|
| 1225 |
-
'noise': 0.
|
| 1226 |
}
|
| 1227 |
|
| 1228 |
# 根據居住環境動態調整權重
|
|
@@ -1243,6 +1490,13 @@ def calculate_final_weighted_score(scores: dict, user_prefs: UserPreferences,
|
|
| 1243 |
base_weights['exercise'] *= 1.2
|
| 1244 |
base_weights['experience'] *= 0.8
|
| 1245 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1246 |
# 有���童時的特殊調整
|
| 1247 |
if user_prefs.has_children:
|
| 1248 |
base_weights['noise'] *= 1.3
|
|
@@ -1268,16 +1522,12 @@ def calculate_final_weighted_score(scores: dict, user_prefs: UserPreferences,
|
|
| 1268 |
|
| 1269 |
def amplify_score_range(score: float) -> float:
|
| 1270 |
"""擴大分數範圍,使差異更明顯"""
|
| 1271 |
-
min_score = 0.
|
| 1272 |
-
max_score = 0.
|
| 1273 |
|
| 1274 |
-
#
|
| 1275 |
normalized = (score - 0.5) / 0.5
|
|
|
|
| 1276 |
|
| 1277 |
-
# 非線性轉換
|
| 1278 |
-
amplified = math.pow(abs(normalized), 1.5) * math.copysign(1, normalized)
|
| 1279 |
-
|
| 1280 |
-
# 映射回目標範圍
|
| 1281 |
final = min_score + (max_score - min_score) * ((amplified + 1) / 2)
|
| 1282 |
-
|
| 1283 |
-
return min(max_score, max(min_score, final))
|
|
|
|
| 285 |
return min(0.5, max(-0.35, bonus))
|
| 286 |
|
| 287 |
|
| 288 |
+
# @staticmethod
|
| 289 |
+
# def calculate_additional_factors(breed_info: dict, user_prefs: 'UserPreferences') -> dict:
|
| 290 |
+
# """計算額外的評估因素"""
|
| 291 |
+
# factors = {
|
| 292 |
+
# 'versatility': 0.0, # 多功能性
|
| 293 |
+
# 'trainability': 0.0, # 可訓練度
|
| 294 |
+
# 'energy_level': 0.0, # 能量水平
|
| 295 |
+
# 'grooming_needs': 0.0, # 美容需求
|
| 296 |
+
# 'social_needs': 0.0, # 社交需求
|
| 297 |
+
# 'weather_adaptability': 0.0 # 氣候適應性
|
| 298 |
+
# }
|
| 299 |
+
|
| 300 |
+
# temperament = breed_info.get('Temperament', '').lower()
|
| 301 |
+
# size = breed_info.get('Size', 'Medium')
|
| 302 |
+
|
| 303 |
+
# # 1. 多功能性評估
|
| 304 |
+
# versatile_traits = ['intelligent', 'adaptable', 'trainable', 'athletic']
|
| 305 |
+
# working_roles = ['working', 'herding', 'hunting', 'sporting', 'companion']
|
| 306 |
+
|
| 307 |
+
# trait_score = sum(0.2 for trait in versatile_traits if trait in temperament)
|
| 308 |
+
# role_score = sum(0.2 for role in working_roles if role in breed_info.get('Description', '').lower())
|
| 309 |
+
|
| 310 |
+
# factors['versatility'] = min(1.0, trait_score + role_score)
|
| 311 |
+
|
| 312 |
+
# # 2. 可訓練度評估
|
| 313 |
+
# trainable_traits = {
|
| 314 |
+
# 'intelligent': 0.3,
|
| 315 |
+
# 'eager to please': 0.3,
|
| 316 |
+
# 'trainable': 0.2,
|
| 317 |
+
# 'quick learner': 0.2
|
| 318 |
+
# }
|
| 319 |
+
# factors['trainability'] = min(1.0, sum(value for trait, value in trainable_traits.items()
|
| 320 |
+
# if trait in temperament))
|
| 321 |
+
|
| 322 |
+
# # 3. 能量水平評估
|
| 323 |
+
# exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
|
| 324 |
+
# energy_levels = {
|
| 325 |
+
# 'VERY HIGH': 1.0,
|
| 326 |
+
# 'HIGH': 0.8,
|
| 327 |
+
# 'MODERATE': 0.6,
|
| 328 |
+
# 'LOW': 0.4,
|
| 329 |
+
# 'VARIES': 0.6
|
| 330 |
+
# }
|
| 331 |
+
# factors['energy_level'] = energy_levels.get(exercise_needs, 0.6)
|
| 332 |
+
|
| 333 |
+
# # 4. 美容需求評估
|
| 334 |
+
# grooming_needs = breed_info.get('Grooming Needs', 'MODERATE').upper()
|
| 335 |
+
# grooming_levels = {
|
| 336 |
+
# 'HIGH': 1.0,
|
| 337 |
+
# 'MODERATE': 0.6,
|
| 338 |
+
# 'LOW': 0.3
|
| 339 |
+
# }
|
| 340 |
+
# coat_penalty = 0.2 if any(term in breed_info.get('Description', '').lower()
|
| 341 |
+
# for term in ['long coat', 'double coat']) else 0
|
| 342 |
+
# factors['grooming_needs'] = min(1.0, grooming_levels.get(grooming_needs, 0.6) + coat_penalty)
|
| 343 |
+
|
| 344 |
+
# # 5. 社交需求評估
|
| 345 |
+
# social_traits = ['friendly', 'social', 'affectionate', 'people-oriented']
|
| 346 |
+
# antisocial_traits = ['independent', 'aloof', 'reserved']
|
| 347 |
+
|
| 348 |
+
# social_score = sum(0.25 for trait in social_traits if trait in temperament)
|
| 349 |
+
# antisocial_score = sum(-0.2 for trait in antisocial_traits if trait in temperament)
|
| 350 |
+
# factors['social_needs'] = min(1.0, max(0.0, social_score + antisocial_score))
|
| 351 |
+
|
| 352 |
+
# # 6. 氣候適應性評估
|
| 353 |
+
# climate_terms = {
|
| 354 |
+
# 'cold': ['thick coat', 'winter', 'cold climate'],
|
| 355 |
+
# 'hot': ['short coat', 'warm climate', 'heat tolerant'],
|
| 356 |
+
# 'moderate': ['adaptable', 'all climate']
|
| 357 |
+
# }
|
| 358 |
+
|
| 359 |
+
# climate_matches = sum(1 for term in climate_terms[user_prefs.climate]
|
| 360 |
+
# if term in breed_info.get('Description', '').lower())
|
| 361 |
+
# factors['weather_adaptability'] = min(1.0, climate_matches * 0.3 + 0.4) # 基礎分0.4
|
| 362 |
+
|
| 363 |
+
# return factors
|
| 364 |
+
|
| 365 |
+
|
| 366 |
@staticmethod
|
| 367 |
def calculate_additional_factors(breed_info: dict, user_prefs: 'UserPreferences') -> dict:
|
| 368 |
+
"""
|
| 369 |
+
計算額外的評估因素,結合品種特性與使用者需求的全面評估系統
|
| 370 |
+
|
| 371 |
+
此函數整合了:
|
| 372 |
+
1. 多功能性評估 - 品種的多樣化能力
|
| 373 |
+
2. 訓練性評估 - 學習和服從能力
|
| 374 |
+
3. 能量水平評估 - 活力和運動需求
|
| 375 |
+
4. 美容需求評估 - 護理和維護需求
|
| 376 |
+
5. 社交需求評估 - 與人互動的需求程度
|
| 377 |
+
6. 氣候適應性 - 對環境的適應能力
|
| 378 |
+
7. 運動類型匹配 - 與使用者運動習慣的契合度
|
| 379 |
+
8. 生活方式適配 - 與使用者日常生活的匹配度
|
| 380 |
+
"""
|
| 381 |
factors = {
|
| 382 |
'versatility': 0.0, # 多功能性
|
| 383 |
'trainability': 0.0, # 可訓練度
|
| 384 |
'energy_level': 0.0, # 能量水平
|
| 385 |
'grooming_needs': 0.0, # 美容需求
|
| 386 |
'social_needs': 0.0, # 社交需求
|
| 387 |
+
'weather_adaptability': 0.0,# 氣候適應性
|
| 388 |
+
'exercise_match': 0.0, # 運動匹配度
|
| 389 |
+
'lifestyle_fit': 0.0 # 生活方式適配度
|
| 390 |
}
|
| 391 |
|
| 392 |
temperament = breed_info.get('Temperament', '').lower()
|
| 393 |
+
description = breed_info.get('Description', '').lower()
|
| 394 |
size = breed_info.get('Size', 'Medium')
|
| 395 |
|
| 396 |
+
# 1. 多功能性評估 - 加強品種用途評估
|
| 397 |
+
versatile_traits = {
|
| 398 |
+
'intelligent': 0.25,
|
| 399 |
+
'adaptable': 0.25,
|
| 400 |
+
'trainable': 0.20,
|
| 401 |
+
'athletic': 0.15,
|
| 402 |
+
'versatile': 0.15
|
| 403 |
+
}
|
| 404 |
|
| 405 |
+
working_roles = {
|
| 406 |
+
'working': 0.20,
|
| 407 |
+
'herding': 0.15,
|
| 408 |
+
'hunting': 0.15,
|
| 409 |
+
'sporting': 0.15,
|
| 410 |
+
'companion': 0.10
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
# 計算特質分數
|
| 414 |
+
trait_score = sum(value for trait, value in versatile_traits.items()
|
| 415 |
+
if trait in temperament)
|
| 416 |
+
|
| 417 |
+
# 計算角色分數
|
| 418 |
+
role_score = sum(value for role, value in working_roles.items()
|
| 419 |
+
if role in description)
|
| 420 |
+
|
| 421 |
+
# 根據使用者需求調整多功能性評分
|
| 422 |
+
purpose_traits = {
|
| 423 |
+
'light_walks': ['calm', 'gentle', 'easy-going'],
|
| 424 |
+
'moderate_activity': ['adaptable', 'balanced', 'versatile'],
|
| 425 |
+
'active_training': ['intelligent', 'trainable', 'working']
|
| 426 |
+
}
|
| 427 |
+
|
| 428 |
+
if user_prefs.exercise_type in purpose_traits:
|
| 429 |
+
matching_traits = sum(1 for trait in purpose_traits[user_prefs.exercise_type]
|
| 430 |
+
if trait in temperament)
|
| 431 |
+
trait_score += matching_traits * 0.15
|
| 432 |
|
| 433 |
factors['versatility'] = min(1.0, trait_score + role_score)
|
| 434 |
|
| 435 |
+
# 2. 訓練性評估 - 考慮使用者經驗
|
| 436 |
trainable_traits = {
|
| 437 |
'intelligent': 0.3,
|
| 438 |
'eager to please': 0.3,
|
| 439 |
'trainable': 0.2,
|
| 440 |
+
'quick learner': 0.2,
|
| 441 |
+
'obedient': 0.2
|
| 442 |
+
}
|
| 443 |
+
|
| 444 |
+
base_trainability = sum(value for trait, value in trainable_traits.items()
|
| 445 |
+
if trait in temperament)
|
| 446 |
+
|
| 447 |
+
# 根據使用者經驗調整訓練性評分
|
| 448 |
+
experience_multipliers = {
|
| 449 |
+
'beginner': 1.2, # 新手更需要容易訓練的狗
|
| 450 |
+
'intermediate': 1.0,
|
| 451 |
+
'advanced': 0.8 # 專家能處理較難訓練的狗
|
| 452 |
}
|
|
|
|
|
|
|
| 453 |
|
| 454 |
+
factors['trainability'] = min(1.0, base_trainability *
|
| 455 |
+
experience_multipliers.get(user_prefs.experience_level, 1.0))
|
| 456 |
+
|
| 457 |
+
# 3. 能量水平評估 - 強化運動需求匹配
|
| 458 |
exercise_needs = breed_info.get('Exercise Needs', 'MODERATE').upper()
|
| 459 |
energy_levels = {
|
| 460 |
+
'VERY HIGH': {
|
| 461 |
+
'score': 1.0,
|
| 462 |
+
'min_exercise': 120,
|
| 463 |
+
'ideal_exercise': 150
|
| 464 |
+
},
|
| 465 |
+
'HIGH': {
|
| 466 |
+
'score': 0.8,
|
| 467 |
+
'min_exercise': 90,
|
| 468 |
+
'ideal_exercise': 120
|
| 469 |
+
},
|
| 470 |
+
'MODERATE': {
|
| 471 |
+
'score': 0.6,
|
| 472 |
+
'min_exercise': 60,
|
| 473 |
+
'ideal_exercise': 90
|
| 474 |
+
},
|
| 475 |
+
'LOW': {
|
| 476 |
+
'score': 0.4,
|
| 477 |
+
'min_exercise': 30,
|
| 478 |
+
'ideal_exercise': 60
|
| 479 |
+
}
|
| 480 |
}
|
|
|
|
| 481 |
|
| 482 |
+
breed_energy = energy_levels.get(exercise_needs, energy_levels['MODERATE'])
|
| 483 |
+
|
| 484 |
+
# 計算運動時間匹配度
|
| 485 |
+
if user_prefs.exercise_time >= breed_energy['ideal_exercise']:
|
| 486 |
+
energy_score = breed_energy['score']
|
| 487 |
+
else:
|
| 488 |
+
# 如果運動時間不足,按比例降低分數
|
| 489 |
+
deficit_ratio = max(0.4, user_prefs.exercise_time / breed_energy['ideal_exercise'])
|
| 490 |
+
energy_score = breed_energy['score'] * deficit_ratio
|
| 491 |
+
|
| 492 |
+
factors['energy_level'] = energy_score
|
| 493 |
+
|
| 494 |
+
# 4. 美容需求評估 - 加入更多毛髮類型考量
|
| 495 |
grooming_needs = breed_info.get('Grooming Needs', 'MODERATE').upper()
|
| 496 |
grooming_levels = {
|
| 497 |
'HIGH': 1.0,
|
| 498 |
'MODERATE': 0.6,
|
| 499 |
'LOW': 0.3
|
| 500 |
}
|
|
|
|
|
|
|
|
|
|
| 501 |
|
| 502 |
+
# 特殊毛髮類型評估
|
| 503 |
+
coat_adjustments = 0
|
| 504 |
+
if 'long coat' in description:
|
| 505 |
+
coat_adjustments += 0.2
|
| 506 |
+
if 'double coat' in description:
|
| 507 |
+
coat_adjustments += 0.15
|
| 508 |
+
if 'curly' in description:
|
| 509 |
+
coat_adjustments += 0.15
|
| 510 |
+
|
| 511 |
+
# 根據使用者承諾度調整
|
| 512 |
+
commitment_multipliers = {
|
| 513 |
+
'low': 1.5, # 低承諾度時加重美容需求的影響
|
| 514 |
+
'medium': 1.0,
|
| 515 |
+
'high': 0.8 # 高承諾度時降低美容需求的影響
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
base_grooming = grooming_levels.get(grooming_needs, 0.6) + coat_adjustments
|
| 519 |
+
factors['grooming_needs'] = min(1.0, base_grooming *
|
| 520 |
+
commitment_multipliers.get(user_prefs.grooming_commitment, 1.0))
|
| 521 |
+
|
| 522 |
+
# 5. 社交需求評估 - 加強家庭情況考量
|
| 523 |
+
social_traits = {
|
| 524 |
+
'friendly': 0.25,
|
| 525 |
+
'social': 0.25,
|
| 526 |
+
'affectionate': 0.20,
|
| 527 |
+
'people-oriented': 0.20
|
| 528 |
+
}
|
| 529 |
+
|
| 530 |
+
antisocial_traits = {
|
| 531 |
+
'independent': -0.20,
|
| 532 |
+
'aloof': -0.20,
|
| 533 |
+
'reserved': -0.15
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
social_score = sum(value for trait, value in social_traits.items()
|
| 537 |
+
if trait in temperament)
|
| 538 |
+
antisocial_score = sum(value for trait, value in antisocial_traits.items()
|
| 539 |
+
if trait in temperament)
|
| 540 |
+
|
| 541 |
+
# 家庭情況調整
|
| 542 |
+
if user_prefs.has_children:
|
| 543 |
+
child_friendly_bonus = 0.2 if 'good with children' in temperament else 0
|
| 544 |
+
social_score += child_friendly_bonus
|
| 545 |
|
|
|
|
|
|
|
| 546 |
factors['social_needs'] = min(1.0, max(0.0, social_score + antisocial_score))
|
| 547 |
|
| 548 |
+
# 6. 氣候適應性評估 - 更細緻的環境適應評估
|
| 549 |
+
climate_traits = {
|
| 550 |
+
'cold': {
|
| 551 |
+
'positive': ['thick coat', 'winter', 'cold climate'],
|
| 552 |
+
'negative': ['short coat', 'heat sensitive']
|
| 553 |
+
},
|
| 554 |
+
'hot': {
|
| 555 |
+
'positive': ['short coat', 'heat tolerant', 'warm climate'],
|
| 556 |
+
'negative': ['thick coat', 'cold climate']
|
| 557 |
+
},
|
| 558 |
+
'moderate': {
|
| 559 |
+
'positive': ['adaptable', 'all climate'],
|
| 560 |
+
'negative': []
|
| 561 |
+
}
|
| 562 |
+
}
|
| 563 |
+
|
| 564 |
+
climate_score = 0.4 # 基礎分數
|
| 565 |
+
if user_prefs.climate in climate_traits:
|
| 566 |
+
# 正面特質加分
|
| 567 |
+
climate_score += sum(0.2 for term in climate_traits[user_prefs.climate]['positive']
|
| 568 |
+
if term in description)
|
| 569 |
+
# 負面特質減分
|
| 570 |
+
climate_score -= sum(0.2 for term in climate_traits[user_prefs.climate]['negative']
|
| 571 |
+
if term in description)
|
| 572 |
+
|
| 573 |
+
factors['weather_adaptability'] = min(1.0, max(0.0, climate_score))
|
| 574 |
+
|
| 575 |
+
# 7. 運動類型匹配評估
|
| 576 |
+
exercise_type_traits = {
|
| 577 |
+
'light_walks': ['calm', 'gentle'],
|
| 578 |
+
'moderate_activity': ['adaptable', 'balanced'],
|
| 579 |
+
'active_training': ['athletic', 'energetic']
|
| 580 |
}
|
| 581 |
|
| 582 |
+
if user_prefs.exercise_type in exercise_type_traits:
|
| 583 |
+
match_score = sum(0.25 for trait in exercise_type_traits[user_prefs.exercise_type]
|
| 584 |
+
if trait in temperament)
|
| 585 |
+
factors['exercise_match'] = min(1.0, match_score + 0.5) # 基礎分0.5
|
| 586 |
+
|
| 587 |
+
# 8. 生活方式適配評估
|
| 588 |
+
lifestyle_score = 0.5 # 基礎分數
|
| 589 |
+
|
| 590 |
+
# 空間適配
|
| 591 |
+
if user_prefs.living_space == 'apartment':
|
| 592 |
+
if size == 'Small':
|
| 593 |
+
lifestyle_score += 0.2
|
| 594 |
+
elif size == 'Large':
|
| 595 |
+
lifestyle_score -= 0.2
|
| 596 |
+
elif user_prefs.living_space == 'house_large':
|
| 597 |
+
if size in ['Large', 'Giant']:
|
| 598 |
+
lifestyle_score += 0.2
|
| 599 |
+
|
| 600 |
+
# 時間可用性適配
|
| 601 |
+
time_availability_bonus = {
|
| 602 |
+
'limited': -0.1,
|
| 603 |
+
'moderate': 0,
|
| 604 |
+
'flexible': 0.1
|
| 605 |
+
}
|
| 606 |
+
lifestyle_score += time_availability_bonus.get(user_prefs.time_availability, 0)
|
| 607 |
+
|
| 608 |
+
factors['lifestyle_fit'] = min(1.0, max(0.0, lifestyle_score))
|
| 609 |
+
|
| 610 |
return factors
|
| 611 |
|
| 612 |
|
|
|
|
| 1464 |
breed_info: dict, adaptability_bonus: float) -> float:
|
| 1465 |
"""計算最終加權分數"""
|
| 1466 |
base_weights = {
|
| 1467 |
+
'space': 0.30,
|
| 1468 |
+
'exercise': 0.25,
|
| 1469 |
'grooming': 0.15,
|
| 1470 |
+
'experience': 0.15,
|
| 1471 |
+
'health': 0.10,
|
| 1472 |
+
'noise': 0.05
|
| 1473 |
}
|
| 1474 |
|
| 1475 |
# 根據居住環境動態調整權重
|
|
|
|
| 1490 |
base_weights['exercise'] *= 1.2
|
| 1491 |
base_weights['experience'] *= 0.8
|
| 1492 |
|
| 1493 |
+
if user_prefs.exercise_time > 120: # 高運動時間
|
| 1494 |
+
base_weights['exercise'] *= 1.5
|
| 1495 |
+
base_weights['space'] *= 1.3
|
| 1496 |
+
elif user_prefs.exercise_time < 45: # 低運動時間
|
| 1497 |
+
base_weights['exercise'] *= 0.7
|
| 1498 |
+
base_weights['health'] *= 1.2
|
| 1499 |
+
|
| 1500 |
# 有���童時的特殊調整
|
| 1501 |
if user_prefs.has_children:
|
| 1502 |
base_weights['noise'] *= 1.3
|
|
|
|
| 1522 |
|
| 1523 |
def amplify_score_range(score: float) -> float:
|
| 1524 |
"""擴大分數範圍,使差異更明顯"""
|
| 1525 |
+
min_score = 0.40 # 降低最小分數
|
| 1526 |
+
max_score = 0.98 # 提高最高分數
|
| 1527 |
|
| 1528 |
+
# 使用更激進的非線性轉換
|
| 1529 |
normalized = (score - 0.5) / 0.5
|
| 1530 |
+
amplified = math.pow(abs(normalized), 1.3) * math.copysign(1, normalized)
|
| 1531 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1532 |
final = min_score + (max_score - min_score) * ((amplified + 1) / 2)
|
| 1533 |
+
return max(min_score, min(max_score, final))
|
|
|