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>
This commit is contained in:
commit
964a841de1
3978 files changed
+58013356
No files matched your search
@@ -0,0 +1,63 @@
|
||||
"""Assemble only end-balanced, validated tie rows from local review files.
|
||||
|
||||
Never writes a saved job. Publication must run the independent geometry gate.
|
||||
"""
|
||||
import argparse
|
||||
import copy
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(root/'src/backend' if (root/'src/backend').is_dir() else root))
|
||||
from tie_end_spacing import envelope_margins
|
||||
|
||||
|
||||
def prepare(paths):
|
||||
reviews = [json.load(open(path)) for path in paths]
|
||||
result = copy.deepcopy(reviews[0])
|
||||
selected = {}
|
||||
rejected = []
|
||||
for review in reviews:
|
||||
plan = review['result']
|
||||
ids = set(plan['quantityDistributionReview']['group_ids'])
|
||||
rejected.extend(plan['quantityDistributionReview'].get('failures', []))
|
||||
for group in plan['rebar_groups']:
|
||||
if group.get('id') not in ids:
|
||||
continue
|
||||
rhythm = group['quantity_distribution'].get('rhythm', {})
|
||||
lengths = rhythm.get('side_lengths_m', [])
|
||||
counts = rhythm.get('side_counts', [])
|
||||
margins = rhythm.get('end_margins_m', [])
|
||||
pitch = rhythm.get('source_cycle_pitch_m', 0)
|
||||
errors = [abs(envelope_margins(side)[0]-envelope_margins(side)[1]) for side in margins]
|
||||
reason = None
|
||||
if len(lengths)!=2 or len(counts)!=2 or len(errors)!=2 or not pitch:
|
||||
reason = 'missing physical-side balance proof'
|
||||
elif (rhythm.get('end_spacing_priority') == 'equal_ends' and rhythm.get('end_balance_required',True)
|
||||
and max(errors)>rhythm.get('end_balance_tolerance_m',1e-6)+1e-8):
|
||||
reason = 'straight body end residual requires explicit acceptance'
|
||||
elif abs(lengths[0]-lengths[1])>=rhythm['repeat_m']-1e-6 and counts[0]==counts[1]:
|
||||
reason = 'longer side still has the same quantity'
|
||||
if reason:
|
||||
rejected.append({'block':group['rebar_block'],'mark':group['mark'],
|
||||
'error':reason,'side_end_imbalance_m':errors})
|
||||
continue
|
||||
selected[group['id']] = group
|
||||
plan = result['result']
|
||||
plan['rebar_groups'] = [g for g in plan['rebar_groups'] if g.get('id') not in selected]+list(selected.values())
|
||||
plan['quantityDistributionReview'] = {'group_ids':sorted(selected),'failures':rejected,
|
||||
'engineering_approved':False,'scope':'body ties only; wing drawing errors preserved'}
|
||||
result['failures'] = rejected
|
||||
return result
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
parser=argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('reviews',nargs='+')
|
||||
parser.add_argument('--output',required=True)
|
||||
args=parser.parse_args()
|
||||
result=prepare(args.reviews)
|
||||
with open(args.output,'x') as stream:
|
||||
json.dump(result,stream,ensure_ascii=False,allow_nan=False)
|
||||
print(json.dumps({'eligible':len(result['result']['quantityDistributionReview']['group_ids']),
|
||||
'rejected':result['failures']},ensure_ascii=False))
|
||||
Reference in new issue
Block a user