/* ============================================================================= * B05_Profile/logic/B05_Profile_Pipeline_Follow.ts * 노선이 움직인 뒤 관 목록 화면 값(PLAN 349-0d) — 배수유역도가 알린 관 목록(옛 누가거리)을 가게 관 초안 * (계산 묶음 follow 가 좌표로 다시 매긴 누가거리)에 맞춤. 짝 = 관 고정 id(411-B · 옮겨 차례가 바뀌어도 * 그 관) · id 없는 관(막 놓은 관)끼리는 누가거리 차례 · 관 수가 다르면 그대로(배수유역도가 아직 안 받은 고침). * 순수 계산(DOM · fetch · 세션 없음). * ========================================================================== */ interface Span { chainage_m: number; start_m?: number | null; end_m?: number | null; id?: string | null; } /** 관 알림 목록의 측점 · 구간을 가게 관 초안 쪽으로 — 초안이 없으면(저장분) 그대로. */ export function followPipeReports( reports: ReadonlyArray, pipes: ReadonlyArray | null, ): R[] { if (!pipes || pipes.length !== reports.length) return [...reports]; const byChainage = (a: Span, b: Span): number => a.chainage_m - b.chainage_m; const byId = new Map(pipes.flatMap((pipe) => (pipe.id ? [[pipe.id, pipe]] : []))); const paired = (report: R): boolean => Boolean(report.id && byId.has(report.id)); const loose = [...pipes].filter((pipe) => !reports.some((r) => r.id && r.id === pipe.id)); const to = loose.sort(byChainage); const sorted = [...reports].sort(byChainage); let next = 0; return sorted.map((report) => { const pipe = paired(report) ? byId.get(report.id!)! : to[next++]; if (!pipe) return report; const chainage = Math.round(pipe.chainage_m * 100) / 100; // 알림 목록 자릿수(`buildPipeReports`) const shift = chainage - report.chainage_m; const moved = (own: number | null | undefined, from: number | null | undefined) => own ?? (from == null ? from : from + shift); return { ...report, chainage_m: chainage, ...(report.start_m != null ? { start_m: moved(pipe.start_m, report.start_m) } : {}), ...(report.end_m != null ? { end_m: moved(pipe.end_m, report.end_m) } : {}), }; }); }