97 lines
5.1 KiB
Python
97 lines
5.1 KiB
Python
import os, sys, re
|
|
|
|
sys.stdout.reconfigure(encoding='utf-8')
|
|
|
|
target_files = [
|
|
# 02_토목부문
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제1장_도로포장공사.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제2장_하천공사.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제3장_터널공사.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제4장_궤도공사.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제5장_강구조공사.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제6장_관부설및접합공사.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제7장_항만공사.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제8장_지반조사.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제9장_측량.md',
|
|
# 05_유지관리부문
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제1장_공통.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제2장_토목.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제3장_건축.md',
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제4장_기계설비.md',
|
|
# 04_기계설비부문 제13장
|
|
'resources/knowledge/original/원가계산/건설공사_표준품셈/04_기계설비부문/제13장_플랜트설비공사.md',
|
|
]
|
|
|
|
print("=== Scanning for Page Boundary Duplicate/Overlapped Rows ===")
|
|
|
|
page_markers = [
|
|
r'^\s*→\s*\d+',
|
|
r'^\s*\d+\s*[가-힣]+부문',
|
|
r'^\s*[가-힣]+부문\s*\d+',
|
|
r'^\s*제\d+장\s*[가-힣]+\s*\d+',
|
|
r'^\s*\d+\s*제\d+장',
|
|
r'^\s*→\s*$',
|
|
r'^\s*→[가-힣]+부문\d+',
|
|
]
|
|
page_regex = re.compile('|'.join(page_markers))
|
|
|
|
boundary_cases = []
|
|
|
|
for fpath in target_files:
|
|
fname = os.path.basename(fpath)
|
|
with open(fpath, 'r', encoding='utf-8') as f:
|
|
lines = f.readlines()
|
|
|
|
for idx, line in enumerate(lines):
|
|
line_str = line.strip()
|
|
if page_regex.search(line_str):
|
|
l_no = idx + 1
|
|
# Found page boundary at l_no
|
|
# Look at 30 lines before and 30 lines after
|
|
before_lines = [lines[i].strip() for i in range(max(0, idx-30), idx) if lines[i].strip().startswith('|')]
|
|
after_lines = [lines[i].strip() for i in range(idx+1, min(len(lines), idx+31)) if lines[i].strip().startswith('|')]
|
|
|
|
# Filter out divider lines
|
|
before_data = [l for l in before_lines if not all(re.match(r'^:?-+:?$', c) for c in [x.strip() for x in l.split('|')[1:-1]] if c)]
|
|
after_data = [l for l in after_lines if not all(re.match(r'^:?-+:?$', c) for c in [x.strip() for x in l.split('|')[1:-1]] if c)]
|
|
|
|
if not before_data or not after_data:
|
|
continue
|
|
|
|
# Check for duplicate rows or squashed rows between before and after
|
|
for b_idx, bl in enumerate(before_data):
|
|
b_cells = [c.strip() for c in bl.split('|')[1:-1]]
|
|
b_nums = set(re.findall(r'\b\d+(?:\.\d+)?\b', bl))
|
|
b_words = set(re.findall(r'[가-힣A-Za-z0-9]+', bl))
|
|
|
|
for a_idx, al in enumerate(after_data):
|
|
a_cells = [c.strip() for c in al.split('|')[1:-1]]
|
|
# 1. Exact match
|
|
if b_cells == a_cells and len([c for c in b_cells if c not in ["", "-", "〃"]]) >= 2:
|
|
boundary_cases.append({
|
|
'file': fname,
|
|
'boundary_line': l_no,
|
|
'marker': line_str,
|
|
'type': 'exact_match_across_boundary',
|
|
'before_row': bl[:80],
|
|
'after_row': al[:80]
|
|
})
|
|
# 2. After row contains multiple before rows (squashed overlap)
|
|
a_words = set(re.findall(r'[가-힣A-Za-z0-9]+', al))
|
|
a_nums = set(re.findall(r'\b\d+(?:\.\d+)?\b', al))
|
|
if len(b_nums) >= 2 and b_nums.issubset(a_nums) and len(b_words.intersection(a_words)) >= 2:
|
|
boundary_cases.append({
|
|
'file': fname,
|
|
'boundary_line': l_no,
|
|
'marker': line_str,
|
|
'type': 'squashed_overlap_across_boundary',
|
|
'before_row': bl[:80],
|
|
'after_row': al[:80]
|
|
})
|
|
|
|
print(f"Total boundary cases found: {len(boundary_cases)}")
|
|
for bc in boundary_cases:
|
|
print(f"[{bc['file']}:L{bc['boundary_line']}] {bc['marker']} - {bc['type']}")
|
|
print(f" Before: {bc['before_row']}")
|
|
print(f" After: {bc['after_row']}")
|