/* 136-1 폼 → 캐시 chute 헬퍼 — `applyPipeOptionsToCache`(B06_Section_UI_Page_Pipe_Options.ts)를 그 자리에서 * 트랜스파일해 돌림 · 도수로/돌붙임 상자가 관 · BOX · 세월교 · 물넘이 포장 제원 `chute` 에 바로 얹히는지 · * 다시 그린 카드. 짝 = `test_136_chute_form_cache.py`. 로더는 `helper_b06_draft_pipe_replay.cjs` 와 같음. */ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); const ROOT = path.join(__dirname, "..", ".."); const cache = new Map(); const session = new Map(); const fakeStorage = { getItem: (k) => session.get(k) ?? null, setItem: (k, v) => session.set(k, String(v)), removeItem: (k) => session.delete(k), }; globalThis.window = { sessionStorage: fakeStorage, localStorage: fakeStorage }; globalThis.sessionStorage = fakeStorage; globalThis.localStorage = fakeStorage; function loadTs(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 localRequire = (request) => { if (request.startsWith("@ui/")) return new Proxy({}, { get: () => () => {} }); if (request.startsWith("@util/")) return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); if (request.startsWith("@config/")) return loadTs(path.join(ROOT, "config", `${request.slice(8)}.ts`)); return request.startsWith(".") ? loadTs(path.join(path.dirname(full), `${request}.ts`)) : require(request); }; new Function("exports", "module", "require", js)(box.exports, box, localRequire); cache.set(full, box.exports); return box.exports; } const options = loadTs(path.join(ROOT, "B06_Section", "B06_Section_UI_Page_Pipe_Options.ts")); const box = (at) => ({ chainage_m: 120, top_thickness_m: 0.3, inner_height_m: 2, slab_thickness_m: 0.3, wing_in: {}, wing_out: {}, _at: at, }); const detail = { cross_sections: [ { chainage_m: 85, culvert: { chainage_m: 85.05, diameter_m: 1, inlet: {}, outlet: {} } }, { chainage_m: 118, box: box(118) }, { chainage_m: 120, box: box(120) }, { chainage_m: 160, ford: { chainage_m: 160, diameter_m: 1, wing_in: {}, wing_out: {} } }, { chainage_m: 196, ford_pavement: { chainage_m: 200, span_m: 9, depth_m: 0.3 } }, { chainage_m: 200, ford_pavement: { chainage_m: 200, span_m: 9, depth_m: 0.3 } }, ], }; let refreshed = []; const ctx = { detail: () => detail, ford: { setPipe: () => {}, setWing: () => {} }, box: { setBody: () => {}, setWing: () => {} }, revetOffset: { update: () => {}, adjustFor: () => ({ h: null, m: null }) }, overrideOptions: () => {}, refreshCard: (at) => refreshed.push(at), }; const at = (i) => detail.cross_sections[i]; const step = (chainage, patch, whole = true) => { refreshed = []; options.applyPipeOptionsToCache(ctx, chainage, patch, whole); return { pipe: at(0).culvert.chute ?? null, box: [at(1).box.chute ?? null, at(2).box.chute ?? null], ford: at(3).ford.chute ?? null, pave: [at(4).ford_pavement.chute ?? null, at(5).ford_pavement.chute ?? null], refreshed: [...new Set(refreshed)].sort((a, b) => a - b), }; }; const out = { pipeAdd: step(85.05, { chute_add_1_structure: "돌붙임", chute_add_1_thickness: 40 }), pipeSame: step(85.05, { chute_add_1_structure: "돌붙임", chute_add_1_thickness: 40 }), replayNoChute: step(85.05, { pipe_diameter_mm: 1000 }, false), pipeRemove: step(85.05, { pipe_diameter_mm: 1000 }), boxAdd: step(120, { chute_add_1_structure: "도수로" }), fordAdd: step(160, { chute_add_1_structure: "돌붙임", chute_add_1_thickness: 50 }), paveAdd: step(200, { ford_chute_1_structure: "돌붙임", chute_add_1_structure: "도수로" }), }; process.stdout.write(JSON.stringify(out));