- 계산 묶음을 종단도 한 벌(sharedProfile)이 세움 — B06 바로 열기 · 새로고침도 노선 초안 셈 · 종단 보기는 다리만 받음(알림은 pipeline 바인딩) - 초안 둔 채 열기 = 측점을 가게에 냄 · 초안 전 저장 상세를 열 때 맡김(버리면 saved) - 초안 동안 측점 갈아끼움 = 메모리만(세션 section-detail = 저장 노선 그대로) - 시험 test_365_page_pipeline(초안 둔 채 열기 같은 상세 · 버림 saved · 세션 안 덮음) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TteK8mfYZetk5P3bEZkyVZ
110 lines
3.2 KiB
JavaScript
110 lines
3.2 KiB
JavaScript
/* 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);
|