"""475-1 — 노선 선 소수 자리 한 벌(요구 275 ① · 브라우저 ↔ 서버 저장 차). 짝 = 서버 노선 geojson `_route_geojson` x · y 4자리 = 계획노선 csv `write_route_csv` = 브라우저 route 단계 `draftLine`(`B05_Profile_Pipeline_RouteGround.ts`). 같은 선이면 측점 · 지반 · 계획선 · 면적 짝이 모두 같아 누가토량 차가 사라짐(옛 3자리 = 교점 끌기 0.8 ㎥). 고정 자료 = `fixtures/golden_472` · 브라우저 길 = `helper_472_1_browser.mjs` 옮김 인자 · 서버 길 = `helper_475_1_moved.server_moved`(노선 저장 체인 DB 없이). ./venv/Scripts/python.exe -m pytest resources/tester/test_475_1_route_digits.py -q """ from __future__ import annotations import copy import helper_472_1_paths as paths import helper_475_1_moved as moved import pytest from B05_Profile.B05_Profile_Router_Replan import _vertices_of from common_util.common_util_route_geometry import write_route_csv WALL = { "structure_id": "wall600", "type_id": "retaining_wall", "placement": "interval", "chainage_m": 600.0, "start_m": 595.0, "end_m": 605.0, "options": { "wall_form": "콘크리트", "length_m": 10, "height_m": 2, "before_m": 5, "after_m": 5, "side": "자동(성토 쪽)", }, "memo": "", "placement_source": "manual", "status": "draft", "revision": 0, "geometry": None, "summary_item": None, "group_items": None, "x": 208785.614, "y": 367845.1028, } # 교점 9(360 m 언저리) 동 +5 m · 같은 끌기 + 옹벽 595–605 + 추가 측점 510 CASES = { "drag": {"node": 9, "dx": 5, "dy": 0}, "drag_wall_plus": {"node": 9, "dx": 5, "dy": 0, "plus": [510], "structures": [WALL]}, } def test_geojson_자리_csv_와_같음(tmp_path) -> None: from B05_Profile.B05_Profile_Engine import _route_geojson line = [[208785.61234567, 367845.10285, 512.34567], [208790.00005001, 367850.99994999, 1.0]] write_route_csv(tmp_path / "r.csv", [{"x": x, "y": y} for x, y, _ in line]) csv_xy = [list(p) for p in _vertices_of(tmp_path / "r.csv")] geo = _route_geojson(line)["geometry"]["coordinates"] assert [[x, y] for x, y, _ in geo] == csv_xy assert geo[0][0] == 208785.6123 and geo[0][2] == 512.346 @pytest.fixture(scope="module", params=list(CASES)) def pair(request, tmp_path_factory) -> tuple[dict, dict]: if not (paths.ROOT / "config" / "node_modules" / "vite").is_dir(): pytest.skip("프론트엔드 의존성 미설치") move = copy.deepcopy(CASES[request.param]) work = tmp_path_factory.mktemp(request.param) browser = paths.browser(work, move) # 추가 측점 = 브라우저가 새 노선으로 따라간 자리(페이지 [저장]이 보내는 값) if move.get("plus"): move["plus"] = [s["chainage_m"] for s in browser["stations"] if "plus-" in (s["key"] or "")] server = moved.server_moved( paths.stage_project(work / "project"), {**move, "draft": browser["draft"]} ) return browser, server def test_그린_선_서버_선_같음(pair) -> None: browser, server = pair assert browser["route_line"] == server["route_line"] def test_누가토량_차_002_안(pair) -> None: browser, server = pair b, s = browser["final_cumulative_m3"], server["final_cumulative_m3"] assert browser["station_count"] == server["station_count"] assert abs(b - s) <= 0.02, f"브라우저 {b} · 서버 {s}"