- 흙막이 양식 한 벌(design_structure_guard) — 배관 · 박스 · 세월교가 같은 칸(형태 · 길이 · 높이 · 측점 전후) · 추가 흙막이 · 도수로/돌붙임 상자
- 세월교 · 박스 유입 · 유출: 흙막이 고르면 흙막이 칸(키 {side}_revet_* · 기본 찰 10 · 1.5 · 5 · 5) · [연동][경사] 옵션 줄
- B06 측벽 높이 · 좌우 · 상하 · 바닥판 읽기 줄을 세월교 · 박스 유입 · 유출 칸에 안 옮김(강조만)
- 유입 · 유출 「없음」 = 목록 램프 · 구조물 조합 잇기 줄 없음(명세 none)
- 세월교: 수량(련) 관경 바로 뒤 · 련 기본 2 · 새 시설 빈 월류 높이 = 유량 오면 필요 수심 · 종류 바꿀 때 유량 넘김
- 물넘이 포장: 경사각 기본 3° · 월류 폭 · 높이 칸(세월교와 같은 키 ford_width_m · ford_height_m · 같은 계산)
- 구조물정의 판 18(판_17 이력) · 이름 표 · 집계표 선택 컨테이너 짝 · 저장 병합 키
- 시험: 세월교 · 박스 · 물넘이 명세 기대값 · 흙막이 짝 자리 옮김
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVPp2o6Mh2FZJr72yW3ofZ
72 lines
3.1 KiB
JavaScript
72 lines
3.1 KiB
JavaScript
/* 박스암거 명세 단위검증 헬퍼(PLAN 52-2) — `design_structure_spec.ts` · `design_structure_box.ts` 를
|
||
* 그 자리에서 트랜스파일해 Node 로 돌림(같은 폴더 명세 import 는 따라 옮김). 결과 = JSON 한 벌.
|
||
* 인자 `names` 면 박스암거 이름 표(정의 `종류.box_culvert.이름`)만 냄.
|
||
*/
|
||
const fs = require("fs");
|
||
const path = require("path");
|
||
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
||
|
||
const ROOT = path.join(__dirname, "..", "..");
|
||
const load = (file) => {
|
||
const src = fs.readFileSync(path.join(ROOT, "A00_Common", "design", file), "utf8");
|
||
const js = ts.transpileModule(src, {
|
||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
||
}).outputText;
|
||
const box = { exports: {} };
|
||
// 같은 폴더 명세(흙막이 양식 · 65-2)는 그 자리에서 옮김
|
||
const near = (m) => (m.startsWith("./") ? load(`${m.slice(2)}.ts`) : require(m));
|
||
new Function("exports", "module", "require", js)(box.exports, box, near);
|
||
return box.exports;
|
||
};
|
||
const s = load("design_structure_spec.ts");
|
||
const b = load("design_structure_box.ts");
|
||
const SPEC = b.BOX_SPEC;
|
||
|
||
if (process.argv[2] === "names") {
|
||
process.stdout.write(JSON.stringify(s.nameTable(SPEC)));
|
||
process.exit(0);
|
||
}
|
||
|
||
/** 화면이 하는 차례 그대로 — 옛 값 정리 → 명세 읽기 → 본체 칸 되찾기 → 저장 옵션. */
|
||
const roundTrip = (options, edit) => {
|
||
const state = s.readState(SPEC, b.boxOptionsIn(options));
|
||
Object.assign(state.body[0], b.bodyOf(options));
|
||
edit?.(state);
|
||
return { state, out: { ...s.writeOptions(SPEC, state), ...b.bodyOptions(state.body[0]) } };
|
||
};
|
||
const body = SPEC.containers.find((c) => c.id === "body");
|
||
const width = body.items.find((i) => i.id === "width");
|
||
|
||
const old = { body_width_m: 3, body_height_m: 2.5, wing_in: "있음", wing_in_length_m: 2 };
|
||
const out = {
|
||
containers: SPEC.containers.map((c) => [c.id, c.title, c.required]),
|
||
links: SPEC.containers.map((c) => s.linkOf(c, 1)),
|
||
sizes: body.items[0].choices.map((c) => c.value),
|
||
structures: SPEC.containers[1].items[0].choices.map((c) => c.value),
|
||
customHidden: s.branchOf(width, { size: "2.0×2.0" }),
|
||
customShown: s.branchOf(width, { size: "사용자 입력" }),
|
||
old: roundTrip(old),
|
||
preset: roundTrip({ body_width_m: 2, body_height_m: 2, wing_out: "없음" }),
|
||
toPreset: roundTrip(old, (st) => {
|
||
st.body[0].size = "3.0×3.0";
|
||
st.outlet[0].structure = "흙막이";
|
||
}),
|
||
toCustom: roundTrip({ body_width_m: 2, body_height_m: 2 }, (st) => {
|
||
st.body[0].size = "사용자 입력";
|
||
st.body[0].width = "2.4";
|
||
st.body[0].height = "1.8";
|
||
}),
|
||
blank: roundTrip({}),
|
||
// 52-19 — 사용자 입력에서 한 칸 · 두 칸 비우고 저장 → 다시 열기
|
||
oneBlank: roundTrip({ body_height_m: 2.5 }),
|
||
bothBlank: roundTrip({ body_width_m: 2, body_height_m: 2 }, (st) => {
|
||
st.body[0].size = "사용자 입력";
|
||
st.body[0].width = "";
|
||
st.body[0].height = "";
|
||
}),
|
||
keys: s.specKeys(SPEC),
|
||
retired: SPEC.retired,
|
||
};
|
||
out.bothBlankAgain = roundTrip(out.bothBlank.out);
|
||
process.stdout.write(JSON.stringify(out));
|