Files
Aislo/B05_Profile/logic/B05_Profile_Route_Reset.ts
T
eomsangdonandClaude Opus 5.5 d2bf68b598 feat(492-2 노선 바뀜 확인): 모양 바뀐 노선 초안 띠 · [저장] · 추천 [적용] 확인 창(지워질 수) · 저장 뒤 초기화 알림
- 판정 = 저장 노선 대 초안이 그릴 선 정점 1 mm(`routeShapeChanged` · 파이썬 `route_shape_changed` 짝) · 스냅 · 간격 · 지형만 = 아님
- 띠 = 평면(노선 편집) 위 한 줄 · B06 평면 패널로 같이 옮겨짐 · 저장 노선 = 페이지 자료 줄 `pageRoutePlan`(조작마다 안 물음)
- [저장] 확인 창 = 잠금 막 · 서버 요청 앞 · 구조물 · 관 · 추가 측점 · 종단 편집 수 · [취소] = 요청 0 · 추천 [적용] 같은 글 · 수
- 저장 뒤 = 응답 `steps.route.route_reset` 지운 수 한 줄 · 초기화면 세션 초안 통째 비움 → 서버 정본으로 다시 세움 · 옛 서버(칸 없음) = 알림 건너뜀
- 시험: 새 test_283_route_reset_confirm(띠 · 확인 창 수 · [취소] · 스냅만 · 거울) · 저장 헬퍼 셋 확인 창 가짜 · 476-2 확인 글 기대 고침

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 07:20:10 +09:00

78 lines
3.7 KiB
TypeScript

/* =============================================================================
* B05_Profile/logic/B05_Profile_Route_Reset.ts
* 노선 모양 바뀐 [저장] = 초기화(요구 283 · 284 · 285 · 492-2) — 브라우저 판정 · 띠 글 · 확인 창 글 · 저장 뒤 알림 글.
*
* 판정 = 저장 노선(그린 선) 대 초안이 그릴 선(`draftLine` · 서버가 쓰는 자릿수) — `routeShapeChanged`
* (짝 = 파이썬 `B05_Profile_Engine_Grade_Carry.route_shape_changed` · 정점 1 mm · 거울 시험
* resources/tester/test_283_route_reset_confirm.py). 스냅 켬끔 · 간격만 = 선 그대로 = 초기화 아님.
* 정본은 서버 판정(응답 `route_reset`) — 여기는 저장 전에 무엇이 지워지는지 알리는 몫.
* ========================================================================== */
import type { RouteDraft } from "../../A00_Common/design/logic/design_pipeline_types";
import { routeShapeChanged } from "./B05_Profile_Grade_Carry";
import { draftLine } from "./B05_Profile_Pipeline_RouteGround";
type Vertex = [number, number];
/** 지금 캐시에서 지워질 수 — 사용자 구조물 · 관 · 추가 측점 · 종단 편집. */
export interface RouteResetCounts {
structures: number;
pipes: number;
plusStations: number;
profileEdits: number;
}
/** 서버 응답 `route_reset`(sub4 약속) — 초기화했나 · 지운 수. */
export interface RouteReset {
reset: boolean;
dropped?: { structures?: number; pipes?: number; plus_stations?: number };
}
export const ROUTE_RESET_BAND =
"노선이 바뀌어 [저장] 하면 초기화 — 구조물 · 관 · 추가 측점 · 종단 · 횡단 손 입력이 지워지고 새 노선으로 다시 셈";
const xy = (line: ReadonlyArray<Vertex>) => line.map(([x, y]) => ({ x, y }));
/** 초안이 저장 노선 모양을 바꾸나 — 초안 없음 = 아님 · 저장 선을 모름 = 바뀜으로 봄(묻는 쪽이 안전). */
export function draftShapeChanged(
savedLine: ReadonlyArray<Vertex> | null,
draft: RouteDraft | null,
minRadiusM: number,
): boolean {
if (!draft?.nodes || draft.nodes.length < 2) return false;
if (!savedLine || savedLine.length < 2) return true;
return routeShapeChanged(xy(savedLine), xy(draftLine(draft, minRadiusM).line));
}
/** 확인 창 글 — [저장](노선 고침) · [적용](추천 노선) 같은 글 · 수. */
export function routeResetConfirmText(counts: RouteResetCounts, action: "저장" | "적용"): string {
const head = action === "저장" ? "노선이 바뀌어 [저장]하면" : "추천 노선을 [적용]하면";
return (
`${head} 초기화합니다 — 구조물 ${counts.structures} · 관 ${counts.pipes} · ` +
`추가 측점 ${counts.plusStations} · 종단 편집 ${counts.profileEdits} · 횡단 손 입력이 지워지고 ` +
`새 노선으로 다시 셉니다(세류선 교차 관 · 측점 · 초기 종단 · 횡단). ${action}할까요?`
);
}
/** 모양 바뀐 초안이면 묻고 답(지워질 수는 물을 때만 셈) · 안 바뀌면 묻지 않고 true. */
export async function askRouteReset(
changed: boolean,
counts: () => Promise<RouteResetCounts>,
ask: (text: string) => Promise<boolean>,
): Promise<boolean> {
return !changed || ask(routeResetConfirmText(await counts(), "저장"));
}
/** 저장 뒤 알림 한 줄 — 초기화가 아니면 null. */
export function routeResetNotice(
reset: RouteReset | null | undefined,
crossing = 0,
): string | null {
if (!reset?.reset) return null;
const dropped = reset.dropped ?? {};
return (
`노선이 바뀌어 초기화했습니다 — 지움: 구조물 ${dropped.structures ?? 0} · 관 ${dropped.pipes ?? 0} · ` +
`추가 측점 ${dropped.plus_stations ?? 0} · 새 교차 관 ${crossing}`
);
}