1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
| class EuroNCAP2026Scoring: """ Euro NCAP 2026评分体系 Stage 1: Safe Driving - DSM (Driver State Monitoring): 最多25分 - SBR (Seat Belt Reminder): 最多10分 - SS (Speed Support): 最多15分 - OM (Occupant Monitoring): 最多10分 """ STAGE1_MAX_SCORE = 100 DSM_SCORING = { 'distraction_detection': { 'max_points': 8, 'scenarios': ['D-01', 'D-02', 'D-03', 'D-04', 'D-05'], 'requirements': { 'detection_time_sec': 3, 'warning_sequence': True, 'default_on': True } }, 'fatigue_detection': { 'max_points': 8, 'scenarios': ['F-01', 'F-02', 'F-03', 'F-04', 'F-05'], 'requirements': { 'perclos_threshold': 30, 'warning_levels': 2, 'default_on': True } }, 'unresponsive_driver': { 'max_points': 6, 'scenarios': ['UD-01', 'UD-02'], 'requirements': { 'detection_time_sec': 10, 'intervention': 'controlled_stop' } }, 'impairment_detection': { 'max_points': 3, 'scenarios': ['I-01'], 'requirements': { 'alcohol_detection': True, 'warning_strategy': True } } } OM_SCORING = { 'child_presence_detection': { 'max_points': 5, 'scenarios': ['CPD-01', 'CPD-02', 'CPD-03', 'CPD-04'], 'requirements': { 'detection_time_sec': 60, 'vital_signs': True, 'warning': 'visual_audible' } }, 'out_of_position': { 'max_points': 3, 'scenarios': ['OOP-01', 'OOP-02', 'OOP-03'], 'requirements': { 'feet_dashboard': True, 'body_lean': True, 'warning_time_sec': 30 } }, 'seatbelt_misuse': { 'max_points': 2, 'scenarios': ['SM-01', 'SM-02'], 'requirements': { 'wrong_position': True, 'warning': True } } } def calculate_dsm_score(self, test_results: dict) -> dict: """ 计算DSM得分 Args: test_results: 测试结果 {scenario_id: pass/fail, ...} Returns: {total_score, breakdown, compliance_rate} """ total_score = 0 breakdown = {} for category, config in self.DSM_SCORING.items(): category_score = 0 passed_scenarios = 0 for scenario_id in config['scenarios']: if test_results.get(scenario_id, False): passed_scenarios += 1 pass_rate = passed_scenarios / len(config['scenarios']) category_score = config['max_points'] * pass_rate breakdown[category] = { 'score': category_score, 'max_points': config['max_points'], 'pass_rate': pass_rate } total_score += category_score max_total = sum(c['max_points'] for c in self.DSM_SCORING.values()) return { 'total_score': total_score, 'max_score': max_total, 'breakdown': breakdown, 'compliance_rate': total_score / max_total } def calculate_om_score(self, test_results: dict) -> dict: """计算OM得分""" total_score = 0 breakdown = {} for category, config in self.OM_SCORING.items(): category_score = 0 passed_scenarios = 0 for scenario_id in config['scenarios']: if test_results.get(scenario_id, False): passed_scenarios += 1 pass_rate = passed_scenarios / len(config['scenarios']) category_score = config['max_points'] * pass_rate breakdown[category] = { 'score': category_score, 'max_points': config['max_points'], 'pass_rate': pass_rate } total_score += category_score max_total = sum(c['max_points'] for c in self.OM_SCORING.values()) return { 'total_score': total_score, 'max_score': max_total, 'breakdown': breakdown, 'compliance_rate': total_score / max_total } def determine_star_rating(self, total_percentage: float) -> int: """确定星级""" if total_percentage >= 80: return 5 elif total_percentage >= 70: return 4 elif total_percentage >= 60: return 3 elif total_percentage >= 50: return 2 else: return 1
|