/* 365-1 헬퍼 — 노선 초안 동안 측점 갈아끼움은 캐시(메모리)만 · 세션 상세 = 저장 노선 그대로. * node helper_365_swap.mjs <묶음.mjs> * vite ssr 로 묶은 진짜 모듈(helper_365_swap_entry.ts) · 표준출력 JSON 한 벌. 짝 = test_365_page_pipeline.py. */ import { pathToFileURL } from "node:url"; const store = () => { const m = new Map(); return { getItem: (k) => (m.has(k) ? m.get(k) : null), setItem: (k, v) => m.set(k, String(v)), removeItem: (k) => m.delete(k), key: (i) => [...m.keys()][i] ?? null, get length() { return m.size; }, clear: () => m.clear(), }; }; globalThis.window = globalThis; globalThis.sessionStorage = store(); globalThis.localStorage = store(); const any = new Proxy(function () {}, { get: (_t, k) => (k === Symbol.toPrimitive ? () => 0 : any), apply: () => any, construct: () => any, }); globalThis.document = any; globalThis.requestAnimationFrame = (run) => setTimeout(run, 0); const m = await import(pathToFileURL(process.argv[2]).href); const P = "p365"; const R = 9; localStorage.setItem("frd_current_project_id", P); const section = (chainage_m, kind) => ({ station_id: `station_${String(Math.round(chainage_m * 1000)).padStart(12, "0")}`, chainage_m, label: "", kind, center_z: 100, azimuth_deg: 90, center_x: chainage_m, center_y: 0, frame: { left_xy: [0, 1] }, samples: [{ offset_m: 0, elevation_m: 100, valid: true }], design: { design_elevation_m: 101 }, }); const saved = { longitudinal: { length_m: 60, stations: [], profile_alignment: { policy: { station_interval_m: 20 } }, }, cross_sections: [ section(0, "bp"), section(20, "regular"), section(40, "regular"), section(60, "ep"), ], }; const station = (key, chainageM, kind) => ({ key, chainageM, x: chainageM, y: 0, azimuthDeg: 90, left: [0, 1], kind, id: null, ground: { centerZ: 99, left: [{ offsetM: 0.5, z: 99.1 }], right: [{ offsetM: 0.5, z: 98.9 }] }, planRadiusM: null, curveOuterSide: null, curveWideningM: null, }); const list = (...at) => at.map((c, i) => station( i === 0 ? "end:BP" : i === at.length - 1 ? "end:EP" : `grid:${c}`, c, i === 0 || i === at.length - 1 ? "end" : "grid", ), ); const chainages = (detail) => detail?.cross_sections.map((s) => s.chainage_m) ?? null; const shop = m.useDesignStore(P, null); m.writeState("section-detail", saved, P, R); await m.loadSectionDetail(P, R); // 세션 한 벌 → 캐시 const out = {}; // 노선 초안 동안 — 측점 하나 늘어난 목록 shop.set("routeDraft", { nodes: [], rev: 1 }); const draft = await m.swapSectionStations(P, R, list(0, 20, 30, 40, 60)); out.draft = { swapped: draft !== null, cache: chainages(await m.loadSectionDetail(P, R)), session: chainages(m.readState("section-detail", P, R)), }; // 초안 없음(저장 노선) — 갈아끼움이 세션까지 shop.set("routeDraft", null); const plain = await m.swapSectionStations(P, R, list(0, 20, 50, 60)); out.saved = { swapped: plain !== null, cache: chainages(await m.loadSectionDetail(P, R)), session: chainages(m.readState("section-detail", P, R)), }; process.stdout.write(JSON.stringify(out)); process.exit(0);