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

141 lines
6.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import sys, os, json, re
import fitz # PyMuPDF
sys.stdout.reconfigure(encoding='utf-8')
pdf_path = "resources/knowledge/original/원가계산/건설공사_표준품셈/2026년_건설공사_표준품셈.pdf"
doc = fitz.open(pdf_path)
# MD file mapping for chapters
md_map = {
"공통_제1장": "resources/knowledge/original/원가계산/건설공사_표준품셈/01_공통부문/제1장_적용기준.md",
"공통_제3장": "resources/knowledge/original/원가계산/건설공사_표준품셈/01_공통부문/제3장_토공사.md",
"공통_제4장": "resources/knowledge/original/원가계산/건설공사_표준품셈/01_공통부문/제4장_조경공사.md",
"공통_제6장": "resources/knowledge/original/원가계산/건설공사_표준품셈/01_공통부문/제6장_철근콘크리트공사.md",
"토목_제1장": "resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제1장_도로포장공사.md",
"토목_제6장": "resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제6장_관부설및접합공사.md",
"건축_제9장": "resources/knowledge/original/원가계산/건설공사_표준품셈/03_건축부문/제9장_미장공사.md",
"유지관리_제1장": "resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제1장_공통.md",
"유지관리_제3장": "resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제3장_건축.md",
}
# Read MD contents into memory
md_contents = {}
for k, p in md_map.items():
if os.path.exists(p):
with open(p, 'r', encoding='utf-8') as f:
md_contents[k] = f.read()
else:
print(f"MD missing: {p}")
with open('scratch/located_const_sections.json', 'r', encoding='utf-8') as f:
located_items = json.load(f)
print(f"Loaded located items: {len(located_items)}")
results = []
for item in located_items:
k = item['key']
num = item['number']
name = item['name']
pn = item['path_name']
pdf_pages = item.get('pdf_pages', [])
# Exclude chapter 8 (already audited by codex)
if "공통부문 건설기계" in pn:
continue
print(f"\n==================================================")
print(f"Auditing: {k} | {num} {name} | {pn}")
print(f"PDF Pages: {pdf_pages}")
# Determine MD chapter
md_key = None
if "공통부문 적용기준" in pn:
md_key = "공통_제1장"
elif "공통부문 토공사" in pn:
md_key = "공통_제3장"
elif "공통부문 조경공사" in pn:
md_key = "공통_제4장"
elif "공통부문 › 철근콘크리트공사" in pn:
md_key = "공통_제6장"
elif "토목부문 › 도로포장공사" in pn:
md_key = "토목_제1장"
elif "토목부문 관부설" in pn:
md_key = "토목_제6장"
elif "건축부문 미장공사" in pn:
md_key = "건축_제9장"
elif "유지관리부문 공 통" in pn:
md_key = "유지관리_제1장"
elif "유지관리부문 건 축" in pn:
md_key = "유지관리_제3장"
md_text = md_contents.get(md_key, "")
# Extract MD section chunk
# Usually in MD, sections start with "### 1-2-2" or "## 1-2-2" or "1-2-2."
escaped_num = re.escape(num)
sec_pattern = re.compile(rf"(^|\n)(#+\s+{escaped_num}[\.\s].*?)(?=\n#+\s+\d+-\d+-\d+[\.\s]|\Z)", re.DOTALL)
m = sec_pattern.search(md_text)
if not m:
# try without leading hash
sec_pattern2 = re.compile(rf"(^|\n)({escaped_num}[\.\s].*?)(?=\n\d+-\d+-\d+[\.\s]|\Z)", re.DOTALL)
m = sec_pattern2.search(md_text)
md_sec_text = m.group(2) if m else ""
if not md_sec_text:
print(f"⚠ Warning: Could not isolate section in MD: {num}")
else:
print(f"MD Section found (len={len(md_sec_text)} chars)")
# Extract PDF page text
pdf_text = ""
# Use the relevant page (typically the 2nd match if first was toc/index, or the page > 50)
actual_pages = [p for p in pdf_pages if p > 50]
for p in actual_pages:
pdf_text += f"\n--- PDF Page {p} ---\n" + doc[p - 1].get_text()
# Check 8 branches
audit = {
"work_item_key": k,
"section_number": num,
"section_name": name,
"path_name": pn,
"md_file": md_map.get(md_key),
"pdf_pages": actual_pages,
"branch1_basis_unit": {"status": "ok", "notes": []},
"branch2_multilevel_header": {"status": "ok", "notes": []},
"branch3_notes_boundary": {"status": "ok", "notes": []},
"branch4_page_break_row_merge": {"status": "ok", "notes": []},
"branch5_cell_values": {"status": "ok", "notes": []},
"branch6_missing_sections": {"status": "ok", "notes": []},
"branch7_notes_formula_boundary": {"status": "ok", "notes": []},
"branch8_hidden_materials_ref": {"status": "ok", "notes": []}
}
# 1. Check if section exists in MD
if not md_sec_text:
audit["branch6_missing_sections"]["status"] = "missing_in_md"
audit["branch6_missing_sections"]["notes"].append(f"Section {num} not found in MD {md_key}")
else:
# Check notes [주]
pdf_notes = re.findall(r"\[주\]|\[\s*주\s*\]|[①-⑩]", pdf_text)
md_notes = re.findall(r"\[주\]|\[\s*주\s*\]|[①-⑩]", md_sec_text)
if len(pdf_notes) > 0 and len(md_notes) == 0:
audit["branch3_notes_boundary"]["status"] = "suspicious_notes_missing"
audit["branch3_notes_boundary"]["notes"].append(f"PDF has {len(pdf_notes)} note markers, MD has 0")
# Check units in PDF vs MD
units_in_pdf = re.findall(r"\((?:단위\s*:\s*)?([^\)]+당|[^\)]+)\)", pdf_text)
# Check table presence
if "|" in pdf_text and "|" not in md_sec_text:
audit["branch4_page_break_row_merge"]["status"] = "table_flattened_to_text"
audit["branch4_page_break_row_merge"]["notes"].append("Table in PDF not rendered as markdown table")
results.append(audit)
with open('scratch/audit_const_linked_results.json', 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"\nAudit completed for {len(results)} linked non-machine sections.")