From 7498d6a2ec1809d0958f5c743c6082f11ddebf59 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Wed, 2 Sep 2026 11:32:51 +0900 Subject: [PATCH] =?UTF-8?q?refactor(B06):=20API=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8=EC=9D=84=20=EB=B3=84=EB=8F=84=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EB=A1=9C=20=EB=B6=84=EB=A6=AC=20(700=EC=A4=84=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `B06_Section_Api_Fetch.ts` 704줄 중 486줄이 타입 선언이었다. 타입을 `B06_Section_Api_Types.ts` 로 옮기고 `_Api_Fetch` 는 요청 함수만 남긴다. 호출 코드는 손대지 않았다 — `_Api_Fetch` 가 `export type *` 로 그대로 다시 내보내므로 기존 import 경로가 전부 유효하다. 계약이 아니라 파일만 나눈 것이다. 결과: 704줄 → 236줄(요청 함수) + 492줄(타입). 둘 다 700줄 이내. 검증: `tsc --noEmit` 통과, `pytest tmp/tests/ -q` 356 passed / 0 failed, prettier 정합. Co-Authored-By: Claude Opus 5 (1M context) --- B06_Section/B06_Section_Api_Fetch.ts | 498 +-------------------------- B06_Section/B06_Section_Api_Types.ts | 492 ++++++++++++++++++++++++++ 2 files changed, 507 insertions(+), 483 deletions(-) create mode 100644 B06_Section/B06_Section_Api_Types.ts diff --git a/B06_Section/B06_Section_Api_Fetch.ts b/B06_Section/B06_Section_Api_Fetch.ts index 3ce92495..ab2ff622 100644 --- a/B06_Section/B06_Section_Api_Fetch.ts +++ b/B06_Section/B06_Section_Api_Fetch.ts @@ -12,494 +12,26 @@ * 규칙: * - 모든 제어 상수는 config_frontend에서 참조 (하드코딩 금지). * - 오류 응답 형식 {status:"error", message:"..."}을 Error로 변환. + * - **타입 선언은 `B06_Section_Api_Types.ts`에 있다**(700줄 제한, 2026-09-02). + * 기존 호출 코드가 깨지지 않도록 여기서 그대로 다시 내보낸다. * ========================================================================== */ import { API_BASE_URL, API_TIMEOUT_MS } from "@config/config_frontend"; import type { - BalloonOffsets, - EarthworkConversion, - GroundType, - HaulEquipmentLimit, -} from "@util/common_util_mass_haul_types"; + CrossDesign, + CrossDesignRequest, + CrossDesignResponse, + CrossSectionPatch, + SectionConfirmResponse, + SectionContextResponse, + SectionDetailResponse, + SectionSummaryResponse, + StandardCrossSection, +} from "./B06_Section_Api_Types"; -export interface SectionOptionDefaults { - station_interval_m: number; - cross_half_width_m: number; - cross_sample_interval_m: number; - long_sample_interval_m: number; - vertical_exaggeration: number; -} - -/** 측구 규격(상단폭/저폭/깊이, m). */ -export interface DitchSpec { - top_width_m: number; - bottom_width_m: number; - depth_m: number; -} - -/** 지반그룹 하나의 표준 횡단면 기본값 (config STANDARD_CROSS_SECTION 사본). */ -export interface StandardCrossGroup { - road_width_m: number; - shoulder_left_m: number; - shoulder_right_m: number; - ditch: DitchSpec; - /** 암 그룹만 존재: L형 측구(폭/깊이, m). */ - ditch_l_type?: { width_m: number; depth_m: number }; - cross_slope_pct: { min: number; max: number }; - fill_slope_ratio: number; - cut_slope_ratio: number; - /** 포장 그룹만 존재: 포장층 두께(m). */ - pavement_thickness_m?: number; -} - -/** 표준 횡단면 설정 패널 그룹 키. */ -export type StandardCrossKey = "soil" | "rock" | "paved"; - -export type StandardCrossSection = Record; - -// 지반유형·토량환산계수·운반장비 한계거리는 B05 계획 유토곡선과 공유하므로 정의처를 -// `@util/common_util_mass_haul_types` 한 곳에 두고 여기서는 재수출만 한다(사본 금지). -export type { - GroundType, - EarthworkConversionFactor, - EarthworkConversion, - HaulEquipmentLimit, - BalloonOffsets, -} from "@util/common_util_mass_haul_types"; - -/** 물넘이포장 제원 — 정의처는 렌더 모듈이다(사본 금지, 타입 전용 import라 순환 없음). */ -import type { FordPavementSpec } from "./B06_Section_UI_Cross_Ford_Pavement"; -import type { RevetmentSpec } from "./B06_Section_UI_Cross_Revetment"; -export type { FordPavementSpec, RevetmentSpec }; - -export interface SectionContextResponse { - project_id: string; - route_id: number | null; - filter_key: string | null; - method: string | null; - smooth: boolean | null; - crs_epsg: number | null; - /** 프로젝트 등록(B02)에서 정한 임도 종류 — B05 계획선 법정 기준의 출발점(2026-08-19). */ - road_type: string | null; - defaults: SectionOptionDefaults; - /** 표준 횡단면 설정 패널(토사/암/포장) 기본값. */ - standard_cross_section: StandardCrossSection; - /** 암 경계선 기본 오프셋(m)과 상/하 제어 스텝(m). */ - rock_boundary_default_offset_m: number; - rock_boundary_step_m: number; - /** 지반유형별 토량환산계수. 유토곡선은 프론트가 이 값으로 계산한다. */ - earthwork_conversion: EarthworkConversion; - /** 평균운반거리별 운반장비 경계. 유토곡선의 토량 분배가 이 값으로 장비를 고른다. */ - haul_equipment_limits?: HaulEquipmentLimit[]; - /** - * 자연방토 판정 경사(rise/run). 성토측 자연 지반이 이보다 가파르면 흙이 스스로 흘러내려 - * 운반비를 세지 않는다. 못 받으면 프론트는 **자연방토 없음**으로 본다(보수적). - */ - natural_spoil_min_ground_slope?: number | null; -} - -/** 종단 요약 조회 결과 (SectionSummaryResponse) */ -export interface SectionSummaryResponse { - status: string; - project_id: string; - route_id: number; - longitudinal: Record | null; - length_m: number | null; - cross_section_count: number; -} - -export interface SectionSample { - chainage_m?: number; - offset_m?: number; - elevation_m?: number | null; - z?: number | null; - valid: boolean; -} - -export interface SectionStation { - station_id: string; - chainage_m: number; - label: string; - /** irregular = 사용자가 구조물용으로 추가한 비정규 측점(프론트 주입, 백엔드 미영속). */ - kind: "bp" | "ep" | "regular" | "irregular"; - /** 비정규 측점의 구조물 설명(백엔드가 확정 시 부여). 복귀 시 사이드바 목록 복원에 쓴다. */ - structure?: string; - center_z: number | null; - azimuth_deg: number | null; - center_x: number; - center_y: number; - /** 횡단 기준 등고가 높은 쪽(측구 설계 기본 방향). B05 solve 자동 판정 + 사용자 변경. */ - uphill_side?: "left" | "right" | null; - frame: { left_xy: [number, number] }; -} - -/** 계획선 샘플 (계획고와 지반고, 그 차이). */ -export interface DesignProfileSample { - chainage_m: number; - elevation_m: number; - ground_elevation_m: number; - difference_m: number; -} - -/** 절·성토 균형을 판정하는 구역 단위 결과. */ -export interface DesignProfileSegment { - index: number; - start_chainage_m: number; - end_chainage_m: number; - cut_area_m2: number; - fill_area_m2: number; - balance_error_m2: number; -} - -export interface DesignProfileSummary { - cut_area_m2: number; - fill_area_m2: number; - balance_error_m2: number; - max_grade_pct: number; - vertical_curve_count: number; - pvi_count: number; - balance_segment_count: number; - balanced: boolean; - main_direction: string; - suggested_elevation_offset_m: number | null; - warnings: string[]; -} - -/** - * 종단 계획선. 횡단 설계 기반 계획선이 추가될 수 있어 배열로 전달된다. - */ -export interface DesignProfile { - id: string; - name: string; - basis: string; - samples: DesignProfileSample[]; - balance_segments: DesignProfileSegment[]; - summary: DesignProfileSummary; -} - -export interface LongitudinalSection { - length_m: number; - samples: SectionSample[]; - stations: SectionStation[]; - design_profiles?: DesignProfile[]; - /** - * 계획선 변화점(PVI) 구조. B05가 편집 기준선으로 사용하며 `design_profiles`는 - * 여기서 파생된다. 구 데이터에는 없을 수 있어 optional이다. - * 구조는 `B05_Profile_UI_Profile_Alignment.ProfileAlignment`. - */ - profile_alignment?: unknown; -} - -/** - * 배수관 세트의 유입/유출 한쪽 부속 제원 (백엔드 `B06_Section_Engine_Culvert` 산출). - * 구조가 "집수정"이면 기슭막이·보호공 필드가 없다 — 라벨만 쓴다(집수정 단면은 후속). - */ -export interface CulvertSideSpec { - role: "inlet" | "outlet"; - structure: string; - revet_form?: string | null; - revet_height_m?: number | null; - revet_length_m?: number | null; - /** 기준측점 전/후 종방향 몫(m) — 3D 예상형상 배치(2026-08-23). 없으면 길이 절반씩. */ - revet_before_m?: number | null; - revet_after_m?: number | null; - /** 집수정 종방향 길이(m) — structure="집수정"일 때만. 기본 2m. */ - basin_length_m?: number | null; - /** 집수정 기준측점 전/후 몫(m) — 기슭막이와 같은 체계(2026-08-24). 기본 각 1m. */ - basin_before_m?: number | null; - basin_after_m?: number | null; - /** 기슭막이 전면 기울기(1:n). 돌쌓기 전면 1:0.3(교본 7-3). */ - face_slope?: number; - /** 보호공(물받이) 길이 = 낙차고 × 2 (사방교본 교차 참조, 2026-08-19 사용자 확정). */ - apron_length_m?: number; - /** 보호공 두께 1.0m 내외 (사방교본 교차 참조). */ - apron_thickness_m?: number; -} - -/** 배수관 측점의 세트(배관·기슭막이·보호공) 제원 — 횡단 카드 오버레이 입력. */ -export interface CulvertSet { - type: "pipe"; - pipe_kind: string | null; - diameter_m: number; - /** 관 위 최소 토피(m) — 별표2 교량·암거 복토 50㎝ 교차 참조. B05 하향 차단 기준. */ - min_cover_m: number; - inlet: CulvertSideSpec; - outlet: CulvertSideSpec; - /** 독립 기슭막이(관 없는 벽) — true면 관을 그리지 않고 수량에서도 뺀다(2026-08-28). */ - hidden_pipe?: boolean; - /** 독립 기슭막이 설치 측 — "양쪽" | "좌" | "우". 좌/우면 반대쪽 벽을 숨긴다. */ - side?: string; - /** 독립 기슭막이 다단 요청 수(1이면 단일 벽). */ - tiers?: number; -} - -/** 세월교 날개벽 한쪽 — 횡단면엔 안 보이고 바닥판 연장량만 넘긴다. */ -export interface FordWingSpec { - installed: boolean; - height_m: number | null; - length_m: number | null; - angle_deg: number | null; - /** 바닥판 편측 연장(m) = 길이 × cos(각도). 각도는 관축 기준 벌어짐각. */ - slab_extend_m: number; -} - -/** 세월교 측점의 세트 제원 — 양측 ㄴ형 측벽 + 바닥판 + 관, 관 위는 성토 채움. */ -export interface FordSet { - type: "ford"; - pipe_kind: string | null; - diameter_m: number; - /** 관 련수. 단면엔 1개만 그리고 라벨에만 쓴다. */ - pipe_count: number; - /** 구체의 도로 진행 방향 길이(m) = 월류 폭. 기준 측점 전후로 절반씩 걸친다. */ - span_m: number; - /** 월류 높이(m) — 구체 위 노면이 이만큼 낮게 앉는다. 계획고를 통째로 내려 잡으므로 - * 측벽·바닥판·절성토 면적이 함께 따라간다(2026-08-30 사용자 확정). 0 = 내리지 않음. */ - overflow_depth_m: number; - slab_thickness_m: number; - wall_thickness_m: number; - min_cover_m: number; - wing_in: FordWingSpec; - wing_out: FordWingSpec; -} - -/** BOX암거 측점의 세트 제원 — 상판·내공(유로)·저판 + 날개벽 투영 연장. */ -export interface BoxSet { - type: "box"; - /** 사용자 입력 내공(유로) 폭·높이(m). */ - inner_width_m: number; - inner_height_m: number; - /** 부재 두께(m) — 세월교 승계(2026-08-25 사용자 확정). */ - wall_thickness_m: number; - slab_thickness_m: number; - top_thickness_m: number; - /** 암거 위 복토(m) — 별표2 "복토 흙 두께 50㎝ 이상" 교차 참조. */ - cover_m: number; - /** 도로 진행 방향 길이(m) = 내공 폭 + 측벽 2장. 기준 측점 전후로 절반씩 걸친다. */ - span_m: number; - wing_in: FordWingSpec; - wing_out: FordWingSpec; -} - -export interface CrossSection extends SectionStation { - samples: SectionSample[]; - /** DB에 저장된 잠정 설계 지정(있을 때만). 상세 조회 시 얹혀 온다. */ - design?: CrossDesign; - /** 배수관 측점의 세트 제원(있을 때만). `pipe_points.json` 정본 + 레지스트리 기본값. */ - culvert?: CulvertSet; - /** 세월교 구체가 걸치는 측점의 세트 제원(있을 때만). 구체 폭 안이면 여러 측점에 붙는다. */ - ford?: FordSet; - /** BOX암거 구체가 걸치는 측점의 세트 제원(있을 때만). */ - box?: BoxSet; - /** 물넘이포장이 파는 노면 제원(있을 때만). 월류 폭 안의 측점 전부에 붙는다. */ - ford_pavement?: FordPavementSpec; - /** 독립 기슭막이 제원(있을 때만). 구조물 정본 D군 구간 안의 측점 전부에 붙는다. */ - revetment?: RevetmentSpec; -} - -export interface SectionDetailResponse { - longitudinal: LongitudinalSection; - cross_sections: CrossSection[]; - /** 확정 시 저장해 둔 유토곡선 balloon 위치. 브라우저가 바뀌어도 같은 자리에 뜬다. */ - balloon_offsets?: BalloonOffsets | null; -} - -/** 종횡단 확정 결과 (SectionConfirmResponse) */ -export interface SectionConfirmResponse { - status: string; - project_id: string; - route_id: number; - confirmed: boolean; -} - -/** 측점 표준횡단 설계 지정값 (버튼 상태). */ -export type SectionMode = "left_cut" | "right_cut" | "both_cut" | "both_fill"; -export type DitchSide = "left" | "right"; -export type DitchType = "standard" | "l_type"; - -/** 기슭막이 한 벽의 4축 조작값(좌우 x·상하 d·높이 h·형태 m). null = 자동. */ -export interface StoredWallAdjust { - x: number; - d: number | null; - h: number | null; - /** 형태 — B05 폼과 같은 목록(`REVET_FORMS`). 2026-08-29 이전 저장분은 재질 - * 코드("dry"/"wet"/"concrete")라 `revetFormOf`가 형태로 옮겨 읽는다. */ - m: string | null; -} - -/** 다단 기슭막이 한 단의 종방향 구간값(길이·기준측점 전/후 m — 2026-08-29). */ -export interface StoredWallSpan { - length_m: number; - before_m: number; - after_m: number; -} - -/** 다단 기슭막이 단 수(유출 성토부 / 집수정 계류측). */ -export interface StoredExtraWallCounts { - outlet: number; - basin: number; -} - -/** 세월교 측벽 한 매의 저장형 조작값(2026-08-25). */ -export interface StoredFordWallAdjust { - heightM: number | null; - lateralM: number; - slopeM: number; -} - -/** 세월교 측점의 저장형 조작값 — 유입·유출 측벽을 따로 담는다. */ -export interface StoredFordAdjust { - inlet: StoredFordWallAdjust; - outlet: StoredFordWallAdjust; -} - -/** BOX암거 한쪽 끝의 저장형 조작값(2026-08-25). */ -export interface StoredBoxSideAdjust { - lengthM: number; - riseM: number; -} - -/** BOX암거 측점의 저장형 조작값 — 좌·우 끝을 따로 담는다. */ -export interface StoredBoxAdjust { - left: StoredBoxSideAdjust; - right: StoredBoxSideAdjust; -} - -/** 측점 표준횡단 설계 계산 결과(잠정치). data.design에 저장되는 구조와 동일. */ -export interface CrossDesign { - inlet_structure?: "auto" | "revet" | "I" | "L" | "U"; - basin_adjust?: { - innerWidthM: number; - innerHeightM: number; - lateralM: number; - slopeM: number; - }; - /** 세월교 월류 높이만큼 계획고를 내려 잡은 양(m) — 이 값이 있으면 `design_elevation_m`· - * `design_line`·절성토 면적이 **이미 내려간 값**이다. 프론트는 이 값으로 "월류가 - * 없었다면" 노면을 점선으로 되그린다(2026-08-30 사용자 확정). */ - surface_drop_m?: number; - /** 세월교 측벽 조작값(유입·유출) — 높이·좌우·상하(2026-08-25). */ - ford_adjust?: StoredFordAdjust; - /** BOX암거 구체 조작값(좌·우 끝) — 길이·표고(2026-08-25). */ - box_adjust?: StoredBoxAdjust; - /** 기슭막이 4축 조작값 — 키는 역할("inlet"/"outlet"/"extra0"…/"bextra0"…). - * 세션 전용이던 값을 정본에 남긴다(2026-08-24: 3D는 확정 결과물). */ - revet_adjust?: Record; - /** 다단 기슭막이 단 수 — 유출 성토부·집수정 계류측. */ - extra_wall_counts?: StoredExtraWallCounts; - /** 다단 기슭막이 **단별** 구간값 — 키는 벽 키("extra0"…/"bextra0"…). 기준벽 연장에 - * 종속되지 않고 단마다 따로 잡는다(2026-08-29 사용자). 없으면 기본 10m(5/5). */ - extra_spans?: Record; - /** 연동 해제(측점별 — 2026-08-24 사용자). 옆 측점에서 연장돼 온 기슭막이의 위치 - * 4축을 이 측점에서 따로 잡는다. 구조물 추가가 아니라 3D 위치의 개별 지정이다. */ - revet_link_detached?: boolean; - /** 종단경사 반영(소유 측점 1개 = 기슭막이 한 벌 전체 공통, 기본 켬). - * 끄면 연장 구간의 표고를 소유 측점과 같게 본다. */ - revet_follow_grade?: boolean; - ground_type: GroundType; - geometry_preset: "soil" | "rock"; - section_mode: SectionMode; - ditch_side: DitchSide; - /** 측구 형식(일반/L형). 양성(측구 없음)은 null. */ - ditch_type: DitchType | null; - cut_slope_ratio: number; - /** 2단계 절토의 토사(상단) 경사비. 암 지반에서만 의미. */ - soil_cut_slope_ratio?: number; - /** 암반 경계 기준 2단계 경사 적용 여부(엔진이 실제 적용했는지). */ - two_stage_slope?: boolean; - fill_slope_ratio: number; - roadbed_width_m: number; - carriageway_width_m: number; - cross_slope_pct: number; - ditch: - | { type: "standard"; top_width_m: number; bottom_width_m: number; depth_m: number } - | { type: "l_type"; width_m: number; depth_m: number } - | { type: "none" }; - /** 측구 생성 여부(엔진이 자동/override 반영해 실제 적용한 결과). */ - ditch_enabled?: boolean; - /** 포장 중첩 여부와 포장층 두께(포장 시). */ - paved: boolean; - pavement_thickness_m?: number; - /** B05 법정 경사 분석의 포장 제안 여부(사용자 토글과 무관하게 유지). */ - pavement_suggested?: boolean; - /** 노면(노견 포함) 양 끝점 — 노면 렌더링 기준. */ - road_edges: { - left: { offset_m: number; elevation_m: number }; - right: { offset_m: number; elevation_m: number }; - }; - /** 차도(노견 제외) 양 끝점 — 포장 범위 기준. */ - carriageway_edges?: { - left: { offset_m: number; elevation_m: number }; - right: { offset_m: number; elevation_m: number }; - }; - design_elevation_m: number; - cut_area_m2: number; - /** - * 절토 내역(합 = `cut_area_m2`). 지표면~암반 경계선이 토사, 그 아래가 암이다. - * 경계선을 올리내리면 두 값이 함께 바뀌고 유토곡선도 따라 움직인다. - * 구 데이터에는 없으므로 optional — 없으면 `cut_area_m2` 전량을 지반유형으로 본다. - */ - cut_soil_area_m2?: number; - cut_rock_area_m2?: number; - /** 암반부에 적용할 지반유형(`ripping_rock`/`blasting_rock`). 토사 측점은 null. */ - cut_rock_kind?: GroundType | null; - fill_area_m2: number; - /** 성토측 자연 지반 경사(rise/run). 자연방토 판정 입력. 성토측이 없으면 null. */ - fill_ground_slope?: number | null; - ditch_area_m2: number; - design_line: Array<{ offset_m: number; elevation_m: number }>; - /** 확정 시 병합되는 암 경계선 오프셋(m). 세션 값이 우선이며 복원 폴백으로 쓴다. */ - rock_boundary_offset_m?: number; - /** 측점 개별 표시 반폭(m, 2026-08-06). 확정 시 병합되며 세션 값이 우선이다. */ - display_half_width_m?: number; -} - -export interface CrossDesignResponse { - status: string; - chainage_m: number; - design: CrossDesign; -} - -export interface CrossDesignRequest { - chainage_m: number; - ground_type: GroundType; - section_mode: SectionMode; - ditch_side?: DitchSide | null; - /** 측구 형식(일반/L형). L형은 암 지반에서만 허용된다. */ - ditch_type?: DitchType; - /** 포장 중첩 여부 — 횡단경사·포장층만 포장 그룹 값으로 계산된다. */ - paved?: boolean; - /** 암 경계선 오프셋(m, 지면선 기준 하향 음수). 암 지반 2단계 절토 무릎 계산용. */ - rock_boundary_offset_m?: number | null; - /** 암 지반 2단계 경사 적용 여부(기본 true, 토글로 해제). */ - two_stage_slope?: boolean; - /** 측구 생성 여부. null/미지정=자동 판정, true/false=수동 override. */ - ditch_enabled?: boolean | null; - /** 설정 패널 편집값. 요청값 → config 기본값 순으로 우선한다. */ - standard_cross_section?: StandardCrossSection; -} - -/** 확정 시 측점별 data.design에 병합할 프론트 세션 보관값. */ -export interface CrossSectionPatch { - chainage_m: number; - rock_boundary_offset_m?: number; - /** 측점 개별 표시 반폭(m, 2026-08-06 사용자 지시). */ - display_half_width_m?: number; - inlet_structure?: "auto" | "revet" | "I" | "L" | "U"; - basin_adjust?: { - innerWidthM: number; - innerHeightM: number; - lateralM: number; - slopeM: number; - }; - revet_adjust?: Record; - ford_adjust?: StoredFordAdjust; - box_adjust?: StoredBoxAdjust; - extra_wall_counts?: StoredExtraWallCounts; - extra_spans?: Record; - /** 연동 해제(측점별)·종단경사 반영(전체 공통) — 2026-08-24 사용자. */ - revet_link_detached?: boolean; - revet_follow_grade?: boolean; -} +// 타입 정본은 `B06_Section_Api_Types.ts`. 기존 호출부가 여기서 가져오던 것을 +// 그대로 쓰도록 다시 내보낸다 — 이동은 파일만 나눈 것이고 계약은 그대로다. +export type * from "./B06_Section_Api_Types"; /** 공통 fetch 헬퍼: 타임아웃 + 인증 헤더 + 오류 응답 변환. */ async function requestJson(path: string, init: RequestInit): Promise { diff --git a/B06_Section/B06_Section_Api_Types.ts b/B06_Section/B06_Section_Api_Types.ts new file mode 100644 index 00000000..23d7e724 --- /dev/null +++ b/B06_Section/B06_Section_Api_Types.ts @@ -0,0 +1,492 @@ +/* ============================================================================= + * B06_Section_Api_Types.ts + * 3차 워크플로우(종·횡단) API 응답·요청 **타입 정본**. + * `B06_Section_Api_Fetch.ts`에서 잘라 냈다(700줄 제한, 2026-09-02) — 그 파일은 + * 704줄 중 486줄이 타입 선언이었다. 호출 코드는 종전처럼 `_Api_Fetch`에서 타입을 + * 가져와도 되고(그쪽이 그대로 다시 내보낸다) 이 파일에서 직접 가져와도 된다. + * ========================================================================== */ +import type { + BalloonOffsets, + EarthworkConversion, + GroundType, + HaulEquipmentLimit, +} from "@util/common_util_mass_haul_types"; + +export interface SectionOptionDefaults { + station_interval_m: number; + cross_half_width_m: number; + cross_sample_interval_m: number; + long_sample_interval_m: number; + vertical_exaggeration: number; +} + +/** 측구 규격(상단폭/저폭/깊이, m). */ +export interface DitchSpec { + top_width_m: number; + bottom_width_m: number; + depth_m: number; +} + +/** 지반그룹 하나의 표준 횡단면 기본값 (config STANDARD_CROSS_SECTION 사본). */ +export interface StandardCrossGroup { + road_width_m: number; + shoulder_left_m: number; + shoulder_right_m: number; + ditch: DitchSpec; + /** 암 그룹만 존재: L형 측구(폭/깊이, m). */ + ditch_l_type?: { width_m: number; depth_m: number }; + cross_slope_pct: { min: number; max: number }; + fill_slope_ratio: number; + cut_slope_ratio: number; + /** 포장 그룹만 존재: 포장층 두께(m). */ + pavement_thickness_m?: number; +} + +/** 표준 횡단면 설정 패널 그룹 키. */ +export type StandardCrossKey = "soil" | "rock" | "paved"; + +export type StandardCrossSection = Record; + +// 지반유형·토량환산계수·운반장비 한계거리는 B05 계획 유토곡선과 공유하므로 정의처를 +// `@util/common_util_mass_haul_types` 한 곳에 두고 여기서는 재수출만 한다(사본 금지). +export type { + GroundType, + EarthworkConversionFactor, + EarthworkConversion, + HaulEquipmentLimit, + BalloonOffsets, +} from "@util/common_util_mass_haul_types"; + +/** 물넘이포장 제원 — 정의처는 렌더 모듈이다(사본 금지, 타입 전용 import라 순환 없음). */ +import type { FordPavementSpec } from "./B06_Section_UI_Cross_Ford_Pavement"; +import type { RevetmentSpec } from "./B06_Section_UI_Cross_Revetment"; +export type { FordPavementSpec, RevetmentSpec }; + +export interface SectionContextResponse { + project_id: string; + route_id: number | null; + filter_key: string | null; + method: string | null; + smooth: boolean | null; + crs_epsg: number | null; + /** 프로젝트 등록(B02)에서 정한 임도 종류 — B05 계획선 법정 기준의 출발점(2026-08-19). */ + road_type: string | null; + defaults: SectionOptionDefaults; + /** 표준 횡단면 설정 패널(토사/암/포장) 기본값. */ + standard_cross_section: StandardCrossSection; + /** 암 경계선 기본 오프셋(m)과 상/하 제어 스텝(m). */ + rock_boundary_default_offset_m: number; + rock_boundary_step_m: number; + /** 지반유형별 토량환산계수. 유토곡선은 프론트가 이 값으로 계산한다. */ + earthwork_conversion: EarthworkConversion; + /** 평균운반거리별 운반장비 경계. 유토곡선의 토량 분배가 이 값으로 장비를 고른다. */ + haul_equipment_limits?: HaulEquipmentLimit[]; + /** + * 자연방토 판정 경사(rise/run). 성토측 자연 지반이 이보다 가파르면 흙이 스스로 흘러내려 + * 운반비를 세지 않는다. 못 받으면 프론트는 **자연방토 없음**으로 본다(보수적). + */ + natural_spoil_min_ground_slope?: number | null; +} + +/** 종단 요약 조회 결과 (SectionSummaryResponse) */ +export interface SectionSummaryResponse { + status: string; + project_id: string; + route_id: number; + longitudinal: Record | null; + length_m: number | null; + cross_section_count: number; +} + +export interface SectionSample { + chainage_m?: number; + offset_m?: number; + elevation_m?: number | null; + z?: number | null; + valid: boolean; +} + +export interface SectionStation { + station_id: string; + chainage_m: number; + label: string; + /** irregular = 사용자가 구조물용으로 추가한 비정규 측점(프론트 주입, 백엔드 미영속). */ + kind: "bp" | "ep" | "regular" | "irregular"; + /** 비정규 측점의 구조물 설명(백엔드가 확정 시 부여). 복귀 시 사이드바 목록 복원에 쓴다. */ + structure?: string; + center_z: number | null; + azimuth_deg: number | null; + center_x: number; + center_y: number; + /** 횡단 기준 등고가 높은 쪽(측구 설계 기본 방향). B05 solve 자동 판정 + 사용자 변경. */ + uphill_side?: "left" | "right" | null; + frame: { left_xy: [number, number] }; +} + +/** 계획선 샘플 (계획고와 지반고, 그 차이). */ +export interface DesignProfileSample { + chainage_m: number; + elevation_m: number; + ground_elevation_m: number; + difference_m: number; +} + +/** 절·성토 균형을 판정하는 구역 단위 결과. */ +export interface DesignProfileSegment { + index: number; + start_chainage_m: number; + end_chainage_m: number; + cut_area_m2: number; + fill_area_m2: number; + balance_error_m2: number; +} + +export interface DesignProfileSummary { + cut_area_m2: number; + fill_area_m2: number; + balance_error_m2: number; + max_grade_pct: number; + vertical_curve_count: number; + pvi_count: number; + balance_segment_count: number; + balanced: boolean; + main_direction: string; + suggested_elevation_offset_m: number | null; + warnings: string[]; +} + +/** + * 종단 계획선. 횡단 설계 기반 계획선이 추가될 수 있어 배열로 전달된다. + */ +export interface DesignProfile { + id: string; + name: string; + basis: string; + samples: DesignProfileSample[]; + balance_segments: DesignProfileSegment[]; + summary: DesignProfileSummary; +} + +export interface LongitudinalSection { + length_m: number; + samples: SectionSample[]; + stations: SectionStation[]; + design_profiles?: DesignProfile[]; + /** + * 계획선 변화점(PVI) 구조. B05가 편집 기준선으로 사용하며 `design_profiles`는 + * 여기서 파생된다. 구 데이터에는 없을 수 있어 optional이다. + * 구조는 `B05_Profile_UI_Profile_Alignment.ProfileAlignment`. + */ + profile_alignment?: unknown; +} + +/** + * 배수관 세트의 유입/유출 한쪽 부속 제원 (백엔드 `B06_Section_Engine_Culvert` 산출). + * 구조가 "집수정"이면 기슭막이·보호공 필드가 없다 — 라벨만 쓴다(집수정 단면은 후속). + */ +export interface CulvertSideSpec { + role: "inlet" | "outlet"; + structure: string; + revet_form?: string | null; + revet_height_m?: number | null; + revet_length_m?: number | null; + /** 기준측점 전/후 종방향 몫(m) — 3D 예상형상 배치(2026-08-23). 없으면 길이 절반씩. */ + revet_before_m?: number | null; + revet_after_m?: number | null; + /** 집수정 종방향 길이(m) — structure="집수정"일 때만. 기본 2m. */ + basin_length_m?: number | null; + /** 집수정 기준측점 전/후 몫(m) — 기슭막이와 같은 체계(2026-08-24). 기본 각 1m. */ + basin_before_m?: number | null; + basin_after_m?: number | null; + /** 기슭막이 전면 기울기(1:n). 돌쌓기 전면 1:0.3(교본 7-3). */ + face_slope?: number; + /** 보호공(물받이) 길이 = 낙차고 × 2 (사방교본 교차 참조, 2026-08-19 사용자 확정). */ + apron_length_m?: number; + /** 보호공 두께 1.0m 내외 (사방교본 교차 참조). */ + apron_thickness_m?: number; +} + +/** 배수관 측점의 세트(배관·기슭막이·보호공) 제원 — 횡단 카드 오버레이 입력. */ +export interface CulvertSet { + type: "pipe"; + pipe_kind: string | null; + diameter_m: number; + /** 관 위 최소 토피(m) — 별표2 교량·암거 복토 50㎝ 교차 참조. B05 하향 차단 기준. */ + min_cover_m: number; + inlet: CulvertSideSpec; + outlet: CulvertSideSpec; + /** 독립 기슭막이(관 없는 벽) — true면 관을 그리지 않고 수량에서도 뺀다(2026-08-28). */ + hidden_pipe?: boolean; + /** 독립 기슭막이 설치 측 — "양쪽" | "좌" | "우". 좌/우면 반대쪽 벽을 숨긴다. */ + side?: string; + /** 독립 기슭막이 다단 요청 수(1이면 단일 벽). */ + tiers?: number; +} + +/** 세월교 날개벽 한쪽 — 횡단면엔 안 보이고 바닥판 연장량만 넘긴다. */ +export interface FordWingSpec { + installed: boolean; + height_m: number | null; + length_m: number | null; + angle_deg: number | null; + /** 바닥판 편측 연장(m) = 길이 × cos(각도). 각도는 관축 기준 벌어짐각. */ + slab_extend_m: number; +} + +/** 세월교 측점의 세트 제원 — 양측 ㄴ형 측벽 + 바닥판 + 관, 관 위는 성토 채움. */ +export interface FordSet { + type: "ford"; + pipe_kind: string | null; + diameter_m: number; + /** 관 련수. 단면엔 1개만 그리고 라벨에만 쓴다. */ + pipe_count: number; + /** 구체의 도로 진행 방향 길이(m) = 월류 폭. 기준 측점 전후로 절반씩 걸친다. */ + span_m: number; + /** 월류 높이(m) — 구체 위 노면이 이만큼 낮게 앉는다. 계획고를 통째로 내려 잡으므로 + * 측벽·바닥판·절성토 면적이 함께 따라간다(2026-08-30 사용자 확정). 0 = 내리지 않음. */ + overflow_depth_m: number; + slab_thickness_m: number; + wall_thickness_m: number; + min_cover_m: number; + wing_in: FordWingSpec; + wing_out: FordWingSpec; +} + +/** BOX암거 측점의 세트 제원 — 상판·내공(유로)·저판 + 날개벽 투영 연장. */ +export interface BoxSet { + type: "box"; + /** 사용자 입력 내공(유로) 폭·높이(m). */ + inner_width_m: number; + inner_height_m: number; + /** 부재 두께(m) — 세월교 승계(2026-08-25 사용자 확정). */ + wall_thickness_m: number; + slab_thickness_m: number; + top_thickness_m: number; + /** 암거 위 복토(m) — 별표2 "복토 흙 두께 50㎝ 이상" 교차 참조. */ + cover_m: number; + /** 도로 진행 방향 길이(m) = 내공 폭 + 측벽 2장. 기준 측점 전후로 절반씩 걸친다. */ + span_m: number; + wing_in: FordWingSpec; + wing_out: FordWingSpec; +} + +export interface CrossSection extends SectionStation { + samples: SectionSample[]; + /** DB에 저장된 잠정 설계 지정(있을 때만). 상세 조회 시 얹혀 온다. */ + design?: CrossDesign; + /** 배수관 측점의 세트 제원(있을 때만). `pipe_points.json` 정본 + 레지스트리 기본값. */ + culvert?: CulvertSet; + /** 세월교 구체가 걸치는 측점의 세트 제원(있을 때만). 구체 폭 안이면 여러 측점에 붙는다. */ + ford?: FordSet; + /** BOX암거 구체가 걸치는 측점의 세트 제원(있을 때만). */ + box?: BoxSet; + /** 물넘이포장이 파는 노면 제원(있을 때만). 월류 폭 안의 측점 전부에 붙는다. */ + ford_pavement?: FordPavementSpec; + /** 독립 기슭막이 제원(있을 때만). 구조물 정본 D군 구간 안의 측점 전부에 붙는다. */ + revetment?: RevetmentSpec; +} + +export interface SectionDetailResponse { + longitudinal: LongitudinalSection; + cross_sections: CrossSection[]; + /** 확정 시 저장해 둔 유토곡선 balloon 위치. 브라우저가 바뀌어도 같은 자리에 뜬다. */ + balloon_offsets?: BalloonOffsets | null; +} + +/** 종횡단 확정 결과 (SectionConfirmResponse) */ +export interface SectionConfirmResponse { + status: string; + project_id: string; + route_id: number; + confirmed: boolean; +} + +/** 측점 표준횡단 설계 지정값 (버튼 상태). */ +export type SectionMode = "left_cut" | "right_cut" | "both_cut" | "both_fill"; +export type DitchSide = "left" | "right"; +export type DitchType = "standard" | "l_type"; + +/** 기슭막이 한 벽의 4축 조작값(좌우 x·상하 d·높이 h·형태 m). null = 자동. */ +export interface StoredWallAdjust { + x: number; + d: number | null; + h: number | null; + /** 형태 — B05 폼과 같은 목록(`REVET_FORMS`). 2026-08-29 이전 저장분은 재질 + * 코드("dry"/"wet"/"concrete")라 `revetFormOf`가 형태로 옮겨 읽는다. */ + m: string | null; +} + +/** 다단 기슭막이 한 단의 종방향 구간값(길이·기준측점 전/후 m — 2026-08-29). */ +export interface StoredWallSpan { + length_m: number; + before_m: number; + after_m: number; +} + +/** 다단 기슭막이 단 수(유출 성토부 / 집수정 계류측). */ +export interface StoredExtraWallCounts { + outlet: number; + basin: number; +} + +/** 세월교 측벽 한 매의 저장형 조작값(2026-08-25). */ +export interface StoredFordWallAdjust { + heightM: number | null; + lateralM: number; + slopeM: number; +} + +/** 세월교 측점의 저장형 조작값 — 유입·유출 측벽을 따로 담는다. */ +export interface StoredFordAdjust { + inlet: StoredFordWallAdjust; + outlet: StoredFordWallAdjust; +} + +/** BOX암거 한쪽 끝의 저장형 조작값(2026-08-25). */ +export interface StoredBoxSideAdjust { + lengthM: number; + riseM: number; +} + +/** BOX암거 측점의 저장형 조작값 — 좌·우 끝을 따로 담는다. */ +export interface StoredBoxAdjust { + left: StoredBoxSideAdjust; + right: StoredBoxSideAdjust; +} + +/** 측점 표준횡단 설계 계산 결과(잠정치). data.design에 저장되는 구조와 동일. */ +export interface CrossDesign { + inlet_structure?: "auto" | "revet" | "I" | "L" | "U"; + basin_adjust?: { + innerWidthM: number; + innerHeightM: number; + lateralM: number; + slopeM: number; + }; + /** 세월교 월류 높이만큼 계획고를 내려 잡은 양(m) — 이 값이 있으면 `design_elevation_m`· + * `design_line`·절성토 면적이 **이미 내려간 값**이다. 프론트는 이 값으로 "월류가 + * 없었다면" 노면을 점선으로 되그린다(2026-08-30 사용자 확정). */ + surface_drop_m?: number; + /** 세월교 측벽 조작값(유입·유출) — 높이·좌우·상하(2026-08-25). */ + ford_adjust?: StoredFordAdjust; + /** BOX암거 구체 조작값(좌·우 끝) — 길이·표고(2026-08-25). */ + box_adjust?: StoredBoxAdjust; + /** 기슭막이 4축 조작값 — 키는 역할("inlet"/"outlet"/"extra0"…/"bextra0"…). + * 세션 전용이던 값을 정본에 남긴다(2026-08-24: 3D는 확정 결과물). */ + revet_adjust?: Record; + /** 다단 기슭막이 단 수 — 유출 성토부·집수정 계류측. */ + extra_wall_counts?: StoredExtraWallCounts; + /** 다단 기슭막이 **단별** 구간값 — 키는 벽 키("extra0"…/"bextra0"…). 기준벽 연장에 + * 종속되지 않고 단마다 따로 잡는다(2026-08-29 사용자). 없으면 기본 10m(5/5). */ + extra_spans?: Record; + /** 연동 해제(측점별 — 2026-08-24 사용자). 옆 측점에서 연장돼 온 기슭막이의 위치 + * 4축을 이 측점에서 따로 잡는다. 구조물 추가가 아니라 3D 위치의 개별 지정이다. */ + revet_link_detached?: boolean; + /** 종단경사 반영(소유 측점 1개 = 기슭막이 한 벌 전체 공통, 기본 켬). + * 끄면 연장 구간의 표고를 소유 측점과 같게 본다. */ + revet_follow_grade?: boolean; + ground_type: GroundType; + geometry_preset: "soil" | "rock"; + section_mode: SectionMode; + ditch_side: DitchSide; + /** 측구 형식(일반/L형). 양성(측구 없음)은 null. */ + ditch_type: DitchType | null; + cut_slope_ratio: number; + /** 2단계 절토의 토사(상단) 경사비. 암 지반에서만 의미. */ + soil_cut_slope_ratio?: number; + /** 암반 경계 기준 2단계 경사 적용 여부(엔진이 실제 적용했는지). */ + two_stage_slope?: boolean; + fill_slope_ratio: number; + roadbed_width_m: number; + carriageway_width_m: number; + cross_slope_pct: number; + ditch: + | { type: "standard"; top_width_m: number; bottom_width_m: number; depth_m: number } + | { type: "l_type"; width_m: number; depth_m: number } + | { type: "none" }; + /** 측구 생성 여부(엔진이 자동/override 반영해 실제 적용한 결과). */ + ditch_enabled?: boolean; + /** 포장 중첩 여부와 포장층 두께(포장 시). */ + paved: boolean; + pavement_thickness_m?: number; + /** B05 법정 경사 분석의 포장 제안 여부(사용자 토글과 무관하게 유지). */ + pavement_suggested?: boolean; + /** 노면(노견 포함) 양 끝점 — 노면 렌더링 기준. */ + road_edges: { + left: { offset_m: number; elevation_m: number }; + right: { offset_m: number; elevation_m: number }; + }; + /** 차도(노견 제외) 양 끝점 — 포장 범위 기준. */ + carriageway_edges?: { + left: { offset_m: number; elevation_m: number }; + right: { offset_m: number; elevation_m: number }; + }; + design_elevation_m: number; + cut_area_m2: number; + /** + * 절토 내역(합 = `cut_area_m2`). 지표면~암반 경계선이 토사, 그 아래가 암이다. + * 경계선을 올리내리면 두 값이 함께 바뀌고 유토곡선도 따라 움직인다. + * 구 데이터에는 없으므로 optional — 없으면 `cut_area_m2` 전량을 지반유형으로 본다. + */ + cut_soil_area_m2?: number; + cut_rock_area_m2?: number; + /** 암반부에 적용할 지반유형(`ripping_rock`/`blasting_rock`). 토사 측점은 null. */ + cut_rock_kind?: GroundType | null; + fill_area_m2: number; + /** 성토측 자연 지반 경사(rise/run). 자연방토 판정 입력. 성토측이 없으면 null. */ + fill_ground_slope?: number | null; + ditch_area_m2: number; + design_line: Array<{ offset_m: number; elevation_m: number }>; + /** 확정 시 병합되는 암 경계선 오프셋(m). 세션 값이 우선이며 복원 폴백으로 쓴다. */ + rock_boundary_offset_m?: number; + /** 측점 개별 표시 반폭(m, 2026-08-06). 확정 시 병합되며 세션 값이 우선이다. */ + display_half_width_m?: number; +} + +export interface CrossDesignResponse { + status: string; + chainage_m: number; + design: CrossDesign; +} + +export interface CrossDesignRequest { + chainage_m: number; + ground_type: GroundType; + section_mode: SectionMode; + ditch_side?: DitchSide | null; + /** 측구 형식(일반/L형). L형은 암 지반에서만 허용된다. */ + ditch_type?: DitchType; + /** 포장 중첩 여부 — 횡단경사·포장층만 포장 그룹 값으로 계산된다. */ + paved?: boolean; + /** 암 경계선 오프셋(m, 지면선 기준 하향 음수). 암 지반 2단계 절토 무릎 계산용. */ + rock_boundary_offset_m?: number | null; + /** 암 지반 2단계 경사 적용 여부(기본 true, 토글로 해제). */ + two_stage_slope?: boolean; + /** 측구 생성 여부. null/미지정=자동 판정, true/false=수동 override. */ + ditch_enabled?: boolean | null; + /** 설정 패널 편집값. 요청값 → config 기본값 순으로 우선한다. */ + standard_cross_section?: StandardCrossSection; +} + +/** 확정 시 측점별 data.design에 병합할 프론트 세션 보관값. */ +export interface CrossSectionPatch { + chainage_m: number; + rock_boundary_offset_m?: number; + /** 측점 개별 표시 반폭(m, 2026-08-06 사용자 지시). */ + display_half_width_m?: number; + inlet_structure?: "auto" | "revet" | "I" | "L" | "U"; + basin_adjust?: { + innerWidthM: number; + innerHeightM: number; + lateralM: number; + slopeM: number; + }; + revet_adjust?: Record; + ford_adjust?: StoredFordAdjust; + box_adjust?: StoredBoxAdjust; + extra_wall_counts?: StoredExtraWallCounts; + extra_spans?: Record; + /** 연동 해제(측점별)·종단경사 반영(전체 공통) — 2026-08-24 사용자. */ + revet_link_detached?: boolean; + revet_follow_grade?: boolean; +}