"""편집 창 종단 띠 — [확인]과 같은 노선 점으로 균형 종단을 셈한다(PLAN 75-1). ./venv/Scripts/python.exe -m pytest resources/tester/test_75_profile_strip.py -q """ import asyncio from pathlib import Path from uuid import uuid4 from B05_Profile import B05_Profile_Router_Replan as replan from B05_Profile import B05_Profile_Router_RouteInitial as initial from common_util.common_util_route_geometry import read_planned_route_csv NODES = [(0.0, 0.0), (120.0, 35.0), (180.0, 140.0), (310.0, 150.5)] RADIUS_M = 25.0 def _strip_points(monkeypatch, tmp_path: Path, criteria=None) -> tuple[list, object]: seen: dict = {} async def paths(_pid): return tmp_path, "x" async def plan_criteria(_pid): return RADIUS_M, 0.0, 0.0 async def profile_of(_pid, _root, points, crit, curves=None): seen["points"], seen["criteria"], seen["curves"] = points, crit, curves return {"stations_m": [0.0, 20.0], "plan_m": [1.0, 2.0]} monkeypatch.setattr(replan, "_project_paths", paths) monkeypatch.setattr(replan, "_plan_criteria", plan_criteria) monkeypatch.setattr(initial, "balanced_profile_of", profile_of) request = initial.ProfilePreviewRequest( vertices=[ replan.RouteVertexInput(x=x, y=y, curve=i != 2, radius_m=40.0 if i == 1 else None) for i, (x, y) in enumerate(NODES) ], criteria=criteria, ) answer = asyncio.run(initial.profile_preview(uuid4(), request)) assert answer["profile"]["plan_m"] == [1.0, 2.0] return seen["points"], seen["criteria"] def test_띠_노선점은_확인이_읽는_CSV와_같다(monkeypatch, tmp_path: Path) -> None: points, _ = _strip_points(monkeypatch, tmp_path) working = tmp_path / "planned_route.csv" replan._write_planned_polyline( working, NODES, RADIUS_M, simplify=False, curve_flags=[True, True, False, True], radii=[None, 40.0, None, None], ) stored = read_planned_route_csv(working) assert stored is not None assert [(p["x"], p["y"]) for p in points] == [(v.x, v.y) for v in stored.vertices] assert len(points) > len(NODES) # 원호가 펴져 있다 def test_띠는_그_노선의_곡선표로_확폭을_맨다(monkeypatch, tmp_path: Path) -> None: seen: dict = {} async def paths(_pid): return tmp_path, "x" async def plan_criteria(_pid): return RADIUS_M, 0.0, 0.0 async def profile_of(_pid, _root, _points, _crit, curves=None): seen["curves"] = curves return {"stations_m": [0.0, 20.0], "plan_m": [1.0, 2.0]} monkeypatch.setattr(replan, "_project_paths", paths) monkeypatch.setattr(replan, "_plan_criteria", plan_criteria) monkeypatch.setattr(initial, "balanced_profile_of", profile_of) request = initial.ProfilePreviewRequest( vertices=[ replan.RouteVertexInput(x=x, y=y, curve=i != 2, radius_m=40.0 if i == 1 else None) for i, (x, y) in enumerate(NODES) ] ) asyncio.run(initial.profile_preview(uuid4(), request)) assert seen["curves"] and 40.0 in [c["radius_m"] for c in seen["curves"]] assert all({"start", "apex", "end", "radius_m"} <= set(c) for c in seen["curves"]) def test_띠는_지금_추천_제약을_싣는다(monkeypatch, tmp_path: Path) -> None: criteria = replan.RouteInitialCriteria(max_grade_pct=12.0) _, got = _strip_points(monkeypatch, tmp_path, criteria) assert got.max_grade_pct == 12.0 def test_확인_목표는_같은_셈의_측점_계획고(monkeypatch, tmp_path: Path) -> None: async def profile_of(*_args): return {"stations_m": [0.0, 20.0, 31.5], "plan_m": [5.0, 6.0, 6.5], "cut_m3": 1.0} monkeypatch.setattr(initial, "balanced_profile_of", profile_of) target = asyncio.run(initial.balanced_target(uuid4(), tmp_path, [], None)) assert target == ([0.0, 20.0, 31.5], [5.0, 6.0, 6.5])