Files
Aislo/resources/tester/test_455_old_policy_warning.py
T

106 lines
3.5 KiB
Python

"""455 (433-13 ③) 옛 정책 종단 — 법정 최소 R · L 미달 경고가 초안 · 저장 뒤 같음.
까닭: 옛 저장 정책엔 `min_vertical_radius_m` · `min_curve_length_m` 가 없어 화면 초안(저장
정책 그대로) 경고 0 · 노선 [저장](새 정책)에서야 뜸. 고침: 빈 값은 첫 계획선 설계 기준(criteria =
설계속도 법정값)
— TS `readAlignment` ↔ 서버 `rebuild_alignment_profile` 같은 규칙(`helper_455_old_policy.cjs`).
"""
from __future__ import annotations
import copy
import json
import math
import subprocess
import sys
from pathlib import Path
HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from B05_Profile.B05_Profile_Engine_Grade import GradeDesignOptions # noqa: E402
from B05_Profile.B05_Profile_Engine_Grade_Profile import ( # noqa: E402
design_ground_following_profile,
rebuild_alignment_profile,
)
# 설계속도 40 — 법정 최소 R 450 · L 40 > 기본 L 20 → 곡선마다 미달
OPTIONS = GradeDesignOptions(
max_grade_pct=14.0,
max_reverse_grade_pct=5.0,
min_vertical_radius_m=450.0,
min_curve_length_m=40.0,
min_tangent_length_m=20.0,
vertical_curve_skip_delta_pct=0.5,
design_speed_kph=40,
)
def _ground(s: float) -> float:
return 100.0 + 0.05 * s + 2.0 * math.sin(s / 30.0)
def _fresh() -> dict:
samples = [
{"chainage_m": float(s), "elevation_m": round(_ground(s), 6), "valid": True}
for s in range(0, 401)
]
stations = [{"chainage_m": float(s), "kind": "regular"} for s in range(0, 401, 20)]
data = {"length_m": 400.0, "samples": samples, "stations": stations}
alignment, profile = design_ground_following_profile(data, OPTIONS, station_interval_m=20.0)
data["profile_alignment"], data["design_profiles"] = alignment, [profile]
return data
def _old() -> dict:
data = _fresh()
for key in ("min_vertical_radius_m", "min_curve_length_m"):
data["profile_alignment"]["policy"].pop(key)
return data
def _law(warnings: list[str]) -> list[str]:
return [text for text in warnings if "법정 최소" in text]
def _ts(tmp_path: Path, data: dict) -> dict:
source = tmp_path / "in455.json"
source.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
["node", str(HERE / "helper_455_old_policy.cjs"), str(source)],
capture_output=True,
text=True,
encoding="utf-8",
cwd=str(ROOT),
check=False,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def test_새_정책_경고_기준(tmp_path: Path) -> None:
fresh = _fresh()
law = _law(fresh["profile_alignment"]["warnings"])
assert law
assert _ts(tmp_path, fresh)["warnings"] == law
def test_옛_정책_초안_경고_저장_뒤와_같음(tmp_path: Path) -> None:
expected = _law(_fresh()["profile_alignment"]["warnings"])
old = _old()
ts = _ts(tmp_path, copy.deepcopy(old))
assert ts["policy"]["min_vertical_radius_m"] == 450.0
assert ts["policy"]["min_curve_length_m"] == 40.0
assert ts["warnings"] == expected
alignment, _profile = rebuild_alignment_profile(old, {})
assert _law(alignment["warnings"]) == expected
assert alignment["policy"]["min_curve_length_m"] == 40.0
def test_criteria_없는_판은_그대로(tmp_path: Path) -> None:
old = _old()
old["design_profiles"][0].pop("criteria")
assert _ts(tmp_path, copy.deepcopy(old))["warnings"] == []