"""측구 — **선택과 결과를 가른다** (2026-09-09 정리, 계획서 0장). ⚠⚠ 한 칸(`ditch_enabled`)에 두 뜻이 담겨 있었다 — 결과(실제 섰나)를 그대로 다시 입력으로 넣어 읽었으므로 **한 번 저장되면 자동 판정이 영영 다시 안 돌았다.** 계획고를 내려 절토가 생겨도 측구가 안 서고 아무 말도 안 나왔다. ⇒ **선택은 `ditch_choice`**(없음 = 자동) · **결과는 `ditch_enabled`**(실제 섰나). ⚠ 옛 저장분은 `ditch_enabled` 로 오고, **자동값과 다를 때만** 선택으로 살린다 — 같으면 자동이 그렇게 냈던 것이고, 다르면 사용자가 일부러 바꾼 것이다(설계 의도 보존). """ from __future__ import annotations import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[2] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from B06_Section.B06_Section_Engine_Design import compute_cross_design # noqa: E402 def _ground(slope: float) -> list[dict]: return [ {"offset_m": round(x * 0.5, 3), "elevation_m": round(100.0 + slope * x * 0.5, 4)} for x in range(-24, 25) ] def _design(**kwargs): return compute_cross_design( _ground(kwargs.pop("slope", 0.35)), 100.4, ground_type="soil", section_mode="left_cut", ditch_side="left", **kwargs, ) def test_자동이면_선택이_비어_있다() -> None: design = _design() assert design["ditch_enabled"] is True # 절토측이라 자동으로 섬 assert design["ditch_choice"] is None # **선택한 적 없음** def test_결과를_다시_넣어도_자동이_계속_돈다() -> None: """⚠ 이것이 고친 자리 — 종전에는 결과가 선택으로 굳어 자동이 다시 안 돌았다.""" first = _design() second = _design(ditch_enabled=first["ditch_enabled"]) assert second["ditch_choice"] is None, "결과가 선택으로 굳었다" assert second["ditch_enabled"] == first["ditch_enabled"] def test_옛_저장분이_자동과_다르면_사용자_뜻으로_본다() -> None: """일부러 끈 것은 살린다 — 설계 의도를 잃지 않는다.""" design = _design(ditch_enabled=False) assert design["ditch_choice"] is False assert design["ditch_enabled"] is False def test_자동과_같은_선택은_자동으로_푼다() -> None: """화면 토글이 2단이라 「자동으로 되돌리기」 단추가 없다 — 원래 값으로 다시 누른 것을 선택으로 굳히면 **다시 같은 병**(지형이 바뀌어도 안 따라감)이 된다. """ design = _design(ditch_choice=True) # 자동도 True 인 지형 assert design["ditch_enabled"] is True assert design["ditch_choice"] is None, "자동과 같은 선택이 굳었다" def test_선택은_자동을_이긴다() -> None: off = _design(ditch_choice=False) assert off["ditch_enabled"] is False and off["ditch_choice"] is False on = _design(slope=-0.35, ditch_choice=True) assert on["ditch_enabled"] is True and on["ditch_choice"] is True def test_양성은_선택보다_기하가_먼저다() -> None: """양성 단면은 측구가 설 자리가 없다 — 켜도 안 선다.""" design = compute_cross_design( _ground(-0.35), 102.0, ground_type="soil", section_mode="both_fill", ditch_side="left", ditch_choice=True, ) assert design["ditch_enabled"] is False def test_선택이_저장_patch_까지_실린다() -> None: """⚠ 2026-09-09 화면 실측으로 잡은 자리 — 토글을 눌러도 **아무 일도 안 났다.** 선택이 캐시(`CrossDesignChoice`)·재계산(`Cross_Refresh`)·저장 patch 어느 쪽에도 실리지 않아 **눌린 값이 그 자리에서 버려졌다.** 칸 하나가 빠지면 조용히 사라지므로 통로 네 곳을 함께 지킨다. """ from B06_Section.B06_Section_Schema import CrossSectionPatch patch = CrossSectionPatch(chainage_m=20.0, ditch_choice=False) dumped = {k: v for k, v in patch.model_dump().items() if v is not None} assert dumped["ditch_choice"] is False, "「끔」이 병합에서 걷혀 정본에 안 남는다" def _reads(name: str) -> str: return (PROJECT_ROOT / "B06_Section" / name).read_text(encoding="utf-8") for name in ( "B06_Section_Cross_Design_Session.ts", # 캐시 칸 "B06_Section_UI_Page_Design_Sync.ts", # 캐시에 쓰는 자리 "B06_Section_Cross_Refresh.ts", # 브라우저 재계산이 읽는 자리 "B06_Section_UI_Page_Persist.ts", # [저장]·[확정] patch ): assert "ditch_choice" in _reads(name), f"{name} 에서 측구 선택이 빠졌다"