/* ============================================================================= * A00_Common/design/logic/design_planted_base.ts * 묶음 planline 의 저장 노선 종단 기준(PLAN 386-3) 셈 몫 — 화면 · 가게 · 세션 없는 순수(511-B B-3 · 서버 Node * 묶음 `design_calc_node_stages.ts` 도 같은 셈). 페이지 겉 = `design_pipeline_base.ts`(관 id = 세션 장부) · * `design_profile_base.ts` · `design_structure_status.ts` 가 다시 내보냄. * * 종단도 `listed()`(design_profile)와 같은 셈 — 저장 상세 측점 + 구조물 · 관이 심는 측점(`listedBase`). * 심는 측점 = 종단 보기 구조물 칸(`syncCrossDrainStations`) · 횡단 보기(`planMarkStations`)와 같은 * `planStations` → `plannedIrregular` — 보기가 종단도에 늦게 심어도 묶음은 다시 안 돎. * ========================================================================== */ import type { SectionDetailResponse } from "../../../B06_Section/B06_Section_Api_Fetch"; import type { AlignmentBase } from "../../../B05_Profile/logic/B05_Profile_UI_Profile_Alignment"; import { toAlignmentBase } from "../../../B05_Profile/logic/B05_Profile_UI_Profile_Alignment"; import type { IrregularStation } from "../../../B05_Profile/B05_Profile_UI_IrregularStations"; import { irregularGraphStations, maxChainageOf, } from "../../../B05_Profile/logic/B05_Profile_Profile_Planted"; import { followMovedNodes, oneStationList, planStations, type PlannedStation, type PlanType, } from "../../../common_util/common_util_structure_station"; import { readAlignment } from "../../../B05_Profile/logic/B05_Profile_UI_Profile_Data"; import { seatBornNodes } from "../../../B05_Profile/logic/B05_Profile_Grade_Seat"; import type { PipelineInputs } from "./design_pipeline_types"; /** * 측점 계획 → 종단 측점(측점번호 · 잔여거리 = 간격 기준) — 기준 측점 id = 첫 주인 id(관 = `pipe-…` · * 구조물 = structure_id) · 시작 · 끝 = `{id}:{역할}`(옮겨도 계획고 편집이 따라감 · 272) · 관 기준 측점 = * 「배관」 꼴(관 끌기 · 지우기 길). */ export function plannedIrregular( planned: ReadonlyArray, intervalM: number, ): IrregularStation[] { const interval = intervalM > 0 ? intervalM : 20; return planned.map((station) => { const owner = station.owners[0]; const pipe = owner.startsWith("pipe-") && station.role === "anchor"; const number = Math.floor(station.chainage_m / interval); return { id: station.role === "anchor" ? owner : `${owner}:${station.role}`, station: number, remainder: station.chainage_m - number * interval, chainage_m: station.chainage_m, structure: station.title, ...(pipe ? { structureType: "배관" as const, origin: "pipe" as const } : {}), }; }); } /** 계획선 측점 줄 = 측점 한 벌(서버 일반 + 지금 구조물 측점 · 272) — 표 · ▲▼ · 그래프 · 3D · 횡단 다시 셈(342-1)이 * 같은 목록 · 사라진 구조물 측점의 꼭짓점은 서버와 같게 옮기거나 지우고 새 측점엔 세움(`followMovedNodes` · `seatBornNodes` · 427) · * 늘 저장분에서 셈. 심은 측점이 아직 없으면(null · 시설 줄 입력 전) 저장분 그대로(473). */ export function listedBase( storedBase: AlignmentBase | null, detail: SectionDetailResponse | null, irregularStations: IrregularStation[] | null, ): AlignmentBase | null { if (!storedBase || !detail || !irregularStations) return storedBase; const server = detail.longitudinal.stations; const planted = irregularGraphStations(irregularStations, maxChainageOf(detail.longitudinal)); const list = oneStationList(server, planted); const after = new Set(list.map((station) => station.chainage_m.toFixed(3))); const before = new Set(server.map((station) => station.chainage_m.toFixed(3))); const gone = server .filter((station) => station.kind === "irregular" && !station.grid) .map((station) => station.chainage_m) .filter((chainage) => !after.has(chainage.toFixed(3))); const born = list .map((station) => station.chainage_m) .filter((chainage) => !before.has(chainage.toFixed(3))); const moved = followMovedNodes( storedBase.basePvi, gone, born, Object.keys(readAlignment(detail.longitudinal)?.edits.station_offsets ?? {}), ); return { ...storedBase, basePvi: seatBornNodes(storedBase, moved.nodes, moved.seat, moved.held), stations: list.map((station) => ({ station_id: station.station_id, chainage_m: station.chainage_m, })), }; } /** 저장 상세(종단도가 그리는 것) + 지금 입력이 심는 측점 = 저장 노선 종단 기준. 상세가 없으면 종단도 기준. * `ids` = 관에 관 id 붙임(페이지 = 세션 장부 · 서버 Node = 장부 사본 · 511-B). */ export function plantedBase( source: { base: AlignmentBase | null; detail?: SectionDetailResponse | null }, inputs: Pick, types: ReadonlyArray, ids: (pipes: Array<{ chainage_m: number }>) => Array<{ chainage_m: number; id: string }>, ): AlignmentBase | null { const detail = source.detail ?? null; const stored = detail && readAlignment(detail.longitudinal); if (!detail || !stored) return source.base; const pipes = ids((inputs.pipes ?? []) as Array<{ chainage_m: number }>); const structures = (inputs.structures ?? []) as Parameters[1]; const planted = plannedIrregular(planStations(pipes, structures, types), 20); // 간격 = 이름 몫 · 기준 무관 return listedBase(toAlignmentBase(stored), detail, planted); }