"""터파기 단면 — 관·벽 두 갈래. **근거의 급이 다르므로 갈라 둔다.** ⚠⚠ TS 짝 파일과 **한 벌**이다 — `common_util/common_util_excavation.ts`. 거울 시험: `tmp/tests/test_excavation_mirror.py` (고칠 때 같이 돌릴 것). 화면(B06 횡단도)이 그리고 서버(B08 수량)가 세는 값이라 두 쪽에 같은 수가 있어야 한다. ① 관 — **법정 시방서에 표가 있다** `KCS 44 40 10 배수관(23.01) §3.2(4) 그림 3.2-1`. 「설계도서에 따로 표기되지 않았을 때에는 그림 3.2-1 터파기 기준 폭에 따라야 한다」 ⇒ 기본값으로 쓰고 사용자가 덮어쓰는 구조가 원문과 맞다. ⚠ **관경 + 2b 로 계산하지 않는다** — 표가 관 두께·작업여유를 이미 담고 있다 (Ø800 은 800+2×300=1400 이 아니라 **1600**). 여유폭 b 는 같은 그림의 값: 보통지반 0.30 m · 연약지반 0.50 m(한쪽). ② 벽(돌쌓기·기슭막이) — **법정 근거 없음. 실무 정본 식이 있다** 법령·교본은 「설계도서 지시 폭·기울기·깊이」까지만 정한다 (지식DB `01_임도/02_상세설계/구조물/구조물_기초_토공.md` §1 — 전수 확인). 실무 정본 `original/구조물도/기슭막이/04.구조도(기슭막이).xls` 7탭: 터파기 = 기초 0.5 × (0.7 + 0.2) × 1.0 = 0.45 (버림만 있는 탭은 0.1 × 0.7 = 0.07) + 비탈 H × (평균두께 + 0.2) × 1.0 ⇒ **여유폭은 「+0.2」**(평균두께에 더함), **기초는 깊이 0.5 · 폭 0.9**. ⇒ 정본 탭 제목이 **「기초유 / 기초버림」**이다 — 기초를 안 두는 것이 아니라 **버림으로 얕게 두는 것**이라 뜻이 다르다. 그 축이 곧 **0.45 냐 0.07 이냐**를 가른다. ⚠ **비탈을 주지 않는다 — 정본이 수직으로 센다.** 기울기 항이 식에 아예 없다. 임의로 기울기를 주면 그림과 물량이 어긋난다. ⚠ 값을 지어내지 않는다 — 여기 있는 수는 전부 위 두 출처의 것이고, 사용자가 덮어쓰면 그 값이 이긴다. 화면에는 **근거의 급**(법정 표 / 실무 식)을 노티스로 드러낸다. """ from __future__ import annotations #: 관경(㎜) → 터파기 폭(㎜). `KCS 44 40 10` 그림 3.2-1 표 그대로. PIPE_TRENCH_WIDTH_MM: dict[int, int] = { 300: 700, 350: 800, 400: 900, 450: 1000, 500: 1100, 600: 1200, 700: 1400, 800: 1600, 900: 1700, 1000: 1800, 1100: 2000, 1200: 2100, 1300: 2200, 1400: 2400, 1500: 2500, } #: 한쪽 여유폭(m) — 같은 그림. 표에 없는 관경을 사용자가 넣었을 때의 안내용이다. PIPE_TRENCH_CLEARANCE_NORMAL_M = 0.30 PIPE_TRENCH_CLEARANCE_SOFT_M = 0.50 #: 벽 터파기 — 실무 정본 식의 수(위 문서 참조). WALL_TRENCH_CLEARANCE_M = 0.2 # 평균두께에 더하는 여유 WALL_FOUNDATION_DEPTH_M = 0.5 # 기초 깊이 WALL_FOUNDATION_WIDTH_M = 0.9 # 기초 폭 (0.7 + 0.2) WALL_BLINDING_DEPTH_M = 0.1 # 기초 없이 버림만 있을 때의 깊이 WALL_BLINDING_WIDTH_M = 0.7 # 그때의 폭 (여유폭 0.0 — 버림 탭에는 여유가 없다) #: 근거의 급 — 화면 노티스가 이 값을 그대로 쓴다. BASIS_PIPE = "법정 표(KCS 44 40 10 그림 3.2-1) — 설계도서에 따로 없으면 이 값" #: ⭐ 2026-09-09 **사용자 확정 5차 1번** — 「비탈 터파기를 셀 것인가」에 **「지금 이대로」**로 답이 #: 왔다(기초 + 비탈 두 줄). 그래서 문구에서 **「확인 후 쓸 것」을 걷는다** — 확인이 끝났다. #: ⚠ 「법정 근거 없음」은 그대로 둔다(사실이 안 바뀜) — 근거의 급은 여전히 실무 정본이다. #: ⚠ 소광리 07-구조도는 **비탈 몫을 안 적는다**(설계사무소 간 차이) — 그래도 우리는 정본 #: 04.구조도(기슭막이)의 두 줄을 따른다는 것이 이 확정의 뜻이다. BASIS_WALL = ( "법정 근거 없음 · 실무 정본 식(구조도 기슭막이 xls) — 기초 + 비탈 두 줄." " **2026-09-09 사용자 확정 5차 1번으로 「지금 이대로」 확정**" ) def pipe_trench_width_m(diameter_mm: float | int | None) -> float | None: """관경(㎜)에 대응하는 터파기 폭(m). 표에 없으면 `None`(지어내지 않는다).""" if diameter_mm is None: return None try: key = int(round(float(diameter_mm))) except (TypeError, ValueError): return None width = PIPE_TRENCH_WIDTH_MM.get(key) return None if width is None else width / 1000.0 def wall_trench_area_m2( height_m: float | None, average_thickness_m: float | None, *, has_foundation: bool, ) -> float | None: """벽 터파기 단면적(㎡/m). 높이나 평균두께가 없으면 `None`. 실무 정본 식 그대로: `기초분 + H × (평균두께 + 0.2)`. `has_foundation=False` 면 기초분이 **버림 몫(0.1 × 0.7)**으로 줄어든다. """ if height_m is None or average_thickness_m is None: return None try: height = float(height_m) thickness = float(average_thickness_m) except (TypeError, ValueError): return None if height <= 0 or thickness <= 0: return None base = ( WALL_FOUNDATION_DEPTH_M * WALL_FOUNDATION_WIDTH_M if has_foundation else WALL_BLINDING_DEPTH_M * WALL_BLINDING_WIDTH_M ) return base + height * (thickness + WALL_TRENCH_CLEARANCE_M) def wall_trench_width_m(average_thickness_m: float | None) -> float | None: """벽 터파기 폭(m) — 평균두께 + 여유 0.2. 값이 없으면 `None`.""" if average_thickness_m is None: return None try: thickness = float(average_thickness_m) except (TypeError, ValueError): return None return None if thickness <= 0 else thickness + WALL_TRENCH_CLEARANCE_M