Files
Aislo/resources/tester/helper_91_ground_free.cjs
T

101 lines
3.8 KiB
JavaScript

/* 91 원지반 · 암 제약 삭제 · 유출측 복합경사 헬퍼 — 화면 TS 를 그 자리에서 트랜스파일해 Node 로 돌림.
* 입력 = 73-4 픽스처(세월교 173.09 · 박스 352.14 · 관 180) · 결과 = 표준출력 JSON 한 벌. 짝 = `test_91_ground_free.py`.
*/
const fs = require("fs");
const path = require("path");
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
const ROOT = path.join(__dirname, "..", "..");
const cache = new Map();
// 화면 전용 모듈(토스트 · 글) — 기하 계산엔 안 쓰임
const STUBS = {
"@ui/ui_template_toast": { showToast: () => undefined },
};
function loadTs(file) {
const full = path.resolve(file);
if (cache.has(full)) return cache.get(full);
if (full.endsWith(".json")) {
const data = JSON.parse(fs.readFileSync(full, "utf8"));
cache.set(full, data);
return data;
}
const js = ts.transpileModule(fs.readFileSync(full, "utf8"), {
compilerOptions: {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2020,
esModuleInterop: true,
},
}).outputText;
const box = { exports: {} };
cache.set(full, box.exports);
const localRequire = (request) => {
if (STUBS[request]) return STUBS[request];
const alias = { "@util/": "common_util", "@ui/": "ui_template", "@config/": "config" };
for (const [prefix, dir] of Object.entries(alias))
if (request.startsWith(prefix))
return loadTs(resolve(path.join(ROOT, dir, request.slice(prefix.length))));
return loadTs(resolve(path.join(path.dirname(full), request)));
};
new Function("exports", "module", "require", js)(box.exports, box, localRequire);
cache.set(full, box.exports);
return box.exports;
}
const resolve = (base) =>
[base, `${base}.ts`, path.join(base, "index.ts")].find(
(p) => fs.existsSync(p) && fs.statSync(p).isFile(),
) ?? `${base}.ts`;
const B06 = (f) => path.join(ROOT, "B06_Section", f);
const { computeStoredLayouts } = loadTs(B06("B06_Section_Structure_Layouts.ts"));
const fixture = JSON.parse(
fs.readFileSync(path.join(__dirname, "fixtures", "b06_73_4_body_guard_sections.json"), "utf8"),
);
const sections = fixture.cross_sections;
const at = (c) => sections.find((s) => Math.abs(s.chainage_m - c) < 0.6);
const clone = (v) => JSON.parse(JSON.stringify(v));
const r3 = (v) => Math.round(v * 1000) / 1000;
const out = {};
/** 원지반 사본 — [from, to] 안 샘플을 dz 만큼 옮김. */
const shiftGround = (s, dz, from = -Infinity, to = Infinity) => {
for (const p of s.samples)
if (p.offset_m >= from && p.offset_m <= to && p.elevation_m != null) p.elevation_m += dz;
};
const layoutsOf = (s, base) =>
computeStoredLayouts(
s,
sections.map((x) => (x === base ? s : x)),
);
// ① 91-2 세월교 바닥 — 자동은 하상을 따라감 · 손 값(측벽 높이)은 원지반을 바꿔도 그대로 · 흙막이 기본 높이도
const FORD = at(173.087);
function fordFloor(edit) {
const s = clone(FORD);
for (const role of ["inlet", "outlet"]) s.culvert[role].revet_height_m = null;
edit(s);
const { ford, culvert } = layoutsOf(s, FORD);
return ford.sides.map((side) => {
const wall = culvert.walls.find((w) => w.role === side.role);
return {
role: side.role,
slabTop: r3(side.slabTopElevation),
wallBottom: wall ? r3(Math.min(...wall.points.map((p) => p.elevation))) : null,
};
});
}
const hand = (s) => {
s.design.ford_adjust = {
inlet: { heightM: 2.0, lateralM: 0, slopeM: 0 },
outlet: { heightM: 2.4, lateralM: 0, slopeM: 0 },
};
};
out.fordAuto = fordFloor(() => undefined);
out.fordAutoBedDown = fordFloor((s) => shiftGround(s, -2, -2, 2));
out.fordHand = fordFloor(hand);
out.fordHandBedDown = fordFloor((s) => {
hand(s);
shiftGround(s, -2, -2, 2);
});
process.stdout.write(JSON.stringify(out));