Files
Aislo/resources/tester/helper_272_berm_source.mjs
T
eomsangdonandClaude Opus 5.5 403722e687 refactor(B05·B06): 소단 = 옹벽처럼 측점에 제원 얹음 — 형상 얹기 한 벌 · 세션 사본 berm 걷음 (PLAN 577-2 · 요구 434 · 437)
- 얹기: attachShapes · attach_shapes 에 소단(section.berm · 덮는 소단 없음 = null) · SHAPE_KEYS 에 berm · TS attachBermSpecs ↔ 파이썬 attach_berm_specs · berm_spans_from 짝
- 읽기: 저장 노선 다시 셈(브라우저 · Node cross.refresh) = 얹힌 section.berm(칸 없음 = 저장분 design.berm) · 노선 초안 · 서버 Node 묶음 cross = crossWithShapes 의 얹힌 제원(bermAt · crossWithBerm 걷음)
- 계단은 계산 안쪽 그대로 · [저장] 길(구조물 정본 → cross.berm_spans) 그대로
- 지움: 시설 줄 syncBerm · putBerm(C4.copy) · writeBermSpans · 세션 칸 berm · bermRequest · design_shared bermAt
- 시험: test_272_berm_source 측점 얹기 거울로 · test_323_4 소단 얹음 · 477 · 511-A · 472 떠남 · 365 · 272 고름 헬퍼가 사본 대신 얹힌 소단 · design_pipeline_page 700 줄 → 699(주석 한 줄)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 11:33:06 +09:00

134 lines
4.4 KiB
JavaScript

/* 467 · 577-2 헬퍼 — 소단 원천 한 벌: 구조물 → 소단 구간(TS) · 측점 얹기(TS) · 저장분 소단 제원(TS) ·
* 다시 셈 = 얹힌 `section.berm` · 칸 없으면 저장분 `design.berm`.
* node helper_272_berm_source.mjs <묶음.mjs> <job.json>
* job = { standard, rockDefault, structureCases, storedCases, ground, chainages } · 짝 = `test_272_berm_source.py`.
*/
import { readFileSync } from "node:fs";
import { pathToFileURL } from "node:url";
const writes = [];
const memory = () => {
const m = new Map();
return {
getItem: (k) => (m.has(k) ? m.get(k) : null),
setItem: (k, v) => {
writes.push(k);
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 = memory();
globalThis.localStorage = memory();
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.fetch = async () => new Response("{}", { status: 404 });
const m = await import(pathToFileURL(process.argv[2]).href);
const job = JSON.parse(readFileSync(process.argv[3], "utf8"));
const P = "p272berm";
const R = 5;
const out = {};
/* 1. 거울 — 구조물 → 소단 구간 · 저장분 제원 */
out.spans = job.structureCases.map((list) => m.bermSpansFromStructures(list));
out.stored = job.storedCases.map((spec) => m.storedBermSpec(spec));
/* 2. 측점 얹기 — 구조물마다 측점 목록에 얹은 칸(덮는 소단 없음 = null · 누가거리 없음 = 칸 없음) */
out.attach = job.structureCases.map((list) => {
const sections = job.chainages.map((c) => ({ chainage_m: c }));
m.attachBermSpecs(sections, m.bermSpansFromStructures(list));
return sections;
});
/* 2-2. 시설 줄 칠함 — 종류 표 받기 전 측점(빈 목록)을 종단도에 안 씀 · 받은 뒤 한 번 */
{
const P2 = "p272paint";
const wrote = [];
const fake = {
setStructureTypes: () => undefined,
setStructures: () => undefined,
setIrregularStations: (list) => wrote.push(list.length),
setMinCoverPipes: () => undefined,
resetStationEdit: () => undefined,
};
const lane = m.createFacilityLane(P2, () => fake);
lane.set({ pipes: [] });
lane.set({ structures: [] }, false);
lane.paint();
const before = wrote.length;
lane.setTypes([{ type_id: "berm", name: "소단", placement: "interval" }]);
out.paint = { before, after: wrote.length };
lane.dispose();
}
/* 3. 다시 셈 소단 원천 — 사본 없음(저장분 design.berm) · 사본 = 같은 구간 · 사본 = 빈 목록 */
{
m.writeState("std-cross", job.standard, P);
m.rememberRockBoundaryDefault(P, job.rockDefault);
const detailOf = () => ({
longitudinal: { length_m: 200, stations: [], profile_alignment: { policy: {} } },
cross_sections: [
{
station_id: "station_000000040000",
chainage_m: 40,
label: "",
kind: "regular",
center_z: 96,
azimuth_deg: 90,
center_x: 40,
center_y: 0,
frame: { left_xy: [0, 1] },
uphill_side: "left",
samples: job.ground,
design: {
design_elevation_m: 100,
ground_type: "soil",
section_mode: "both_fill",
ditch_type: "standard",
berm: job.storedBerm,
},
},
],
});
const alignment = {
stations: [{ chainage_m: 40, plan_elevation_m: 100 }],
samples: [
{ chainage_m: 0, elevation_m: 100 },
{ chainage_m: 100000, elevation_m: 100 },
],
balance: { cut_area_m2: 0, fill_area_m2: 0, net_area_m2: 0 },
};
const run = async (berm) => {
const detail = detailOf();
if (berm !== undefined) detail.cross_sections[0].berm = berm;
await m.refreshCrossDesigns({
projectId: P,
routeId: R,
detail,
edits: { station_offsets: {}, curve_radii: {} },
alignment,
});
const design = detail.cross_sections[0].design;
return { fill: design.fill_area_m2 ?? null, cut: design.cut_area_m2 ?? null };
};
out.refresh = {
unattached: await run(undefined),
attachedSame: await run(job.storedBerm),
attachedNone: await run(null),
};
}
process.stdout.write(JSON.stringify(out));