/* 498-2 노선 바뀐 [저장] 계획고 손댐 — 진짜 TS(`logic/B05_Profile_Pipeline_Grade` follow · `gradeTouch`)를 * Node 로 돌림. 표준출력 JSON 한 벌. */ const path = require("path"); const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); function loadTs(file, stubs = {}) { return makeLoader({ root: ROOT, cache: false, requireFor: (full) => (request) => { if (stubs[request]) return stubs[request]; throw new Error(`stub 없음: ${request} (${file})`); }, }).loadTs(path.join(ROOT, file)); } const straightJudge = loadTs("B05_Profile/logic/B05_Profile_Profile_Straight.ts"); const curveLaw = loadTs("B05_Profile/logic/B05_Profile_Profile_CurveLaw.ts"); const pivot = loadTs("B05_Profile/logic/B05_Profile_UI_Profile_Pivot.ts", { "./B05_Profile_Profile_Straight": straightJudge, }); const alignment = loadTs("B05_Profile/logic/B05_Profile_UI_Profile_Alignment.ts", { "./B05_Profile_UI_Profile_Pivot": pivot, "./B05_Profile_Profile_Straight": straightJudge, "./B05_Profile_Profile_CurveLaw": curveLaw, }); const carry = loadTs("B05_Profile/logic/B05_Profile_Grade_Carry.ts", { "./B05_Profile_UI_Profile_Alignment": alignment, }); const grade = loadTs("B05_Profile/logic/B05_Profile_Pipeline_Grade.ts", { "./B05_Profile_Profile_CurveLaw": curveLaw, "../../common_util/common_util_route_follow": {}, "../../common_util/common_util_structure_station": { PLUS_OWNER_PREFIX: "plus-", SAME_STATION_M: 0.005, }, "./B05_Profile_Grade_Seat": loadTs("B05_Profile/logic/B05_Profile_Grade_Seat.ts", { "./B05_Profile_UI_Profile_Alignment": alignment, }), "./B05_Profile_UI_Profile_Alignment": alignment, "./B05_Profile_Grade_Carry": carry, "./B05_Profile_Sections_Stations": { SECTION_STATION_INTERVAL_M: 20 }, "./B05_Profile_Grade_Ground": loadTs("B05_Profile/logic/B05_Profile_Grade_Ground.ts", { "./B05_Profile_Profile_CurveLaw": curveLaw, "./B05_Profile_UI_Profile_Alignment": alignment, }), }); const routeOf = (line) => { const chainage = [0]; for (let i = 1; i < line.length; i += 1) chainage.push( chainage[i - 1] + Math.hypot(line[i][0] - line[i - 1][0], line[i][1] - line[i - 1][1]), ); return { line, curves: [], chainage, lengthM: chainage[chainage.length - 1] }; }; /** 10 m 격자 + 끝 — 묶음 stations 단계 자리. */ const gridOf = (route) => { const out = []; for (let s = 0; s < route.lengthM - 1e-6; s += 10) out.push(Math.round(s * 1000) / 1000); return [...out, Math.round(route.lengthM * 1000) / 1000]; }; const SAVED_LINE = [ [0, 0], [100, 0], [100, 100], [100, 200], ]; const STEPS = [ [ [0, 0], [95, 0], [100, 100], [100, 200], ], [ [0, 0], [90, 0], [100, 100], [100, 200], ], ]; const BASE = [0, 100, 200, 300].map((chainage_m) => ({ chainage_m, elevation_m: 500 })); const SAVED = { station_offsets: { "250.000": 0.5 }, curve_radii: {} }; /** 저장 노선에서 노선 걸음 둘 — 걸음 사이 `between` 이 사용자 계획고 조작(묶음 입력 고침). */ function run(between, after) { const stage = grade.createFollowStage({ savedLine: () => null, stationsAt: (route) => gridOf(route), }); const planline = { policy: { station_interval_m: 20 }, basePvi: BASE }; let now = SAVED; let before = routeOf(SAVED_LINE); let route = before; STEPS.forEach((line, index) => { route = routeOf(line); const patch = stage({ inputs: { route: { nodes: [] }, pipes: null, structures: null, alignment: now }, out: { route }, before: { route: before, planline }, }); if (patch.alignment) now = patch.alignment; if (index === 0 && between) now = between(now); before = route; }); if (after) now = after(now); const reader = { input: (key) => ({ route: { nodes: [] }, alignment: now })[key] ?? null, output: (key) => (key === "route" ? route : null), }; return { now, touch: stage.touch(SAVED, reader) }; } const bump = (key, by) => (edits) => ({ ...edits, station_offsets: { ...edits.station_offsets, [key]: (edits.station_offsets[key] ?? 0) + by }, }); const drop = (edits) => { const offsets = { ...edits.station_offsets }; delete offsets[Object.keys(offsets).sort()[0]]; return { ...edits, station_offsets: offsets }; }; process.stdout.write( JSON.stringify({ plain: run(null, null), lateBump: run(null, bump("60.000", 0.3)), midBump: run(bump("40.000", 0.2), null), removed: run(null, drop), noFirst: grade.createFollowStage({ savedLine: () => null }).touch(SAVED, { input: () => null, output: () => null, }), pure: grade.gradeTouch( { station_offsets: { "10.000": 1, "20.000": 2.5 }, curve_radii: { "30.000": 80 } }, { station_offsets: { "10.000": 1, "20.000": 2, "40.000": 3 }, curve_radii: {} }, ), }), );