/* ============================================================================= * design_structure_guard.ts * 흙막이 공통 양식 — 배관(표 01) · 박스암거(표 02) · 세월교(표 04)가 같은 칸을 씀(PLAN 65-2). * * · 흙막이 = 형태 6 · 길이 · 높이 · 기준측점 전 · 후(길이 = 전 + 후 맞물림) * · 필수 보호공(유입 · 유출)은 구조 갈래마다 저장 키(`{side}_revet_*` 옛 키) · 선택 흙막이 · 도수로/돌붙임은 * 인스턴스 키(`soil_add_{n}_*` · `chute_add_{n}_*`) * import = 꼴만 — 시험이 이 폴더 파일만 옮겨 돌림. * ========================================================================== */ import type { SpecChoice, SpecContainer, SpecItem } from "./design_structure_spec"; export const SOIL_FORMS: SpecChoice[] = [ { value: "돌쌓기(찰)", label: "돌 쌓기(찰)" }, { value: "돌쌓기(메)", label: "돌 쌓기(메)" }, { value: "콘크리트", label: "콘크리트" }, { value: "돌망태", label: "돌망태" }, { value: "통나무·목재틀", label: "통나무/목재틀" }, { value: "바자", label: "바자" }, ]; /** 흙막이 기본값(54-36 · 사면안정 흙막이 정의 기본값과 같음). */ const SOIL_DEFAULTS: Record = { form: "돌쌓기(찰)", length: "10", height: "1.5", before: "5", after: "5", }; /** 형태 · 길이 · 높이 · 전 · 후 — 필수 보호공은 구조 갈래마다 옛 키(`keys`) · 선택 흙막이는 인스턴스 키. * `forms` = 갈래별 형태 선택지(배관 집수정 등) · `defaults` = 새 상자 · 흙막이를 고를 때 칸에 실제 값. */ export function guardItems( keys?: Record>, forms?: Record, defaults = !keys, ): SpecItem[] { const by = (field: string, choices?: Record) => keys ? { item: "structure", map: Object.fromEntries( // 키 없는 갈래 = 그 구조에 없는 칸(집수정 길이 · 전 · 후) — 가림 Object.entries(keys) .filter(([, k]) => k[field]) .map(([structure, k]) => [ structure, { key: k[field], choices: choices?.[structure] }, ]), ), } : undefined; const items: SpecItem[] = [ { id: "form", label: "형태", kind: "select", choices: SOIL_FORMS, by: by("form", forms) }, { id: "length", label: "길이 (m)", kind: "number", split: "length", step: 1, by: by("length") }, { id: "height", label: "높이 (m)", kind: "number", step: 0.1, by: by("height") }, { id: "before", label: "기준측점 전 (m)", kind: "number", split: "before", step: 0.5, by: by("before"), }, { id: "after", label: "기준측점 후 (m)", kind: "number", split: "after", step: 0.5, by: by("after"), }, ]; return defaults ? items.map((item) => ({ ...item, default: SOIL_DEFAULTS[item.id] })) : items; } export const revetKeys = (side: "inlet" | "outlet"): Record => ({ form: `${side}_revet_form`, length: `${side}_revet_length_m`, height: `${side}_revet_height_m`, before: `${side}_revet_before_m`, after: `${side}_revet_after_m`, }); /** 세월교 · 박스 유입 · 유출 흙막이 칸(79-7) — 높이 빈 칸 = 자동(`heightHint` · 횡단도가 셈) · * 절토부 앞 수평공간 칸(`{side}_revet_berm_m`)을 더함. */ export function bodyGuardItems(side: "inlet" | "outlet", heightHint: string): SpecItem[] { const items = guardItems({ 흙막이: revetKeys(side) }, undefined, true).map((item) => item.id === "height" ? { ...item, default: undefined, hint: heightHint } : item, ); const berm: SpecItem = { id: "berm", label: "수평공간 (m)", kind: "number", step: 0.1, default: "1", by: { item: "structure", map: { 흙막이: { key: `${side}_revet_berm_m` } } }, }; return [...items, berm]; } /** 추가 흙막이(선택 · 여러 개) — 사면안정 흙막이(표 09 · 54-26)와 같은 칸 · 구조 고르기 없음(54-30). */ export const SOIL_ADD: SpecContainer = { id: "soil_add", title: "흙막이", required: false, prefix: "soil_add", link: "gsoiladd", items: guardItems(), }; /** 도수로/돌붙임(선택 · 하나만 · 54-48) — 옛 둘 이상은 보이되 [추가]만 숨김. */ export const CHUTE_ADD: SpecContainer = { id: "chute_add", title: "도수로/돌붙임", required: false, prefix: "chute_add", link: "gchuteadd", max: 1, items: [ { id: "structure", label: "구조", kind: "select", choices: [ { value: "도수로", label: "도수로" }, { value: "돌붙임", label: "돌붙임" }, ], }, ], };