- 토적표 칸 = 사용자 견본 32칸 · 보정량계 = 절토 보정량만 · 면 계열(면고르기 · 지장목제거 · 제근 · 노면정리) 거리 = B07 횡단 수량 함수 · 면적 = 앞뒤 평균 × 측점 거리 - 토공집계표 · 운반 시트 = 거창 실무 워크북 같은 이름 시트 칸 · 식 · Q · L = 저장된 유토곡선 배분(서버 · 읽기만) - 시험 test_69_b08_earthwork_tabs.py · 보정량계 시험 정함대로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UoSr2sqvYtBf1dtQdus88s
112 lines
6.3 KiB
Python
112 lines
6.3 KiB
Python
"""토공 보조 탭 셋 — 토공집계표 · 평균운반거리 · 종방향 무대운반거리 (PLAN 69-2).
|
||
|
||
근거 = 거창 실무 워크북(`00.25년_산불_거창(…)내역+수량.xlsx`)의 같은 이름 시트 칸 · 식 그대로.
|
||
|
||
평균운반거리 덤프트럭 · 불도우저 각 토량(Q) · 거리(L) · Q×L · 합계 ·
|
||
평균 = ROUND(ΣQ×L ÷ ΣQ, 2)
|
||
종방향 무대운반거리 무대운반 토량(Q) · 거리(L) · Q×L · 합계 · 평균(같은 식)
|
||
토공집계표 토적표 합계 줄 + 위 두 시트 ΣQ 를 시트 식대로 묶음
|
||
|
||
Q · L 출처 = 저장된 유토곡선 배분(`mass_haul.haul_plan` — B07 토적도가 그리는 것과 같은 정본) ·
|
||
장비 띠(`blocks[].bands[]`)와 떨어진 구간 운반(`transfers[]`)의 `equipment` 로 가름
|
||
(`free_haul` = 무대 · `dozer` = 불도우저 · `dump_truck` = 덤프트럭).
|
||
|
||
암 갈래 — 리핑암 = 「연암」 줄 · 발파암 = 「경암」 줄. 풍화암 · 보통암 · 구조물 쪽 줄(su2 시트)은
|
||
값이 없어 비움(None).
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from decimal import ROUND_HALF_UP, Decimal
|
||
from typing import Any
|
||
|
||
#: 운반 시트 열 — 장비 키
|
||
HAUL_EQUIPMENT = ("dump_truck", "dozer", "free_haul")
|
||
|
||
|
||
def excel_round(value: float, digits: int = 0) -> float:
|
||
"""엑셀 ROUND — 반은 0 에서 먼 쪽(파이썬 round 는 짝수 쪽)."""
|
||
step = Decimal(1).scaleb(-digits)
|
||
return float(Decimal(str(value)).quantize(step, rounding=ROUND_HALF_UP))
|
||
|
||
|
||
def haul_lists(haul_plan: dict[str, Any] | None) -> dict[str, dict[str, Any]]:
|
||
"""장비별 `{rows: [{q, l, ql}], q, ql, average_m}` — 시트 한 줄 = 띠 · 운반 하나."""
|
||
items: dict[str, list[dict[str, float]]] = {key: [] for key in HAUL_EQUIPMENT}
|
||
plan = haul_plan if isinstance(haul_plan, dict) else {}
|
||
bands = [band for block in plan.get("blocks") or [] for band in block.get("bands") or []]
|
||
for item in [*bands, *(plan.get("transfers") or [])]:
|
||
rows = items.get(str(item.get("equipment")))
|
||
q, dist = item.get("volume_m3"), item.get("haul_distance_m")
|
||
if rows is None or not isinstance(q, (int, float)) or not isinstance(dist, (int, float)):
|
||
continue
|
||
rows.append({"q": float(q), "l": float(dist), "ql": float(q) * float(dist)})
|
||
out: dict[str, dict[str, Any]] = {}
|
||
for key, rows in items.items():
|
||
q = sum(row["q"] for row in rows)
|
||
ql = sum(row["ql"] for row in rows)
|
||
out[key] = {
|
||
"rows": rows,
|
||
"q": q,
|
||
"ql": ql,
|
||
"average_m": excel_round(ql / q, 2) if q > 0 else None,
|
||
}
|
||
return out
|
||
|
||
|
||
def _row(group: str, kind: str, spec: str, unit: str, value: float | None, note: str = ""):
|
||
return {"group": group, "kind": kind, "spec": spec, "unit": unit, "value": value, "note": note}
|
||
|
||
|
||
def summary_rows(totals: dict[str, float], haul: dict[str, dict[str, Any]]) -> list[dict[str, Any]]:
|
||
"""토공집계표 줄 — 시트 C5:G37 차례 · 식 그대로(셀 주소는 줄 끝 주석)."""
|
||
t = totals
|
||
r0 = excel_round
|
||
free_q, dump_q, dozer_q = haul["free_haul"]["q"], haul["dump_truck"]["q"], haul["dozer"]["q"]
|
||
diverted = t["diverted_m3"]
|
||
tree = r0(t["tree_removal_fill_area_m2"] * 0.5 + t["tree_removal_cut_area_m2"], 2)
|
||
m3 = "㎥"
|
||
return [
|
||
_row("흙깍기", "토사", "기계(굴삭기)", m3, r0(t["cut_soil_volume_m3"])), # 토적표!E137
|
||
_row("흙깍기", "풍화암", "굴삭기 + 브레카", m3, None),
|
||
_row("흙깍기", "연암", "굴삭기 + 브레카", m3, r0(t["cut_ripping_rock_volume_m3"])),
|
||
_row("흙깍기", "보통암", "굴삭기 + 브레카", m3, None),
|
||
_row("흙깍기", "경암", "발파 + 굴삭기", m3, r0(t["cut_blasting_rock_volume_m3"])),
|
||
_row("측구 터파기", "토사", "기계", m3, r0(t["ditch_soil_volume_m3"])), # 토적표!K137
|
||
_row("측구 터파기", "풍화암", "굴삭기 + 브레카", m3, None),
|
||
_row("측구 터파기", "연암", "굴삭기 + 브레카", m3, r0(t["ditch_ripping_rock_volume_m3"])),
|
||
_row("측구 터파기", "보통암", "굴삭기 + 브레카", m3, None),
|
||
_row("측구 터파기", "경암", "발파 + 굴삭기", m3, r0(t["ditch_blasting_rock_volume_m3"])),
|
||
_row("보정량계", "", "", m3, r0(t["adjusted_total_m3"])), # 토적표!P137
|
||
_row("성토", "", "", m3, r0(t["fill_volume_m3"])), # 토적표!R137
|
||
_row("유용토 소계", "", "", m3, diverted + free_q), # G18+G19
|
||
_row("횡방향유용토", "", "백호우", m3, diverted, "유용토"), # 토적표!S137
|
||
_row("종방향유용토", "", "백호우", m3, free_q, "유용토"), # 종방향무대운반거리!B25
|
||
_row("토사운반", "", "BH+DT+BH", m3, dump_q), # 평균운반거리!B42
|
||
_row("토사운반", "", "19 TON B/D", m3, dozer_q), # 평균운반거리 불도우저 ΣQ
|
||
_row("잔토처리", "", "백호우", m3, r0(t["balance_m3"])), # 토적표!T137
|
||
_row("층따기", "", "백호우", m3, t["benching_area_m2"]), # 토적표!W137
|
||
_row("성토면다짐", "", "", "㎡", r0(t["grading_fill_area_m2"] * 0.8), "성토면80%반영"),
|
||
_row("표토제거", "", "", "㎡", None),
|
||
_row(
|
||
"초류종자살포",
|
||
"",
|
||
"씨드스프레이",
|
||
"㎡",
|
||
r0(t["grading_fill_area_m2"] * 0.5 + t["grading_cut_area_m2"]),
|
||
"성토면50%반영+절토면",
|
||
),
|
||
_row("법면보호공", "", "", "㎡", None),
|
||
# 토적표!AI138 = ROUND(성토 × 0.5 + 절토, 2) → × 0.8
|
||
_row("지장목제거", "", "", "㎡", r0(tree * 0.8), "80%반영"),
|
||
_row("구조물터파기", "토사", "기계(굴삭기)", m3, None, "구조물 수량"),
|
||
_row("구조물터파기", "풍화암", "굴삭기 + 브레카", m3, None),
|
||
_row("구조물터파기", "연암", "굴삭기 + 브레카", m3, None, "구조물 수량"),
|
||
_row("구조물터파기", "보통암", "굴삭기 + 브레카", m3, None),
|
||
_row("구조물터파기", "경암", "발파 + 굴삭기", m3, None),
|
||
_row("토사다짐", "", "", m3, None, "구조물 수량"),
|
||
_row("되메우기", "", "", m3, None, "구조물 수량"),
|
||
_row("잔토", "", "", m3, None, "현장내 성토(유용토)"),
|
||
_row("운반성토", "", "BH+DT+BH", m3, None),
|
||
]
|