diff --git a/backend/tests/test_distance_service.py b/backend/tests/test_distance_service.py index 864a61e..518168c 100644 --- a/backend/tests/test_distance_service.py +++ b/backend/tests/test_distance_service.py @@ -85,8 +85,9 @@ class TestCalculateMaxDistance: distance = calculate_max_distance(case_data) - # 3 * 1.5 * 0.2 * 0.85 * 0.5 * 0.7 = 0.27 km - assert distance == pytest.approx(0.27, rel=0.01) + # 3 * 1.5 * 0.2 * 0.85 * 0.0(ночь) * 0.7 = 0.0 км — + # методичка §12.3.5: без фонаря ночью движение = 0 + assert distance == pytest.approx(0.0, rel=0.01) def test_adult_heavy_rain_field(self): """Test for adult in heavy rain on field.""" @@ -193,12 +194,13 @@ class TestTimeOfDayCoefficient: assert get_time_of_day_coefficient('день') == 1.0 def test_night(self): - assert get_time_of_day_coefficient('ночь') == 0.5 + # Методичка §12.3.5: ночь = 0 (без фонаря движение прекращается) + assert get_time_of_day_coefficient('ночь') == 0.0 def test_twilight(self): - # B5: сумерки/вечер = 0.7 (было 0.5 — канон фронта) - assert get_time_of_day_coefficient('сумерки') == 0.7 - assert get_time_of_day_coefficient('вечер') == 0.7 + # Методичка §12.3.3: за час до заката скорость 50% от обычной + assert get_time_of_day_coefficient('сумерки') == 0.5 + assert get_time_of_day_coefficient('вечер') == 0.5 class TestWeatherCoefficient: diff --git a/services/distance_service.py b/services/distance_service.py index 607c72d..8c01cde 100644 --- a/services/distance_service.py +++ b/services/distance_service.py @@ -82,15 +82,25 @@ def get_base_speed(age: int) -> float: """ Get base movement speed by age (НормС). + ВАЖНО (семантика): в ВЕКТОРе это НЕ «нормальная скорость по асфальту» + из методички ПСО (§12.3.2, стандарт 5 км/ч), а уже готовая скорость + СМЕЩЕНИЯ потерявшегося по лесу: НормС_асфальт × СП, усреднённое + с учётом кружения/остановок/испуга. Канон перенесён из фронтового + расчёта (B5, 3e2692f) и согласован с априорами ПСО «Экстремум»: + 400 случаев 2015 г., 94% найдены в пределах 3 км. + + Следствие: в формуле ВЕКТОРА коэффициент СП применяется ПОВЕРХ этих + значений как поправка конкретной местности (густой лес < простой лес), + поэтому СП = 1.0 соответствует «среднему лесу», а не асфальту. + Оператору НЕ нужно вводить асфальтовую скорость — она уже свёрнута. + Args: age: Age in years Returns: - Base speed in km/h + Base displacement speed in km/h """ - # Скорость смещения потерявшегося ребёнка (не скорость ходьбы) - # ПСО ЭКСТРЕМУМ: 94% найдены в пределах 3 км - # Скорость смещения потерявшегося ребёнка (не скорость ходьбы). + # Скорость смещения потерявшегося (не скорость ходьбы). # Реальное смещение: испуг, кружение, остановки. Основа — ПСО ЭКСТРЕМУМ # (400 случаев, 94% найдены в пределах 3 км). Значения перенесены из # фронтендового расчёта как каноничные (согласовано с методологией). @@ -203,10 +213,16 @@ def get_transport_coefficient(has_transport) -> float: def get_time_of_day_coefficient(time_of_day: str) -> float: """ - Get time of day movement coefficient (ВВС). + ВВС — влияние времени суток (методичка ПСО «Экстремум» §12.3.3). + + - день: 1.0 + - сумерки/вечер: 0.5 («за час до заката скорость 50% от обычной») + - ночь: 0.0 — в примере §12.3.5 этап «ночь» даёт 0 км движения: + без фонаря в лесу ночью пострадавший не перемещается. + (Свет/фонарь/Луна — редкий случай, учитывается оператором вручную.) Args: - time_of_day: Time of day + time_of_day: 'день' | 'сумерки' | 'вечер' | 'ночь' Returns: Time coefficient (0.0 - 1.0) @@ -216,9 +232,9 @@ def get_time_of_day_coefficient(time_of_day: str) -> float: time_lower = time_of_day.lower() if 'ночь' in time_lower: - return 0.5 + return 0.0 elif 'сумерки' in time_lower or 'вечер' in time_lower: - return 0.7 + return 0.5 else: # день return 1.0