diff --git a/B06_Section/logic/B06_Section_Station_Swap.ts b/B06_Section/logic/B06_Section_Station_Swap.ts index 897bbc320..30e03b2c9 100644 --- a/B06_Section/logic/B06_Section_Station_Swap.ts +++ b/B06_Section/logic/B06_Section_Station_Swap.ts @@ -193,7 +193,7 @@ export function swapCrossSections( oldKeys: ReadonlyArray, intervalM: number | null, routeDraft = false, - saved: ReadonlyArray> = [], + saved: ReadonlyArray>> = [], ): StationSwap { const byKey = new Map(detail.cross_sections.map((section, i) => [oldKeys[i], section])); const used = new Set(); @@ -301,7 +301,18 @@ export function swapCrossSections( : fresh ? uphillSide(station) : (prior?.uphill_side ?? null); - if (!prior) return { ...place, uphill_side: uphill, samples, design: freshDesign(uphill) }; + // 지금 상세에 없던 측점이 정본 자리로 돌아옴(관 지움 ↶ 등) = 정본 설계(472 덧 · 지우기 전과 같음) + const restored = + !prior && !routeDraft && !detail.cross_sections.some(atPlace) + ? saved.find((row): boolean => atPlace(row)) + : undefined; + if (!prior) + return { + ...place, + uphill_side: uphill, + samples, + design: restored?.design ? { ...restored.design } : freshDesign(uphill), + }; const reseed = (station.kind === "pipe" || station.kind === "structure") && Math.abs(prior.chainage_m - station.chainageM) > FACILITY_RESEED_M; diff --git a/resources/tester/helper_272_swap_canon.mjs b/resources/tester/helper_272_swap_canon.mjs index f73030665..9b282925c 100644 --- a/resources/tester/helper_272_swap_canon.mjs +++ b/resources/tester/helper_272_swap_canon.mjs @@ -212,6 +212,26 @@ const out = {}; out.pipeGone.canon = report(after)["40.00"].same; } +/* 1-5. 관 지움 → 되돌림(472 덧) — 지금 상세에 없던 측점이 정본 자리로 = 정본 설계(빈 기본 설계 아님) */ +{ + const all = stationsAt(45); + const without = all.filter((s) => s.key !== "pipe:p1"); + const gone = m.swapCrossSections(canonDetail(), without, KEYS, 20, false); + const saved = canonDetail().cross_sections; + const back = m.swapCrossSections(gone.detail, all, keysOf(without), 20, false, saved); + const at45 = back.detail.cross_sections.find((s) => s.chainage_m === 45); + const bare = m + .swapCrossSections(gone.detail, all, keysOf(without), 20, false) + .detail.cross_sections.find((s) => s.chainage_m === 45); + out.pipeRestore = { + design: json(at45.design) === json(canonOf.get(45).design), + copy: at45.design !== saved.find((s) => s.chainage_m === 45).design, + place: report(back.detail)["45.00"].same, + bytes: bytesSame(back.detail, [45]), + bareFresh: bare.design?.mark === undefined, // 정본 없음 = 기본 설계 그대로 + }; +} + /* 2. 가게 길(swapSectionStations) — 가게 routeDraft 로 가름: 없음 · 있음 · 초안 버린 직후 */ const seed = (P, R) => { m.writeState("section-detail", canonDetail(), P, R); diff --git a/resources/tester/test_272_swap_keeps_canon.py b/resources/tester/test_272_swap_keeps_canon.py index e52eca43a..8e06f1e81 100644 --- a/resources/tester/test_272_swap_keeps_canon.py +++ b/resources/tester/test_272_swap_keeps_canon.py @@ -114,7 +114,9 @@ def test_가게_길_초안_있음_버린_직후(out): for at in STRAIGHT: # 초안 차례 = 옛 규칙(기하 새 틀 · 표본 앞 값) assert not s["draft"][at]["same"] and not s["draft"][at]["browser"], at dropped = s["dropped"] - for at in CURVES: # 버린 뒤 = 저장 정본 자리 · 표본(초안 3 cm 자리 표본이 안 남음 · 467 덧 정본 물러섬) + for at in ( + CURVES + ): # 버린 뒤 = 저장 정본 자리 · 표본(초안 3 cm 자리 표본이 안 남음 · 467 덧 정본 물러섬) assert dropped[at]["same"] and not dropped[at]["browser"], at for at in STRAIGHT: # 초안이 안 옮긴 측점 = 앞 횡단 표본(서버) 그대로 assert not dropped[at]["browser"], at @@ -133,3 +135,10 @@ def test_일반_측점_자리_관_지움_다른_목록(out): assert g["sameUntouched"] is True # 일반 측점 그대로 = 같은 목록 assert g["culvertLeft"] is False and g["kind"] == "regular" # 관 카드 안 남음 assert g["canon"] # 그 자리 정본 표본 · 기하 + + +def test_관_지움_되돌림_정본_설계(out): + r = out["pipeRestore"] + assert r["design"] and r["copy"] # 지우기 전 설계(정본 사본) — 빈 기본 설계 아님(472 덧) + assert r["place"] and r["bytes"] + assert r["bareFresh"]