- 자리 칸 목록 한 벌 = 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>
136 lines
4.2 KiB
JavaScript
136 lines
4.2 KiB
JavaScript
/* 475-3 헬퍼 — vite ssr 로 묶은 진짜 모듈(helper_475_3_entry.ts)을 부르고 결과를 JSON 한 벌로.
|
|
* node helper_475_3_seat_carry.mjs <묶음.mjs> <입력.json>
|
|
* 입력 = { seats: [[a, b], …] }(자리 판정 거울 사례).
|
|
*/
|
|
import { readFileSync } from "node:fs";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
const [bundle, inputPath] = process.argv.slice(2);
|
|
const m = await import(pathToFileURL(bundle).href);
|
|
const input = JSON.parse(readFileSync(inputPath, "utf-8"));
|
|
const out = {};
|
|
|
|
out.sameSeat = input.seats.map(([a, b]) => m.sameSeat(a, b));
|
|
|
|
/* 노선 바뀜 넘김 — grid:1 같은 자리 · grid:2 옮김 · grid:3 옮겼지만 값은 새 자리에서 씀(되돌리기로 되살린 값) */
|
|
const A = { x: 0, y: 20, left: [-1, 0] };
|
|
const B = { x: 0, y: 40, left: [-1, 0] };
|
|
const C = { x: 0, y: 60, left: [-1, 0] };
|
|
const C2 = { x: 3, y: 60, left: [-1, 0] };
|
|
const from = [
|
|
{ key: "grid:1", chainageM: 20, seat: A },
|
|
{ key: "grid:2", chainageM: 40, seat: B },
|
|
{ key: "grid:3", chainageM: 60, seat: C },
|
|
];
|
|
const to = [
|
|
{ key: "grid:1", chainageM: 20, seat: A },
|
|
{ key: "grid:2", chainageM: 40.5, seat: { x: 5, y: 40, left: [-1, 0] } },
|
|
{ key: "grid:3", chainageM: 61, seat: C2 },
|
|
];
|
|
const choice = {
|
|
ground_type: "soil",
|
|
ditch_type: "l_type",
|
|
two_stage_slope: true,
|
|
section_mode: "right_cut",
|
|
ditch_side: "left",
|
|
paved: true,
|
|
};
|
|
const raw = {
|
|
rockb: { "grid:1": 1.2, "grid:2": 1.5, "grid:3": 0.9, "@seat": { "grid:3": C2 } },
|
|
cutslope: { "grid:1": 0.8, "grid:2": 0.7 },
|
|
crossdesign: { "grid:1": choice, "grid:2": choice },
|
|
shoulderext: { "grid:2": { left: 0.5 } },
|
|
bermdepth: {},
|
|
};
|
|
const strip = (states) =>
|
|
Object.fromEntries(
|
|
Object.entries(states).map(([name, cells]) => [
|
|
name,
|
|
Object.fromEntries(Object.entries(cells).filter(([key]) => !key.startsWith("@"))),
|
|
]),
|
|
);
|
|
const carried = m.carryKeyedStates((name) => raw[name] ?? {}, from, to);
|
|
out.carried = strip(carried.states);
|
|
out.carriedSeats = carried.states.rockb["@seat"];
|
|
out.outside = carried.outside.size;
|
|
/* 자리 모름(옛 목록) = 옛 동작 그대로 */
|
|
const bare = (list) => list.map(({ key, chainageM }) => ({ key, chainageM }));
|
|
out.unknown = strip(m.carryKeyedStates((name) => raw[name] ?? {}, bare(from), bare(to)).states);
|
|
|
|
/* 미리보기 입력 — 저장분 · 세션 자리 칸 묶음(`seats`) */
|
|
const station = (key, x, y) => ({ key, chainageM: y, x, y, left: [-1, 0] });
|
|
const input2 = {
|
|
standard: {},
|
|
byKey: {
|
|
"grid:1": {
|
|
groundType: "soil",
|
|
rockBoundaryOffsetM: 1,
|
|
sectionMode: "right_cut",
|
|
seats: [{ ...A, fields: ["rockBoundaryOffsetM", "sectionMode"] }],
|
|
},
|
|
"grid:2": {
|
|
groundType: "soil",
|
|
twoStageSlope: true,
|
|
cutSlopeRatio: 0.7,
|
|
seats: [
|
|
{ ...B, fields: ["twoStageSlope"] },
|
|
{ x: 5, y: 40, left: [-1, 0], fields: ["cutSlopeRatio"] },
|
|
],
|
|
},
|
|
},
|
|
};
|
|
out.atSeat = m.crossAtSeat(input2, [station("grid:1", 0, 20), station("grid:2", 5, 40)]).byKey;
|
|
|
|
/* B06 갈아끼움(노선 초안) — 앞 횡단 설계를 이어 받되 자리가 바뀐 측점은 자리 칸 기본값 */
|
|
const hand = {
|
|
ground_type: "soil",
|
|
section_mode: "both_cut",
|
|
ditch_side: "right",
|
|
two_stage_slope: true,
|
|
rock_boundary_offset_m: -1.2,
|
|
cut_slope_ratio_user: 0.8,
|
|
shoulder_extend_left_m: 0.5,
|
|
};
|
|
const section = (chainage, x) => ({
|
|
station_id: `s${chainage}`,
|
|
chainage_m: chainage,
|
|
kind: "regular",
|
|
center_x: x,
|
|
center_y: chainage,
|
|
frame: { left_xy: [-1, 0] },
|
|
samples: [],
|
|
uphill_side: "left",
|
|
design: { ...hand },
|
|
});
|
|
const pipelineStation = (key, chainage, x) => ({
|
|
key,
|
|
kind: "grid",
|
|
chainageM: chainage,
|
|
x,
|
|
y: chainage,
|
|
left: [-1, 0],
|
|
azimuthDeg: 0,
|
|
planRadiusM: null,
|
|
curveOuterSide: null,
|
|
curveWideningM: 0,
|
|
ground: null,
|
|
});
|
|
const detail = {
|
|
longitudinal: { stations: [], length_m: 40 },
|
|
cross_sections: [section(20, 0), section(40, 0)],
|
|
};
|
|
const swapped = (draft) =>
|
|
m
|
|
.swapCrossSections(
|
|
detail,
|
|
[pipelineStation("grid:1", 20, 0), pipelineStation("grid:2", 40, 5)],
|
|
["grid:1", "grid:2"],
|
|
20,
|
|
draft,
|
|
)
|
|
.detail.cross_sections.map((s) => s.design);
|
|
out.swapDraft = swapped(true);
|
|
out.swapNoDraft = swapped(false);
|
|
|
|
process.stdout.write(JSON.stringify(out));
|