Files
Aislo/B05_Profile/logic/B05_Profile_UI_Profile_Guard.ts
T
eomsangdonandClaude Opus 5.5 281c71b55b refactor(logic): 348-1 순수 계산 TS 49 파일 <페이지>/logic/ 로 옮김 — 이름 앞머리 그대로 · 동작 고침 없음
- 옮김: B04 2 · B05 23 · B06 11 · A00_Common/design 13 (9,299 줄) · 이미 logic/ 에 있던 16 파일 그대로
- 안 옮김: 묶음 입구(package.json build:*) · 파이썬 · 순수지만 계산 아닌 8 (보기 결선 · 콜백 · API 타입 · 갈아끼움 알림판)
- import 266 줄(142 파일) · 시험 · 주석 · 짝 표시 문자열 경로 고침 · B05 · B06 CLAUDE.md 짝 줄 logic/
- 시험 도우미 새 경로: 가짜 require 열쇠 · B05()/B06() 부름 · 형제 import 자리 · tsc 묶어 돌리는 시험 · 정규식 · rglob
- design_view_cross 줄 한도 시험 685 → 688 (긴 import 경로 줄바꿈 3줄)
- 확인: typecheck 0 · 서버 묶음 넷(corridor · server-calc · b07-extent · b07-note) 다시 지어 코드 같음(//#region 경로 주석만 다름) · 관련 시험 270 파일 — 남은 실패 19 는 옮기기 전과 같음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
2026-10-16 13:44:50 +09:00

62 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =============================================================================
* B05_Profile_UI_Profile_Guard.ts
* 종단도가 편집 · 경고에 쓰는 **셈만** — 계획선 샘플 보간, 평면 최소곡선반지름 경고
* (구조물 측점 맞추기는 측점 한 벌 `oneStationList` 로 갈음 · 272).
*
* 종단도 한 벌(`A00_Common/design/design_profile.ts`)이 700줄을 넘겨 떼어낸 조각이다
* (계획서 24-2c). 본문 로직과 수치는 그대로이고 화면 상태를 인자로 받는다.
* ========================================================================== */
import type { SectionDetailResponse } from "../../B06_Section/B06_Section_Api_Fetch";
import type { ProfileAlignment } from "./B05_Profile_UI_Profile_Alignment";
/** 계획선 샘플에서 chainage로 계획고·지반고를 되짚는 보간기(최소고 판정 입력). */
export function sampleAt(
alignment: ProfileAlignment | null,
chainageM: number,
field: "elevation_m" | "ground_elevation_m",
): number | null {
const samples = alignment?.samples;
if (!samples?.length) return null;
if (chainageM <= samples[0].chainage_m) return samples[0][field];
for (let i = 1; i < samples.length; i += 1) {
if (chainageM <= samples[i].chainage_m) {
const span = samples[i].chainage_m - samples[i - 1].chainage_m;
const t = span <= 1e-12 ? 0 : (chainageM - samples[i - 1].chainage_m) / span;
return samples[i - 1][field] + (samples[i][field] - samples[i - 1][field]) * t;
}
}
return samples[samples.length - 1][field];
}
/**
* 법정 평면 최소곡선반지름을 밑도는 측점을 센다(별표2 Ⅰ.2.다.(1), 2026-09-06).
* 반경은 횡단 측점마다 실려 오고(`plan_radius_m`), 하한은 계획선 정책이 들고 있다.
* **경고만** 낸다 — 노선을 고칠지는 사용자 판단이다.
*/
export function planCurveWarning(
alignment: ProfileAlignment | null,
detail: SectionDetailResponse | null,
): {
count: number;
worstRadiusM: number;
limitM: number;
hairpin: number;
} | null {
const limit = alignment?.policy.min_plan_radius_m ?? 0;
const sections = detail?.cross_sections ?? [];
if (!limit || !sections.length) return null;
const hairpinLimit = alignment?.policy.hairpin_min_radius_m ?? 0;
let count = 0;
let hairpin = 0;
let worst = Number.POSITIVE_INFINITY;
sections.forEach((section) => {
const radius = section.plan_radius_m;
if (typeof radius !== "number" || !Number.isFinite(radius) || radius >= limit) return;
count += 1;
worst = Math.min(worst, radius);
if (hairpinLimit > 0 && radius < hairpinLimit) hairpin += 1;
});
return count ? { count, worstRadiusM: worst, limitM: limit, hairpin } : null;
}