# -*- coding: utf-8 -*- """380-2 사토장 · 토취장(site) 자리 = 가장 가까운 기존 측점 · 새 측점 안 심음(요구 241-8). 기존 측점 = 일반(격자 · 시종점) · 구조물(irregular) · 추가(plus). 아무 m 를 넣어도 그중 가장 가까운 측점 · 가운데면 앞 측점 · 목록이 비면 정수 m. 폼 [추가] · 끌기 · 우클릭이 같은 맞춤 · 옛 소수 자동 맞춤은 기존 측점(끝 소수 포함)에 선 site 를 안 옮김. 진짜 TS 를 `helper_380_2_site_station.cjs` 가 Node 로 돌린다. """ from __future__ import annotations import json import subprocess from pathlib import Path import pytest HERE = Path(__file__).resolve().parent ROOT = HERE.parents[1] STATIONS = [ {"chainage_m": 0.0, "kind": "bp"}, {"chainage_m": 20.0, "kind": "regular"}, {"chainage_m": 33.4, "kind": "irregular"}, # 옛 소수 구조물 측점 {"chainage_m": 40.0, "kind": "regular"}, {"chainage_m": 60.0, "kind": "regular"}, {"chainage_m": 79.8, "kind": "ep"}, # 끝 소수 ] PLUS = [47.0, 20.0] # 추가 측점(같은 m 는 하나) # (친 m, 기대 측점) TYPED = [ (25.0, 20.0), (27.0, 33.4), # 구조물 측점 (43.0, 40.0), (44.0, 47.0), # 추가 측점 (10.0, 0.0), # 가운데 = 앞 측점 (53.5, 47.0), # 가운데 = 앞 측점 (78.0, 79.8), # 끝 소수 그대로 (1000.0, 79.8), # 노선 밖 = 끝 (-5.0, 0.0), (60.0, 60.0), ] OFF_GRID = [ {"placement": "site", "chainage_m": 79.8}, # 기존 측점(끝 소수) — 안 옮김 {"placement": "site", "chainage_m": 33.4}, # 기존 구조물 측점 — 안 옮김 {"placement": "site", "chainage_m": 50.3}, # 소수 · 측점 아님 — 가까운 기존 측점으로 {"placement": "site", "chainage_m": 55.0}, # 정수 — 옛 규칙대로 안 옮김 {"placement": "point", "chainage_m": 79.8}, # site 아님 — 옛 규칙(정수 m) ] pytestmark = pytest.mark.skipif( not (ROOT / "config" / "node_modules" / "typescript").is_dir(), reason="프론트엔드 의존성 미설치", ) @pytest.fixture(scope="module") def ts(tmp_path_factory) -> dict: source = tmp_path_factory.mktemp("s380") / "in.json" source.write_text( json.dumps( { "stations": STATIONS, "plus": PLUS, "typed": [value for value, _ in TYPED], "offGrid": OFF_GRID, } ), encoding="utf-8", ) proc = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", str(HERE / "helper_380_2_site_station.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_기존_측점_일반_구조물_추가(ts) -> None: assert ts["existing"] == [0.0, 20.0, 33.4, 40.0, 47.0, 60.0, 79.8] def test_아무_m_입력_가까운_기존_측점(ts) -> None: assert ts["snap"] == [expected for _, expected in TYPED] assert ts["twice"] == ts["snap"] # 두 번 맞춰도 같음 assert ts["emptySnap"] == 25 # 목록 전 = 정수 m def test_site_만_기존_측점_그_밖_정수(ts) -> None: assert ts["siteFor"] == 20 and ts["pointFor"] == 25 assert ts["movedSite"] == 33.4 # 끌기 = 가까운 기존 측점 assert ts["movedPoint"] == 35 def test_옛_자동_맞춤은_기존_측점_site_안_옮김(ts) -> None: assert ts["offGrid"] == [False, False, True, False, True] assert ts["planned"] == [[2, 47.0], [4, 79.0]] # 끝 79.8 아래 정수 def test_상세_CAD_글_사토장_부피_줄() -> None: """맞춘 기존 측점 = 상세 모달 CAD 글 측점(±0.51 m) — 종류 이름 + 「사토장 부피」 줄.""" import sys if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from B07_DesignDetail.B07_DesignDetail_Engine_Cad_CulvertNote import ( structure_note_lines, with_option_lines, ) things = with_option_lines( [ { "name": "유용토운반작업장(사토장)", "pipe": False, "at": 33.4, "summary_item": None, "group_items": None, "type_id": "spoil_bank", "options": {"capacity_m3": 150}, } ] ) assert structure_note_lines(things, 33.4) == [ "유용토운반작업장(사토장)", "상세 내용: 사토장 부피 150㎥", ] assert structure_note_lines(things, 40.0) == [] # 이웃 측점엔 없음