- 관 측점 열쇠 갈림(세션 pipe-s1 ↔ 계산 줄 pipe:p35100) = 415-1 로 풀림 · B06 연 길은 초안 카드 조절 그대로(화면) - B05 만 연 길(새로고침 · 조정창 맵 없음) · 세월 · BOX · 연동 칸은 안 옮겨짐 → 갈아끼움 알림 뒤 Station_Keys 가 ROUTE_CARRY_STATES(측점 열쇠 칸 빼고) 세션 칸을 바로 새 자리로 · 조정창 맵이 옮긴 칸은 그대로(Swap_Bus afterAnySwap) - 시험: test_415 누가거리 조절 · 노선 바뀜 대조 = 417 넘김 규칙(사면 쉬프트 · 소단 깊이 넘김) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TteK8mfYZetk5P3bEZkyVZ
159 lines
6.0 KiB
JavaScript
159 lines
6.0 KiB
JavaScript
/* 415 H1 헬퍼 — 관만 옮김 = 횡단 고침을 측점 열쇠째 옮김 · 노선이 바뀜 = 「노선 바뀜」 넘김 규칙.
|
|
* node helper_415_swap.mjs <묶음.mjs>
|
|
* 묶음 = 346-2 진입점(`helper_346_2_swap_entry.ts` · vite ssr 진짜 모듈) · 표준출력 JSON 한 벌. 짝 = test_415_page_split.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);
|
|
globalThis.__toasts = [];
|
|
|
|
const m = await import(pathToFileURL(process.argv[2]).href);
|
|
const P = "p415";
|
|
const R = 3;
|
|
const out = {};
|
|
|
|
/* 옛 목록 — 시점 · 격자 넷 · 관 하나(45.054) · 종점(간격 20 m) */
|
|
const section = (chainage_m, kind, extra = {}) => ({
|
|
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 },
|
|
...extra,
|
|
});
|
|
const detail = () => ({
|
|
longitudinal: {
|
|
length_m: 100,
|
|
stations: [],
|
|
profile_alignment: { policy: { station_interval_m: 20 } },
|
|
},
|
|
cross_sections: [
|
|
section(0, "bp"),
|
|
section(20, "regular"),
|
|
section(40, "regular"),
|
|
section(45.054, "irregular", { structure: "파형강관 D800", culvert: {} }),
|
|
section(60, "regular"),
|
|
section(80, "regular"),
|
|
section(100, "ep"),
|
|
],
|
|
});
|
|
const station = (key, chainageM, kind, id = null, dy = 0) => ({
|
|
key,
|
|
chainageM,
|
|
x: chainageM,
|
|
y: dy,
|
|
azimuthDeg: 90,
|
|
left: [0, 1],
|
|
kind,
|
|
id,
|
|
ground: { centerZ: 99, left: [{ offsetM: 0.5, z: 99.1 }], right: [{ offsetM: 0.5, z: 98.9 }] },
|
|
planRadiusM: null,
|
|
curveOuterSide: null,
|
|
curveWideningM: null,
|
|
});
|
|
/** 관 자리 `pipeAt` · 노선 옆 밀림 `dy`(0 = 노선 그대로) · 종점 `endAt`. */
|
|
const list = (pipeAt, dy = 0, endAt = 100) =>
|
|
[
|
|
station("end:BP", 0, "end", null, dy),
|
|
station("grid:1", 20, "grid", null, dy),
|
|
station("grid:2", 40, "grid", null, dy),
|
|
station("pipe:pipe-s1", pipeAt, "pipe", "pipe-s1", dy),
|
|
station("grid:3", 60, "grid", null, dy),
|
|
station("grid:4", 80, "grid", null, dy),
|
|
station("end:EP", endAt, "end", null, dy),
|
|
].sort((a, b) => a.chainageM - b.chainageM);
|
|
|
|
const choice = (mode) => ({ ground_type: "soil", section_mode: mode, ditch_side: "right" });
|
|
const snap = () => ({
|
|
choices: [...m.crossDesignChoices(P, R).entries()]
|
|
.sort((a, b) => a[0] - b[0])
|
|
.map(([at, c]) => [at, c.ground_type ?? null, c.section_mode ?? null]),
|
|
shoulder: Object.entries(m.readState("shoulderext", P, R) ?? {})
|
|
.filter(([k]) => k !== "@at")
|
|
.map(([k, v]) => [k, v]),
|
|
berm: Object.entries(m.readState("bermdepth", P, R) ?? {})
|
|
.filter(([k]) => k !== "@at")
|
|
.map(([k, v]) => [k, v]),
|
|
});
|
|
|
|
/* 1. 순수 — 관만 옮김 = moved 아님 · 노선이 옆으로 밀림 = moved */
|
|
{
|
|
const keys = ["end:BP", "grid:1", "grid:2", "pipe:pipe-s1", "grid:3", "grid:4", "end:EP"];
|
|
out.pure = {
|
|
pipeOnly: m.swapCrossSections(detail(), list(50), keys, 20).moved,
|
|
route: m.swapCrossSections(detail(), list(50, 0.5, 95), keys, 20).moved,
|
|
};
|
|
}
|
|
|
|
/* 2. 가게 측점 → 상세 갈아끼움 · 세션 고침 */
|
|
{
|
|
m.writeState("section-detail", detail(), P, R);
|
|
m.writeState("pipe-ids", { next: 2, ids: [{ id: "pipe-s1", at: 45.054 }] }, P);
|
|
await m.loadSectionDetail(P, R); // 세션 한 벌 → 캐시 · 측점 열쇠 세움
|
|
m.writeCrossDesignChoice(P, R, 40, choice("right_cut")); // 단면 유형
|
|
m.writeCrossDesignChoice(P, R, 45.054, choice("left_cut")); // 관 측점 고침
|
|
m.writeState("shoulderext", { "@at": { "grid:1": 20 }, "grid:1": { left: 0.7 } }, P, R); // 사면 쉬프트
|
|
m.writeState("bermdepth", { "@at": { "grid:3": 60 }, "grid:3": { right: 0.4 } }, P, R); // 소단 깊이
|
|
// 누가거리 조절(415-3) — 조정창 맵 없이(B05 만 연 페이지 · 새로고침) · 관 자리 옹벽 · 세월 · 연동 두 겹 · 격자 폭
|
|
m.writeState("revetx", { "45.05:outlet": { x: 0.3 }, "20.00:inlet": { x: 0.1 } }, P, R);
|
|
m.writeState("fordadjust", { 45.05: { w: 1 } }, P, R);
|
|
m.writeState("revetlink", { detached: { 45.05: true }, grade: {} }, P, R);
|
|
out.before = snap();
|
|
const stop = m.followSwaps(
|
|
P,
|
|
() => R,
|
|
{ visible: () => true },
|
|
async () => undefined,
|
|
);
|
|
// 관 5 m 옮김(노선 그대로) — 관 자리 장부도 새 자리
|
|
m.writeState("pipe-ids", { next: 2, ids: [{ id: "pipe-s1", at: 50 }] }, P);
|
|
m.useDesignStore(P, null).set("stations", list(50));
|
|
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
out.pipeMoved = { ...snap(), toasts: globalThis.__toasts.length };
|
|
out.adjusts = {
|
|
revetx: m.readState("revetx", P, R),
|
|
fordadjust: m.readState("fordadjust", P, R),
|
|
revetlink: m.readState("revetlink", P, R),
|
|
};
|
|
// 관 한 번 더(10 m) — 둘째 옮김도 그대로(첫 옮김 뒤 관 id 를 앎)
|
|
m.writeState("pipe-ids", { next: 2, ids: [{ id: "pipe-s1", at: 55 }] }, P);
|
|
m.useDesignStore(P, null).set("stations", list(55));
|
|
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
out.pipeMovedAgain = snap();
|
|
// 노선이 바뀜(옆으로 0.5 m · 종점 95 m) = 넘김 규칙 — 단면 유형 · 사면 쉬프트 · 소단 깊이 버림 · 지반 유형 넘김
|
|
m.useDesignStore(P, null).set("stations", list(55, 0.5, 95));
|
|
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
out.routeMoved = snap();
|
|
stop();
|
|
}
|
|
|
|
process.stdout.write(JSON.stringify(out));
|