/* 관 초안 옵션 되얹기 단위검증 헬퍼(PLAN 24-7a) — TS 를 그 자리에서 트랜스파일해 Node 로 돌린다. * 새로고침 뒤 캐시 상세(저장분)에 저장 전에 고친 관 옵션(월류 폭 · 관경)이 다시 얹히는지 본다. * 결과는 표준출력에 JSON 한 벌. 화면 그릇은 쓰지 않는다. * * ⚠ 확장자가 `.cjs` 인 까닭은 `helper_b05_structures_form_summary.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) => { // 화면 공용 부품(@ui/…)은 이 시험이 안 쓰는 것이라 아무 일 안 하는 함수로 막아 둠 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")); // 캐시 상세(저장분) — 세월교(월류 폭 10) · 배수관(관경 1000) · 옹벽 없음 const detail = { cross_sections: [ { chainage_m: 85.05, culvert: { pipe_kind: "파형강관", diameter_m: 1.0, inlet: {}, outlet: {} }, }, { chainage_m: 173.09, ford: { span_m: 10, diameter_m: 1.0, pipe_count: 1, wing_in: {}, wing_out: {} }, }, ], }; const sent = []; const ctx = { detail: () => detail, ford: { setPipe: (chainageM, patch) => { sent.push({ chainageM, patch }); if (patch.ford_width_m) detail.cross_sections[1].ford.span_m = patch.ford_width_m; }, setWing: () => {}, }, box: {}, revetOffset: { update: () => sent.push({ revet: true }) }, overrideOptions: () => {}, refreshCard: () => {}, }; // 초안: 세월교 월류 폭 3.5 · 배수관 관경 1200 · 기슭막이 높이(조정창 정본이라 되살리지 않음) options.replayDraftPipeOptions(ctx, [ { chainage_m: 85.05, options: { pipe_diameter_mm: 1200, outlet_revet_height_m: 2.5 } }, { chainage_m: 173.09, facility: "ford_bridge", options: { ford_width_m: 3.5 } }, { chainage_m: 258.12, options: {} }, ]); options.replayDraftPipeOptions(ctx, null); process.stdout.write( JSON.stringify({ fordSpan: detail.cross_sections[1].ford.span_m, culvertDiameter: detail.cross_sections[0].culvert.diameter_m, fordCalls: sent.filter((s) => s.chainageM === 173.09).length, revetTouched: sent.some((s) => s.revet === true), }), );