/* PLAN 317 단위검증 헬퍼 — 구조물 측점에서 종류를 바꾸면 그 측점 횡단을 새로 뜬 것으로(저장분은 빼 둠). * `withDraftStations` 를 Node 로 돌림 · 서버 부르는 모듈은 흉내 · 결과 = 표준출력 JSON 한 벌. * 짝 = `test_317_kind_change_station.py`. */ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1) const ROOT = path.join(__dirname, "..", ".."); const state = { draftPipes: null, draftStructures: null, savedPipes: [], savedStructures: [] }; const STUBS = { "../B04_PreProcess/B04_PreProcess_Api_Fetch": { fetchDetailPipePoints: async () => ({ pipe_points: state.savedPipes }), }, "../B05_Profile/B05_Profile_Api_Structures": { fetchStructures: async () => ({ structures: state.savedStructures }), fetchStructureTypes: async () => [], readPendingStructures: () => state.draftStructures, }, "../B05_Profile/B05_Profile_Api_Pipes_Draft": { readPendingPipes: () => state.draftPipes }, "./B06_Section_Api_Fetch": { previewStructureSections: async (_p, chainages) => chainages.map((at) => ({ chainage_m: at, kind: "irregular", design: { fresh: true } })), }, }; // 페이지 자료 줄(386-2) — 진짜 design_page_data 가 같은 서버 흉내를 부름 STUBS["../../B04_PreProcess/B04_PreProcess_Api_Fetch"] = STUBS["../B04_PreProcess/B04_PreProcess_Api_Fetch"]; STUBS["../../B05_Profile/B05_Profile_Api_Structures"] = STUBS["../B05_Profile/B05_Profile_Api_Structures"]; 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) => { if (CATALOG.isCatalogRequest(m)) return CATALOG; if (STUBS[m]) return STUBS[m]; if (m.startsWith("@util/")) return load(path.join(ROOT, "common_util", `${m.slice(6)}.ts`)); if (m.startsWith(".")) return load(path.join(path.dirname(file), `${m}.ts`)); return new Proxy({}, { get: () => () => {} }); }; new Function("exports", "module", "require", js)(box.exports, box, near); return box.exports; }; const drafts = load(path.join(ROOT, "B06_Section", "B06_Section_Section_Drafts.ts")); const { forgetDraftStations } = drafts; // 상세 맞춤 = 측점 계획 → 형상 얹기(`Section_Store.withDraftWalls` 와 같은 차례 · 323-4) const withDraftStations = async (detail, projectId, routeId) => { await drafts.withDraftStations(detail, projectId, routeId); await drafts.withDraftShapes(detail, projectId); }; const detail = { cross_sections: [ { chainage_m: 0, kind: "regular", design: { old: true } }, { chainage_m: 50, kind: "irregular", design: { old: true } }, ], }; const at50 = () => detail.cross_sections.find((s) => Math.abs(s.chainage_m - 50) < 0.01); const snap = () => ({ count: detail.cross_sections.length, fresh: Boolean(at50()?.design?.fresh), old: Boolean(at50()?.design?.old), preview: Boolean(at50()?.preview), }); (async () => { state.savedPipes = [{ chainage_m: 50, facility: "ford_pavement" }]; const out = {}; state.draftPipes = [{ chainage_m: 50, facility: "ford_pavement", options: { ford_width_m: 3 } }]; await withDraftStations(detail, "p1", 1); out.same_kind = snap(); state.draftPipes = [{ chainage_m: 50, facility: "box_culvert" }]; await withDraftStations(detail, "p1", 1); out.changed_kind = snap(); state.draftPipes = [{ chainage_m: 50, facility: "ford_pavement" }]; await withDraftStations(detail, "p1", 1); out.back_to_saved = snap(); // 여러 번 바꿈 — 앞 종류 제원이 남아 겹치지 않음(317-3 · 미리 뜬 횡단은 한 벌을 다시 씀) const facilityKeys = () => Object.keys(at50() ?? {}) .filter((key) => ["culvert", "ford", "box", "ford_pavement"].includes(key)) .sort(); state.draftPipes = [{ chainage_m: 50, facility: "box_culvert" }]; await withDraftStations(detail, "p1", 1); out.first_switch = facilityKeys(); state.draftPipes = [{ chainage_m: 50, facility: "ford_bridge" }]; await withDraftStations(detail, "p1", 1); out.second_switch = facilityKeys(); forgetDraftStations("p1"); process.stdout.write(JSON.stringify(out)); })().catch((error) => { process.stderr.write(String(error && error.stack ? error.stack : error)); process.exit(1); });