"""PLAN 448(442-2) 거울 — 「페이지 설정」 TS 기준표 ↔ 파이썬 법정 기준 전수. TS `logic/B05_Profile_Grade_Criteria.ts`(511-B B-3 · 화면 `_UI_Panel_Fields.ts` 에서 옮김) PROFILE_CRITERIA · SPEED_CHOICES 와 `gradeLimitPct` 규칙 (고를 수 없는 속도 = 첫 선택지 · 넣은 값 > 0 이면 그 값 · 아니면 표)을 파이썬 `FOREST_ROAD_PROFILE_CRITERIA` · `resolve_grade_options(...).max_grade_pct` 와 임도 종류 × 속도 × 지형 × 입력 유무 전부 대조. TS 표는 `helper_442_2_page_settings.cjs` 가 꺼냄. ./venv/Scripts/python.exe -m pytest resources/tester/test_442_2_grade_limit_mirror.py -q """ from __future__ import annotations import itertools import json import subprocess from pathlib import Path import pytest from B05_Profile.B05_Profile_Engine_Grade import resolve_grade_options from config.config_system_design import FOREST_ROAD_PROFILE_CRITERIA as PY HERE = Path(__file__).parent @pytest.fixture(scope="module") def ts_tables(): proc = subprocess.run( ["node", str(HERE / "helper_442_2_page_settings.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr out = json.loads(proc.stdout) return out["criteria"], out["speedChoices"] def test_속도별_기울기_반경_표가_같음(ts_tables): criteria, _ = ts_tables assert sorted(int(speed) for speed in criteria) == sorted(PY["design_speed"]) for speed, legal in PY["design_speed"].items(): ts = criteria[str(speed)] assert ts["grade"] == legal["max_grade_pct"] assert ts["radius"] == legal["min_vertical_radius_m"] def test_종류별_속도_선택지가_같음(ts_tables): _, choices = ts_tables for road, allowed in choices.items(): assert tuple(allowed) == tuple(PY["selectable_design_speeds"].get(road, (20,))) def _ts_limit(criteria, choices, road, speed, terrain, typed): allowed = choices.get(road, [20]) speed = speed if speed in allowed else allowed[0] # syncSpeedChoices if typed is not None and typed > 0: return float(typed) return float(criteria[str(speed)]["grade"][terrain]) def test_기울기_상한_전수(ts_tables): criteria, choices = ts_tables cases = itertools.product( ["trunk", "fire", "work", "branch"], [20, 30, 40], ["normal", "special"], [None, 11.5] ) for road, speed, terrain, typed in cases: py = resolve_grade_options( road, terrain_type=terrain, design_speed_kph=speed, stored={} if typed is None else {"max_grade_pct": typed}, ) assert _ts_limit(criteria, choices, road, speed, terrain, typed) == py.max_grade_pct, ( road, speed, terrain, typed, )