From 11197931459579c7231b448f1a52468b0e78147b Mon Sep 17 00:00:00 2001 From: viktot14-ai Date: Wed, 9 Sep 2026 10:56:28 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20distance=5Fserv?= =?UTF-8?q?ice=20=D0=BF=D0=BE=D0=B4=20=D0=BA=D0=B0=D0=BD=D0=BE=D0=BD=20B5?= =?UTF-8?q?=20(3e2692f)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Тесты проверяли старые бэкендовские скорости (1.0–5.5 км/ч), тогда как B5 перенёс в живую копию services/distance_service.py каноничные displacement-скорости фронта (0.3–2.5 км/ч, априоры ПСО «Экстремум», 94% в 3 км) и сумерки 0.7. Обновлены ожидания (пересчитаны все кейсы): - TestBaseSpeed: 0.3/0.7/1.2/1.5/2.0/2.5/2.5/1.5 по возрастам - 5 кейсов calculate_max_distance пересчитаны (5.12→1.92 и т.д.) - test_twilight: 0.5 → 0.7 - test_statistics_values: base_speed 4.0 → 1.5 - test_fatigue_minimum: 27.0 → 13.5 - Добавлена контрольная точка B5: bike 8yo 2h лес = 5.4 км Коэффициенты в services/ НЕ тронуты (B1-safe) — только тесты. 201 passed, 0 failed. --- backend/tests/test_distance_service.py | 125 ++++++++++++++----------- 1 file changed, 69 insertions(+), 56 deletions(-) diff --git a/backend/tests/test_distance_service.py b/backend/tests/test_distance_service.py index 47ea196..864a61e 100644 --- a/backend/tests/test_distance_service.py +++ b/backend/tests/test_distance_service.py @@ -18,12 +18,18 @@ from services.distance_service import ( class TestCalculateMaxDistance: - """Test the main distance calculation function.""" + """Test the main distance calculation function. + + Ожидания соответствуют каноничным displacement-скоростям B5 (3e2692f): + get_base_speed 0.3–2.5 км/ч по априорам ПСО «Экстремум» (94% в 3 км). + Контрольная точка B5: bike 8yo 2h лес = 5.4 км. + """ def test_boy_10_years_4_hours_forest_rain(self): """ - Test case from requirements: - Мальчик 10 лет, 4 часа, лес, дождь → ~5 км + Мальчик 10 лет, 4 часа, лес, дождь. + Пересчитано под канон B5: НормС(10)=1.5 + Distance = 4 * 1.5 * 0.5 * 0.8 * 1.0 * 0.8 = 1.92 km """ case_data = { 'age': 10, @@ -32,20 +38,10 @@ class TestCalculateMaxDistance: 'time_of_day': 'день', 'weather': 'дождь' } - + distance = calculate_max_distance(case_data) - - # Expected calculation: - # Time = 4 hours - # НормС (age 10) = 4.0 km/h - # СП (лес) = 0.5 - # СУТ (4 hours) = 1.0 - (0.05 * 4) = 0.8 - # ВВС (день) = 1.0 - # ВП (дождь) = 0.8 - # Distance = 4 * 4.0 * 0.5 * 0.8 * 1.0 * 0.8 = 5.12 km - - assert 4.5 <= distance <= 5.5, f"Expected ~5 km, got {distance} km" - assert distance == pytest.approx(5.12, rel=0.01) + + assert distance == pytest.approx(1.92, rel=0.01) def test_young_child_short_time(self): """Test for young child (3 years) with short elapsed time.""" @@ -56,11 +52,11 @@ class TestCalculateMaxDistance: 'time_of_day': 'день', 'weather': 'нет' } - + distance = calculate_max_distance(case_data) - - # Expected: 1 * 2.0 * 0.5 * 0.95 * 1.0 * 1.0 = 0.95 km - assert distance == pytest.approx(0.95, rel=0.01) + + # 1 * 0.7 * 0.5 * 0.95 * 1.0 * 1.0 = 0.33 km + assert distance == pytest.approx(0.33, rel=0.01) def test_teenager_long_time_road(self): """Test for teenager on road with longer elapsed time.""" @@ -71,11 +67,11 @@ class TestCalculateMaxDistance: 'time_of_day': 'день', 'weather': 'нет' } - + distance = calculate_max_distance(case_data) - - # Expected: 6 * 5.0 * 0.8 * 0.7 * 1.0 * 1.0 = 16.8 km - assert distance == pytest.approx(16.8, rel=0.01) + + # 6 * 2.0 * 0.8 * 0.7 * 1.0 * 1.0 = 6.72 km + assert distance == pytest.approx(6.72, rel=0.01) def test_elderly_night_swamp(self): """Test for elderly person at night in swamp.""" @@ -86,11 +82,11 @@ class TestCalculateMaxDistance: 'time_of_day': 'ночь', 'weather': 'туман' } - + distance = calculate_max_distance(case_data) - - # Expected: 3 * 3.0 * 0.2 * 0.85 * 0.5 * 0.7 = 0.54 km - assert distance == pytest.approx(0.54, rel=0.01) + + # 3 * 1.5 * 0.2 * 0.85 * 0.5 * 0.7 = 0.27 km + assert distance == pytest.approx(0.27, rel=0.01) def test_adult_heavy_rain_field(self): """Test for adult in heavy rain on field.""" @@ -101,46 +97,62 @@ class TestCalculateMaxDistance: 'time_of_day': 'день', 'weather': 'ливень' } - + distance = calculate_max_distance(case_data) - - # Expected: 2 * 5.0 * 0.9 * 0.9 * 1.0 * 0.6 = 4.86 km - assert distance == pytest.approx(4.86, rel=0.01) + + # 2 * 2.5 * 0.9 * 0.9 * 1.0 * 0.6 = 2.43 km + assert distance == pytest.approx(2.43, rel=0.01) + + def test_bike_8yo_canonical_b5(self): + """Контрольная точка B5: bike 8yo 2h лес = 5.4 км (СУ bike ×5).""" + case_data = { + 'age': 8, + 'elapsed_hours': 2.0, + 'terrain_primary': 'лес', + 'time_of_day': 'день', + 'weather': 'нет', + 'has_transport': 'bike', + 'diagnosis_type': [], + } + + distance = calculate_max_distance(case_data) + + assert distance == pytest.approx(5.4, rel=0.01) class TestBaseSpeed: - """Test НормС (base speed) by age.""" + """Test НормС (base speed) by age — каноничные displacement-скорости B5.""" def test_infant(self): - assert get_base_speed(1) == 1.0 - assert get_base_speed(2) == 1.0 + assert get_base_speed(1) == 0.3 + assert get_base_speed(2) == 0.3 def test_preschool(self): - assert get_base_speed(3) == 2.0 - assert get_base_speed(5) == 2.0 + assert get_base_speed(3) == 0.7 + assert get_base_speed(5) == 0.7 def test_young_child(self): - assert get_base_speed(6) == 3.0 - assert get_base_speed(8) == 3.0 + assert get_base_speed(6) == 1.2 + assert get_base_speed(8) == 1.2 def test_preteen(self): - assert get_base_speed(10) == 4.0 - assert get_base_speed(12) == 4.0 + assert get_base_speed(10) == 1.5 + assert get_base_speed(12) == 1.5 def test_teenager(self): - assert get_base_speed(13) == 5.0 - assert get_base_speed(15) == 5.0 - assert get_base_speed(16) == 5.5 - assert get_base_speed(17) == 5.5 + assert get_base_speed(13) == 2.0 + assert get_base_speed(15) == 2.0 + assert get_base_speed(16) == 2.5 + assert get_base_speed(17) == 2.5 def test_adult(self): - assert get_base_speed(25) == 5.0 - assert get_base_speed(50) == 5.0 - assert get_base_speed(64) == 5.0 + assert get_base_speed(25) == 2.5 + assert get_base_speed(50) == 2.5 + assert get_base_speed(64) == 2.5 def test_elderly(self): - assert get_base_speed(65) == 3.0 - assert get_base_speed(80) == 3.0 + assert get_base_speed(65) == 1.5 + assert get_base_speed(80) == 1.5 class TestTerrainCoefficient: @@ -184,8 +196,9 @@ class TestTimeOfDayCoefficient: assert get_time_of_day_coefficient('ночь') == 0.5 def test_twilight(self): - assert get_time_of_day_coefficient('сумерки') == 0.5 - assert get_time_of_day_coefficient('вечер') == 0.5 + # B5: сумерки/вечер = 0.7 (было 0.5 — канон фронта) + assert get_time_of_day_coefficient('сумерки') == 0.7 + assert get_time_of_day_coefficient('вечер') == 0.7 class TestWeatherCoefficient: @@ -294,7 +307,7 @@ class TestDistanceStatistics: terrain='лес' ) - assert stats['base_speed_kmh'] == 4.0 + assert stats['base_speed_kmh'] == 1.5 assert stats['terrain_coefficient'] == 0.5 assert stats['max_distance_km'] > 0 assert 0 <= stats['zone_probability'] <= 1.0 @@ -336,6 +349,6 @@ class TestFatigueCoefficient: } distance = calculate_max_distance(case_data) - - # 20 * 5.0 * 0.9 * 0.3 * 1.0 * 1.0 = 27.0 - assert distance == pytest.approx(27.0, rel=0.01) + + # 20 * 2.5 * 0.9 * 0.3 * 1.0 * 1.0 = 13.5 + assert distance == pytest.approx(13.5, rel=0.01)