fix(b08): 옹벽 기초 터파기 옆면 1:0.5 — 실무 식생옹벽블럭 기초 터파기와 같은 자리에서 기울기(브레인 판정 고침)

- 밑폭 2.2(기초 1.6 + 여유 0.3×2) · 윗폭 = 밑폭 + 0.5 × 판 깊이 × 2 = 2.9 · 깊이 0.7 → m당 터파기 1.54 → 1.785 · 되메우기 0.36 → 0.605 · 잔토 1.18 그대로
- 검증 프로젝트 내역 본체 124,202,681 → 124,424,547원(+221,866 = 구조물터파기 0~1m 15.4→17.85㎥ +213,375 · 되메우기 24.6→27.05㎥ +8,491)
- 그림 터파기 점선을 사다리꼴로 · 「밑폭 2.20 · 윗폭 2.90 × 깊이 0.70」 · 표 사유와 같은 말

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
This commit is contained in:
2026-09-14 06:11:47 +09:00
co-authored by Claude Opus 5
parent ce5bfb7722
commit aba96f6116
4 changed files with 36 additions and 23 deletions
@@ -152,7 +152,10 @@ def billing_of(
#: 단면으로 터파기를 세운 줄의 사유 — 표 사유·구조물도 그림이 **같은 말**(브레인 판정 2026-09-14). #: 단면으로 터파기를 세운 줄의 사유 — 표 사유·구조물도 그림이 **같은 말**(브레인 판정 2026-09-14).
SECTION_TRENCH_NOTE = "터파기는 기초 폭 + 양쪽 여유로 수직 — 지반선이 제원에 없어 비탈분 제외" SECTION_TRENCH_NOTE = (
"터파기는 기초 폭 + 양쪽 여유 · 옆면 1:0.5(판 깊이 기준)"
" — 벽 높이 몫은 지반선이 제원에 없어 제외"
)
def earthwork_missing_note(entry: dict[str, Any]) -> str | None: def earthwork_missing_note(entry: dict[str, Any]) -> str | None:
@@ -202,8 +205,9 @@ def section_trench_components(
) -> tuple[list[dict[str, Any]], float] | None: ) -> tuple[list[dict[str, Any]], float] | None:
"""단면이 있는 관측 줄의 터파기·되메우기·잔토(`destination: earthwork`)와 파는 깊이(m). """단면이 있는 관측 줄의 터파기·되메우기·잔토(`destination: earthwork`)와 파는 깊이(m).
브레인 판정 — 기초 폭 + 양쪽 여유(0.3, 같은 파일 식생옹벽블럭 기초 터파기)로 **수직** · 같은 파일 식생옹벽블럭 기초 터파기 식 — 밑폭 = 기초 폭 + 양쪽 여유 0.3 · 옆면 1:0.5
깊이 = 기초 + 버림 + 기초잡석 · **비탈분(벽 높이 몫)은 안 셈**(지반선이 제원에 없음). (윗폭 = 밑폭 + 0.5 × 판 깊이 × 2) · 깊이 = 기초 + 버림 + 기초잡석 · 벽 높이 몫은 안 셈
(지반선이 제원에 없음). 브레인 판정 2026-09-14 — 처음 수직에서 1:0.5 로 고침.
⚠ 되메우기 = 터파기 − 그 안에 든 것(기초·전단키 콘크리트 + 버림 + 기초잡석) — 잔토 = 든 것. ⚠ 되메우기 = 터파기 − 그 안에 든 것(기초·전단키 콘크리트 + 버림 + 기초잡석) — 잔토 = 든 것.
""" """
section = entry.get("section") or {} section = entry.get("section") or {}
@@ -211,11 +215,12 @@ def section_trench_components(
if not trench: if not trench:
return None return None
footing, key, blinding = section["footing"], section["key"], section["blinding"] footing, key, blinding = section["footing"], section["key"], section["blinding"]
clearance = trench["clearance_m"] clearance, slope = trench["clearance_m"], trench.get("side_slope", 0.0)
width = footing["width_m"] + 2 * clearance width = footing["width_m"] + 2 * clearance
depth = footing["thickness_m"] + blinding["thickness_m"] + rubble_thickness_m depth = footing["thickness_m"] + blinding["thickness_m"] + rubble_thickness_m
top_width = width + 2 * slope * depth
key_below = max(key["depth_m"] - blinding["thickness_m"] - rubble_thickness_m, 0.0) key_below = max(key["depth_m"] - blinding["thickness_m"] - rubble_thickness_m, 0.0)
excavation = width * depth + key["width_m"] * key_below excavation = (width + top_width) / 2 * depth + key["width_m"] * key_below
layer_width = footing["width_m"] + 2 * blinding["overhang_m"] - key["width_m"] layer_width = footing["width_m"] + 2 * blinding["overhang_m"] - key["width_m"]
filled = ( filled = (
footing["width_m"] * footing["thickness_m"] footing["width_m"] * footing["thickness_m"]
@@ -224,10 +229,11 @@ def section_trench_components(
) )
backfill = excavation - filled backfill = excavation - filled
basis = ( basis = (
f"(기초 {footing['width_m']:g} + 여유 {clearance:g}×2) × 깊이 {depth:.2f}" f"(밑폭 {width:.2f}(기초 {footing['width_m']:g} + 여유 {clearance:g}×2)"
f" + 윗폭 {top_width:.2f}(1:{slope:g})) ÷ 2 × 깊이 {depth:.2f}"
f"(기초 {footing['thickness_m']:g} + 버림 {blinding['thickness_m']:g}" f"(기초 {footing['thickness_m']:g} + 버림 {blinding['thickness_m']:g}"
f" + 기초잡석 {rubble_thickness_m:g})" f" + 기초잡석 {rubble_thickness_m:g})"
f" · {SECTION_TRENCH_NOTE} · 여유는 소광리 식생옹벽블럭 기초 터파기" f" · {SECTION_TRENCH_NOTE} · 여유·기울기는 소광리 식생옹벽블럭 기초 터파기"
) )
rows = [ rows = [
("터파기", excavation, basis), ("터파기", excavation, basis),
@@ -297,22 +297,23 @@ def _wall_figure(
# 터파기 — 표 줄과 같은 식(기초 폭 + 양쪽 여유 · 수직 · 기초 윗면에서 기초잡석 밑까지). 점선. # 터파기 — 표 줄과 같은 식(기초 폭 + 양쪽 여유 · 수직 · 기초 윗면에서 기초잡석 밑까지). 점선.
trench = section.get("trench") trench = section.get("trench")
clearance = trench["clearance_m"] if trench else 0.0 clearance = trench["clearance_m"] if trench else 0.0
side = (trench or {}).get("side_slope", 0.0) * (f_t + b_t + rubble)
dig_bottom = -(b_t + rubble) dig_bottom = -(b_t + rubble)
if trench: if trench:
shapes.append( shapes.append(
_path( _path(
[ [
(-clearance, f_t), (-clearance - side, f_t),
(-clearance, dig_bottom), (-clearance, dig_bottom),
(f_w + clearance, dig_bottom), (f_w + clearance, dig_bottom),
(f_w + clearance, f_t), (f_w + clearance + side, f_t),
], ],
"guide", "guide",
dash=True, dash=True,
) )
) )
right = max(f_w + over, f_w + clearance) + 0.2 right = max(f_w + over, f_w + clearance + side) + 0.2
weep_area, weep_dia, _weep_basis = weep_hole_spec(sheet.get("options") or {}) weep_area, weep_dia, _weep_basis = weep_hole_spec(sheet.get("options") or {})
blinding_width = f_w + 2 * over - k_w blinding_width = f_w + 2 * over - k_w
shapes += [ shapes += [
@@ -359,8 +360,9 @@ def _wall_figure(
if trench: if trench:
shapes.append( shapes.append(
_text( _text(
f"터파기 폭 {f_w + 2 * clearance:.2f} × 깊이 {f_t - dig_bottom:.2f} m" f"터파기 {f_w + 2 * clearance:.2f} · 윗폭 {f_w + 2 * (clearance + side):.2f}"
f" (기초 {f_w:g} + 여유 {clearance:g}×2)", f" × 깊이 {f_t - dig_bottom:.2f} m (기초 {f_w:g} + 여유 {clearance:g}×2"
f" · 옆면 1:{trench.get('side_slope', 0.0):g})",
(right, f_t + 0.25), (right, f_t + 0.25),
"left", "left",
) )
@@ -45,7 +45,8 @@
}, },
"trench": { "trench": {
"clearance_m": 0.3, "clearance_m": 0.3,
"note": "소광리 「옹벽2.0」 탭에 터파기 줄이 없음 → 같은 파일 「식생옹벽블럭(H=2.0)」 F31 기초 터파기 밑폭 = 기초 폭 + 0.6(양쪽 0.3). 브레인 판정(2026-09-14) — 수직 · 비탈분 제외(지반선이 제원에 없음)" "side_slope": 0.5,
"note": "소광리 「옹벽2.0」 탭에 터파기 줄이 없음 → 같은 파일 「식생옹벽블럭(H=2.0)」 F31·H31 기초 터파기 — 밑폭 = 기초 폭 + 0.6(양쪽 0.3) · 윗폭 = 밑폭 + 0.5 × 판 깊이 × 2(옆면 1:0.5). 브레인 판정(2026-09-14, 수직 → 1:0.5 로 고침) · 벽 높이 몫은 지반선이 제원에 없어 제외"
} }
}, },
"components": [ "components": [
+14 -10
View File
@@ -157,21 +157,22 @@ def _amounts(structure: dict) -> dict:
return {row["name"]: row for row in structure["components"]} return {row["name"]: row for row in structure["components"]}
def test_옹벽_터파기는_기초_폭과_양쪽_여유로_수직이고_토공으로만_간다() -> None: def test_옹벽_터파기는_기초_폭과_양쪽_여유_옆면_1대0점5이고_토공으로만_간다() -> None:
wall = _wall_table() wall = _wall_table()
rows = _amounts(wall) rows = _amounts(wall)
# 폭 1.6 + 0.3×2 = 2.2 · 깊이 기초 0.4 + 버림 0.1 + 기초잡석 0.2 = 0.7 → 1.54/m # 폭 1.6 + 0.3×2 = 2.2 · 깊이 0.4 + 0.1 + 0.2 = 0.7 · 옆면 1:0.5 → 윗폭 2.9
assert abs(rows["터파기"]["amount"] - 15.4) < 1e-9 # (2.2 + 2.9) ÷ 2 × 0.7 = 1.785/m
# 든 것 = 기초·전단키 0.745 + (버림 + 잡석) 1.45 × 0.3 = 1.18 → 되메우기 0.36/m assert abs(rows["터파기"]["amount"] - 17.85) < 1e-9 # 수직일 때 15.4(2026-09-14 판정으로 고침)
# 든 것 = 기초·전단키 0.745 + (버림 + 잡석) 1.45 × 0.3 = 1.18 → 되메우기 0.605/m
assert abs(rows["잔토처리"]["amount"] - 11.8) < 1e-9 assert abs(rows["잔토처리"]["amount"] - 11.8) < 1e-9
assert abs(rows["되메우기"]["amount"] - 3.6) < 1e-9 assert abs(rows["되메우기"]["amount"] - 6.05) < 1e-9 # 수직일 때 3.6
assert {rows[k]["destination"] for k in ("터파기", "되메우기", "잔토처리")} == {"earthwork"} assert {rows[k]["destination"] for k in ("터파기", "되메우기", "잔토처리")} == {"earthwork"}
assert abs(rows["기초잡석"]["amount"] - 2.9) < 1e-9 # 원문 버림 0.145 × 2 assert abs(rows["기초잡석"]["amount"] - 2.9) < 1e-9 # 원문 버림 0.145 × 2
assert wall["trench_depth_m"] == 0.7 assert wall["trench_depth_m"] == 0.7
assert "비탈분 제외" in rows["터파기"]["basis"] assert "1:0.5" in rows["터파기"]["basis"] and "지반선" in rows["터파기"]["basis"]
# 잡석을 얇게 두면 전단키가 그 밑으로 나와 그 몫을 더 팜: 2.2×0.6 + 0.35×0.1 # 잡석을 얇게 두면 전단키가 그 밑으로 나와 그 몫을 더 팜: (2.2+2.8)/2×0.6 + 0.35×0.1
thin = _amounts(_wall_table(rubble=0.1)) thin = _amounts(_wall_table(rubble=0.1))
assert abs(thin["터파기"]["amount"] - 13.55) < 1e-9 assert abs(thin["터파기"]["amount"] - 15.35) < 1e-9
def test_옹벽_물구멍관은_제원_칸이_닿고_돌쌓기와_같은_규격으로_합쳐진다() -> None: def test_옹벽_물구멍관은_제원_칸이_닿고_돌쌓기와_같은_규격으로_합쳐진다() -> None:
@@ -196,8 +197,11 @@ def test_옹벽_그림은_기초잡석_두께를_산출_조건에서_받고_사
_wall_sheet() | {"options": {"length_m": 10}}, _wall_sheet() | {"options": {"length_m": 10}},
) )
trench = [note for note in table_notes if "터파기" in note] trench = [note for note in table_notes if "터파기" in note]
assert trench and trench[0] in texts and "비탈분 제외" in trench[0] assert trench and trench[0] in texts and "지반선" in trench[0]
assert "터파기 폭 2.20 × 깊이 0.80 m (기초 1.6 + 여유 0.3×2)" in texts # 잡석 0.3 # 잡석 0.3 → 깊이 0.8 · 한쪽 0.4
assert (
"터파기 밑폭 2.20 · 윗폭 3.00 × 깊이 0.80 m (기초 1.6 + 여유 0.3×2 · 옆면 1:0.5)" in texts
)
assert not any(text.startswith("기초잡석") for text in _texts(build_figure(_wall_sheet(), 0))) assert not any(text.startswith("기초잡석") for text in _texts(build_figure(_wall_sheet(), 0)))