109 lines
5.6 KiB
TypeScript
109 lines
5.6 KiB
TypeScript
/* =============================================================================
|
|
* 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<PlannedStation>,
|
|
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<PipelineInputs, "pipes" | "structures">,
|
|
types: ReadonlyArray<PlanType>,
|
|
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<typeof planStations>[1];
|
|
const planted = plannedIrregular(planStations(pipes, structures, types), 20); // 간격 = 이름 몫 · 기준 무관
|
|
return listedBase(toAlignmentBase(stored), detail, planted);
|
|
}
|