/* 186-1 묻힌 관 유출 벽 설계선 접힘 헬퍼 — 화면 TS 를 그 자리에서 트랜스파일해 Node 로 돌림. * 입력 = 검증_랩탑메인 No.14+12.22 사본(`fixtures/b06_186_1_pipe_292.json`) · 73-4 픽스처 관 340(절토 쪽 유출). * 결과 = 표준출력 JSON 한 벌. 짝 = `test_186_1_outlet_fold.py`. */ const fs = require("fs"); const path = require("path"); const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); // 화면 전용 모듈(토스트) — 기하 계산엔 안 쓰임 const STUBS = { "@ui/ui_template_toast": { showToast: () => undefined }, }; const { loadTs } = makeLoader({ root: ROOT, interop: true, requireFor: (full) => (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))); }, }); 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, structureAreaRows } = loadTs(B06("logic/B06_Section_Structure_Layouts.ts")); const { computeCulvertLayout } = loadTs(B06("logic/B06_Section_Cross_Culvert_Geom.ts")); const read = (name) => JSON.parse(fs.readFileSync(path.join(__dirname, "fixtures", name), "utf8")).cross_sections; const clone = (v) => JSON.parse(JSON.stringify(v)); const r2 = (v) => Math.round(v * 100) / 100; /** 유출 쪽 설계선(트림 사면) 점열 · 유출 벽 · 면적 행. */ function study(sections, target) { const section = sections.find((s) => Math.abs(s.chainage_m - target) < 0.01); const { culvert } = computeStoredLayouts(section, sections); const wall = culvert.walls.find((w) => w.role === "outlet"); const trim = culvert.designTrim; const slope = (wall.outward > 0 ? trim.maxSlope : trim.minSlope).points; const row = structureAreaRows(sections).find((r) => Math.abs(r.chainage_m - target) < 0.01); return { outward: wall.outward, wallTop: r2(wall.topJoint.elevation), groundAtWall: r2(groundOf(section, wall.topJoint.offset)), offsets: slope.map((p) => r2(p.offset)), elevations: slope.map((p) => r2(p.elevation)), cut: row ? row.cut_area_m2 : null, fill: row ? row.fill_area_m2 : null, }; } function groundOf(section, offset) { const s = section.samples; for (let i = 1; i < s.length; i += 1) if (s[i].offset_m >= offset) { const t = (offset - s[i - 1].offset_m) / (s[i].offset_m - s[i - 1].offset_m); return s[i - 1].elevation_m + (s[i].elevation_m - s[i - 1].elevation_m) * t; } return NaN; } const out = {}; // ① 저장값 그대로(유출 d 9.0) · ② 자동 자리(조작값 없음) const stored = read("b06_186_1_pipe_292.json"); out.stored = study(stored, 292.22); const auto = clone(stored); auto[0].design.revet_adjust = null; out.auto = study(auto, 292.22); // ③ 91-4 절토 쪽 배관 유출(73-4 픽스처 관 340 · 유출 = 우측 절토) const base = read("b06_73_4_body_guard_sections.json"); const s340 = clone(base.find((s) => Math.abs(s.chainage_m - 340) < 0.6)); s340.uphill_side = "left"; s340.culvert = { type: "pipe", chainage_m: 340, pipe_kind: "흄관", diameter_m: 1.0, min_cover_m: 0.5, inlet: { role: "inlet", structure: "기슭막이", revet_form: "돌쌓기(찰)" }, outlet: { role: "outlet", structure: "기슭막이", revet_form: "돌쌓기(찰)" }, }; s340.design.inlet_structure = "revet"; const layout = computeCulvertLayout(s340, s340.samples, undefined, "revet"); const wall340 = layout.walls.find((w) => w.role === "outlet"); const slope340 = (wall340.outward > 0 ? layout.designTrim.maxSlope : layout.designTrim.minSlope) .points; out.cut340 = { outward: wall340.outward, offsets: slope340.map((p) => r2(p.offset)), elevations: slope340.map((p) => r2(p.elevation)), }; process.stdout.write(JSON.stringify(out));