- 새 logic/B05_Profile_Structure_Follow followedMarks: 묶음 입력(follow 뒤) 관 · 구조물의 새 누가거리를 알약 목록에 얹음 · 구조물 id 짝 · 구간형 시작 · 끝도 - 관 알약 id(세션 id) ≠ 묶음 관 id(서버 고정 id) — 누가거리 차례 짝 · 관 수가 안 맞으면 관은 안 옮김 - Structures_Marks: 노선 초안이 있으면(지금 프로젝트 묶음) 따라간 목록으로 알약 · 띠 · 툴팁 · 초안 버리면 저장 자리 - 시험 test_346_2_draft_cross_pills 5(횡단 카드 = 새 노선 상세 · 숨은 동안 안 그림 · 초안 버림 = 저장 노선 · 알약 자리) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QfHKQs7J3hQELKMWQMUJEy
60 lines
2.6 KiB
TypeScript
60 lines
2.6 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_Structure_Follow.ts
|
|
* 노선 초안 동안 종단 알약 자리(PLAN 346-2 덧 3) — 계산 묶음 follow 가 좌표로 따라간 관 · 구조물의 새
|
|
* 누가거리를 알약 목록에 얹음. 구조물 = structure_id 로 짝 · 관 알약 id = 세션 id(`pipeIdAt`) 라 묶음 관 id
|
|
* (서버 고정 id)와 다르면 누가거리 차례로 짝.
|
|
*
|
|
* 순수 — 화면 · fetch · 세션 없음.
|
|
* ========================================================================== */
|
|
|
|
interface Placed {
|
|
chainage_m?: number | null;
|
|
start_m?: number | null;
|
|
end_m?: number | null;
|
|
}
|
|
|
|
interface Mark extends Placed {
|
|
structure_id?: string | null;
|
|
}
|
|
|
|
interface Moved extends Placed {
|
|
id?: string | null;
|
|
structure_id?: string | null;
|
|
}
|
|
|
|
const list = (value: unknown): Moved[] => (Array.isArray(value) ? (value as Moved[]) : []);
|
|
const at = (item: Placed): number => item.chainage_m ?? item.start_m ?? 0;
|
|
|
|
/** 알약 목록 → 따라간 자리를 얹은 사본 · 짝 없는 알약은 그대로. `structures` · `pipes` = 묶음 입력(follow 뒤). */
|
|
export function followedMarks<T extends Mark>(
|
|
marks: ReadonlyArray<T>,
|
|
structures: unknown,
|
|
pipes: unknown,
|
|
): T[] {
|
|
const byId = new Map<string, Moved>();
|
|
for (const item of list(structures)) if (item.structure_id) byId.set(item.structure_id, item);
|
|
const movedPipes = list(pipes).filter((pipe) => typeof pipe.chainage_m === "number");
|
|
for (const pipe of movedPipes) if (pipe.id) byId.set(pipe.id, pipe);
|
|
// ponytail: 차례 짝 — 노선을 고쳐 관 차례가 뒤바뀌면 틀림 · 알약이 서버 관 id 를 들면 id 짝으로
|
|
const loose = marks
|
|
.filter((mark) => mark.structure_id?.startsWith("pipe-") && !byId.has(mark.structure_id))
|
|
.sort((a, b) => at(a) - at(b));
|
|
const ids = new Set(marks.map((mark) => mark.structure_id));
|
|
const free = movedPipes.filter((pipe) => !ids.has(pipe.id)).sort((a, b) => at(a) - at(b));
|
|
const paired = new Map<T, Moved>();
|
|
if (loose.length === free.length) loose.forEach((mark, index) => paired.set(mark, free[index]));
|
|
return marks.map((mark) => {
|
|
const moved = (mark.structure_id ? byId.get(mark.structure_id) : undefined) ?? paired.get(mark);
|
|
if (!moved) return mark;
|
|
const shift = at(moved) - at(mark);
|
|
const move = (value: number | null | undefined, next: number | null | undefined) =>
|
|
value == null ? value : (next ?? value + shift);
|
|
return {
|
|
...mark,
|
|
chainage_m: move(mark.chainage_m, moved.chainage_m),
|
|
start_m: move(mark.start_m, moved.start_m),
|
|
end_m: move(mark.end_m, moved.end_m),
|
|
};
|
|
});
|
|
}
|