Files
Pier_v1/Code/교각모델링/compile_rebar_schedule.py
T
ahnyongjooandClaude Sonnet 5.5 964a841de1 chore(rebar): Pier_T_rebar 작업 폴더 초기 구성 및 외부 의존 파일 통합
- Code\rebar_pipeline, review_pipeline, pier-program을 정션에서 실제 폴더로 전환
- Code\rhino_mcp 및 CLAUDE_rhino배경.md 추가, .mcp.json은 PYTHONPATH로 새 위치 사용
- pier-program 내부 .git 제거(이력은 backup\pier-program_20261028.bundle에 보관)
- worktree 가이드 반영(CLAUDE.local.md, HANDOFF.md)
- D:\Rhino-MCP 경로 참조를 새 위치로 치환

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 11:20:18 +09:00

73 lines
3.2 KiB
Python

"""Compile the D3 rebar schedule (SD400 / SD500 tables) and compare bar counts with the model.
Schedule: 판독/3_survey.json text rows (mark rows + diameter-group subtotal rows).
Model counts: verification result files (bar count checks) in 검증/ - not the build inputs.
Writes 검증/rebar_schedule_compare.json and prints a compact table.
"""
import json
from collections import defaultdict
from pathlib import Path
HERE = Path(__file__).resolve().parent
OFF = {False: 0, True: 23750} # SD500 table is shifted by ~23,750 in x
COL = {"mark": 2100, "shape": 3000, "dia": 3900, "n": 4800, "L": 19500, "tot": 20750}
def rows():
texts = json.loads((HERE / "판독" / "3_survey.json").read_text(encoding="utf-8"))["texts"]
out = {False: defaultdict(dict), True: defaultdict(dict)}
for t in texts:
if t["y"] < 15000 or t["y"] > 31000:
continue
sd500 = t["x"] > 21000
x = t["x"] - OFF[sd500]
col = min(COL, key=lambda c: abs(COL[c] - x))
if abs(COL[col] - x) < 400:
out[sd500][round(t["y"] / 10)][col] = t["text"]
elif 21000 - 300 < x < 23500: # subtotal columns right of total
out[sd500][round(t["y"] / 10)].setdefault("extra", []).append((round(x), t["text"]))
return out
def model_counts():
counts = {}
for f in ("verify_rebar_v0.1.04_reloaded.json", "verify_footing_rebar_v0.1.04_reloaded.json",
"verify_coping_rebar_v0.1.08_reloaded.json"):
for r in json.loads((HERE / "검증" / f).read_text(encoding="utf-8"))["results"]:
if r["item"].endswith("bar count") or r["item"].endswith("bar count vs schedule"):
counts[r["item"].split()[0]] = r["actual"]
return counts
def main():
data, mc = rows(), model_counts()
marks, groups = [], []
for sd500, rs in data.items():
last_dia = None
for y in sorted(rs, reverse=True):
r = rs[y]
if r.get("mark", "").strip() and r["mark"][0] in "PBCSU" and r["mark"][1:].isdigit() or r.get("mark") == "UA1":
dia = r.get("dia", "")
dia = last_dia if dia in ('"', "") else dia
last_dia = dia
n = r.get("n")
L = float(r["L"])
tot = float(r["tot"])
if n is None: # B9: quantity blank -> derived
n = f"{tot / L:.0f}*"
marks.append(dict(table="SD500" if sd500 else "SD400", mark=r["mark"], shape=r.get("shape"),
dia=dia, n=n, L=L, total=tot, model=mc.get(r["mark"])))
elif "tot" in r and "extra" in r:
ex = sorted(r["extra"])
groups.append(dict(table="SD500" if sd500 else "SD400", total=r["tot"], extra=[v for _, v in ex]))
json.dump(dict(marks=marks, groups=groups), open(HERE / "검증" / "rebar_schedule_compare.json", "w",
encoding="utf-8"), ensure_ascii=False, indent=1)
for m in marks:
print(m["table"], m["mark"], m["shape"], m["dia"], m["n"], m["L"], m["total"], "model", m["model"])
for g in groups:
print("GROUP", g)
if __name__ == "__main__":
main()