fix(B06): 암 경계 세션 오프셋을 자릿수 때문에 통째로 놓치던 것

세션에 저장하는 쪽(`createRockBoundaryStore`)은 키를 `toFixed(2)` 로 쓰는데 브라우저
재계산은 `toFixed(3)` 문자열로 찾아 **한 건도 못 읽었음**. 서버 경로는 키를 숫자로
바꿔 비교해 문제가 없었으므로 로컬 계산으로 옮기며 생긴 어긋남임.

키를 숫자로 되돌려 0.01m 단위로 맞춤. B06 에서 암 경계선을 올리내린 값이 이제 B05
유토곡선·횡단 면적에도 그대로 반영됨.

화면 검증(5173→5174, 같은 시점): B05 첫 진입 절토 4,774.1㎥ / 성토 16,690.7㎥,
B06 도 같은 값(재계산 입력·결과 로그로 대조 — 측점 65, 샘플 65, 자연방토 25건까지 동일).
B06 을 거치기 전과 후의 값 차이(성토 16,715.5 → 16,690.7)도 사라져 **첫 진입부터 일치**함.
진단용 임시 로그는 제거함.

전체 테스트 183건 통과, `tsc --noEmit` 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-03 21:01:56 +09:00
co-authored by Claude Opus 5
parent bc7b9e3a48
commit 061265f605
+26 -2
View File
@@ -99,6 +99,30 @@ export async function refreshCrossDesigns(input: CrossRefreshInput): Promise<num
return refreshFromServer(input);
}
/**
* 암 경계 세션 오프셋을 **자릿수에 안 휘둘리게** 읽는다.
*
* 저장하는 쪽(`createRockBoundaryStore`)은 키를 `toFixed(2)` 로 쓰고, 서버는 받은 키를
* 숫자로 바꿔 비교했다. 로컬 계산이 문자열 키를 그대로 맞추려다 자릿수가 달라 세션값을
* 통째로 놓쳤고, 그래서 B06 을 다녀오기 전과 후의 절·성토가 달랐다(2026-09-03 실측
* 성토 16,715.5㎥ ↔ 16,690.7㎥). 키를 숫자로 되돌려 0.01m 단위로 맞춘다.
*/
function rockKey(chainageM: number): number {
return Math.round(chainageM * 100) / 100;
}
function readRockOffsets(projectId: string, routeId: number): Map<number, number> {
const raw = readRockBoundarySession(projectId, routeId) ?? {};
const offsets = new Map<number, number>();
for (const [key, value] of Object.entries(raw)) {
const chainage = Number(key);
if (Number.isFinite(chainage) && typeof value === "number" && Number.isFinite(value)) {
offsets.set(rockKey(chainage), value);
}
}
return offsets;
}
/**
* 브라우저 안에서 전 측점을 다시 계산한다(정상 경로).
*
@@ -127,7 +151,7 @@ function refreshLocally(input: CrossRefreshInput): number[] | null {
toDesignProfile(alignment, detail.longitudinal.design_profiles?.[0]),
];
const rockOffsets = readRockBoundarySession(projectId, input.routeId) ?? {};
const rockOffsets = readRockOffsets(projectId, input.routeId);
const rockDefault = readRockBoundaryDefault(projectId);
const updated: number[] = [];
@@ -137,7 +161,7 @@ function refreshLocally(input: CrossRefreshInput): number[] | null {
const design = previous as unknown as Record<string, unknown>;
// 암 경계는 세션 조정값 → 저장분 → config 기본값 순 — 서버
// `recompute_designs_for_alignment` 의 우선순위와 같다.
const sessionOffset = rockOffsets[section.chainage_m.toFixed(3)];
const sessionOffset = rockOffsets.get(rockKey(section.chainage_m));
const storedOffset = design.rock_boundary_offset_m;
const rockBoundaryOffsetM =
typeof sessionOffset === "number"