- 자리 칸 목록 한 벌 = TS `SEAT_KEYS`(Station_Swap · 파이썬 Router_Design 이 그 글을 읽음) — two_stage_slope · rock_boundary_offset_m · cut_slope_ratio_user · section_mode · ditch_side - 자리 판정 한 벌 = `sameSeat` ↔ 파이썬 `same_seat`(중심 0.01 m · 왼쪽 축 1e-3 · 모르면 같은 자리 = 옛 동작) - 끌기 세션 넘김 · Node stations.carry = `carryKeyedStates`(목록 측점 자리 · 값마다 쓴 때 자리 `@seat` — 되돌리기로 되살린 값도 제 자리로) - 미리보기 = `pipelineCrossSource` 가 저장분 · 세션 자리 칸에 자리째 실음 → `crossAtSeat` 가 새 자리면 뺌 - B06 갈아끼움(노선 초안) = 자리 바뀐 측점 설계의 자리 칸 걷고 기본값(`unseated` · 브레인 덧) - 서버 노선 저장 = `carry_cross_inputs` 자리 칸 같은 자리만 · 손 단면 유형 · 측구 방향 = `compute_default_designs` 입력 - 옛 단언 시험 고침(자리 모름 목록 = 같은 자리 = 손 상단측도 넘김 · 「@seat」 칸 거름) · 새 시험 test_475_3_seat_carry - 위키 rules 넘김 규칙 줄 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
156 lines
5.5 KiB
JavaScript
156 lines
5.5 KiB
JavaScript
/* 417 헬퍼 — vite ssr 로 묶은 진짜 모듈(helper_417_entry.ts)을 부르고 결과를 JSON 한 벌로.
|
|
* node helper_417_route_carry.mjs <묶음.mjs> <입력.json>
|
|
* 입력 = { standard: 파이썬 config 표준단면 }.
|
|
*/
|
|
import { readFileSync } from "node:fs";
|
|
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 [bundlePath, inputPath] = process.argv.slice(2);
|
|
const m = await import(pathToFileURL(bundlePath).href);
|
|
const input = JSON.parse(readFileSync(inputPath, "utf8"));
|
|
const P = "p417";
|
|
const R = 7;
|
|
const R2 = 8;
|
|
const raw = (name, route) => m.readState(name, P, route) ?? {};
|
|
const keysOf = (name, route) =>
|
|
Object.keys(raw(name, route))
|
|
.filter((k) => !k.startsWith("@")) // 「@at」 · 「@seat」 = 쓴 때 자리 칸(475-3)
|
|
.sort();
|
|
const section = (chainage_m, kind, extra = {}) => ({
|
|
station_id: `s${chainage_m}`,
|
|
chainage_m,
|
|
kind,
|
|
label: String(chainage_m),
|
|
samples: [],
|
|
design: {},
|
|
...extra,
|
|
});
|
|
const detailOf = (sections) => ({
|
|
longitudinal: {
|
|
stations: sections,
|
|
profile_alignment: { policy: { station_interval_m: 20 } },
|
|
},
|
|
cross_sections: sections,
|
|
});
|
|
const out = {};
|
|
|
|
/* 1. 옛 노선(관 45 m) — B06 조절 · 사면 쉬프트 · 소단 깊이 · 측점 폭 · 상세 표 · 연동을 세션에 */
|
|
m.writeState("pipe-ids", { next: 2, ids: [{ id: "pipe-s1", at: 45 }] }, P);
|
|
const pipe = { structure: "파형강관 D800", culvert: {} };
|
|
m.useStationKeys(
|
|
P,
|
|
R,
|
|
detailOf([
|
|
section(0, "bp"),
|
|
section(20, "regular"),
|
|
section(40, "regular"),
|
|
section(45, "irregular", pipe),
|
|
section(60, "ep"),
|
|
]),
|
|
);
|
|
m.writeShoulderExtend(P, R, 40, "left", 0.5);
|
|
m.writeBermDepth(P, R, 40, "right", 1.2);
|
|
const wall = { x: 0.3, d: null, h: 1.5, m: null };
|
|
m.writeState("revetx", { "45.00:outlet": wall, "40.00:inlet": wall }, P, R);
|
|
m.writeState("boxadjust", { "45.00": { left: { x: 0.2 } } }, P, R);
|
|
m.writeState("crossw", { "40.00": 6 }, P, R);
|
|
m.writeState("detail-table", { "45.00": { rows: 2 } }, P, R);
|
|
m.writeState("revetlink", { detached: { "45.00": true }, grade: {} }, P, R);
|
|
|
|
/* 2. 노선 바뀐 [저장] — 새 노선(관 47 m 로 따라감 · 끝 58 m) 측점 열쇠로 옮김 */
|
|
m.writeState("pipe-ids", { next: 2, ids: [{ id: "pipe-s1", at: 47 }] }, P);
|
|
const next = detailOf([
|
|
section(0, "bp"),
|
|
section(20, "regular", { design: { shoulder_extend_right_m: 0.7, berm_depth_left_m: 0.4 } }),
|
|
section(40, "regular"),
|
|
section(47, "irregular", pipe),
|
|
section(58, "ep"),
|
|
]);
|
|
m.useStationKeys(P, R2, next);
|
|
out.keyedOutside = m.carryStationDrafts(P, R, R2, { quiet: true });
|
|
out.chainageOutside = m.carryChainageStates(P, R, R2);
|
|
out.shoulderKeys = keysOf("shoulderext", R2);
|
|
out.bermKeys = keysOf("bermdepth", R2);
|
|
out.revet = raw("revetx", R2);
|
|
out.box = raw("boxadjust", R2);
|
|
out.width = raw("crossw", R2);
|
|
out.table = raw("detail-table", R2);
|
|
out.link = raw("revetlink", R2);
|
|
|
|
/* 3. 새 상세 설계 칸에 얹음 — 같은 [저장]의 횡단 패치가 실을 값 */
|
|
m.withDraftAdjusts(next, P, R2);
|
|
m.withCarriedEdits(next, P, R2);
|
|
const at = (c) => next.cross_sections.find((s) => s.chainage_m === c).design;
|
|
out.design40 = at(40);
|
|
out.design47 = at(47);
|
|
|
|
/* 4. 평면 초안 횡단 입력 — 세션 사면 쉬프트 · 소단 깊이 + 저장분(세션 없음)도 */
|
|
m.writeState("std-cross", input.standard, P);
|
|
const stations = next.cross_sections.map((s, i) => ({
|
|
key: ["end:BP", "grid:1", "grid:2", "pipe:pipe-s1", "end:EP"][i],
|
|
chainageM: s.chainage_m,
|
|
kind: i === 3 ? "pipe" : "grid",
|
|
}));
|
|
const source = m.pipelineCrossSource(P, next, stations, R2);
|
|
const pick = (entry) =>
|
|
Object.fromEntries(
|
|
Object.entries(entry ?? {}).filter(([k]) => /^(shoulderExtend|bermDepth)/.test(k)),
|
|
);
|
|
out.input40 = pick(source?.input.byKey["grid:2"]);
|
|
out.input20 = pick(source?.input.byKey["grid:1"]);
|
|
|
|
/* 5. 관 id 규칙이 갈림(옛 목록 세션 id · 새 목록 저장 관 id) — 시설 자리 풀이로 옮김 · 없으면 버림 */
|
|
const R3 = 9;
|
|
const R4 = 10;
|
|
const list = [
|
|
{ key: "end:BP", chainageM: 0 },
|
|
{ key: "grid:1", chainageM: 20 },
|
|
{ key: "grid:2", chainageM: 40 },
|
|
{ key: "pipe:p9", chainageM: 52 },
|
|
{ key: "end:EP", chainageM: 60 },
|
|
];
|
|
m.useStationKeyList(P, R3, list);
|
|
m.useStationKeyList(P, R4, list);
|
|
m.writeState("pipe-ids", { next: 2, ids: [{ id: "pipe-s1", at: 45 }] }, P);
|
|
m.useStationKeys(
|
|
P,
|
|
R,
|
|
detailOf([section(0, "bp"), section(45, "irregular", pipe), section(60, "ep")]),
|
|
);
|
|
m.writeState("revetx", { "45.00:outlet": wall }, P, R);
|
|
m.carryChainageStates(P, R, R3, { keyAt: (key) => (key === "pipe:pipe-s1" ? 52 : null) });
|
|
m.carryChainageStates(P, R, R4);
|
|
out.splitResolved = raw("revetx", R3);
|
|
out.splitDropped = raw("revetx", R4);
|
|
// 옛 저장 시설 측점(초안으로 안 따라간 고침) — 좌표 짝으로 새 시설 측점에
|
|
const R5 = 11;
|
|
m.useStationKeyList(P, R5, list);
|
|
m.carryChainageStates(P, R, R5, { movedAt: (c) => (c === 45 ? 52 : null) });
|
|
out.movedByPlace = raw("revetx", R5);
|
|
|
|
process.stdout.write(JSON.stringify(out));
|