diff --git a/B09_Estimation/B09_Estimation_ResourceAxis.py b/B09_Estimation/B09_Estimation_ResourceAxis.py index 9f67f8d1..bbc20b28 100644 --- a/B09_Estimation/B09_Estimation_ResourceAxis.py +++ b/B09_Estimation/B09_Estimation_ResourceAxis.py @@ -437,6 +437,26 @@ class AxisResult: partial_items: dict[str, str] = field(default_factory=dict) +def _tidy_resource_name(cell: str) -> str: + """이름 표기를 카탈로그 쪽으로 맞춘다 — **뜻을 바꾸지 않는 표기 차이만.** + + ① 이름 안 공백 제거 (「굴 삭 기 (무한궤도)」 → 「굴삭기(무한궤도)」) + ② 같은 기종의 다른 이름 (「굴삭기」·「유압식백호우」 → 「굴착기」) + + ⚠ 규격은 안 건드린다 — 규격을 맞추려 들면 엉뚱한 기종이 붙는다. + """ + from B09_Estimation.B09_Estimation_MachineProductivity import MACHINE_NAME_ALIASES + + text = str(cell) + head, sep, tail = text.partition("(") + tight = "".join(head.split()) + for wrong, right in MACHINE_NAME_ALIASES.items(): + if tight == wrong: + tight = right + break + return tight + sep + tail + + def _resolve_cell(catalog: ResourceCatalog, name_cell: str, cells: list[str]): """셀 하나를 카탈로그 한 줄로 푼다 — 세 가지 모양을 차례로 시도한다. @@ -444,6 +464,10 @@ def _resolve_cell(catalog: ResourceCatalog, name_cell: str, cells: list[str]): ② 기종 셀 (「굴착기(무한궤도, 0.7㎥)」 → 이름 + 규격) ③ 규격이 **옆 칸**에 있는 표 (「굴착기 (무한궤도)」 | 「0.7㎥」) """ + # ⚠ **이름 안 공백·표기 차이를 먼저 없앤다.** 품셈은 같은 기종을 「굴 삭 기」· + # 「굴착기」·「유압식백호우」로 섞어 적는다(2026-09-08: 메쌓기 13-6-1 의 + # 「굴 삭 기 (무한궤도)」가 안 붙어 그 공종 장비 몫이 통째로 빠졌다). + name_cell = _tidy_resource_name(name_cell) machine_name, machine_spec = parse_machine_cell(name_cell) plain_name, plain_spec = split_name_and_spec(name_cell) @@ -524,6 +548,13 @@ def match_table( name_cell = cells[1] value_cells = cells[2:] + # ⚠ **공식 계수를 단 줄은 자원 줄이 아니다.** 「유압식백호우 … | k | 0.9」 처럼 + # 같은 줄에 버킷계수가 붙어 오는데, 그 0.9 를 소요량으로 읽으면 **시간당 사용료가 + # 0.9시간분** 붙어 이중이 된다(2026-09-08: 이름 표기를 맞추자 측구터파기에 + # 「굴착기 0.81」 줄이 새로 생겨 발견). 그 줄은 시공능력 공식 쪽에서 쓴다. + if any(_normalize(c).lower() in ("k", "f", "e") for c in value_cells): + continue + # 숫자 셀이 없는 행은 자원 줄이 아니다(제목·설명 행) — 목록에 안 올린다. amount_cell = next( (parse_amount(c) for c in value_cells if parse_amount(c) is not None), None diff --git a/resources/data_cost_resource_axis/resource_axis_2026-01-01.json b/resources/data_cost_resource_axis/resource_axis_2026-01-01.json index 41542a88..0da9168e 100644 --- a/resources/data_cost_resource_axis/resource_axis_2026-01-01.json +++ b/resources/data_cost_resource_axis/resource_axis_2026-01-01.json @@ -1561,6 +1561,20 @@ "variant": "", "work_item_code": "FP-09-19-02" }, + { + "amount": "0.045", + "amount_unit": "㎡", + "group_ratio_pct": null, + "pum_form": "requirement", + "pum_table_id": "F0290", + "raw_row_index": 1, + "resource_code": "0201-0070", + "resource_kind": "machine", + "resource_name": "굴착기(무한궤도)", + "resource_spec": "0.7", + "variant": "", + "work_item_code": "FP-09-19-02" + }, { "amount": "0.0328", "amount_unit": "㎡", @@ -3045,6 +3059,20 @@ "variant": "", "work_item_code": "FP-13-06-01" }, + { + "amount": "0.384", + "amount_unit": "㎡", + "group_ratio_pct": null, + "pum_form": "requirement", + "pum_table_id": "F0419", + "raw_row_index": 4, + "resource_code": "0201-0080", + "resource_kind": "machine", + "resource_name": "굴착기(무한궤도)", + "resource_spec": "0.8", + "variant": "", + "work_item_code": "FP-13-06-01" + }, { "amount": "0.083", "amount_unit": "㎡", @@ -3199,6 +3227,20 @@ "variant": "", "work_item_code": "FP-13-07-02" }, + { + "amount": "0.336", + "amount_unit": "㎡", + "group_ratio_pct": null, + "pum_form": "requirement", + "pum_table_id": "F0423", + "raw_row_index": 4, + "resource_code": "0201-0080", + "resource_kind": "machine", + "resource_name": "굴착기(무한궤도)", + "resource_spec": "0.8", + "variant": "", + "work_item_code": "FP-13-07-02" + }, { "amount": "0.009", "amount_unit": "개", @@ -3604,12 +3646,12 @@ "sha256": "fe454c56c9dc01ad7dae04a8f90d776d08c5ce33badeadb2606b35234bfce7eb" }, "stats": { - "rows": 256, + "rows": 259, "skipped_forms": { "coefficient": 19, "reference": 92, "undetermined": 75 }, - "unmatched": 316 + "unmatched": 311 } } \ No newline at end of file diff --git a/resources/data_cost_resource_axis/unmatched_2026-01-01.json b/resources/data_cost_resource_axis/unmatched_2026-01-01.json index 06e7a35f..3ca2ddb2 100644 --- a/resources/data_cost_resource_axis/unmatched_2026-01-01.json +++ b/resources/data_cost_resource_axis/unmatched_2026-01-01.json @@ -1022,12 +1022,6 @@ "reason": "규격이 없어 같은 이름 여럿 중 고를 수 없음", "work_item_code": "FP-09-10-02" }, - { - "cell": "유압식백호우 (무한궤도,0.7㎥)", - "pum_table_id": "F0258", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-12-01" - }, { "cell": "대형브레이커(㎥/hr)", "pum_table_id": "F0259", @@ -1040,12 +1034,6 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-12-02" }, - { - "cell": "유압식백호우 (무한궤도,0.7㎥)", - "pum_table_id": "F0259", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-12-02" - }, { "cell": "대형브레이커(㎥/hr)", "pum_table_id": "F0260", @@ -1059,22 +1047,28 @@ "work_item_code": "FP-09-12-03" }, { - "cell": "유압식백호우 (무한궤도,0.7㎥)", - "pum_table_id": "F0260", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-12-03" + "cell": "장비 (90%) | 유압식백호우 (무한궤도,0.7㎥) | 육상토사(0~1m)와 동일", + "pum_table_id": "F0262", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-02" }, { - "cell": "유압식백호우 (무한궤도,0.7㎥)", - "pum_table_id": "F0261", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-13-01" + "cell": "장비 (90%) | 유압식백호우 (무한궤도,0.7㎥) | 육상토사(0~1m)와 동일", + "pum_table_id": "F0263", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-03" }, { - "cell": "유압식백호우 (무한궤도,0.7㎥)", - "pum_table_id": "F0264", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-13-04" + "cell": "장비 (90%) | 유압식백호우 (무한궤도,0.7㎥) | 용수토사(0~1m)와 동일", + "pum_table_id": "F0265", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-05" + }, + { + "cell": "장비 (90%) | 유압식백호우 (무한궤도,0.7㎥) | 용수토사(0~1m)와 동일", + "pum_table_id": "F0266", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-06" }, { "cell": "깨기", @@ -1088,12 +1082,6 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-07" }, - { - "cell": "들어 내기", - "pum_table_id": "F0267", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-13-07" - }, { "cell": "깨기", "pum_table_id": "F0268", @@ -1106,6 +1094,12 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-08" }, + { + "cell": "들어내기 | 유압식백호우 (무한궤도,0.7㎥) | 육상 암절취(0~1m)와 동일", + "pum_table_id": "F0268", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-08" + }, { "cell": "깨기", "pum_table_id": "F0269", @@ -1118,6 +1112,12 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-09" }, + { + "cell": "들어 내기 | 유압식백호우 (무한궤도,0.7㎥) | 육상 암절취(0~1m)와 동일", + "pum_table_id": "F0269", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-09" + }, { "cell": "깨기", "pum_table_id": "F0270", @@ -1130,12 +1130,6 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-10" }, - { - "cell": "들어 내기", - "pum_table_id": "F0270", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-13-10" - }, { "cell": "깨기", "pum_table_id": "F0271", @@ -1148,6 +1142,12 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-11" }, + { + "cell": "들어 내기 | 유압식백호우 (무한궤도,0.7㎥) | 용수 암절취(0~1m)와 동일", + "pum_table_id": "F0271", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-11" + }, { "cell": "깨기", "pum_table_id": "F0272", @@ -1160,6 +1160,12 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-12" }, + { + "cell": "들어 내기 | 유압식백호우 (무한궤도,0.7㎥) | 용수 암절취(0~1m)와 동일", + "pum_table_id": "F0272", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-12" + }, { "cell": "깨기", "pum_table_id": "F0273", @@ -1172,12 +1178,6 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-13" }, - { - "cell": "들어 내기", - "pum_table_id": "F0273", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-13-13" - }, { "cell": "깨기", "pum_table_id": "F0274", @@ -1190,6 +1190,12 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-14" }, + { + "cell": "들어 내기 | 유압식백호우 (무한궤도,0.7㎥) | 육상 발파암(1~2m)와 동일", + "pum_table_id": "F0274", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-14" + }, { "cell": "깨기", "pum_table_id": "F0275", @@ -1202,6 +1208,12 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-15" }, + { + "cell": "들어 내기 | 유압식백호우 (무한궤도,0.7㎥) | 육상 발파암(1~2m)와 동일", + "pum_table_id": "F0275", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-15" + }, { "cell": "깨기", "pum_table_id": "F0276", @@ -1214,12 +1226,6 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-16" }, - { - "cell": "들어 내기", - "pum_table_id": "F0276", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-13-16" - }, { "cell": "깨기", "pum_table_id": "F0277", @@ -1232,6 +1238,12 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-13-17" }, + { + "cell": "들어 내기 | 유압식백호우 (무한궤도,0.7㎥) | 용수 발파암(0~1m)와 동일", + "pum_table_id": "F0277", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-17" + }, { "cell": "깨기", "pum_table_id": "F0278", @@ -1245,10 +1257,10 @@ "work_item_code": "FP-09-13-18" }, { - "cell": "유압식백호우 (무한궤도,0.7㎥)", - "pum_table_id": "F0279", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-14-01" + "cell": "들어 내기 | 유압식백호우 (무한궤도,0.7㎥) | 용수 발파암(0~1m)와 동일", + "pum_table_id": "F0278", + "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", + "work_item_code": "FP-09-13-18" }, { "cell": "모래ㆍ사질토ㆍ점토ㆍ점질토", @@ -1286,12 +1298,6 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-09-19-01" }, - { - "cell": "유압식백호우 (무한궤도,0.7㎥)", - "pum_table_id": "F0290", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-09-19-02" - }, { "cell": "공기압축기(3.5㎥/min)", "pum_table_id": "F0291", @@ -1580,30 +1586,12 @@ "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-12-23" }, - { - "cell": "부설", - "pum_table_id": "F0372", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-12-24-02" - }, - { - "cell": "적사", - "pum_table_id": "F0373", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-12-25" - }, { "cell": "운반 및 설치 (목도운반)", "pum_table_id": "F0374", "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", "work_item_code": "FP-12-26" }, - { - "cell": "부설", - "pum_table_id": "F0371", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-12-24-01" - }, { "cell": "접착제", "pum_table_id": "F0376", @@ -1694,12 +1682,6 @@ "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", "work_item_code": "FP-13-06-01" }, - { - "cell": "굴 삭 기 (무한궤도)", - "pum_table_id": "F0419", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-13-06-01" - }, { "cell": "보통인부 | | 〃", "pum_table_id": "F0420", @@ -1724,12 +1706,6 @@ "reason": "자원은 알아봤으나 값을 못 읽었습니다 — 단가가 일부만 섭니다.", "work_item_code": "FP-13-07-02" }, - { - "cell": "굴 삭 기 (무한궤도)", - "pum_table_id": "F0423", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-13-07-02" - }, { "cell": "보통 인부 (인) | 0.9m 1.2m 1.5m 1.8m 2.1m 2.4m 2.7m 3.0m 3.5m 4.0m 4.5m | 0.022 0.034 0.05 0.07 - - - - - - -", "pum_table_id": "F0427", @@ -1880,12 +1856,6 @@ "reason": "같은 갈래 이름이 두 번 나오는 표 — 등급을 단정할 수 없어 버렸습니다.", "work_item_code": "FP-13-13-01" }, - { - "cell": "굴착기 (0.2㎥)", - "pum_table_id": "F0441", - "reason": "카탈로그에 없는 이름 (기계·자재 카탈로그 미확보 포함)", - "work_item_code": "FP-13-13-02" - }, { "cell": "어려운 조건", "pum_table_id": "F0447",