B1: СП(лес)=1.0 — НормС трактуется как скорость смещения по среднему лесу

Решение Виктора: СП(лес) 0.5→1.0. Прежняя таблица учитывала лес дважды
(в НормС и в СП) — подросток 14 лет за 3 часа получал 2.55 км вместо
реалистичных 5.1. Согласуется с априором ПСО (94% находок в 3 км):
радиусы стали верхне-перцентилями, не медианой.

- terrain_map пересчитан относительно среднего леса: лес/простой лес/поле/
  луг/город = 1.0; сложный/густой лес 0.5; болото 0.4; горы/овраг 0.6;
  дорога/тропа 0.8; дефолт 1.0.
- Контрольные точки тестов пересчитаны (6 шт: 1.92→3.84, 0.33→0.665,
  2.43→2.7, 5.4→10.8, 13.5→15.0, stats 0.5→1.0) + операционный тест
  подростка 5.1 км.
- settlement_score пока НЕ тронут — на обдумывание (Виктор).

193 passed.
This commit is contained in:
2026-09-09 19:51:05 +03:00
parent 61308ed444
commit 2aa45e8932
3 changed files with 56 additions and 39 deletions
+24 -23
View File
@@ -22,14 +22,14 @@ class TestCalculateMaxDistance:
Ожидания соответствуют каноничным displacement-скоростям B5 (3e2692f):
get_base_speed 0.3–2.5 км/ч по априорам ПСО «Экстремум» (94% в 3 км).
Контрольная точка B5: bike 8yo 2h лес = 5.4 км.
Контрольная точка B1 2026-09-09: bike 8yo 2h лес = 10.8 км (СП(лес)=1.0).
"""
def test_boy_10_years_4_hours_forest_rain(self):
"""
Мальчик 10 лет, 4 часа, лес, дождь.
Пересчитано под канон B5: НормС(10)=1.5
Distance = 4 * 1.5 * 0.5 * 0.8 * 1.0 * 0.8 = 1.92 km
B1 2026-09-09: СП(лес)=1.0 (было 0.5): 4 * 1.5 * 1.0 * 0.8 * 1.0 * 0.8 = 3.84 km
"""
case_data = {
'age': 10,
@@ -41,7 +41,7 @@ class TestCalculateMaxDistance:
distance = calculate_max_distance(case_data)
assert distance == pytest.approx(1.92, rel=0.01)
assert distance == pytest.approx(3.84, rel=0.01)
def test_young_child_short_time(self):
"""Test for young child (3 years) with short elapsed time."""
@@ -55,8 +55,8 @@ class TestCalculateMaxDistance:
distance = calculate_max_distance(case_data)
# 1 * 0.7 * 0.5 * 0.95 * 1.0 * 1.0 = 0.33 km
assert distance == pytest.approx(0.33, rel=0.01)
# B1 2026-09-09 СП(лес)=1.0: 1 * 0.7 * 1.0 * 0.95 * 1.0 * 1.0 = 0.665 km
assert distance == pytest.approx(0.665, rel=0.01)
def test_teenager_long_time_road(self):
"""Test for teenager on road with longer elapsed time."""
@@ -101,11 +101,11 @@ class TestCalculateMaxDistance:
distance = calculate_max_distance(case_data)
# 2 * 2.5 * 0.9 * 0.9 * 1.0 * 0.6 = 2.43 km
assert distance == pytest.approx(2.43, rel=0.01)
# B1 2026-09-09 СП(поле)=1.0: 2 * 2.5 * 1.0 * 0.9 * 1.0 * 0.6 = 2.7 km
assert distance == pytest.approx(2.7, rel=0.01)
def test_bike_8yo_canonical_b5(self):
"""Контрольная точка B5: bike 8yo 2h лес = 5.4 км (СУ bike ×5)."""
"""Контрольная точка B1 2026-09-09: bike 8yo 2h лес = 10.8 км (СП(лес)=1.0, СУ bike ×5)."""
case_data = {
'age': 8,
'elapsed_hours': 2.0,
@@ -118,7 +118,7 @@ class TestCalculateMaxDistance:
distance = calculate_max_distance(case_data)
assert distance == pytest.approx(5.4, rel=0.01)
assert distance == pytest.approx(10.8, rel=0.01)
class TestBaseSpeed:
@@ -157,7 +157,8 @@ class TestBaseSpeed:
class TestTerrainCoefficient:
"""Test СП (terrain coefficient)."""
"""Test СП (terrain coefficient). Семантика: СП=1.0 — средний лес
(НормС — скорость смещения по среднему лесу; B1-ревью 2026-09-09)."""
def test_road_terrain(self):
assert get_terrain_coefficient('дорога') == 0.8
@@ -165,26 +166,26 @@ class TestTerrainCoefficient:
assert get_terrain_coefficient('тропа') == 0.8
def test_forest_terrain(self):
assert get_terrain_coefficient('лес') == 0.5
assert get_terrain_coefficient('простой лес') == 0.5
assert get_terrain_coefficient('сложный лес') == 0.25
assert get_terrain_coefficient('густой лес') == 0.25
assert get_terrain_coefficient('лес') == 1.0
assert get_terrain_coefficient('простой лес') == 1.0
assert get_terrain_coefficient('сложный лес') == 0.5
assert get_terrain_coefficient('густой лес') == 0.5
def test_open_terrain(self):
assert get_terrain_coefficient('поле') == 0.9
assert get_terrain_coefficient('луг') == 0.9
assert get_terrain_coefficient('поле') == 1.0
assert get_terrain_coefficient('луг') == 1.0
def test_difficult_terrain(self):
assert get_terrain_coefficient('болото') == 0.2
assert get_terrain_coefficient('горы') == 0.3
assert get_terrain_coefficient('овраг') == 0.3
assert get_terrain_coefficient('болото') == 0.4
assert get_terrain_coefficient('горы') == 0.6
assert get_terrain_coefficient('овраг') == 0.6
def test_urban_terrain(self):
assert get_terrain_coefficient('город') == 1.0
assert get_terrain_coefficient('населённый пункт') == 1.0
def test_unknown_terrain(self):
assert get_terrain_coefficient('неизвестно') == 0.5
assert get_terrain_coefficient('неизвестно') == 1.0
class TestTimeOfDayCoefficient:
@@ -310,7 +311,7 @@ class TestDistanceStatistics:
)
assert stats['base_speed_kmh'] == 1.5
assert stats['terrain_coefficient'] == 0.5
assert stats['terrain_coefficient'] == 1.0
assert stats['max_distance_km'] > 0
assert 0 <= stats['zone_probability'] <= 1.0
@@ -352,5 +353,5 @@ class TestFatigueCoefficient:
distance = calculate_max_distance(case_data)
# 20 * 2.5 * 0.9 * 0.3 * 1.0 * 1.0 = 13.5
assert distance == pytest.approx(13.5, rel=0.01)
# B1 2026-09-09 СП(поле)=1.0: 20 * 2.5 * 1.0 * 0.3 * 1.0 * 1.0 = 15.0
assert distance == pytest.approx(15.0, rel=0.01)