import json import sys import re from pathlib import Path sys.stdout.reconfigure(encoding='utf-8') # Load MD with open("resources/knowledge/original/행정규칙/임도 품셈 적용기준 (현 산림사업 표준품셈)/첨부/(산림청고시 제2025-82호) 산림사업 표준품셈.md", "r", encoding="utf-8") as f: md_lines = f.readlines() # Load Master with open('resources/data_work_item_master/work_item_master_2026-01-01.json', 'r', encoding='utf-8') as f: master = json.load(f) sys.path.insert(0, str(Path(__file__).parent.parent)) from scratch.enrich_tables import tables, get_chapter # Map master tables master_tables = {} wi_of_table = {} for wi in master['work_items']: for t in wi.get('tables', []): tid = t.get('pum_table_id') if tid: master_tables[tid] = t wi_of_table[tid] = wi for t in master.get('orphan_tables', []): tid = t.get('pum_table_id') if tid: master_tables[tid] = t # Patterns for basis in pre_context: # e.g., "[100㎡ 당]", "[10a 당]", "[100m 당]", "[10㎥ 당]", "[본당]", "[1공당]", "[개소당]", "[1m3 당]" # Also patterns in table header or first line basis_pattern = re.compile(r'\[\s*([0-9\.\,]*)\s*([a-zA-Z㎡㎥㏊ha본개공mkm㎏gtonLℓ대인組]+)\s*당\s*\]') basis_pattern2 = re.compile(r'\(단위\s*:\s*([^\)]+)\)') basis_audit = [] for i, t in enumerate(tables): tid = t['table_id'] chapter = t['chapter'] pre_lines = t['pre_context'] # 1. Search pre-context for basis found_basis_qty = None found_basis_unit = None found_basis_src = None # Search backwards in pre_lines for pl in reversed(pre_lines): m = basis_pattern.search(pl) if m: qty_str = m.group(1).replace(',', '').strip() found_basis_qty = float(qty_str) if qty_str else 1.0 found_basis_unit = m.group(2).strip() found_basis_src = f"pre_context: '{pl}'" break m2 = basis_pattern2.search(pl) if m2: u = m2.group(1).strip() found_basis_qty = 1.0 found_basis_unit = u found_basis_src = f"unit_parenthesis: '{pl}'" break # 2. Search table header cells header_line = t['lines'][0] if t['lines'] else "" # Look for "단위수량", "단위", etc. # 3. Compare with master mt = master_tables.get(tid) if not mt: continue m_qty = mt.get('basis_quantity') m_unit = mt.get('basis_unit') pform = mt.get('pum_form') # Check if MD has explicit basis but master is None or different if found_basis_unit is not None: if m_unit is None or m_qty is None: basis_audit.append({ 'table_id': tid, 'chapter': chapter, 'line': t['start_line'], 'section': t['section'], 'pum_form': pform, 'issue': 'MD_HAS_BASIS_MASTER_MISSING', 'md_qty': found_basis_qty, 'md_unit': found_basis_unit, 'md_src': found_basis_src, 'master_qty': m_qty, 'master_unit': m_unit }) elif m_qty != found_basis_qty or m_unit != found_basis_unit: # Check unit normalization (e.g. ㎡ vs m2) if not (str(found_basis_qty) == str(m_qty) and found_basis_unit.replace('㎡','m2').replace('㎥','m3') == m_unit.replace('㎡','m2').replace('㎥','m3')): basis_audit.append({ 'table_id': tid, 'chapter': chapter, 'line': t['start_line'], 'section': t['section'], 'pum_form': pform, 'issue': 'BASIS_MISMATCH', 'md_qty': found_basis_qty, 'md_unit': found_basis_unit, 'md_src': found_basis_src, 'master_qty': m_qty, 'master_unit': m_unit }) print(f"Total Basis issues identified: {len(basis_audit)}") from collections import Counter print("By issue type:", Counter(b['issue'] for b in basis_audit)) print("By chapter:", Counter(b['chapter'] for b in basis_audit)) print("\n--- Sample Basis Issues (First 15) ---") for b in basis_audit[:15]: print(f"[{b['table_id']} | Line {b['line']}] {b['chapter']} | {b['section']}") print(f" MD: {b['md_qty']} {b['md_unit']} ({b['md_src']}) vs Master: {b['master_qty']} {b['master_unit']} (form: {b['pum_form']})")