fix(data): 숫자로 시작하는 기종 이름을 버리던 잣대 고침 · 8-1-7 손료보정을 제 표에서 읽음 — 기초단가 잣대 16 → 10
**① 기종 이름 — `(8201) 3D GNSS 머신 가이던스(굴착기용)`** 추출기가 **첫 낱자가 숫자면 쪽번호로 보고 버리던** 탓에 8201 이름을 못 찾고 **옛 벌의 뭉개진 글**을 이어받고 있었음(`배관파이프시 간 당(10-7)분류번호규 격7995-0050…`). 낱자가 하나도 없는 토막만 버리게 고침 — 옛 벌에서 이어받은 이름 7 → **0** · 이름 바로잡힌 줄 1(값은 안 움직임). ⚠ `_build_mach.py` 는 랩탑 메인이 지은 것 — 한 줄 잣대만 고쳤음. **② 8-1-7 손료보정 — 원문이 제 표로 고쳐졌음** 전엔 글로 뭉개져 `덤프트럭2510` 처럼 붙어 있어 「25·10 인지 2·510 인지 못 가름」으로 세고 있었음. 이제 `| 덤프트럭 | 25 | 10 |` 이라 **칸에서 바로** 읽음 — 기종 글은 원문이 낱자 사이에 빈칸을 두므로 (`불도저( 1 9 톤이상 제외)`) 빈칸을 지워 맞댐. 네 줄이 한꺼번에 풀림(보정 셋 + 수 자리 가름). **③ 이름 없는 기종을 세는 자리** — 8-3 에 `(코드) 이름` 머리글이 없어 **양쪽이 다 비어 조용히 지나가는** 자리를 세게 함. 지금은 **0** — 8202~8204 도 머리글이 [주] 줄에 섞여 있어 둘 다 읽고 있음. ⇒ 기초단가 어긋남 23 → **17**(잣대 못 알아봄 16 → **10** · 원문 부재 7). 남은 잣대 10 은 다 랩탑 서브 PDF 몫 — 규격 빈칸 일곱(원문이 기종 이름을 여러 줄로 쪼갬) · 양수기 7993-0020 셋(규격이 주연료 칸에 밀림). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsGw1Dz9HmhuAxGisxmDPF
This commit is contained in:
@@ -123,7 +123,10 @@ def names_in(lines: list[str]) -> dict[str, str]:
|
||||
continue
|
||||
for m in _NAME_AT.finditer(line):
|
||||
name = m.group(2).strip(" .·")
|
||||
if name and not name[0].isdigit():
|
||||
# ⚠ 숫자로 시작하는 이름도 있다 — `(8201) 3D GNSS 머신 가이던스(굴착기용)`.
|
||||
# 첫 낱자가 숫자면 버리던 잣대가 그것을 쪽번호로 보고 내버려, 옛 벌의 뭉개진 글을
|
||||
# 이어받고 있었다(2026-09-18). 낱자가 하나도 없는 토막만 버린다.
|
||||
if name and re.search(r"[가-힣A-Za-z]", name):
|
||||
found.setdefault(m.group(1), re.sub(r"\s+", " ", name))
|
||||
return found
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"schema_version": "1.0",
|
||||
"dataset_id": "mach_base",
|
||||
"effective_date": "2026-01-01",
|
||||
"generated_at": "2026-09-18T14:37:18+09:00",
|
||||
"generated_at": "2026-09-18T17:02:43+09:00",
|
||||
"sources": [
|
||||
{
|
||||
"path": "resources/knowledge/original/원가계산/건설공사_표준품셈/01_공통부문/제8장_건설기계.md",
|
||||
@@ -3177,7 +3177,7 @@
|
||||
},
|
||||
{
|
||||
"machine_code": "8201-0100",
|
||||
"machine_name": "",
|
||||
"machine_name": "3D GNSS 머신 가이던스(굴착기용)",
|
||||
"price_thousand_krw": 55000,
|
||||
"specification": "3D GNSS MG"
|
||||
},
|
||||
@@ -11565,7 +11565,7 @@
|
||||
},
|
||||
{
|
||||
"machine_code": "8201-0100",
|
||||
"machine_name": "배관파이프시 간 당(10-7)분류번호규 격7995-0050ø50-2.6m5,0008-3-9 [80]스마트 건설장비(8201) 3D GNSS 머신 가이던스(굴착기용)",
|
||||
"machine_name": "3D GNSS 머신 가이던스(굴착기용)",
|
||||
"specification": "3D GNSS MG",
|
||||
"loss_coefficient_per_hour": 0.00039299999999999996,
|
||||
"depreciation_coefficient_1e_minus_7": 1800,
|
||||
|
||||
@@ -11,16 +11,6 @@
|
||||
],
|
||||
"labor": {},
|
||||
"machine": {
|
||||
"가격 8201-0100 machine_name": {
|
||||
"source": "3D GNSS 머신 가이던스(굴착기용)",
|
||||
"data": "",
|
||||
"why": "자료 이름이 빔 — 원문 손료표 머리 `(코드) 이름` 엔 이름 있음",
|
||||
"class": "㉯ 남이 고쳐야 풀림",
|
||||
"owner": "랩탑 메인",
|
||||
"owner_ask": "기계 원천 벌(mach_base_2026.json) 재추출 — 그 추출기가 이 저장소에 없어 우리가 못 돌림",
|
||||
"갈래": "잣대 못 알아봄",
|
||||
"class_why": "제8장 8-3 (8201) 손료표 머리가 글로 뭉개져 기종 이름이 표 밖 글줄에 섞였음 — PDF 대조로 표 머리를 되살려 줄 것. 되살리면 추출기·시험이 저절로 읽음."
|
||||
},
|
||||
"셈 연료 원문에 없는 자료 줄": {
|
||||
"source": 0,
|
||||
"data": 1,
|
||||
@@ -41,46 +31,6 @@
|
||||
"갈래": "잣대 못 알아봄",
|
||||
"class_why": "위 7993-0020 과 한 자리 — 그 줄이 고쳐지면 셈도 맞음."
|
||||
},
|
||||
"손료 8201-0100 machine_name": {
|
||||
"source": "3D GNSS 머신 가이던스(굴착기용)",
|
||||
"data": "배관파이프시 간 당(10-7)분류번호규 격7995-0050ø50-2.6m5,0008-3-9 [80]스마트 건설장비(8201) 3D GNSS 머신 가이던스(굴착기용)",
|
||||
"why": "자료 이름 칸에 원문 뭉개진 손료 글이 통째로 들어감 — 자료 이름 틀림",
|
||||
"class": "㉯ 남이 고쳐야 풀림",
|
||||
"owner": "랩탑 메인",
|
||||
"owner_ask": "기계 원천 벌(mach_base_2026.json) 재추출 — 그 추출기가 이 저장소에 없어 우리가 못 돌림",
|
||||
"갈래": "잣대 못 알아봄",
|
||||
"class_why": "위와 한 자리 — 뭉개진 글이 자료 이름 칸에 통째로 들어갔음."
|
||||
},
|
||||
"손료보정 bulldozer_under_19_ton": {
|
||||
"source": "불도저(19톤이상제외)",
|
||||
"data": "2510",
|
||||
"why": "원문 8-1-7 가산비율 표가 글로 뭉개져 이름 칸에 수(`2510`)가 들어앉음 — 25·10 인지 2·510 인지 못 가름(같은 자리를 「손료보정 수 자리 가름」으로 이미 적어 둠). md 가 풀리면 저절로 맞음",
|
||||
"class": "㉯ 남이 고쳐야 풀림",
|
||||
"갈래": "잣대 못 알아봄",
|
||||
"class_why": "원문 8-1-7 가산비율 표가 **글로 뭉개져** 기종 이름 칸에 수(`2510`)가 들어앉음 — 25·10 인지 2·510 인지 가를 수 없음. 값은 원문에 있으나 꼴이 뭉개져 못 읽는 자리(같은 뿌리를 「손료보정 수 자리 가름」 으로도 셈).",
|
||||
"owner": "랩탑 메인",
|
||||
"owner_ask": "8-1-7 가산비율 표가 글로 뭉개진 자리 — 기종 이름과 두 수(암석작업·전석섞인토사)를 갈라 줄 것. `손료보정 수 자리 가름` 과 한 자리라 함께 풀림."
|
||||
},
|
||||
"손료보정 crawler_excavator_or_loader": {
|
||||
"source": "굴착기(무한궤도)및로더(무한궤도)",
|
||||
"data": "2010",
|
||||
"why": "원문 8-1-7 가산비율 표가 글로 뭉개져 이름 칸에 수(`2510`)가 들어앉음 — 25·10 인지 2·510 인지 못 가름(같은 자리를 「손료보정 수 자리 가름」으로 이미 적어 둠). md 가 풀리면 저절로 맞음",
|
||||
"class": "㉯ 남이 고쳐야 풀림",
|
||||
"갈래": "잣대 못 알아봄",
|
||||
"class_why": "원문 8-1-7 가산비율 표가 **글로 뭉개져** 기종 이름 칸에 수(`2510`)가 들어앉음 — 25·10 인지 2·510 인지 가를 수 없음. 값은 원문에 있으나 꼴이 뭉개져 못 읽는 자리(같은 뿌리를 「손료보정 수 자리 가름」 으로도 셈).",
|
||||
"owner": "랩탑 메인",
|
||||
"owner_ask": "8-1-7 가산비율 표가 글로 뭉개진 자리 — 기종 이름과 두 수(암석작업·전석섞인토사)를 갈라 줄 것. `손료보정 수 자리 가름` 과 한 자리라 함께 풀림."
|
||||
},
|
||||
"손료보정 dump_truck": {
|
||||
"source": "덤프트럭",
|
||||
"data": "2510",
|
||||
"why": "원문 8-1-7 가산비율 표가 글로 뭉개져 이름 칸에 수(`2510`)가 들어앉음 — 25·10 인지 2·510 인지 못 가름(같은 자리를 「손료보정 수 자리 가름」으로 이미 적어 둠). md 가 풀리면 저절로 맞음",
|
||||
"class": "㉯ 남이 고쳐야 풀림",
|
||||
"갈래": "잣대 못 알아봄",
|
||||
"class_why": "원문 8-1-7 가산비율 표가 **글로 뭉개져** 기종 이름 칸에 수(`2510`)가 들어앉음 — 25·10 인지 2·510 인지 가를 수 없음. 값은 원문에 있으나 꼴이 뭉개져 못 읽는 자리(같은 뿌리를 「손료보정 수 자리 가름」 으로도 셈).",
|
||||
"owner": "랩탑 메인",
|
||||
"owner_ask": "8-1-7 가산비율 표가 글로 뭉개진 자리 — 기종 이름과 두 수(암석작업·전석섞인토사)를 갈라 줄 것. `손료보정 수 자리 가름` 과 한 자리라 함께 풀림."
|
||||
},
|
||||
"연료 7993-0020": {
|
||||
"source": null,
|
||||
"data": {
|
||||
@@ -167,15 +117,6 @@
|
||||
"owner": "랩탑 서브",
|
||||
"owner_ask": "제8장 8-3 (7430)·(7431) 윈치 · (7811)·(7812) 엔진 · (9030) 예선 표 — PDF 에서 「기종」 칸이 한 칸에 어떻게 적혀 있는지 짚어 줄 것(「수동 싱글드럼」 처럼 한 칸인지, 줄마다 다른 이름인지). 그것이 갈리면 자료의 이어받기가 맞는지 곧 판가름남."
|
||||
},
|
||||
"손료보정 수 자리 가름": {
|
||||
"what": "뭉개진 글의 이어 붙은 수(2510)를 통째로 맞댐",
|
||||
"why": "8-1-7 가산비율 표가 글로 뭉개져 `2510` 처럼 붙음 — 25·10 인지 2·510 인지 못 가름",
|
||||
"class": "㉯ 남이 고쳐야 풀림",
|
||||
"owner": "랩탑 메인",
|
||||
"owner_ask": "기계 원천 벌(mach_base_2026.json) 재추출 — 그 추출기가 이 저장소에 없어 우리가 못 돌림",
|
||||
"갈래": "잣대 못 알아봄",
|
||||
"class_why": "8-1-7 가산비율 표가 글로 뭉개져 `2510` 처럼 붙었음 — 25·10 인지 2·510 인지 PDF 로 갈라 줄 것."
|
||||
},
|
||||
"운전사 기종별 판단": {
|
||||
"what": 121,
|
||||
"why": "기종→운전사 구분(explicit_mappings)은 사람 판단 — 원문 8-1-3 5호는 기종 이름 글만 있음",
|
||||
@@ -554,7 +495,7 @@
|
||||
"센 날": "2026-09-18",
|
||||
"셈": {
|
||||
"원문 부재 / ㉰": 7,
|
||||
"잣대 못 알아봄 / ㉯": 16
|
||||
"잣대 못 알아봄 / ㉯": 10
|
||||
},
|
||||
"잣대": "두 갈래로 가름 — **원문 부재**: 값이 원문·원천에 없거나 원문 밖 말이라 채울 것이 없음 · **잣대 못 알아봄**: 값은 원문에 있는데 전사·읽기가 못 가름 ⇒ 고치면 풀림. ㉮ 영영 할 일 아님 · ㉯ 남이 고쳐야 풀림 · ㉰ 사용자·브레인 판단.",
|
||||
"할 일 아님으로 뺀 줄": 34
|
||||
|
||||
@@ -343,7 +343,8 @@ def read_machine(path: Path) -> dict:
|
||||
return out
|
||||
|
||||
|
||||
#: 손료보정 표는 글로 뭉개짐 — 기종 글 바로 뒤에 `암석작업` `전석섞인토사` 두 수가 붙어 있음(`덤프트럭2510`).
|
||||
#: 8-1-7 손료보정 표의 기종 글 — 원문이 낱자 사이에 빈칸을 두므로(`불도저( 1 9 톤이상 제외)`) **빈칸을 지워** 맞댄다.
|
||||
#: 2026-09-18 md 가 제 표로 고쳐져 두 수(암석작업·전석섞인토사)를 **칸에서 바로** 읽는다(전엔 `덤프트럭2510` 처럼 글로 뭉개져 있었다).
|
||||
ROCK = {"bulldozer_under_19_ton": "불도저(19톤이상제외)", "crawler_excavator_or_loader": "굴착기(무한궤도)및로더(무한궤도)", "dump_truck": "덤프트럭"} # fmt: skip
|
||||
|
||||
|
||||
@@ -379,6 +380,11 @@ def check_machine(src: dict, bad: dict, blind: dict) -> dict:
|
||||
counts[f"{label} 코드 수"] = (len(rows), len(by_code))
|
||||
counts[f"{label} 원문에 없는 자료 줄"] = (0, len(set(by_code) - set(rows) - unread))
|
||||
_unchecked(blind, var, records, {"machine_code", "machine_name", *fields})
|
||||
# 원문 8-3 에 `(코드) 이름` 머리글이 아예 없어 **이름이 빈** 기종 — 양쪽이 다 비어 조용히 지나간다.
|
||||
# 표는 있는데 이름만 없는 자리라 세어 둔다(md 에 머리글이 붙으면 저절로 빠짐).
|
||||
for code, rec in sorted({r["machine_code"]: r for r in v["mach_loss_coef"]["records"]}.items()):
|
||||
if not rec.get("machine_name") and source["names"].get(code[:4]) is None:
|
||||
blind[f"기종 이름 없는 머리글 {code[:4]}"] = {"what": code}
|
||||
# 원문이 규격 칸을 비워 둔 자리에 **자료가 앞 줄 값을 이어받아 채운** 줄 — 원문에 없는 글이라 사람이 볼 자리.
|
||||
loss_by_code = {r["machine_code"]: r for r in v["mach_loss_coef"]["records"]}
|
||||
for code in sorted(source.get("spec_blank", ())):
|
||||
@@ -412,15 +418,24 @@ def check_machine(src: dict, bad: dict, blind: dict) -> dict:
|
||||
)
|
||||
|
||||
text = _t("".join(source["lines"]))
|
||||
rock_rows = {} # 기종 글(빈칸 지움) → (암석작업, 전석섞인토사)
|
||||
for t in md_tables(source["lines"]):
|
||||
if [_t(h) for h in t["headers"]][:2] != ["기종", "가산비율"]:
|
||||
continue
|
||||
for r in t["rows"]:
|
||||
try:
|
||||
rock_rows[_t(r[0])] = (_num(r[1]), _num(r[2]))
|
||||
except ValueError: # 머리 곁줄(`암석작업(연암…)` · `전석섞인토사`)
|
||||
continue
|
||||
for rule in v["mach_rock_adj"]["rules"]:
|
||||
group, pair = rule["machine_group"], f"{rule['rock_work']}{rule['boulder_mixed_soil']}"
|
||||
group = rule["machine_group"]
|
||||
pair = (rule["rock_work"], rule["boulder_mixed_soil"])
|
||||
if group in ROCK:
|
||||
ok = f"{ROCK[group]}{pair}" in text
|
||||
else:
|
||||
ok = pair == "00" and "불도저(19톤이상)의경우는보정하지않는다" in text
|
||||
if not ok:
|
||||
bad[f"손료보정 {group}"] = {"source": ROCK.get(group), "data": pair}
|
||||
blind["손료보정 수 자리 가름"] = {"what": "뭉개진 글의 이어 붙은 수(2510)를 통째로 맞댐"}
|
||||
got = rock_rows.get(ROCK[group])
|
||||
else: # 「불도저(19톤이상)은 보정하지 않는다」 — 표에 줄이 없고 [주]①이 0 을 말한다
|
||||
got = (0, 0) if "불도저(19톤이상)의경우는보정하지않는다" in text else None
|
||||
if got != pair:
|
||||
bad[f"손료보정 {group}"] = {"source": got, "data": list(pair)}
|
||||
_unchecked(blind, "mach_rock_adj.rules", v["mach_rock_adj"]["rules"], {"machine_group", "rock_work", "boulder_mixed_soil"}) # fmt: skip
|
||||
return counts
|
||||
|
||||
|
||||
Reference in New Issue
Block a user