Files
Aislo/E05_StabReport/E05_StabReport_Reinforce.py
T

141 lines
5.3 KiB
Python

"""E05 보고서 s8 보강검토 — E03 보강 검토 저장본(비탈 완화 · 소단 가정 · 벽 외적 안정) → 시트 (PLAN 536-3).
칸 자리 = `resources/master_template/report/stab_report_slots.md` s8.
저장본이 없으면 시트를 뺌(있을 때만) — `build_program` 이 책에서 지움.
"""
from __future__ import annotations
import copy
import hashlib
import json
from pathlib import Path
from typing import Any
from E03_StabSection.E03_StabSection_Router_WhatIf import records
CONDITION_NAMES = {"dry": "건기", "wet": "우기", "seismic": "지진"}
SIDE_NAMES = {"left": "좌", "right": "우"}
ROLE_NAMES = {"cut": "깎기", "fill": "쌓기"}
CASE_NAMES = {"normal": "평상시", "seismic": "지진 시"}
CHECKS = ("sliding", "overturning", "bearing")
ST_NG, ST_OK = 10, 11
def read(project_root: Path) -> list[dict[str, Any]]:
return records(Path(project_root))
def stamp(project_root: Path) -> str:
"""해석 지문용 — 저장본 목록 내용."""
body = json.dumps(read(project_root), ensure_ascii=False, sort_keys=True, default=str)
return hashlib.sha1(body.encode("utf-8")).hexdigest()
def _set(sheet: dict[str, Any], a1: str, value: Any, style: int | None = None) -> None:
cell = dict(sheet["칸"].get(a1) or {})
cell.pop("식", None)
if value is None:
cell.pop("값", None)
else:
cell["값"] = round(value, 6) if isinstance(value, float) else value
if style is not None:
cell["서식"] = style
sheet["칸"][a1] = cell
def _verdict(sheet: dict[str, Any], a1: str, ok: bool | None) -> None:
if ok is None:
_set(sheet, a1, "-")
else:
_set(sheet, a1, "O.K" if ok else "N.G", ST_OK if ok else ST_NG)
def _assume_text(rec: dict[str, Any]) -> str:
a = rec["assume"]
text = f"1:{a['ratio_before']:g} → 1:{a['ratio']:g}"
if a.get("bench_w") and a.get("bench_h"):
text += f" · 소단 폭 {a['bench_w']:g} m / 높이 {a['bench_h']:g} m 마다"
search = rec.get("search")
if search:
goal = CONDITION_NAMES.get(search.get("condition"), "전 조건")
text += (
f" · 최소 완화({goal} 목표)"
if search.get("found")
else f" · 최소 완화 못 찾음({goal} · 끝값)"
)
return text
def fill_reinforce(sheet: dict[str, Any], recs: list[dict[str, Any]], labels: dict) -> None:
"""s8 — 1. 가정 줄(조건마다 한 줄 · 6 행 서식) · 2. 벽 줄(경우마다 한 줄 · 10 행 서식)."""
tpl = {
r: {c: copy.deepcopy(sheet["칸"].get(f"{c}{r}") or {}) for c in "ABCDEFGHI"}
for r in (8, 9, 10)
}
row6 = {c: copy.deepcopy(sheet["칸"].get(f"{c}6") or {}) for c in "ABCDEFGHI"}
for a1 in [k for k in sheet["칸"] if int("".join(ch for ch in k if ch.isdigit())) >= 6]:
del sheet["칸"][a1]
sheet["병합"] = [
m for m in sheet["병합"] if int("".join(ch for ch in m.split(":")[0] if ch.isdigit())) < 6
]
sheet["행"] = {k: v for k, v in sheet["행"].items() if int(k) < 6}
def put_row(r: int, styles: dict[str, dict]) -> None:
for c, cell in styles.items():
sheet["칸"][f"{c}{r}"] = copy.deepcopy(cell)
def name(rec: dict[str, Any]) -> str:
ch = float(rec["chainage_m"])
return rec.get("label") or labels.get(round(ch, 3)) or f"{ch:.2f}"
r = 6
slopes = [x for x in recs if x["type"] == "slope"]
for rec in slopes:
a = rec["assume"]
for cond, after in rec["after"].items():
before = rec["before"].get(cond) or {}
put_row(r, row6)
_set(sheet, f"A{r}", name(rec))
_set(sheet, f"B{r}", f"{SIDE_NAMES[a['side']]} · {ROLE_NAMES[a['role']]}")
_set(sheet, f"C{r}", _assume_text(rec))
_set(sheet, f"D{r}", CONDITION_NAMES.get(cond, cond))
_set(sheet, f"E{r}", before.get("fs"))
_set(sheet, f"F{r}", after.get("fs"))
_set(sheet, f"G{r}", after.get("required"))
_verdict(sheet, f"H{r}", before.get("ok"))
_verdict(sheet, f"I{r}", after.get("ok"))
r += 1
if not slopes:
put_row(r, row6)
_set(sheet, f"A{r}", "가정 없음")
r += 1
r += 1
put_row(r, tpl[8])
sheet["병합"].append(f"A{r}:I{r}")
sheet["행"][str(r)] = sheet["행"][str(r + 1)] = {"높이": 22}
put_row(r + 1, tpl[9])
r += 2
walls = [x for x in recs if x["type"] == "wall"]
for rec in walls:
p = rec["params"]
for wall in rec["walls"]:
for case in wall["cases"]:
put_row(r, tpl[10])
_set(sheet, f"A{r}", name(rec))
_set(
sheet,
f"B{r}",
f"{wall.get('name') or '벽'} · {CASE_NAMES[case['case']]} · "
f"{'Coulomb' if p['method'] == 'coulomb' else 'Rankine'} · 수위 {p['water_ratio']:g}H",
)
for c, need, check in zip("CEG", "DFH", CHECKS):
fs = case["fs"][check]
_set(sheet, f"{c}{r}", fs if fs == fs and abs(fs) < 1e6 else None)
_set(sheet, f"{need}{r}", case["required"][check])
_verdict(sheet, f"I{r}", all(case["ok"].values()))
r += 1
if not walls:
put_row(r, tpl[10])
_set(sheet, f"A{r}", "벽 검토 없음")