/* PLAN 323-5 고름 한 칸 헬퍼 — 진짜 `design_pipe_ids.ts`(관 세션 id) · `design_selection.ts`(고름 · 관 옮김 따라가기) · * `design_pick_match.ts`(고름 강조 한 규칙)를 그 자리에서 트랜스파일해 Node 로 돌림(세션만 흉내) · 결과 = 표준출력 JSON. * 짝 = `test_323_5_pick.py`. */ const fs = require("fs"); const path = require("path"); const ROOT = path.join(__dirname, "..", ".."); const ts = require(path.join(ROOT, "config", "node_modules", "typescript")); const memory = new Map(); const store = { getItem: (k) => (memory.has(k) ? memory.get(k) : null), setItem: (k, v) => memory.set(k, String(v)), removeItem: (k) => memory.delete(k), key: (i) => [...memory.keys()][i] ?? null, get length() { return memory.size; }, }; globalThis.window = { sessionStorage: store, localStorage: store, addEventListener: () => {} }; globalThis.sessionStorage = store; globalThis.localStorage = store; const cache = new Map(); function load(file) { const full = path.resolve(file); if (cache.has(full)) return cache.get(full); const js = ts.transpileModule(fs.readFileSync(full, "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const box = { exports: {} }; cache.set(full, box.exports); const need = (spec) => load(path.join(path.dirname(full), `${spec}.ts`)); new Function("exports", "module", "require", js)(box.exports, box, need); return box.exports; } const D = (name) => path.join(ROOT, "A00_Common", "design", `${name}.ts`); const ids = load(D("design_pipe_ids")); const sel = load(D("design_selection")); const match = load(D("design_pick_match")); const out = {}; // ① 관 세션 id — 자리마다 차례 · 같은 자리(0.51 안)면 같은 id · 프로젝트 없으면 옛 자리 이름 ids.usePipeIds("P"); const a = ids.pipeIdAt(85.05); out.ids = [a, ids.pipeIdAt(85), ids.pipeIdAt(173), ids.pipeChainageOf(a)]; ids.usePipeIds(null); out.legacy = [ids.pipeIdAt(85), ids.pipeChainageOf("pipe-85.00"), ids.pipeChainageOf("w1")]; ids.usePipeIds("P"); // ② 옮겨도 id 그대로 — 고름도 자리만 새로(부재키 그대로) · 새 자리 id = 그 id sel.selectDesign("P", { chainageM: 85.05, structureId: a }, { partKey: "inlet" }); ids.followMovedPipe("P", 85.05, 90); out.moved = [sel.readSelection("P"), ids.pipeIdAt(90), ids.pipeChainageOf(a)]; // 다른 것을 골랐으면 고름 그대로 · 관 id 는 따라감 const b = ids.pipeIdAt(173); sel.selectDesign("P", { chainageM: 300, structureId: "w1" }); ids.followMovedPipe("P", 173, 180); out.other = [sel.readSelection("P"), ids.pipeIdAt(180) === b]; // ③ 강조 한 규칙 const L = match.pickLights; out.lights = { idOverPlace: L({ chainageM: 93, structureId: "w1" }, { chainageM: 101, structureId: "w1" }), idDiffers: L({ chainageM: 101, structureId: "w2" }, { chainageM: 101, structureId: "w1" }), placeNear: L({ chainageM: 85, structureId: null }, { chainageM: 85.4 }), placeFar: L({ chainageM: 85, structureId: null }, { chainageM: 85.6 }), partOnly: L({ chainageM: 85, partKey: "inlet" }, { chainageM: 85, part: "outlet" }), partSame: L({ chainageM: 85, partKey: "inlet" }, { chainageM: 85, part: "inlet" }), partNoTag: L({ chainageM: 85, partKey: "inlet" }, { chainageM: 85 }), wholePick: L({ chainageM: 85 }, { chainageM: 85, part: "outlet" }), none: L(null, { chainageM: 85 }), }; // ④ 카드 통째 형상 칠하기 — 부분 · 관 계열 · 포장층은 제 손잡이 몫 class Shape { constructor(attrs) { this.attrs = attrs; this.on = false; this.classList = { toggle: (_c, v) => (this.on = v) }; } getAttribute(k) { return this.attrs[k] ?? null; } } const shapes = [ new Shape({ "data-structure-id": "ud-1" }), new Shape({ "data-structure-id": "w1", "data-part": "own" }), new Shape({ "data-structure-id": a, "data-part": "concrete" }), new Shape({ "data-structure-id": "pave-1", "data-pave-type": "pavement_concrete" }), ]; const root = { querySelectorAll: () => shapes }; match.paintPicked(root, { structureId: "ud-1" }); const lit1 = shapes.map((s) => s.on); match.paintPicked(root, { structureId: "w1" }); out.paint = [lit1, shapes.map((s) => s.on)]; process.stdout.write(JSON.stringify(out));