/* ============================================================================= * B05_Profile/logic/B05_Profile_Drainage_Live.ts * 배수유역 [업데이트](요구 326-6 · 347-2) — 순수 규칙만. 화면 · fetch 는 `B05_Profile_UI_Drainage_Live.ts`. * * - 대상 = 평면(노선 초안) · 관 자리만 — 종단 · 횡단 조작은 배수유역 결과를 안 바꿈(묶음 deps 와 같음). * - 노선 초안이 없으면(저장 노선 그대로) 낡음 아님 — 관 조작은 세부 유역 나눔(0.2 s)이 바로 맞춤. * - 저절로 셈하지 않음 — [업데이트]를 누를 때만 지금 노선으로 처음부터 셈. * - 묶음이 같은 입력으로 다시 돌면(입력 지문 같음) 낡음 · 떠 있는 요청을 그대로 둠. * - 답 채택 = 보낸 차례 · 입력 지문이 지금과 같고 서버가 그만두지 않았을 때만(늦은 답 버림). * ========================================================================== */ /** 묶음 drainage 단계 입력 → 낡았는가 — 노선 초안이 있을 때만. */ export const draftMakesStale = (route: unknown): boolean => route !== null && route !== undefined; /** 묶음 drainage 입력 지문 — 노선 초안(판 번호 rev 뺌) · 관 id · 자리(cm). */ export function inputKey(route: unknown, pipes: unknown): string { const draft = route && typeof route === "object" ? { ...route, rev: undefined } : null; const spots = Array.isArray(pipes) ? pipes.map((pipe) => `${pipe?.id ?? ""}@${Math.round(Number(pipe?.chainage_m) * 100)}`).sort() : []; return JSON.stringify([draft, spots]); } /** 「지금 노선으로 셈」 몸통 — 서버 `post_drainage_live`. */ export function liveRequestBody

( generation: number, route: unknown, points: P[], ): { generation: number; route: unknown; points: P[] } { return { generation, route: route ?? null, points }; } /** 답을 화면에 올리는가 — 서버가 그만둔 답 · 옛 차례 · 입력이 바뀐 뒤 답은 버림. */ export function acceptLive( response: { status?: string; generation?: number }, sent: { generation: number; key: string }, now: { generation: number; key: string }, ): boolean { return ( response.status !== "superseded" && sent.generation === now.generation && sent.key === now.key && (response.generation === undefined || response.generation === sent.generation) ); }