Files
Aislo/resources/tester/helper_52_structure_spec.cjs
T
eomsangdonandClaude Sonnet 5.5 fc36f0ae4e feat(B05): 노면공 시작 · 종료 측점 · 길이 출력 · 기준 · 전/후 없음(87-1)
- 노면공 명세 byRange: 위치 줄 = 시작 · 종료 측점만(기준 측점 칸 없음 · 알약 = 시점) · 상세 내용 = 포장사양 → 길이(시작~종료 출력) → 높이
- 포장사양 선택지 콘크리트 · 아스콘 · 쇄석 · 높이 기본 0.20 m
- 저장 꼴: placement interval · start_m · end_m · options.pave_spec · height_m · 옛 length_m · before_m · after_m 은 [수정] 저장 때 뺌
- 구조물정의 판 20(판_19 이력) · 노면공 길이 · 전 · 후 옵션 빼고 height_m 기본값
- 시험: test_52_10 맞춤

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVPp2o6Mh2FZJr72yW3ofZ
2026-10-08 12:03:38 +09:00

172 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 구조물 명세 공용 틀 · 배관 명세 단위검증 헬퍼(PLAN 52-1) — `design_structure_spec.ts` ·
* `design_structure_pipe.ts` 를 그 자리에서 트랜스파일해 Node 로 돌림(꼴만 import). 결과 = JSON 한 벌.
* 인자 `names` 면 배관 이름 표(정의 `종류.pipe.이름`)만 냄.
*/
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, deps = {}) => {
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: {} };
const near = (m) => (m.startsWith("./") ? load(`${m.slice(2)}.ts`) : require(m)); // 같은 폴더 명세
new Function("exports", "module", "require", js)(box.exports, box, (m) => deps[m] ?? near(m));
return box.exports;
};
const s = load("design_structure_spec.ts");
const road = load("design_structure_road.ts");
const { PIPE_SPEC, STRUCTURE_SPECS } = load("design_structure_pipe.ts", {
"./design_structure_road": road,
});
// 노면공 › 콘크리트 포장(PLAN 52-10) — 옛 상세 칸은 남고 명세 키만 오감
if (process.argv[2] === "road") {
const spec = STRUCTURE_SPECS.pavement_concrete;
const old = {
length_m: 12,
before_m: 4,
after_m: 8,
thickness_cm: 20,
joint_spacing_m: 6,
pave_spec: "콘크리트",
height_m: 0.2,
};
const state = s.readState(spec, old);
const edited = JSON.parse(JSON.stringify(state));
edited.detail[0].height = "0.35";
const cleared = JSON.parse(JSON.stringify(state));
cleared.detail[0].height = "";
process.stdout.write(
JSON.stringify({
registered: Object.keys(STRUCTURE_SPECS),
same: spec === road.PAVEMENT_SPEC,
containers: spec.containers.map((c) => [c.id, c.title, c.required, c.link]),
choices: road.PAVE_SPEC_CHOICES.map((c) => c.value),
items: spec.containers[0].items.map((i) => [i.id, i.label, i.kind]),
state,
edited: s.writeOptions(spec, edited),
cleared: s.writeOptions(spec, cleared),
keys: s.specKeys(spec),
retired: spec.retired,
dropped: spec.dropped,
byRange: spec.byRange,
}),
);
process.exit(0);
}
// 기타(PLAN 52-14) — 선택 컨테이너 「상세 내용」 비고 글 · 길이 상한 · 비우기 · 이름 표
if (process.argv[2] === "etc") {
const spec = STRUCTURE_SPECS.etc;
const old = { name: "배수판", etc_detail_2_note: "옛 비고", etc_detail_5_note: "둘째" };
const state = s.readState(spec, old);
const edited = JSON.parse(JSON.stringify(state));
edited.detail[0].note = " 새 비고 ";
edited.detail[1].note = "";
edited.detail.push({ note: "가".repeat(s.TEXT_MAX + 30) });
const out = s.writeOptions(spec, edited);
process.stdout.write(
JSON.stringify({
same: spec === road.ETC_SPEC,
containers: spec.containers.map((c) => [c.id, c.title, c.required, c.prefix, c.link]),
items: spec.containers[0].items.map((i) => [i.id, i.label, i.kind]),
state,
edited: out,
max: s.TEXT_MAX,
longLen: out.etc_detail_3_note?.length ?? 0,
keys: s.specKeys(spec),
names: s.nameTable(spec),
links: [1, 2].map((n) => s.linkOf(spec.containers[0], n)),
}),
);
process.exit(0);
}
// 선택 컨테이너 「하나만」(PLAN 52-17) — 종류.컨테이너 → max · 옛 저장 둘은 다 읽힘
if (process.argv[2] === "max") {
const max = {};
for (const [type, spec] of Object.entries(STRUCTURE_SPECS))
for (const c of spec.containers) if (!c.required) max[`${type}.${c.id}`] = c.max ?? null;
const old = { ford_chute_1_structure: "도수로", ford_chute_2_structure: "돌붙임" };
const state = s.readState(STRUCTURE_SPECS.ford_pavement, old);
process.stdout.write(
JSON.stringify({
max,
oldTwo: state.chute.length,
back: s.writeOptions(STRUCTURE_SPECS.ford_pavement, state),
}),
);
process.exit(0);
}
if (process.argv[2] === "names") {
process.stdout.write(JSON.stringify(s.nameTable(PIPE_SPEC)));
process.exit(0);
}
const old = {
pipe_kind: "흄관",
wing_wall_type: "A-TYPE",
pipe_diameter_mm: 1000,
inlet_type: "집수정",
inlet_structure: "L",
inlet_basin_length_m: 2,
inlet_basin_before_m: 1,
inlet_basin_after_m: 1,
outlet_type: "기슭막이",
outlet_revet_form: "돌쌓기(메)",
outlet_revet_length_m: 10,
outlet_revet_height_m: 2.5,
soil_add_2_structure: "기슭막이",
soil_add_2_form: "바자",
soil_add_5_length_m: 4,
chute_add_1_structure: "도수로",
};
const state = s.readState(PIPE_SPEC, old);
const back = s.writeOptions(PIPE_SPEC, state);
// 흙막이로 바꿈 → 갈래 키가 기슭막이 쪽 · also(inlet_structure revet)
const soil = JSON.parse(JSON.stringify(state));
soil.inlet[0].structure = "기슭막이";
soil.inlet[0].form = "콘크리트";
soil.inlet[0].length = "6";
const soilOut = s.writeOptions(PIPE_SPEC, soil);
const inlet = PIPE_SPEC.containers.find((c) => c.id === "inlet");
const form = inlet.items.find((i) => i.id === "form");
const keys = s.specKeys(PIPE_SPEC);
const out = {
containers: PIPE_SPEC.containers.map((c) => [c.id, c.title, c.required]),
state,
back,
soilOut,
formBasin: s.choicesOf(form, { structure: "집수정" }).map((c) => c.label),
formSoil: s.choicesOf(form, { structure: "기슭막이" }).map((c) => c.label),
formNone: s.branchOf(form, {}),
outletForms: s
.choicesOf(
PIPE_SPEC.containers.find((c) => c.id === "outlet").items.find((i) => i.id === "form"),
{ structure: "기슭막이" },
)
.map((c) => c.label),
keys,
links: PIPE_SPEC.containers.map((c) => s.linkOf(c, 2)),
split: {
lengthFromSides: s.solveSplit({ length: "10", before: "3", after: "4" }, ["after", "before"]),
beforeFromLength: s.solveSplit({ length: "10", before: "3", after: "4" }, ["after", "length"]),
defaultKeepsLength: s.solveSplit({ length: "10", before: "3", after: "" }, ["before"]),
blankKept: s.solveSplit({ length: "", before: "3", after: "4" }, ["before", "length"]),
clamp: s.solveSplit({ length: "2", before: "", after: "5" }, ["after", "length"]),
},
names: {
renamed: s.itemLabel(inlet, form, { "inlet.form": "모양" }),
title: s.containerTitle(inlet, {}, "그룹 이름"),
titleOwn: s.containerTitle(inlet, { inlet: "유입 보호" }, "그룹 이름"),
choice: s.choiceLabel(inlet, form, { value: "U", label: "ㄷ형" }, {}),
},
};
process.stdout.write(JSON.stringify(out));