/* ============================================================================= * B05_Profile_Api_RouteInitial.ts * 초기노선 갈래 요청(계획서 20) — 로직 하나를 골라 서버가 새 계획노선 노드를 낸다. * * POST /projects/{id}/route/initial { mode, weights?, criteria? } → 노드 · 비교값 · 공통 제약 기준값 * * 계산 자리는 **서버 단독**(CLAUDE.md 5장 ③) — 화면은 부르고, 받은 노드를 편집 캐시에 싣고, * 받은 비교값·기준값을 보이기만 한다. 모양은 계획서 20 「API」 줄(서버 `initial_route`) — * 답을 펴는 자리는 `normalizeRouteInitial`(`_RouteEdit_Initial_Model`) 한 곳이다. * ========================================================================== */ import { requestJson } from "./B05_Profile_Api_Replan"; /** 갈래 셈 대기 상한 — 노선 여러 벌을 셈해 견주므로 넉넉히 잡는다. */ const INITIAL_TIMEOUT_MS = 5 * 60 * 1000; /** 로직 이름 — 서버와 같은 낱말을 쓴다. `follow` 는 예상노선 추종(처음 초기값). */ export type RouteInitialLogic = "follow" | "earthwork" | "gentle" | "weighted"; /** 비중 계산의 세 비중(%) — 합 100. */ export interface RouteInitialWeights { expected: number; earthwork: number; grade: number; } /** 공통 제약 겹침 값 — 화면 네 칸(계획서 20 확정). 비우면 서버가 프로젝트 기본값을 쓴다. * 이름은 서버 몸통과 그대로(snake_case) — 변환 없이 그대로 실어 보낸다. */ export interface RouteInitialCriteria { max_grade_pct?: number; min_radius_m?: number; stream_offset_m?: number; grade_smooth_m?: number; } export interface RouteInitialRequest { mode: RouteInitialLogic; weights?: RouteInitialWeights; criteria?: RouteInitialCriteria; } /** 서버 길이 아직 없다(404·405) — 화면은 이 글로 알린다. */ export const ROUTE_INITIAL_MISSING = "초기노선 갈래 서버 길이 아직 없습니다(계획서 20 · sub3 대기)."; /** 로직 하나로 초기노선을 묻는다. 답의 모양은 `normalizeRouteInitial` 이 편다. */ export async function fetchRouteInitial( projectId: string, request: RouteInitialRequest, ): Promise { try { return await requestJson( `/projects/${projectId}/route/initial`, { method: "POST", body: JSON.stringify(request) }, INITIAL_TIMEOUT_MS, ); } catch (error) { const message = error instanceof Error ? error.message : ""; if (/HTTP 40[45]|Not Found|Method Not Allowed/.test(message)) { throw new Error(ROUTE_INITIAL_MISSING); } throw error; } }