Files
Aislo/resources/tester/helper_266_card_toggle.mjs
T

156 lines
5.5 KiB
JavaScript

/* PLAN 439 헬퍼 — 저장 노선 cross 차례(`refreshSavedCross`)가 카드 단추(복합경사 · 측구 · 지반)를 늘 다시 셈:
* 묶음 측점 = 상세 측점(돌려줌) · 다름 1 mm 넘게(null = 묶음 엔진 · 카드 자료는 고침) · 서버 폴백에 카드 선택 실음.
* node helper_266_card_toggle.mjs <묶음.mjs> <job.json>
* 짝 = `test_266_card_toggle_mismatch.py` · 표준출력 JSON 한 벌.
*/
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);
globalThis.matchMedia = () => ({ matches: false, addEventListener() {}, removeEventListener() {} });
globalThis.addEventListener = () => undefined;
globalThis.removeEventListener = () => undefined;
globalThis.screen = { width: 1920, height: 1080 };
globalThis.location = {
href: "http://localhost/",
pathname: "/",
search: "",
hash: "",
origin: "http://localhost",
};
const job = JSON.parse(readFileSync(process.argv[3], "utf8"));
// 서버 폴백 창구만 받아 적음 — 그 밖 요청은 404(격자 없음 = 넓힘 안 함)
const previews = [];
globalThis.fetch = async (url, init) => {
if (String(url).includes("/cross-design/preview")) {
previews.push(JSON.parse(init.body));
return Response.json({ designs: [] });
}
return new Response("{}", { status: 404 });
};
const m = await import(pathToFileURL(process.argv[2]).href);
const R = 7;
const EDITS = { station_offsets: {}, curve_radii: {} };
const alignment = {
stations: job.sections.map((s) => ({ chainage_m: s.chainage_m, plan_elevation_m: s.plan_z })),
samples: job.sections.map((s) => ({ chainage_m: s.chainage_m, elevation_m: s.plan_z })),
balance: { cut_area_m2: 0, fill_area_m2: 0, net_area_m2: 0 },
};
const detailOf = (withLine) => ({
longitudinal: withLine
? { length_m: 1000, stations: [], profile_alignment: { policy: {} } }
: { length_m: 1000, stations: [] },
cross_sections: job.sections.map(({ plan_z, ...section }) => ({
...structuredClone(section),
design: {
ground_type: "ripping_rock",
section_mode: job.mode,
design_elevation_m: plan_z,
},
})),
});
const pick = (design) => ({
ground_type: design.ground_type,
two_stage_slope: design.two_stage_slope ?? null,
ditch_enabled: design.ditch_enabled ?? null,
cut: design.cut_area_m2 ?? null,
fill: design.fill_area_m2 ?? null,
line: JSON.stringify(design.design_line ?? null),
});
/** 카드 단추 줄 차례 — 처음 셈 → 복합경사 켬 → 측구 끔 → 지반 흙. `shift` = 묶음 측점 어긋남(m). */
async function toggles(projectId, shift) {
m.writeState("std-cross", job.standard, projectId);
m.rememberRockBoundaryDefault(projectId, job.rockDefault);
const detail = detailOf(true);
const target = detail.cross_sections[job.target];
const stations = detail.cross_sections.map((s, i) => ({
key: `s${i}`,
chainageM: s.chainage_m + shift,
}));
const steps = [];
const run = async (tag) => {
const updated = [];
let calls = 0; // 받는 쪽 = 카드 다시 그림 + 종단 · 유토 다시 그림(design_shared) — 한 걸음에 한 번
const out = await m.refreshSavedCross(
{ projectId, routeId: R, detail, edits: EDITS, alignment },
stations,
(rows) => (calls++, updated.push(...rows)),
);
steps.push({
tag,
out: out ? Object.keys(out.byKey).length : null,
updated,
calls,
...pick(target.design),
});
};
await run("open");
const choice = {
ground_type: "ripping_rock",
section_mode: job.mode,
ditch_side: null,
ditch_type: "standard",
paved: false,
two_stage_slope: false,
ditch_choice: null,
};
for (const [tag, over] of [
["two_stage", { two_stage_slope: true }],
["ditch_off", { ditch_choice: false }],
["soil", { ground_type: "soil" }],
]) {
Object.assign(choice, over);
m.writeCrossDesignChoice(projectId, R, target.chainage_m, { ...choice });
await run(tag);
}
// 사면 이동 한 걸음(B06 ◀▶ 0.1 m · 깎기 쪽 · 441 · 요구 268-4)
m.writeShoulderExtend(projectId, R, target.chainage_m, job.mode.split("_")[0], 0.1);
await run("slope");
return { target: target.chainage_m, steps };
}
const out = { same: await toggles("p266a", 0), mismatch: await toggles("p266b", 0.002) };
/* 선형 저장분 없음 — 옛 서버 폴백 걷음(511-B B-4) · 부름 0 */
{
const projectId = "p266c";
m.writeState("std-cross", job.standard, projectId);
const detail = detailOf(false);
const at = detail.cross_sections[job.target].chainage_m;
m.writeCrossDesignChoice(projectId, R, at, {
ground_type: "soil",
section_mode: job.mode,
two_stage_slope: true,
ditch_choice: false,
});
await m.refreshSavedCross({ projectId, routeId: R, detail, edits: EDITS }, [], () => undefined);
out.server = { at, calls: previews.length };
}
process.stdout.write(JSON.stringify(out));