# -*- coding: utf-8 -*- """344-3 측점 열쇠 거울 — `common_util_station_key.py` ↔ `common_util_station_key.ts` 같은 열쇠. 일반 grid:k(누가거리 ÷ 간격 반올림 · 0.5 는 위로) · 관 pipe: · 구조물 structure: · 시종점 end:BP/EP · id 모름 at:<0.01 m> · 옛 열쇠(누가거리 글) · at: 의 누가거리. """ import json import subprocess import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[2] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from common_util.common_util_station_key import ( # noqa: E402 chainage_key, dedupe_station_keys, loose_chainage, station_key, ) TS = PROJECT_ROOT / "common_util" / "common_util_station_key.ts" TYPESCRIPT = PROJECT_ROOT / "config" / "node_modules" / "typescript" CASES = [ ("bp", 0.0, 20.0, None, "structure", "anchor"), # 5파 — 묶음 측점 종류(grid · end) · 구간형 시작 · 끝(:start · :end) ("grid", 41.3, 20.0, "2", "structure", "anchor"), ("grid", 41.3, 20.0, None, "structure", "anchor"), ("end", 0.0, 20.0, None, "structure", "anchor"), ("end", 99.0, 20.0, None, "structure", "anchor"), ("end", 99.0, 20.0, "EP", "structure", "anchor"), ("structure", 30.0, 20.0, "st-9", "structure", "start"), ("structure", 36.0, 20.0, "st-9", "structure", "end"), ("irregular", 30.0, 20.0, "st-9", "structure", "start"), ("pipe", 30.0, 20.0, None, "structure", "end"), ("ep", 812.345, 20.0, None, "structure"), ("regular", 40.0, 20.0, None, "structure"), ("regular", 50.0, 20.0, None, "structure"), # 2.5 → 3(위로) ("regular", 69.996, 20.0, None, "structure"), ("regular", 40.0, None, None, "structure"), ("irregular", 85.054, 20.0, "pipe-s3", "pipe"), ("irregular", 85.054, 20.0, "st-7", "structure"), ("irregular", 85.054, 20.0, None, "structure"), ("irregular", 1.005, 20.0, None, "structure"), ("pipe", 12.344, 20.0, "pipe-s1", "structure"), ("structure", 12.345, 20.0, None, "structure"), ] DEDUPE = (["grid:1", "structure:st-1", "grid:1", "structure:st-1"], [20.0, 25.0, 20.004, 25.006]) LOOSE = ["85.05", "at:85.05", "grid:4", "pipe:pipe-s3", "-1.5", "end:BP"] SCRIPT = r""" const ts = require(process.argv[1]); const fs = require("fs"); const src = fs.readFileSync(process.argv[2], "utf8"); const opts = { compilerOptions: { module: ts.ModuleKind.CommonJS } }; const js = ts.transpileModule(src, opts).outputText; const box = { exports: {} }; new Function("exports", "module", js)(box.exports, box); const m = box.exports; const input = JSON.parse(process.argv[3]); process.stdout.write(JSON.stringify({ keys: input.cases.map((c) => m.stationKey(c[0], c[1], c[2], c[3], c[4], c[5] ?? "anchor")), dedupe: m.dedupeStationKeys(input.dedupe[0], input.dedupe[1]), chainage: input.cases.map((c) => m.chainageKey(c[1])), loose: input.loose.map((k) => m.looseChainage(k)), })); """ def test_파이썬과_TS_열쇠_같음(): proc = subprocess.run( [ "node", "-e", SCRIPT, str(TYPESCRIPT), str(TS), json.dumps({"cases": CASES, "loose": LOOSE, "dedupe": DEDUPE}), ], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr out = json.loads(proc.stdout) assert out["keys"] == [station_key(*case) for case in CASES] assert out["chainage"] == [chainage_key(case[1]) for case in CASES] assert out["loose"] == [loose_chainage(key) for key in LOOSE] assert out["dedupe"] == dedupe_station_keys(*DEDUPE) def test_열쇠_규칙(): assert station_key("bp", 0.0, 20.0) == "end:BP" assert station_key("ep", 812.3, 20.0) == "end:EP" assert station_key("regular", 50.0, 20.0) == "grid:3" assert station_key("irregular", 85.054, 20.0, "pipe-s3", "pipe") == "pipe:pipe-s3" assert station_key("irregular", 85.054, 20.0) == "at:85.05" assert loose_chainage("85.05") == 85.05 and loose_chainage("grid:4") is None # 5파 — 구간형 시작 · 끝 · 기준은 그대로 · 원래 격자 번호 · 같은 열쇠 둘째는 at: assert station_key("structure", 30.0, 20.0, "st-9", role="start") == "structure:st-9:start" assert station_key("structure", 33.0, 20.0, "st-9") == "structure:st-9" assert station_key("grid", 41.3, 20.0, "2") == "grid:2" assert station_key("end", 99.0, 20.0) == "end:EP" assert dedupe_station_keys(*DEDUPE) == ["grid:1", "structure:st-1", "at:20.00", "at:25.01"]