/* PLAN 260 단위검증 헬퍼 — [상세] 표 위 CAD 칸 · 옛 글 옮김 · 횡단배수 미리 넣음. * `B06_Section_UI_Cross_Detail_Cad.ts` 를 그 자리에서 트랜스파일해 Node 로 돌린다(CAD · 세션 · 서버 = 흉내). * 결과는 표준출력에 JSON 한 벌 · 인자 `mirror` = 표준입력 입력으로 거울 결과(260-4). 확장자 `.cjs` 까닭은 `helper_108_drag_box_hit.cjs` 머리와 같다. */ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); const ROOT = path.join(__dirname, "..", ".."); // 인자 `load` = 표준입력 {pipes, structures, types} 를 세션 · 서버 흉내로 `loadNoteThings`(265-2) const DATA = { pipes: [], structures: [], types: [] }; const STUBS = { "@ui/cad_host/cad_host": { createCadHost: () => ({}) }, "../A00_Common/b_page_state": { readState: () => null, writeState: () => undefined }, "../A00_Common/design/design_selection": { PIPE_MATCH_M: 0.51 }, "../B04_PreProcess/B04_PreProcess_Api_Fetch": { fetchDetailPipePoints: async () => ({ pipe_points: DATA.pipes }), }, "../B05_Profile/B05_Profile_Api_Pipes_Draft": { readPendingPipes: () => null }, "../B05_Profile/B05_Profile_Api_Structures": { fetchStructures: async () => ({ structures: DATA.structures }), fetchStructureTypes: async () => DATA.types, readPendingStructures: () => null, }, // 좌측 패널 옵션 줄(166-1)은 test_166_1 이 진짜 명세로 봄 — 여기는 조합 줄 · 마크만 "../B05_Profile/B05_Profile_UI_Structures_Balloon": { structureOptionLines: () => [] }, }; function loadTs(file) { const js = ts.transpileModule(fs.readFileSync(file, "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const box = { exports: {} }; const localRequire = (request) => { if (STUBS[request]) return STUBS[request]; throw new Error(`흉내 없는 모듈: ${request}`); }; new Function("exports", "module", "require", js)(box.exports, box, localRequire); return box.exports; } // 관 길이 정수(265-3) = 실제 `pipeLengthWhole` · 조합 참조 읽기(265-2) = 실제(둘 다 import 없음) STUBS["./B06_Section_UI_Cross_Culvert_Const"] = loadTs( path.join(ROOT, "B06_Section", "B06_Section_UI_Cross_Culvert_Const.ts"), ); STUBS["../common_util/common_util_summary_item"] = loadTs( path.join(ROOT, "common_util", "common_util_summary_item.ts"), ); const cad = loadTs(path.join(ROOT, "B06_Section", "B06_Section_UI_Cross_Detail_Cad.ts")); const wall = (role, form, height, length) => ({ role, structure: "기슭막이", revet_form: form, revet_height_m: height, revet_length_m: length, }); const culvert = (extra = {}) => ({ type: "pipe", chainage_m: 1433, pipe_kind: null, diameter_m: 1.2, min_cover_m: 0.5, inlet: wall("inlet", "돌쌓기(찰)", 2, 10), outlet: wall("outlet", "돌쌓기(메)", 2, 10), ...extra, }); const section = (spec, design = { pipe_length_m: 22 }, chainage = 1433) => ({ chainage_m: chainage, station_id: "s", samples: [], culvert: spec, design, }); /** 엔티티 → 비교하기 쉬운 꼴(종류 · 글 · 자리 · 색). */ const brief = (entities) => entities.map((entity) => ({ type: entity.type, label: entity.shapeData.label ?? null, align: entity.shapeData.options?.textAlign ?? null, x: entity.shapeData.basePoint?.x ?? entity.shapeData.center?.x ?? null, y: entity.shapeData.basePoint?.y ?? entity.shapeData.center?.y ?? null, color: entity.lineColor, layer: entity.layerId, })); const run = (sec, lines = []) => brief(cad.noteEntities(sec, "NO.71+13", lines)); const LINES = ["기슭막이 찰쌓기 2.0m", "돌붙임 찰붙임"]; const out = { full: run(section(culvert()), LINES), noLength: run(section(culvert(), {})), basin: run( section( culvert({ inlet: { role: "inlet", structure: "집수정", basin_form: "L", basin_height_m: 1.7, basin_length_m: 2, }, }), ), [], ), chuteFallback: run(section(culvert({ chute: { structure: "도수로", thickness_m: 0.45 } })), []), noSides: run( section( culvert({ inlet: { role: "inlet", structure: "" }, outlet: { role: "outlet", structure: "" }, }), ), [], ), none: run(section(undefined)), ford: run(section(culvert({ body: "ford" }))), hidden: run(section(culvert({ hidden_pipe: true }))), neighbour: run(section(culvert(), { pipe_length_m: 22 }, 1440)), // 마크 없이 조합 줄만(구조물 측점 · 265-2) = 측점부터 왼쪽 끝 linesOnly: run(section(undefined), LINES), legacy: brief(cad.legacyNoteEntities("\nL형 측구 \n\n집수정 보강\n")), legacyEmpty: cad.legacyNoteEntities(" ").length, station: [ cad.stationNoLabel(1433, 20), cad.stationNoLabel(1420, 20), cad.stationNoLabel(1439.97, 20), ], }; // 거울(260-4 · 265-2) — 시험이 표준입력으로 준 같은 입력 [{section, station, things, chainage, interval}] // → TS 조합 줄 · 엔티티 · 측점 이름(파이썬 짝 `_Engine_Cad_CulvertNote` 와 대조) if (process.argv[2] === "mirror") { const cases = JSON.parse(fs.readFileSync(0, "utf8")); const mirrored = cases.map((item) => { const lines = cad.structureNoteLines(item.things ?? [], item.section.chainage_m); return { lines, entities: cad.noteEntities(item.section, item.station, lines), station: cad.stationNoLabel(item.chainage, item.interval), at: cad.thingsAt(item.things ?? [], item.section.chainage_m).length, }; }); process.stdout.write(JSON.stringify(mirrored)); } else if (process.argv[2] === "load") { Object.assign(DATA, JSON.parse(fs.readFileSync(0, "utf8"))); cad.loadNoteThings("p").then((things) => process.stdout.write(JSON.stringify(things))); } else process.stdout.write(JSON.stringify(out));