"""돌쌓기 벽 두께 — 실무 구조물도 식 (2026-09-08 사용자 확정 2차 ②). ⚠ 겨누는 것 여섯 ① **뒷길이가 두께를 움직인다** — 옛 식(0.45+0.10H / 0.45+0.40H)에는 뒷길이가 없어 35 로 바꿔도 같은 값이 섰다 ② 상부 = 뒷길이 + 0.30 ③ 하부 = 상부 + 0.30 × (H − 1.0) ④ ⚠ H ≤ 1.0 에서 하부가 상부보다 얇아지지 않는다(음수 몫을 0 으로 눅임) ⑤ 두께가 **돌 입적·터파기의 밑수**다 — 둘이 같이 움직인다 ⚠ 2026-09-09 랩탑 보조가 확정 5차로 **막자갈을 이 축에서 떼어 냈다** — 뒷채움 폭은 정본 여섯 탭 공통값(상 0.30 · 하 0.45)이지 벽 두께가 아니었다. 시험이 겨누던 자리를 **입적**으로 옮긴다(같은 식을 근거에 싣는 줄). ⑥ 근거 문구에 그 식이 적힌다 """ from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT)) from B08_Quantity.B08_Quantity_Engine_UnitQuantity import stone_masonry # noqa: E402 def 성분(height_m: float, back_cm: int) -> dict: components, _ = stone_masonry( height_m, 10.0, {"height_m": height_m, "length_m": 10.0, "back_len_cm": back_cm}, wet=True, face="성토", ) return {c.name: c for c in components} def 평균두께(height_m: float, back_cm: int) -> float: top = back_cm / 100.0 + 0.30 bottom = top + 0.30 * max(height_m - 1.0, 0.0) return (top + bottom) / 2.0 def test_뒷길이가_두께를_움직인다() -> None: """⚠ 옛 식에는 뒷길이가 없었다 — 45 든 35 든 터파기가 같은 값으로 섰다.""" 굵은 = 성분(2.0, 45)["터파기"].amount 가는 = 성분(2.0, 35)["터파기"].amount assert 굵은 > 가는 def test_상부는_뒷길이에_0_30을_더한_값() -> None: basis = 성분(2.5, 45)["입적"].basis assert "상부 0.75" in basis # 0.45 + 0.30 def test_하부는_높이_1m를_넘는_만큼_두꺼워진다() -> None: basis = 성분(2.5, 45)["입적"].basis assert "하부 1.20" in basis # 0.75 + 0.30 × (2.5 − 1.0) def test_1m_이하에서는_상하부가_같다() -> None: """⚠ (H−1) 을 그대로 곱하면 낮은 벽에서 하부가 상부보다 **얇아진다**.""" basis = 성분(0.8, 35)["입적"].basis assert "상부 0.65" in basis and "하부 0.65" in basis def test_터파기가_평균두께에_매인다() -> None: got = 성분(2.5, 45)["터파기"].amount assert abs(got - 2.5 * (평균두께(2.5, 45) + 0.2) * 10.0) < 1e-6 def test_뒷길이가_커져도_막자갈은_안_는다() -> None: """⚠ 2026-09-09 확정 5차로 막자갈이 **뒷채움 정본 폭**(상 0.30 · 하 0.45)으로 갈렸다. 옛 식에서는 「입적 − 몸통」이라 뒷길이를 따라 아주 조금 움직였는데(12.653 → 12.630 → 12.607), 지금은 **뒷길이를 아예 안 본다** — 값이 셋 다 같다. 두께가 실제로 움직이는 것은 **입적·터파기·잔토**에서 드러난다. """ 막자갈 = [성분(2.5, b)["막자갈"].amount for b in (35, 45, 55)] assert len(set(막자갈)) == 1 터파기 = [성분(2.5, b)["터파기"].amount for b in (35, 45, 55)] assert 터파기 == sorted(터파기) and 터파기[2] - 터파기[0] > 4.0 def test_근거에_식이_적힌다() -> None: """⚠ 값만 바뀌고 근거가 그대로면 왜 달라졌는지 화면에서 못 짚는다.""" for name in ("입적", "터파기"): basis = 성분(2.5, 45)[name].basis assert "실무 구조물도 식" in basis def test_입적이_줄로_선다() -> None: """정본 계산표 좌측 열 이름 그대로다 — 「체적」으로 바꾸지 않는다 (확정 ⑦).""" got = 성분(2.5, 45)["입적"] assert got.unit == "㎥" assert abs(got.amount - 2.5 * 10.0 * 평균두께(2.5, 45)) < 1e-9 def test_석적은_정본에_없다는_사유를_달고_선다() -> None: """⚠ 뒤집힌 시험이다 — 종전에는 「안 낸다」였다. 2026-09-09 확정 5차 작은 것 4 로 **세우기로 정했다.** 다만 정본 여섯 탭에는 없고 소광리 시트에만 있는 줄이라 **그 사실이 근거에 적혀야** 한다(값만 서고 출처가 없으면 나중에 어디서 왔는지 못 짚는다). """ got = 성분(2.5, 45)["석적"] assert got.unit == "㎥" assert "정본에 없는 줄" in got.basis and "소광리" in got.basis def test_입적은_자재총괄에_안_섞인다() -> None: """⚠ 보여 주기만 하는 줄이다 — 자재로 서면 돌을 두 번 센다.""" from B08_Quantity.B08_Quantity_Engine_MaterialSummary import build_table as 자재 from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table as 원단위 unit = 원단위( [ { "structure_id": "s1", "type_id": "masonry_wet", "start_m": 0.0, "end_m": 10.0, "options": {"height_m": 2.5, "length_m": 10.0, "back_len_cm": 45}, } ] ) assert 성분(2.5, 45)["입적"].destination == "reference" assert all(row["name"] != "입적" for row in 자재(unit)["rows"])