Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Se7ytqbohmBQnfYpwYFnYf
128 lines
4.6 KiB
Python
128 lines
4.6 KiB
Python
"""432-3 MC 곡선 측점 열쇠 — MC 가 움직여도 B06 고침이 그 곡선 측점을 따라감.
|
|
|
|
- 열쇠 `curve:<누가거리>` 는 MC 가 0.01 m 만 움직여도 바뀜 → 예전엔 「노선 밖 고침」으로 버림.
|
|
- 이제 옛 목록에만 있는 곡선 열쇠 → 새 목록에만 있는 가장 가까운 곡선 열쇠(10 m 안 · 하나씩).
|
|
- 짝: `common_util_station_key` `curve_moves` ↔ `curveMoves`(거울) · 서버 `carry_cross_inputs` ·
|
|
B06 세션 `carryStationDrafts` · `carryChainageStates`(진짜 모듈 · vite ssr).
|
|
"""
|
|
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from B05_Profile.B05_Profile_Route_Save_Parts import carry_cross_inputs
|
|
from common_util.common_util_station_key import curve_moves
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
ROOT = HERE.parents[1]
|
|
TS = ROOT / "common_util" / "common_util_station_key.ts"
|
|
TYPESCRIPT = ROOT / "config" / "node_modules" / "typescript"
|
|
|
|
CASES = [
|
|
# MC 하나 1.75 m 움직임 · 하나 그대로 · 하나 15 m(못 이음)
|
|
(
|
|
[("end:BP", 0.0), ("curve:47.35", 47.35), ("curve:70.00", 70.0), ("curve:90.00", 90.0)],
|
|
[("end:BP", 0.0), ("curve:49.10", 49.1), ("curve:70.00", 70.0), ("curve:105.00", 105.0)],
|
|
),
|
|
# 두 옛 MC 가 한 새 MC 를 다툼 — 앞엣것이 가장 가까운 것만 · 둘째는 다음 가까운 것
|
|
(
|
|
[("curve:10.00", 10.0), ("curve:14.00", 14.0)],
|
|
[("curve:12.00", 12.0), ("curve:20.00", 20.0)],
|
|
),
|
|
# 곡선 아닌 열쇠는 안 이음 · 같은 거리 = 앞 차례
|
|
(
|
|
[("grid:1", 20.0), ("curve:30.00", 30.0)],
|
|
[("grid:2", 21.0), ("curve:25", 25.0), ("curve:35", 35.0)],
|
|
),
|
|
([], []),
|
|
]
|
|
|
|
MIRROR = r"""
|
|
const ts = require(process.argv[1]);
|
|
const src = require("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 cases = JSON.parse(process.argv[3]);
|
|
const moves = cases.map(([a, b]) => Object.fromEntries(box.exports.curveMoves(a, b)));
|
|
process.stdout.write(JSON.stringify(moves));
|
|
"""
|
|
|
|
|
|
def test_곡선_이음_규칙():
|
|
assert curve_moves(*CASES[0]) == {"curve:47.35": "curve:49.10"}
|
|
assert curve_moves(*CASES[1]) == {"curve:10.00": "curve:12.00", "curve:14.00": "curve:20.00"}
|
|
assert curve_moves(*CASES[2]) == {"curve:30.00": "curve:25"}
|
|
|
|
|
|
def test_파이썬과_TS_같음():
|
|
proc = subprocess.run(
|
|
["node", "-e", MIRROR, str(TYPESCRIPT), str(TS), json.dumps(CASES)],
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=60,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
assert json.loads(proc.stdout) == [curve_moves(*case) for case in CASES]
|
|
|
|
|
|
def test_서버_노선_저장_넘김은_움직인_MC_로():
|
|
old_keys = dict(CASES[0][0])
|
|
new_keys = dict(CASES[0][1])
|
|
designs = {47.35: {"ground_type": "rock"}, 90.0: {"ground_type": "soil"}}
|
|
inputs, _adjusts, dropped = carry_cross_inputs(old_keys, new_keys, designs, ["ground_type"], [])
|
|
assert inputs == {49.1: {"ground_type": "rock"}}
|
|
assert dropped == 1 # 15 m 움직인 MC = 다른 곡선 · 「노선 밖 고침」
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def session(tmp_path_factory):
|
|
work = tmp_path_factory.mktemp("b432")
|
|
build = subprocess.run(
|
|
[
|
|
"node",
|
|
str(ROOT / "config" / "node_modules" / "vite" / "bin" / "vite.js"),
|
|
"build",
|
|
"--configLoader",
|
|
"runner",
|
|
"--ssr",
|
|
"../resources/tester/helper_432_3_entry.ts",
|
|
"--outDir",
|
|
str(work),
|
|
"--logLevel",
|
|
"error",
|
|
],
|
|
cwd=ROOT,
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=300,
|
|
)
|
|
assert build.returncode == 0, build.stderr
|
|
bundle = work / "bundle.mjs"
|
|
shutil.copy(work / "helper_432_3_entry.js", bundle)
|
|
proc = subprocess.run(
|
|
["node", str(HERE / "helper_432_3_curve_key.mjs"), str(bundle)],
|
|
cwd=ROOT,
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=120,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
def test_B06_세션_고침이_움직인_MC_를_따라감(session):
|
|
assert set(session["cards"]) == {"49.10"}
|
|
assert session["cards"]["49.10"]["ground_type"] == "rock"
|
|
assert session["shoulder"] == {"49.10": {"left": 0.5}}
|
|
assert session["crossw"] == {"49.10": 3.2}
|
|
assert session["outside"] == 1 # 90 m MC 카드 — 15 m 움직임 = 버림
|
|
assert session["states"] == 0
|