Files
Aislo/B08_Quantity/B08_Quantity_Summary_Sheet.py
T
eomsangdon ce33e56a00 Merge remote-tracking branch 'origin/sub_laptop_5' into sub_laptop_2
# Conflicts:
#	B04_PreProcess/B04_PreProcess_Router_Basins.py
#	B08_Quantity/B08_Quantity_Router_Summary.py
2026-10-09 15:54:20 +09:00

79 lines
3.1 KiB
Python

"""B08 구조물 집계표 모음 상자 — 열 · 측점 줄 · 계 · 사본 주인별 값 · 칸 출처.
`B08_Quantity_Router_Summary.py` 가 700줄을 넘어 뗌(10-9 통합) — 셈 규칙은 그쪽 그대로.
"""
from __future__ import annotations
from typing import Any
class _Copy(str):
"""잇기 조합 id + 그 사본 주인 id(`linked_snapshots` 키 · `{구조물 id}__{그룹}`) — 145-3."""
copy: str
def _linked(combo: str | None, copy: str) -> str | None:
"""잇기 조합에 사본 주인 id 를 붙임 — 본체 조합(그냥 글)은 시설 id 가 주인."""
if combo is None:
return None
out = _Copy(combo)
out.copy = copy
return out
class _Sheet:
"""열 · 측점 줄 · 계를 모음 — 같은 측점(1 cm)의 같은 열은 더함."""
def __init__(self) -> None:
self.columns: dict[str, dict[str, Any]] = {}
self.rows: dict[int, dict[str, Any]] = {}
self.owner = "" # 지금 셈하는 시설 — 사본 없어 안 센 칸의 시설을 모음(143-1)
self.unlinked: set[str] = set()
self.sources: list[list[Any]] = [] # 칸마다 [열, 값, 시설, 조합] — 자재 재연결(143-4)
def add(
self,
chainage: float,
key: str,
sort: tuple[Any, ...],
group: list[str],
label: str,
value: float | None,
combos: list[str | None],
) -> None:
if not any(combos): # 그 칸을 낸 조합 사본이 없음 — 안 셈(143-1)
self.unlinked.add(self.owner)
return
cid = f"pipe:{key}"
column = self.columns.setdefault(
cid,
{"id": cid, "group": group, "label": label, "combos": [], "owners": {}, "_sort": sort},
)
for combo in combos:
if combo and combo not in column["combos"]:
column["combos"].append(str(combo))
row = self.rows.setdefault(round(chainage * 100), {"chainage_m": chainage, "values": {}})
if value is not None: # 열은 세움 — 놓였는데 값이 빈칸인 것이 보여야 함
row["values"][cid] = round((row["values"].get(cid) or 0.0) + value, 3)
# 사본 주인별 값(145-3 · 설계내역서가 대가 호표에 이음) — 잇기 사본이 먼저 · 없으면 본체
owner = next((c.copy for c in combos if isinstance(c, _Copy)), self.owner)
owners = column["owners"]
owners[owner] = round(owners.get(owner, 0.0) + value, 3)
self.sources.append([cid, value, self.owner, [c for c in combos if c]])
def result(self) -> dict[str, Any]:
columns = sorted(self.columns.values(), key=lambda column: column["_sort"])
rows = [self.rows[key] for key in sorted(self.rows)]
total: dict[str, float] = {}
for row in rows:
for cid, value in row["values"].items():
total[cid] = round(total.get(cid, 0.0) + value, 3)
return {
"columns": [{k: v for k, v in c.items() if k != "_sort"} for c in columns],
"rows": rows,
"total": total,
"sources": self.sources,
}