- 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>
86 lines
4.0 KiB
Python
86 lines
4.0 KiB
Python
"""Stage order of the T-pier app and the Rhino step list for a build up to a given gate.
|
|
|
|
Gates follow the required work order: G1 shape -> G2 column rebar -> G3 footing rebar -> G4 coping rebar
|
|
-> G5 sole plates & bearings. A build "up to Gk" always rebuilds G1..Gk in a fresh document, so every
|
|
gate model is reproducible from params alone.
|
|
|
|
Per-pier options (2026-10-13, Ulsan P1 = second T-pier form):
|
|
params["scope"] gates modelled for this pier (default all); others are skipped ("범위 밖")
|
|
params["builders"] {gate: script} replacing the default builder (e.g. G1 -> concrete_tapered.py)
|
|
expected["checkers"] {gate: script} replacing the default checker (e.g. G1 -> g1_tapered.py)
|
|
"""
|
|
import json
|
|
from pathlib import Path
|
|
|
|
RHINO_DIR = Path(__file__).resolve().parent / "rhino"
|
|
|
|
GATES = [
|
|
("G1", "형상(콘크리트·말뚝·받침대좌·패드)", "concrete.py"),
|
|
("G2", "기둥 철근", "column_rebar.py"),
|
|
("G3", "확대기초 철근", "footing_rebar.py"),
|
|
("G4", "코핑 철근", "coping_rebar.py"),
|
|
("G5", "교량받침·솔플레이트", "bearings.py"),
|
|
]
|
|
CHECKERS = {"G1": "g1_shape.py", "G2": "g2_column_rebar.py", "G3": "g3_footing_rebar.py",
|
|
"G4": "g4_coping_rebar.py", "G5": "g5_bearings.py"}
|
|
# Object id prefixes created by each gate (after the pier id), used for negative tests and the
|
|
# "earlier gates unchanged" fingerprint comparison.
|
|
GATE_PREFIXES = {"G1": ["LC", "FT", "CL", "CP", "PL", "BS", "BP"], "G2": ["R-P", "RC-P"], "G3": ["R-B", "RC-B", "PT"],
|
|
"G4": ["R-C", "RC-C", "R-S", "RC-S"], "G5": ["BB", "SP"]}
|
|
# "PT": shaft cage plate (Ramp-A P1 G3, 2026-10-13). Ramp-A shaft cage bars carry "R-P1-1" etc. (marks P1-1 ...),
|
|
# so they fall under the G2 prefixes in the unchanged check; that is harmless (all earlier gates are compared)
|
|
REBAR_GATES = {"G2", "G3", "G4"}
|
|
TOLERANCE_MM = 0.001
|
|
|
|
|
|
def gate_ids():
|
|
return [g for g, _, _ in GATES]
|
|
|
|
|
|
def _json(path):
|
|
return json.loads(Path(path).read_text(encoding="utf-8")) if path and Path(path).exists() else {}
|
|
|
|
|
|
def scope_of(params_path):
|
|
"""Gates modelled for this pier (params["scope"], default all), in gate order."""
|
|
sc = _json(params_path).get("scope")
|
|
return [g for g in gate_ids() if not sc or g in sc]
|
|
|
|
|
|
def builder_of(params_path, gate):
|
|
default = {g: s for g, _, s in GATES}[gate]
|
|
return _json(params_path).get("builders", {}).get(gate, default)
|
|
|
|
|
|
def checker_of(expected_path, gate):
|
|
return _json(expected_path).get("checkers", {}).get(gate, CHECKERS[gate])
|
|
|
|
|
|
def build_steps(params_path, upto="G5"):
|
|
"""Rhino steps for G1..`upto`: builders, diameter colours after the last rebar stage, display state."""
|
|
ids = gate_ids()
|
|
if upto not in ids:
|
|
raise ValueError(f"unknown gate {upto}")
|
|
scope = scope_of(params_path)
|
|
chosen = [(g, n, builder_of(params_path, g)) for g, n, _ in GATES[: ids.index(upto) + 1] if g in scope]
|
|
glb = {"PARAMS_PATH": str(Path(params_path).resolve())}
|
|
steps = []
|
|
last_rebar = max((i for i, (g, _, _) in enumerate(chosen) if g in REBAR_GATES), default=None)
|
|
for i, (g, _, script) in enumerate(chosen):
|
|
steps.append({"name": f"{g}:{script}", "script": RHINO_DIR / script, "globals": dict(glb, GATE=g)})
|
|
if i == last_rebar:
|
|
steps.append({"name": f"{g}:rebar_colours.py", "script": RHINO_DIR / "rebar_colours.py", "globals": glb})
|
|
steps.append({"name": "display.py", "script": RHINO_DIR / "display.py", "globals": glb})
|
|
return steps
|
|
|
|
|
|
def check_steps(expected_path, out_dir, gates=None, tag=""):
|
|
"""Rhino steps running the gate checkers; each writes <out_dir>/<gate><tag>.json."""
|
|
steps = []
|
|
for g in gates or gate_ids():
|
|
chk = checker_of(expected_path, g)
|
|
steps.append({"name": f"{g}:{chk}", "script": RHINO_DIR / "checks" / chk,
|
|
"globals": {"EXPECTED_PATH": str(Path(expected_path).resolve()),
|
|
"RESULT_PATH": str(Path(out_dir).resolve() / f"{g}{tag}.json")}})
|
|
return steps
|