120 lines
5.7 KiB
Python
120 lines
5.7 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',
|
|
]
|
|
|
|
# Common worker / equipment names that do NOT represent condition categories
|
|
WORKER_EQUIP_KEYWORDS = {
|
|
'특별인부', '보통인부', '인부', '조력공', '포장공', '철근공', '형틀목공', '목공', '비계공', '석공',
|
|
'용접공', '배관공', '덕트공', '도장공', '미장공', '방수공', '잠수부', '보링공', '갱부', '착암공',
|
|
'궤도공', '전공', '통신공', '플랜트배관공', '기계설치공', '제관공', '용접기', '크레인', '트럭',
|
|
'굴착기', '로더', '덤프트럭', '진동롤러', '머캐덤롤러', '탠덤롤러', '타이어롤러', '살수차', '지게차',
|
|
'발전기', '공기압축기', '모터그레이더', '불도저', '아스팔트피니셔', '콘크리트페이버', '플레이트콤팩터',
|
|
'중급기술자', '초급기술자', '고급기술자', '특급기술자', '측량보조', '측량기사', '일반기계운전사'
|
|
}
|
|
|
|
def is_worker_or_equip(text):
|
|
clean = re.sub(r'[\s\(\)\d\+]+', '', text)
|
|
return any(w in clean for w in WORKER_EQUIP_KEYWORDS)
|
|
|
|
true_grouped_tables = []
|
|
|
|
for fpath in target_files:
|
|
fname = os.path.basename(fpath)
|
|
with open(fpath, 'r', encoding='utf-8') as f:
|
|
lines = f.readlines()
|
|
|
|
tables = []
|
|
cur_t = []
|
|
cur_start = 0
|
|
cur_title = ""
|
|
|
|
for idx, l in enumerate(lines):
|
|
line_str = l.strip()
|
|
if not line_str.startswith('|'):
|
|
if line_str and not line_str.startswith('>'):
|
|
cur_title = line_str
|
|
if cur_t:
|
|
tables.append((cur_start, cur_title, cur_t))
|
|
cur_t = []
|
|
else:
|
|
if not cur_t:
|
|
cur_start = idx + 1
|
|
cur_t.append((idx + 1, line_str))
|
|
if cur_t:
|
|
tables.append((cur_start, cur_title, cur_t))
|
|
|
|
for t_start, t_title, t_rows in tables:
|
|
data_rows = []
|
|
for lno, r_str in t_rows:
|
|
cells = [c.strip() for c in r_str.split('|')[1:-1]]
|
|
if all(re.match(r'^:?-+:?$', c) for c in cells if c):
|
|
continue
|
|
if cells and cells[0] in ["비고", "비 고", "주", "[주]"]:
|
|
continue
|
|
data_rows.append((lno, r_str, cells))
|
|
|
|
if len(data_rows) < 3:
|
|
continue
|
|
|
|
# Check classification number in rows
|
|
has_item_no = False
|
|
for lno, r_str, cells in data_rows[1:]:
|
|
c0 = cells[0] if cells else ""
|
|
if re.match(r'^\d+-\d+(?:-\d+)?', c0) or re.match(r'^[A-Z]\d{4}', c0):
|
|
has_item_no = True
|
|
break
|
|
if has_item_no:
|
|
continue
|
|
|
|
# Analyze first column (and second column) to see if there are multi-row condition groupings
|
|
groups = {}
|
|
cur_group = None
|
|
for lno, r_str, cells in data_rows[1:]:
|
|
c0 = cells[0] if cells else ""
|
|
if c0 and not is_worker_or_equip(c0):
|
|
cur_group = c0
|
|
if cur_group:
|
|
groups.setdefault(cur_group, []).append((lno, r_str))
|
|
|
|
# If there are 2 or more true non-worker groups, this is a grouped table!
|
|
if len(groups) >= 2 and any(len(rows) >= 1 for rows in groups.values()):
|
|
true_grouped_tables.append({
|
|
'file': fname,
|
|
'line': t_start,
|
|
'title': t_title[:60],
|
|
'groups': list(groups.keys()),
|
|
'group_details': {k: len(v) for k, v in groups.items()},
|
|
'total_rows': len(data_rows)
|
|
})
|
|
|
|
print(f"=== Truly Grouped / Condition Branch Tables: {len(true_grouped_tables)} found ===")
|
|
by_f = {}
|
|
for tgt in true_grouped_tables:
|
|
by_f.setdefault(tgt['file'], []).append(tgt)
|
|
|
|
for f, tbls in sorted(by_f.items()):
|
|
print(f"\n[{f}] ({len(tbls)}개)")
|
|
for t in tbls:
|
|
g_str = ", ".join([f"{k}({v}행)" for k, v in t['group_details'].items()][:4])
|
|
print(f" L{t['line']:<5} | {t['title'][:35]:<35} | {g_str}")
|