diff --git a/A00_Common/design/design_pipeline_page.ts b/A00_Common/design/design_pipeline_page.ts index 895ecb64e..69f6a0bcc 100644 --- a/A00_Common/design/design_pipeline_page.ts +++ b/A00_Common/design/design_pipeline_page.ts @@ -337,6 +337,8 @@ function createPagePipeline( saved, ) : list; + /** 다시 셈 창구가 낸 cross 출력(365-4) — 엔진 재사용에서 뺌. */ + const savedOut = new WeakSet(); const pipe = createDesignPipeline({ stages: { route: createRouteStage({ @@ -363,9 +365,11 @@ function createPagePipeline( // 단면 유형 기본값 = 새 지형 상단측(서버 노선 저장 규칙) — 단계 본문은 그대로 부름 · 저장 노선 = 다시 셈 // 창구 한 벌(카드 · 유토곡선이 보는 상세 설계 · 365-4) cross: (ctx) => { + // 엔진은 다시 셈 창구가 낸 앞 출력을 이어 쓰지 않음 — 초안 = 새로고침과 같은 값(365-4) const engine = () => crossStage.stage({ ...ctx, + prev: ctx.prev && savedOut.has(ctx.prev) ? null : ctx.prev, inputs: { ...ctx.inputs, cross: crossWithUphill( @@ -379,7 +383,12 @@ function createPagePipeline( !ctx.inputs.route && detail && typeof routeId === "number" ? options.savedCross?.(detail, routeId, ctx.out.ground?.stations ?? []) : null; - return saved ? saved.then((out) => out ?? engine()) : engine(); + if (!saved) return engine(); + return saved.then((out) => { + if (!out) return engine(); + savedOut.add(out); + return out; + }); }, footprint: footprintStage, masshaul: createMassHaulStage(() => earthwork), diff --git a/resources/tester/helper_365_page_pipeline.cjs b/resources/tester/helper_365_page_pipeline.cjs index 8ee5eecee..eb9f29bfa 100644 --- a/resources/tester/helper_365_page_pipeline.cjs +++ b/resources/tester/helper_365_page_pipeline.cjs @@ -341,16 +341,26 @@ async function run() { const Q = "proj-365b"; window.localStorage.setItem("frd_current_project_id", Q); let refreshCalls = 0; - const qBridge = pageMod.routeDraftBridge(Q, link(), { + let qBridge = pageMod.routeDraftBridge(Q, link(), { stationIntervalM: job.interval, savedCross: async (detail, _routeId, stations) => { if (!detailMod.detailCross(detail, stations)) return null; refreshCalls += 1; + // 창구가 고친 설계 흉내 — 계획고 = 지금 종단(엔진이 「같은 자리」로 볼 값) · 면적 표시 999 + const profile = pageMod.pagePipeline(Q).output("profile"); + detail.cross_sections.forEach((section) => { + section.design = { + ...section.design, + design_elevation_m: alignment.planElevationAt(profile, section.chainage_m), + cut_area_m2: 999, + fill_area_m2: 999, + }; + }); return detailMod.detailCross(detail, stations); }, }); pageMod.pipelineEarthwork(Q, { conversion: job.conversion }); - const qPipe = pageMod.pagePipeline(Q); + let qPipe = pageMod.pagePipeline(Q); await settle(runs().length + 1); await tick(20); const openCalls = refreshCalls; @@ -369,6 +379,25 @@ async function run() { qPipe.output("cross").byKey[firstKey]?.detail === job.detail.cross_sections[0].design, }; + // ⑩ 다시 셈 창구로 연 뒤 끈 초안 = 새로고침(초안 둔 채 다시 열기) 초안 — 엔진이 창구 출력을 안 이어 씀 + mark = runs().length; + qBridge.edited(draftOf(shift(n - 2, 0, 2))); + await settle(mark + 1); + await tick(job.haulDelayMs + 30); + const dragRows = shownRows(Q); + pageMod.disposePagePipeline(Q); + qBridge = pageMod.routeDraftBridge(Q, link(), { stationIntervalM: job.interval }); + pageMod.pipelineEarthwork(Q, { conversion: job.conversion }); + qPipe = pageMod.pagePipeline(Q); + await settle(runs().length + 1); + await tick(job.haulDelayMs + 30); + const reopenRows = shownRows(Q); + const sameAfterReload = { + rows: dragRows?.length ?? 0, + same: JSON.stringify(dragRows) === JSON.stringify(reopenRows), + marked: (dragRows ?? []).filter((row) => row[2] === 999).length, + }; + // ⑧ 중심점 좌우(356-3 꼴) — 노선 한 걸음 → 새 종단이 오면 계획고 맞춤 · 첫 차례는 cross 전에 밀림(무거운 셈 한 번) let graded = false; const stopShift = qPipe.subscribe((event) => { @@ -389,7 +418,18 @@ async function run() { .map((r) => ({ outcome: r.outcome, cross: "cross" in r.stages, sources: r.sources })); pageMod.disposePagePipeline(Q); page.clearDrafts(Q); - return { kept, b05, b06, dropped, edit, loop, pane: paneCheck, saved, shiftRuns }; + return { + kept, + b05, + b06, + dropped, + edit, + loop, + pane: paneCheck, + saved, + shiftRuns, + sameAfterReload, + }; } run() diff --git a/resources/tester/test_365_page_pipeline.py b/resources/tester/test_365_page_pipeline.py index a77d6797b..fbc1c2841 100644 --- a/resources/tester/test_365_page_pipeline.py +++ b/resources/tester/test_365_page_pipeline.py @@ -150,6 +150,11 @@ def test_365_4_중심점_좌우_횡단_한_번(r): assert runs[1]["sources"] == ["route", "grade"] # 밀린 노선 범위 + 계획고 = 한 차례 +def test_365_4_창구로_연_뒤_초안_새로고침과_같음(r): + s = r["sameAfterReload"] + assert s["rows"] > 5 and s["marked"] == 0 and s["same"] + + def test_365_4_다시_그림_한_번(): swap = (ROOT / "B06_Section/B06_Section_UI_Page_Station_Swap.ts").read_text(encoding="utf-8") view = (ROOT / "A00_Common/design/design_view_cross.ts").read_text(encoding="utf-8")