Согласование радиуса: summary = max_distance × средний психотип-множитель

- search_engine: max_distance_km передаётся в analyzer (case_data).
- rules_analysis: search_radius = max_distance × _psychotype_radius_multiplier
  (среднее по полосам 0-500/0.5-1.5/1.5-2.5/2.5+). Убран двойной учёт
  age/season: score_zone.distance_multiplier их уже содержит, а max_distance
  их тоже учёл — раньше radius = multiplier×2.0 (хардкод) давал 1.6 км при
  радиусе 2.4 км.
- UI: подсказка у «×0.8» — коэффициент скоринга, не радиуса.
- Тест: согласованность summary↔формула.
This commit is contained in:
2026-09-09 23:25:06 +03:00
parent 1fe3b37d1a
commit 1513bad538
4 changed files with 41 additions and 4 deletions
+18 -1
View File
@@ -69,4 +69,21 @@ class TestZoneReason:
r1 = _build_zone_reason(zone, case)
r2 = _build_zone_reason(dict(zone), dict(case))
assert r1 == r2
assert 'совпадает с направлением' in r1
assert 'совпадает с направлением' in r1
class TestRadiusConsistency:
def test_summary_radius_matches_max_times_multiplier(self):
"""Радиус в summary = max_distance × психотип-множитель (согласован с хедером)."""
import asyncio
from services.rules_analysis import rules_analyze
case = {
'age': 9, 'gender': 'м', 'season': 'лето', 'elapsed_hours': 4.0,
'profiles': ['гармоничный'], 'psychotype': 'harmonic',
'psychotype_modifiers': {'zone_0_500': 1.0, 'zone_500_1500': 1.0,
'zone_1500_2500': 1.1, 'zone_2500plus': 1.0},
'max_distance_km': 2.4,
'lat': 54.5, 'lon': 28.5,
}
result = asyncio.run(rules_analyze(case))
# Средний психотип-множитель полос (1.0+1.0+1.1+1.0)/4 = 1.025 → 2.4×1.025=2.46→2.5
assert result.search_radius_km == 2.5, result.search_radius_km
assert f'{result.search_radius_km} км' in result.summary