feat(B05): 측점 입력 전역 정규화 — 잔여거리 넘침을 측점번호로 올림
측점 표기 규칙(2026-08-18 사용자 확정): 잔여거리는 [0, 간격 20m) 범위만 유효, 넘치면 측점번호로 올려 표시한다(1+30 → 2+10). 저장 수치는 원래 누가거리라 계산은 이미 동일했고, 입력 칸 표시를 확정(change) 시점에 정규화한다. 시작·기준·종료 측점 세 칸 공통(stationFields 확장). 검증(헤드 브라우저): 1+30→2+10.0, 0+45→2+5.0, 3+19.9 유지, 3+20→4+0.0 PASS. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* 저장은 누가거리(m), 화면 입출력만 측점번호+잔여거리.
|
||||
* ========================================================================== */
|
||||
|
||||
import { chainageToStation } from "./B05_Profile_Util_Station";
|
||||
import { chainageToStation, stationToChainage } from "./B05_Profile_Util_Station";
|
||||
|
||||
export function field(labelText: string, input: HTMLElement): HTMLLabelElement {
|
||||
const wrapper = document.createElement("label");
|
||||
@@ -44,7 +44,14 @@ export interface StationFields {
|
||||
clearInvalid: () => void;
|
||||
}
|
||||
|
||||
export function stationFields(labelText: string): StationFields {
|
||||
export function stationFields(
|
||||
labelText: string,
|
||||
/** 측점간격(m) 공급자 — 주면 입력 확정(change) 때 표시를 정규화한다:
|
||||
* 잔여거리는 [0, 간격) 범위만 유효하고, 넘치면 측점번호로 올린다(1+30 → 2+10).
|
||||
* 프로그램 전역 공통 규칙(2026-08-18 사용자 확정). 저장 수치는 원래부터
|
||||
* 누가거리라 표시만 맞추면 된다. */
|
||||
getInterval?: () => number,
|
||||
): StationFields {
|
||||
const station = numberInput("1", "0");
|
||||
station.placeholder = "측점";
|
||||
const remainder = numberInput("0.1", "0");
|
||||
@@ -57,6 +64,27 @@ export function stationFields(labelText: string): StationFields {
|
||||
station.classList.toggle("is-invalid", bad);
|
||||
remainder.classList.toggle("is-invalid", bad);
|
||||
};
|
||||
|
||||
if (getInterval) {
|
||||
const normalize = (): void => {
|
||||
const intervalM = getInterval();
|
||||
if (!(intervalM > 0)) return;
|
||||
const stationText = station.value.trim();
|
||||
const remainderText = remainder.value.trim();
|
||||
if (!stationText && !remainderText) return;
|
||||
const stationNo = stationText ? Number(stationText) : 0;
|
||||
const rest = remainderText ? Number(remainderText) : 0;
|
||||
if (!Number.isFinite(stationNo) || stationNo < 0 || !Number.isFinite(rest) || rest < 0)
|
||||
return;
|
||||
// 잔여 넘침(≥간격)·소수 측점번호만 손본다 — 그 외 표기는 사용자가 친 그대로 둔다.
|
||||
if (rest < intervalM && Number.isInteger(stationNo)) return;
|
||||
const parts = chainageToStation(stationToChainage(stationNo, rest, intervalM), intervalM);
|
||||
station.value = String(parts.station);
|
||||
remainder.value = parts.remainder.toFixed(1);
|
||||
};
|
||||
// 다른 change 리스너(옵션 잠금·임시 배치)보다 먼저 등록돼 정규화된 값이 읽힌다.
|
||||
[station, remainder].forEach((input) => input.addEventListener("change", normalize));
|
||||
}
|
||||
return {
|
||||
wrap,
|
||||
station,
|
||||
|
||||
@@ -119,9 +119,11 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
|
||||
const typeSelect = select([]);
|
||||
// 위치 입력 순서 = 시작 측점 → 기준 측점 → 종료 측점 (2026-08-17 사용자 확정).
|
||||
// 점형은 기준 측점만 보인다.
|
||||
const startFields = stationFields("시작 측점");
|
||||
const anchorFields = stationFields("기준 측점");
|
||||
const endFields = stationFields("종료 측점");
|
||||
// 측점 표기 전역 규칙(2026-08-18): 잔여거리는 [0, 간격) — 넘치면 측점번호로
|
||||
// 올려 표시한다(1+30 → 2+10). 정규화는 stationFields가 입력 확정 때 처리.
|
||||
const startFields = stationFields("시작 측점", () => callbacks.getInterval());
|
||||
const anchorFields = stationFields("기준 측점", () => callbacks.getInterval());
|
||||
const endFields = stationFields("종료 측점", () => callbacks.getInterval());
|
||||
const memoField = document.createElement("input");
|
||||
memoField.type = "text";
|
||||
memoField.placeholder = "메모(선택)";
|
||||
|
||||
Reference in New Issue
Block a user