"""기계 손료계수 · 시간당 경비 미리보기(PLAN 821-2 · 요구서 796 1 장). ⚠ 짝: `common_util/common_util_machine_coef.ts` — 같은 셈 · 같은 차례(거울 시험 `resources/tester/test_821_2_machine_coef.py`). 한쪽만 고치면 화면과 저장이 갈림. 계수(건설품셈 공통 8-1-5 · 시간당 10^-7): 상각비계수 = 상각비율 ÷ 내용시간 · 정비비계수 = 정비비율 ÷ 내용시간 · 관리비계수 = 연간관리비율 × 평균취득가격 비율 ÷ 연간표준가동시간 · 평균취득가격 비율 = (1.1 N + 0.9) ÷ 2N · N = 내용시간 ÷ 연간표준가동시간 · 계수마다 정수로 반올림 · 손료계수 = 셋의 합. 미리보기 = 서버 기계경비식(GC000267 ~)을 기본 옵션(보정 없음)으로 부른 값과 같은 끝수 — 손료 = 가격(천원) × 1000 × 손료계수 ÷ 10^7 원 미만 버림 · 줄 금액은 0.1 원 아래 버림 · 잡품 = 버린 주연료 금액 × 잡재료율 % · 비목 합은 원 미만 버림(B09 끝수 `master_cut.engine`). 정본은 서버 식(`M02_Machine_Hourly`) — 이것은 화면 즉시 셈용. """ from __future__ import annotations import math INPUTS = ("내용시간", "연간표준가동시간", "상각비율", "정비비율", "연간관리비율") COEFS = ("상각비계수", "정비비계수", "관리비계수", "손료계수") _E = 1e-6 # 끊는 경계 부동소수 흔들림 막음 def _num(v) -> float: return float(v) if isinstance(v, (int, float)) and not isinstance(v, bool) else 0.0 def _half_up(x: float) -> int: return math.floor(x + 0.5 + _E) def _tenth(x: float) -> float: """줄 금액 = 0.1 원 아래 버림(B09 끝수 줄 자리).""" return math.floor(x * 10 + _E) / 10 def coef(life, yearly, dep, rep, mgmt) -> dict | None: """(내용시간 · 연간표준가동시간 · 상각 · 정비 · 연간관리 비율) → 계수 넷 · 못 셈 = None.""" life, yearly, dep, rep, mgmt = (_num(x) for x in (life, yearly, dep, rep, mgmt)) if life <= 0 or yearly <= 0: return None n = life / yearly s = _half_up(dep / life * 1e7) j = _half_up(rep / life * 1e7) g = _half_up(mgmt * (1.1 * n + 0.9) / (2 * n) / yearly * 1e7) return {"상각비계수": s, "정비비계수": j, "관리비계수": g, "손료계수": s + j + g} def coef_of(values: dict) -> dict | None: """값 묶음(기계 줄 `값`)에서 품셈 입력 다섯이 다 수일 때만 계수 넷.""" if not all(isinstance(values.get(k), (int, float)) for k in INPUTS): return None return coef(*(values[k] for k in INPUTS)) def preview( values: dict, fuel: float, wage: float, power: float = 0.0, hour: float = 1 / 8 ) -> dict: """값 묶음 + 유가(원/ℓ) · 노임(원/일) · 전력(원/kWh) · 시간환산 → 시간당 줄 · 비목 · 계.""" loss = math.floor(_num(values.get("가격")) * 1000 * _num(values.get("손료계수")) / 1e7 + _E) oil = _tenth(_num(values.get("주연료")) * _num(fuel)) misc = _tenth(oil * _num(values.get("잡재료율")) / 100) elec = _tenth(_num(values.get("전력")) * _num(power)) crew = _tenth(_num(values.get("조종원")) * hour * _num(wage)) labor, material = math.floor(crew + _E), math.floor(oil + misc + elec + _E) return { "손료": loss, "주연료": oil, "잡품": misc, "전력": elec, "조종원": crew, "노무비": labor, "재료비": material, "경비": loss, "계": labor + material + loss, }