Files
Aislo/B06_Section/B06_Section_UI_Cross_Culvert_Wire.ts
T
eomsangdonandClaude Opus 5 9a58e3b1bd feat(B06): 유출부 보호공 삭제·성토부선 전환 + 추가 기슭막이(계단식)
- 보호공(돌붙임) 띠 삭제, 윗면 선만 성토부선(계획선)으로 유지 — 구간별
  사면길이·5m 초과 여부 툴팁 표기
- 성토부 5m 이상이면 조정창 +로 추가 기슭막이(배관 없는 동일 형상 벽)
  계단식 추가 — 자동 자리는 배관용과 같은 규칙(1:1.2 최소 자리)
- 추가 벽도 ◀/▶/↺ 이동(안쪽 한계 = 앞 구조물), 마지막 벽 - 삭제
- 개수·이동량 세션 보관(b06:extrawall / revetx extra{n} 키)
- 700줄 제한: Extra(성토부선·추가 벽)·Wire(카드 배선) 분리 신설

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 13:24:47 +09:00

75 lines
3.3 KiB
TypeScript

/* =============================================================================
* B06_Section_UI_Cross_Culvert_Wire.ts
* 횡단 카드의 배수관 세트 **계산 호출 + 이동량 되받기(토스트)** — Cross_View에서
* 분리(700줄 제한). 카드가 다시 그려질 때마다 한 번 불린다.
* ========================================================================== */
import type { CrossSection, SectionSample } from "./B06_Section_Api_Fetch";
import { computeCulvertLayout } from "./B06_Section_UI_Cross_Culvert";
import type { CulvertLayout, RevetKey } from "./B06_Section_UI_Cross_Culvert";
import type {
ExtraWallControl,
InletStructureControl,
RevetOffsetControl,
} from "./B06_Section_UI_Cross_View";
import { showToast } from "@ui/ui_template_elements";
import { L } from "./B06_Section_UI_Section_Common";
/**
* 배수관 세트 기하 계산 + 제어 상태 동기화.
*
* ① 세션의 이동량(기슭막이·추가 벽)·유입 구조물 선택을 모아 기하를 계산하고,
* ② 성토부가 짧아져 못 세운 추가 벽은 개수를 잘라 동기화하며(고아 이동량 방지),
* ③ 요청 이동량이 한계에 잘렸으면 실제 적용값으로 되돌려 담는다 — 안 그러면 눌러도
* 안 움직이는데 창의 숫자만 계속 커진다(2026-08-21 사용자 지적). 잘린 순간에는
* **왜 안 움직였는지 토스트**로 알린다(2026-08-22 사용자 — 13+15.7처럼 자동
* 자리가 이미 안쪽 한계라 ◀가 그대로 먹히지 않는 경우). 조작 중(그 벽이 선택된
* 상태)일 때만 띄운다 — 리로드로 복원된 옛 세션 값에는 침묵.
*/
export function computeCardCulvert(
section: CrossSection,
sourceSamples: SectionSample[],
activeRevet: RevetKey | null,
revetOffset?: RevetOffsetControl,
inletStructure?: InletStructureControl,
extraWalls?: ExtraWallControl,
): CulvertLayout | null {
const layout = computeCulvertLayout(
section,
sourceSamples,
revetOffset
? {
inlet: revetOffset.shiftFor(section, "inlet"),
outlet: revetOffset.shiftFor(section, "outlet"),
extras: Array.from({ length: extraWalls?.countFor(section) ?? 0 }, (_, i) =>
revetOffset.shiftFor(section, `extra${i}`),
),
}
: undefined,
inletStructure?.valueFor(section),
);
if (!layout) return null;
if (extraWalls && extraWalls.countFor(section) > layout.extraWalls.length) {
extraWalls.syncCount(section.chainage_m, layout.extraWalls.length);
}
if (revetOffset) {
const roles: Array<[RevetKey, number]> = [
["inlet", layout.revetShift.inlet],
["outlet", layout.revetShift.outlet],
...layout.revetShift.extras.map((applied, i): [RevetKey, number] => [`extra${i}`, applied]),
];
for (const [role, applied] of roles) {
const requested = revetOffset.shiftFor(section, role);
if (activeRevet === role && Math.abs(requested - applied) > 0.05) {
// 이동량 부호: + = 계류측 바깥. 요청이 적용보다 작으면 안쪽 요청이 잘린 것.
showToast(
L(requested < applied ? "B06_Cross_Revet_Limit_Inward" : "B06_Cross_Revet_Limit_Outward"),
"info",
);
}
revetOffset.syncShift(section.chainage_m, role, applied);
}
}
return layout;
}