"""Audit all saved quantity-based body ties, including unreplaced legacy rows.""" import argparse import json from pathlib import Path import sys root = Path(__file__).resolve().parents[1] sys.path.insert(0, str(root/'src/backend' if (root/'src/backend').is_dir() else root)) from quantity_review_validation import bend_paths, validate from tie_end_spacing import inspect_visible_ends def audit(job_path, verify_attachment=False): plan = json.loads(Path(job_path).read_text())['result'] rows = [] for group in plan['rebar_groups']: distribution = group.get('quantity_distribution', {}) if (distribution.get('target_kind') != 'cycle' or not distribution.get('records') or group.get('source_body_tie_binding', {}).get('host_role') not in ('top', 'bottom')): continue bends = bend_paths(group) ends = inspect_visible_ends(plan, group, [b['path'] for b in bends]) if verify_attachment: ends['attachment_and_containment'] = validate(plan, group) rows.append({'id': group['id'], 'block': group['rebar_block'], 'mark': group['mark'], 'count': len(bends), **ends}) return {'job': Path(job_path).stem, 'rows': rows, 'pass': all(row['pass'] for row in rows)} if __name__ == '__main__': parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('jobs', nargs='+') parser.add_argument('--output', required=True) parser.add_argument('--verify-attachment', action='store_true') args = parser.parse_args() reports = [audit(job, args.verify_attachment) for job in args.jobs] with open(args.output, 'x') as stream: json.dump(reports, stream, ensure_ascii=False, indent=2) for report in reports: for row in report['rows']: print(report['job'][:4], row['block'], row['mark'], 'straight' if row['end_balance_required'] else 'skew-exempt', [[round(v*1000,3) for v in side] for side in row['end_margins_m']], 'END-EQUAL/EXEMPT' if row['pass'] else 'END-RESIDUAL')