/* ============================================================================= * B06_Section_Section_Adjusts.ts * 저장 안 한 조정창 값(세션 · 측점 누가거리 열쇠)을 상세 설계 칸에 얹음 — 상세 가게가 읽을 때 한 번(387-4). * * 조정창(`_UI_Page_Station_Controls` · `_Ford_Controls` · `_Span_Control`)이 고칠 때 캐시에 얹는 것과 같은 * 칸 · 같은 꼴. 예전에는 고칠 때만 얹어 새로고침 · B05 만 연 페이지는 세션 값을 몰랐음 — 카드 그리기가 면적을 * 고쳐 들어 B06 을 연 뒤에만 면적이 바뀜(B05 만 연 면적 ≠ B06). 조정창은 세션 → 설계 순으로 읽으니 겹쳐도 같음. * ========================================================================== */ import { readState } from "../A00_Common/b_page_state"; import type { CrossDesign, SectionDetailResponse } from "./B06_Section_Api_Fetch"; import { DEFAULT_BASIN_ADJUST, ZERO_ADJUST } from "./B06_Section_UI_Cross_Culvert_Types"; import type { WallAdjust } from "./B06_Section_UI_Cross_Culvert_Types"; import { fordAdjustOf } from "./B06_Section_UI_Cross_Ford_Geom"; import { DEFAULT_BOX_SIDE_ADJUST } from "./B06_Section_UI_Cross_Box_Geom"; type Cells = Record; type Obj = Record; const INLET = ["auto", "revet", "I", "L", "U"]; const isObj = (value: unknown): value is Obj => !!value && typeof value === "object"; const count = (value: unknown): number => Number.isInteger(value) && (value as number) > 0 ? (value as number) : 0; /** 조정창 읽기와 같은 꼴 — 옛 숫자 = x 이동량 · d 0 = 기본 자리(null). */ function wallAdjust(value: unknown): WallAdjust | null { if (typeof value === "number" && Number.isFinite(value)) return { ...ZERO_ADJUST, x: value }; if (!isObj(value)) return null; const partial = value as Partial; return { ...ZERO_ADJUST, ...partial, d: partial.d ? partial.d : null }; } export function withDraftAdjusts( detail: SectionDetailResponse, projectId: string, routeId: number, ): void { const read = (name: Parameters[0]): Cells => readState(name, projectId, routeId) ?? {}; const revet = read("revetx"); const basin = read("basinadjust"); const inlet = read("inletstruct"); const extra = read("extrawall"); const spans = read("extraspan"); const ford = read("fordadjust"); const box = read("boxadjust"); const link = read("revetlink") as { detached?: Cells; grade?: Cells }; for (const section of detail.cross_sections) { const design = section.design as (CrossDesign & Obj) | null | undefined; if (!design) continue; const at = section.chainage_m.toFixed(2); const own = (cells: Cells): Array<[string, unknown]> => Object.entries(cells) .filter(([key]) => key.startsWith(`${at}:`)) .map(([key, value]) => [key.slice(at.length + 1), value]); for (const [role, value] of own(revet)) { const adjust = wallAdjust(value); if (adjust) design.revet_adjust = { ...(design.revet_adjust ?? {}), [role]: adjust }; } if (typeof inlet[at] === "string" && INLET.includes(inlet[at] as string)) design.inlet_structure = inlet[at] as CrossDesign["inlet_structure"]; if (isObj(basin[at])) design.basin_adjust = { ...DEFAULT_BASIN_ADJUST, ...basin[at] }; if (at in extra || `b${at}` in extra) design.extra_wall_counts = { outlet: count(extra[at]), basin: count(extra[`b${at}`]) }; for (const [wall, value] of own(spans)) { const span = value as { lengthM: number; beforeM: number; afterM: number } | null; if (!span || !Number.isFinite(span.beforeM) || !Number.isFinite(span.afterM)) continue; design.extra_spans = { ...(design.extra_spans ?? {}), [wall]: { length_m: span.lengthM, before_m: span.beforeM, after_m: span.afterM }, }; } if (isObj(link.detached) && at in link.detached) design.revet_link_detached = !!link.detached[at]; if (isObj(link.grade) && at in link.grade) design.revet_follow_grade = !!link.grade[at]; if (isObj(ford[at])) design.ford_adjust = fordAdjustOf(ford[at]); const sides = box[at] as { left?: Obj; right?: Obj } | undefined; if (isObj(sides)) design.box_adjust = { left: { ...DEFAULT_BOX_SIDE_ADJUST, ...sides.left }, right: { ...DEFAULT_BOX_SIDE_ADJUST, ...sides.right }, }; } }