Files
Aislo/resources/tester/scratch/audit_basis.py
T

124 lines
4.5 KiB
Python

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']})")