refactor(B06): API 타입 선언을 별도 파일로 분리 (700줄 제한)

`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) <noreply@anthropic.com>
This commit is contained in:
2026-09-02 11:32:51 +09:00
co-authored by Claude Opus 5
parent dc91a5e831
commit 7498d6a2ec
2 changed files with 507 additions and 483 deletions
+15 -483
View File
@@ -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<StandardCrossKey, StandardCrossGroup>;
// 지반유형·토량환산계수·운반장비 한계거리는 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<string, unknown> | 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<string, StoredWallAdjust>;
/** 다단 기슭막이 단 수 — 유출 성토부·집수정 계류측. */
extra_wall_counts?: StoredExtraWallCounts;
/** 다단 기슭막이 **단별** 구간값 — 키는 벽 키("extra0"…/"bextra0"…). 기준벽 연장에
* 종속되지 않고 단마다 따로 잡는다(2026-08-29 사용자). 없으면 기본 10m(5/5). */
extra_spans?: Record<string, StoredWallSpan>;
/** 연동 해제(측점별 — 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<string, StoredWallAdjust>;
ford_adjust?: StoredFordAdjust;
box_adjust?: StoredBoxAdjust;
extra_wall_counts?: StoredExtraWallCounts;
extra_spans?: Record<string, StoredWallSpan>;
/** 연동 해제(측점별)·종단경사 반영(전체 공통) — 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<T>(path: string, init: RequestInit): Promise<T> {
+492
View File
@@ -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<StandardCrossKey, StandardCrossGroup>;
// 지반유형·토량환산계수·운반장비 한계거리는 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<string, unknown> | 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<string, StoredWallAdjust>;
/** 다단 기슭막이 단 수 — 유출 성토부·집수정 계류측. */
extra_wall_counts?: StoredExtraWallCounts;
/** 다단 기슭막이 **단별** 구간값 — 키는 벽 키("extra0"…/"bextra0"…). 기준벽 연장에
* 종속되지 않고 단마다 따로 잡는다(2026-08-29 사용자). 없으면 기본 10m(5/5). */
extra_spans?: Record<string, StoredWallSpan>;
/** 연동 해제(측점별 — 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<string, StoredWallAdjust>;
ford_adjust?: StoredFordAdjust;
box_adjust?: StoredBoxAdjust;
extra_wall_counts?: StoredExtraWallCounts;
extra_spans?: Record<string, StoredWallSpan>;
/** 연동 해제(측점별)·종단경사 반영(전체 공통) — 2026-08-24 사용자. */
revet_link_detached?: boolean;
revet_follow_grade?: boolean;
}