"""B09 원가계산 — **치즐 소모량**(대형브레이커 깨기 · PLAN 1장 Ⓐ-3 · 2026-09-14 브레인 판정). 품셈 표가 브레이커 줄 옆에 「치즐소모량(본/hr)」을 줌 — 제8장 [주]⑤ 「브레이커 … 손료 및 치즐 소모율을 **추가**」. 실무 원본(영월·봉화·울진) 단가산출근거 「(2) 치즐 손료 · M=0.006 × 223,000 / Q = 382.2 W/㎥」 — 재료비(재료비 집계표 M00118 치즐(대형 브레이카) 본). 수량 치즐(본/hr) ÷ Q × 장비 배분율 — 브레이커 줄과 같은 D(단가산출)에 나란히(Q 를 함께 실음) 단가 자원 목록 `AR-M` 치즐 — **수동 단가가 들어와야** 제목이 섬(임의 단가 없음) · 안 들어오면 종전대로 「못 붙은 줄」 ⚠ 기계 층(`X-0230` 대형브레이커)은 부착 장비라 손료만 — 치즐은 그 안에 없어 이중계상 아님(시험). """ from __future__ import annotations from decimal import Decimal from typing import Any #: 자원 목록 치즐(대형브레이커용 · 본) — `resource_catalog_ext` 에 올린 코드. CHISEL_CODE = "AR-M-a2926452" #: 치즐을 붙이는 기계 — 대형브레이커(분류 0230). BREAKER_PREFIX = "0230-" CHISEL_MISSING = "치즐소모량(본/hr) — 치즐 단가 없음(「자재 단가」 탭에서 넣으면 붙음)" #: ⚠ 선례를 함께 적음(2026-09-14 브레인 판정) — 사용자가 「같은 방식으로 유추할지」를 스스로 고르게. CHISEL_AVERAGE_NOT_GIVEN = ( "치즐(평균 갈래) — 원문 9-4-1 [주]① 은 Q 평균만 정하고 치즐 평균은 안 줌(지어내지 않음)" " · 참고 선례: 9-12-3 발파암 표는 같은 자리에서 치즐 평균" " 「(0.006+0.02+0.03)/3 = 0.018」 을 스스로 적음 — 같은 방식으로 볼지는 판정 대기" ) def chisel_per_hour(node: dict[str, Any]) -> Decimal | None: """표의 「치즐소모(량)(본/hr)」 줄 값 — 그 이름 칸 뒤 첫 수. 없으면 `None`.""" from B09_Estimation.B09_Estimation_MachineProductivity import parse_measure for table in node.get("tables", []): for row in table.get("raw_row") or []: cells = ["".join(str(cell).split()) for cell in row] for index, cell in enumerate(cells): if not cell.startswith("치즐소모"): continue value = next( (parse_measure(t) for t in cells[index + 1 :] if parse_measure(t)), None ) if value: return value return None def attach_chisel( book: Any, title_code: str, per_hour: Decimal | None, capacity: Decimal, share: Decimal = Decimal(1), ) -> bool: """치즐 줄을 그 제목의 D 에 붙임 — 치즐 제목(수동 단가)이 없거나 소모량이 없으면 `False`.""" if not per_hour or CHISEL_CODE not in book.titles: return False book.add_output_detail( title_code, CHISEL_CODE, per_hour / capacity * share, note=( f"치즐 {per_hour} 본/hr ÷ Q {capacity}" + (f" × 배분 {share}" if share != 1 else "") + " — 품셈 제8장 [주]⑤ 치즐 소모율 추가" ), output=capacity, ) return True def without_chisel_labels(labels: list[str]) -> list[str]: """치즐이 붙은 뒤 「못 붙은 줄」 에서 치즐 글을 걷음.""" return [label for label in labels if "치즐" not in label]