- swapCrossSections 같은 자리 원천 끝에 저장 정본(Section_Canon CanonRow 에 자리 · 표본 · Section_Store 가 savedDesigns 넘김) — 옮겼다 제자리로 온 관 · 버린 노선 초안 뒤 측점 = 정본 표본 · 기하 - sameStationList — 시설 측점(irregular) 자리가 일반 측점으로 돌아가면 다른 목록(관 지운 카드가 남던 흠) - design_facility_lane paint — 종류 표 전 빈 측점을 종단도에 안 씀 - 시험 test_272_swap_keeps_canon · test_272_berm_source 에 셋(옛 코드 실패 확인) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
3.9 KiB
TypeScript
92 lines
3.9 KiB
TypeScript
/* =============================================================================
|
|
* B06_Section_Section_Canon.ts
|
|
* 세션 상세(`section-detail`) = **저장 정본만**(387-7) — 서버에서 받은 그대로 한 벌 · 갈아끼움 · 되돌림 ·
|
|
* 다시 셈 결과는 안 씀(메모리 캐시 몫). 세션 글은 **한 번만** 풂 — 상세 가게(`_Section_Store`)와 계산 묶음
|
|
* cross 입력(`design_pipeline_cross`)이 이 파일을 함께 봄(예전에는 둘이 따로 1.5 MB 를 풂).
|
|
* 가벼운 자리 — 상세 가게의 화면 줄기를 안 끌고 묶음 입력이 부름.
|
|
* ========================================================================== */
|
|
|
|
import { readState } from "../A00_Common/b_page_state";
|
|
import type { CrossSection, SectionDetailResponse } from "./B06_Section_Api_Fetch";
|
|
|
|
/** 정본 측점 설계 — 받을 때 뜬 사본(다시 셈 · 초안 얹기가 고치는 캐시 객체와 따로) · 자리 · 표본(제자리로 돌아온
|
|
* 측점이 정본 표본을 다시 씀 · 467 · 배열은 받은 것 그대로 · 다시 셈은 새 배열로 갈아 끼움). */
|
|
export type CanonRow = { chainage_m: number; design: CrossSection["design"] } & Partial<
|
|
Pick<
|
|
CrossSection,
|
|
| "center_x"
|
|
| "center_y"
|
|
| "center_z"
|
|
| "frame"
|
|
| "samples"
|
|
| "azimuth_deg"
|
|
| "plan_radius_m"
|
|
| "curve_outer_side"
|
|
| "curve_widening_m"
|
|
| "uphill_side"
|
|
>
|
|
>;
|
|
|
|
const canon = new Map<string, CanonRow[]>();
|
|
/** 묶음이 먼저 푼 세션 상세 — 상세 가게가 처음 읽을 때 가져감(다시 안 풂). */
|
|
const parsed = new Map<string, SectionDetailResponse>();
|
|
const keyOf = (projectId: string, routeId: number): string => `${projectId}:${routeId}`;
|
|
|
|
/** 서버에서 받은(또는 세션에서 푼) 정본의 설계 사본을 떠 둠. */
|
|
export function keepCanon(projectId: string, routeId: number, detail: SectionDetailResponse): void {
|
|
const key = keyOf(projectId, routeId);
|
|
parsed.delete(key);
|
|
canon.set(
|
|
key,
|
|
detail.cross_sections.map((section) => ({
|
|
chainage_m: section.chainage_m,
|
|
design: section.design ? { ...section.design } : section.design,
|
|
center_x: section.center_x,
|
|
center_y: section.center_y,
|
|
center_z: section.center_z,
|
|
frame: section.frame,
|
|
samples: section.samples,
|
|
azimuth_deg: section.azimuth_deg,
|
|
plan_radius_m: section.plan_radius_m,
|
|
curve_outer_side: section.curve_outer_side,
|
|
curve_widening_m: section.curve_widening_m,
|
|
uphill_side: section.uphill_side,
|
|
})),
|
|
);
|
|
}
|
|
|
|
/** 새로고침 — 세션 상세(묶음이 먼저 풀었으면 그 객체) · 정본 사본도 뜸. */
|
|
export function sessionDetail(projectId: string, routeId: number): SectionDetailResponse | null {
|
|
const key = keyOf(projectId, routeId);
|
|
const ready = parsed.get(key);
|
|
if (ready) {
|
|
parsed.delete(key);
|
|
return ready;
|
|
}
|
|
const stored = readState<SectionDetailResponse>("section-detail", projectId, routeId);
|
|
if (stored) keepCanon(projectId, routeId, stored);
|
|
return stored;
|
|
}
|
|
|
|
/** 정본 측점 설계(묶음 cross 입력 · 365-5) — 아직 안 읽었으면 세션에서 한 번(상세 가게가 그 객체를 이어 씀). */
|
|
export function savedDesigns(projectId: string, routeId: number): CanonRow[] | null {
|
|
const key = keyOf(projectId, routeId);
|
|
if (!canon.has(key)) {
|
|
const stored = readState<SectionDetailResponse>("section-detail", projectId, routeId);
|
|
if (!stored) return null;
|
|
keepCanon(projectId, routeId, stored);
|
|
parsed.set(key, stored);
|
|
}
|
|
return canon.get(key) ?? null;
|
|
}
|
|
|
|
/** 정본이 바뀜(새로 받을 것) — 사본을 버림. 노선을 안 주면 그 프로젝트 전부. */
|
|
export function forgetCanon(projectId: string, routeId?: number): void {
|
|
for (const map of [canon, parsed])
|
|
for (const key of [...map.keys()])
|
|
if (
|
|
routeId === undefined ? key.startsWith(`${projectId}:`) : key === keyOf(projectId, routeId)
|
|
)
|
|
map.delete(key);
|
|
}
|