DawnC commited on
Commit
676cf64
1 Parent(s): 9e010e9

Update scoring_calculation_system.py

Browse files
Files changed (1) hide show
  1. 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 = ['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
 
@@ -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.25,
1221
- 'exercise': 0.20,
1222
  'grooming': 0.15,
1223
- 'experience': 0.18,
1224
- 'health': 0.12,
1225
- 'noise': 0.10
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.45
1272
- max_score = 0.95
1273
 
1274
- # 正規化到 0-1 範圍
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))