/* ============================================================================= * B06_Section_UI_Page_Link_Session.ts * 연동 기슭막이 옵션(연동 해제·종단경사 반영)의 **세션 보관** — 측점 제어기 * (`_UI_Page_Station_Controls.ts`)에서 700줄 제한으로 분리했다(2026-08-25). * 두 플래그는 한 세션 항목에 같이 담아 확정 전 리로드에도 살아남는다. * * 측점별 조작값을 담는 **한 겹 맵**도 여기서 낸다(`createSessionMap`, 2026-09-02) — * 반폭·기슭막이 4축·유입 형식·집수정·추가 벽 수·단별 구간값이 같은 모양(읽기 → 항목 * 검증 → 담기 / 쓰기 → 통째 직렬화)이라 제어기마다 짝을 두던 것을 하나로 모았다. * ========================================================================== */ /** 세션에 담기는 측점별 조작값 한 겹 맵. */ export interface SessionMap { values: Map; /** 세션값 읽기 — 맵을 비우고 다시 채운다. */ load: () => void; /** 맵을 통째로 세션에 쓴다. */ persist: () => void; } /** * 세션 보관 맵을 만든다. `accept` 가 항목마다 값을 검증·정규화해 돌려주고, * `undefined` 를 내면 그 항목은 버린다(손상값·옛 형식 정리 자리). */ export function createSessionMap( sessionKey: () => string | null, accept: (value: unknown) => V | undefined, ): SessionMap { const values = new Map(); return { values, load(): void { values.clear(); const key = sessionKey(); if (!key) return; try { const raw = window.sessionStorage.getItem(key); if (!raw) return; const parsed = JSON.parse(raw) as Record; Object.entries(parsed).forEach(([entry, value]) => { const taken = accept(value); if (taken !== undefined) values.set(entry, taken); }); } catch { /* 손상된 세션 값은 무시 — 정본·기본값으로 재시작. */ } }, persist(): void { const key = sessionKey(); if (!key) return; try { window.sessionStorage.setItem(key, JSON.stringify(Object.fromEntries(values))); } catch { /* 세션 저장 실패는 무시(용량 초과 등) — 값은 메모리에 유지된다. */ } }, }; } export interface LinkFlagMaps { detached: Map; followGrade: Map; load: () => void; persist: () => void; } export function createLinkFlagSession(sessionKey: () => string | null): LinkFlagMaps { const detached = new Map(); const followGrade = new Map(); return { detached, followGrade, load(): void { detached.clear(); followGrade.clear(); const key = sessionKey(); if (!key) return; try { const raw = window.sessionStorage.getItem(key); if (!raw) return; const parsed = JSON.parse(raw) as { detached?: Record; grade?: Record; }; Object.entries(parsed.detached ?? {}).forEach(([at, value]) => detached.set(at, !!value)); Object.entries(parsed.grade ?? {}).forEach(([at, value]) => followGrade.set(at, !!value)); } catch { /* 손상된 세션 값은 무시 — 정본·기본값으로 재시작. */ } }, persist(): void { const key = sessionKey(); if (!key) return; window.sessionStorage.setItem( key, JSON.stringify({ detached: Object.fromEntries(detached), grade: Object.fromEntries(followGrade), }), ); }, }; }