/* 409-2 평면 마커 고름 풂(b05-plan · 값 없음) = 좌측 폼 · 목록 강조도 풂 — 진짜 `design_selection` · * `design_pick_escape` · `design_pick_profile` 을 Node 로 돌림. 종단도 · 폼 · 오른쪽 횡단 판은 흉내. * 표준출력 JSON 한 벌 · 짝 = test_409_mark_top_deselect.py. */ const fs = require("fs"); const path = require("path"); const ROOT = path.join(__dirname, "..", ".."); const ts = require(path.join(ROOT, "config", "node_modules", "typescript")); function loadTs(file, stubs = {}) { const js = ts.transpileModule(fs.readFileSync(path.join(ROOT, file), "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const box = { exports: {} }; const localRequire = (request) => { if (stubs[request]) return stubs[request]; throw new Error(`stub 없음: ${request}`); }; new Function("exports", "module", "require", js)(box.exports, box, localRequire); return box.exports; } globalThis.window = { addEventListener() {}, removeEventListener() {} }; globalThis.document = { querySelector: () => null }; const store = new Map(); const DSel = loadTs("A00_Common/design/design_selection.ts", { "../b_page_state": { readState: (key, pid) => store.get(`${key}:${pid}`) ?? null, writeState: (key, value, pid) => store.set(`${key}:${pid}`, value), }, }); const ESC = loadTs("A00_Common/design/design_pick_escape.ts", { "./design_selection": DSel }); const IRR = { irregularStationId: (id) => `irregular:${id}`, isPipeStation: () => true }; const SY = loadTs("B05_Profile/B05_Profile_UI_Selection.ts", { "../A00_Common/design/design_selection": DSel, "./B05_Profile_UI_IrregularStations": IRR, }); const PP = loadTs("A00_Common/design/design_pick_profile.ts", { "./design_selection": DSel, "./design_pipe_ids": { pipeIdAt: (at) => `pipe-${at.toFixed(2)}` }, "./design_pick_escape": ESC, "../../B05_Profile/B05_Profile_UI_Selection": SY, "../../B05_Profile/B05_Profile_UI_IrregularStations": IRR, }); const PID = "p409"; const sel = (chainageM, structureId, from) => DSel.selectDesign(PID, chainageM === null ? DSel.NO_SELECTION : { chainageM, structureId }, { from, }); /* 폼 — 관 폼을 닫으면 진짜 폼처럼 관 고름도 비움(`resetForm` → onPipeSelect(null) → b05 풂) */ const form = { open: null, resets: 0 }; const profile = { structure: null }; PP.bindProfilePick( PID, { profile: { setSelectedStation: () => (profile.structure = null), setSelectedStructure: (id) => (profile.structure = id), }, form: { hasSelection: () => form.open !== null, selectById: () => { const wasPipe = form.open === "pipe"; form.open = null; form.resets += 1; if (wasPipe) sel(null, null, "b05"); }, }, }, { visible: () => true, onDispose() {} }, { irregular: () => [], pipes: () => [{ chainage_m: 80.17 }], sections: () => [] }, ); /* 오른쪽 횡단 판 흉내 — 받은 알림(낸 쪽) */ const crossSaw = []; DSel.subscribeSelection(PID, (selection, from) => crossSaw.push([selection.chainageM, from])); const out = {}; // 관 마커 고름 → 폼 열림 → 평면 마커 고름 풂 sel(80.17, null, "b05"); form.open = "pipe"; crossSaw.length = 0; sel(null, null, ESC.PLAN_PICK_FROM); out.pipeRelease = { form: { ...form }, crossSaw: [...crossSaw], session: DSel.readSelection(PID) }; // 구조물 고름 → 폼 → 풂 sel(40, "A", "b05"); form.open = "A"; sel(null, null, ESC.PLAN_PICK_FROM); out.structureRelease = { form: { ...form }, pill: profile.structure }; // 평면 눈금 클릭(값 있음 · b05-plan) = 폼 안 닫음(옛 그대로) form.open = "A"; sel(20, null, ESC.PLAN_PICK_FROM); out.tickKeepsForm = form.open; // 폼 없음 = 안 부름 form.open = null; const resets = form.resets; sel(null, null, ESC.PLAN_PICK_FROM); out.noFormNoReset = form.resets - resets; out.planName = ESC.PLAN_PICK_FROM; process.stdout.write(JSON.stringify(out));