/* 65장 세월교 · 박스암거 · 물넘이 포장 명세 단위검증 헬퍼 — `design_structure_*.ts` 를 그 자리에서 트랜스파일해 * Node 로 돌림(같은 폴더 명세 import 는 따라 옮김). 결과 = JSON 한 벌. 짝 = `test_65_ford_defaults.py`. */ 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 load = (file) => { if (cache.has(file)) return cache.get(file); const js = ts.transpileModule(fs.readFileSync(file, "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const box = { exports: {} }; cache.set(file, box.exports); const near = (m) => { const base = m.startsWith("@config/") ? path.join(ROOT, "config", m.slice(8)) : path.join(path.dirname(file), m); return load(`${base}.ts`); }; new Function("exports", "module", "require", js)(box.exports, box, near); return box.exports; }; const D = (f) => path.join(ROOT, "A00_Common", "design", f); const s = load(D("design_structure_spec.ts")); const { FORD_SPEC, withLegacyGuards } = load(D("design_structure_ford.ts")); const { BOX_SPEC } = load(D("design_structure_box.ts")); const { FORD_PAVEMENT_SPEC } = load(D("design_structure_ford_pavement.ts")); const calc = load(D("design_structure_ford_calc.ts")); /** 상자마다 칸 id · 갈래(구조 값 → 저장 키) — 칸 목록 대조용. */ const items = (spec) => Object.fromEntries( spec.containers.map((c) => [ c.id, c.items.map((i) => [i.id, i.by ? Object.keys(i.by.map) : null, i.default ?? null]), ]), ); const none = (spec) => Object.fromEntries( spec.containers.map((c) => [ c.id, [s.isNone(c, { structure: "없음" }), s.isNone(c, { structure: "흙막이" })], ]), ); // 세월교 유입 흙막이 · 유출 없음 · 추가 흙막이 1 · 도수로 1 → 저장 → 다시 읽기 const fordState = s.readState(FORD_SPEC, withLegacyGuards({ pipe_diameter_mm: 1000 })); fordState.inlet[0] = { structure: "흙막이", form: "돌망태", length: "8", height: "1.2", before: "3", after: "5", }; fordState.outlet[0] = { structure: "없음" }; fordState.soil_add.push({ form: "바자", length: "6", height: "1", before: "3", after: "3" }); fordState.chute_add.push({ structure: "돌붙임" }); const fordOut = s.writeOptions(FORD_SPEC, fordState); const fordBack = s.readState(FORD_SPEC, withLegacyGuards(fordOut)); // 박스 유출 흙막이 → 저장 키 const boxState = s.readState(BOX_SPEC, {}); boxState.outlet[0] = { structure: "흙막이", form: "콘크리트", length: "4", height: "2" }; const boxOut = s.writeOptions(BOX_SPEC, boxState); // 물넘이 포장 경사각 · 월류 폭 · 높이 const paveState = s.readState(FORD_PAVEMENT_SPEC, { ford_slope_deg: 3, ford_width_m: 5 }); paveState.slope[0].height = String(calc.fordHeightM(2.54, 5)); const paveOut = s.writeOptions(FORD_PAVEMENT_SPEC, paveState); process.stdout.write( JSON.stringify({ ford: items(FORD_SPEC), box: items(BOX_SPEC), pave: items(FORD_PAVEMENT_SPEC), fordNone: none(FORD_SPEC), boxNone: none(BOX_SPEC), fordOut, fordBack, boxOut, paveOut, paveRetired: FORD_PAVEMENT_SPEC.retired, fordKeys: s.specKeys(FORD_SPEC), boxKeys: s.specKeys(BOX_SPEC), paveKeys: s.specKeys(FORD_PAVEMENT_SPEC), table: [0.5, 2.54, 8, 30].flatMap((q) => [3, 5, 10, 20].map((b) => [q, b, calc.fordHeightM(q, b)]), ), }), );