Files
Aislo/B08_Quantity/B08_Quantity_Haul_Cycle.py
T
eomsangdonandClaude Opus 5.5 01bca00e3c feat(b08): 운반 사이클시간 짝 · 로직 입력 거리 채움 (253-2)
- B08_Quantity_Haul_Cycle.py · .ts 짝 — 건설품셈 8-2-8 덤프트럭 · 거창 25 단가산출 1308~1347행 재현(t1 5.33 · t2 101.23 · Cm 109.78)
- 로직 입력 이름 채움 Cm · 사이클시간 · t2 · 운반거리 · 덮은 칸(own) 그대로
- B09 셈(hand_sources) 때 거리이정표 거리로 다시 채움 · 덮개 ref 에 cycle · own 남김

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JywHxQuWPk6UYXTebyrBoU
2026-10-11 14:03:54 +09:00

103 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""B08 운반 사이클시간(PLAN 253-2) — 건설품셈 8-2-8 덤프트럭 · 거리이정표 거리 → 운반 로직 입력.
⚠ 짝 = `B08_Quantity_Haul_Cycle.ts`(같은 식) — 한쪽을 고치면 다른 쪽도 ·
거울 시험 `resources/tester/test_253_2_haul_cycle.py`.
조작 중은 TS 짝(「운반 단가」 모달)이 바로 셈 · B09 셈 때 서버가 이 파일로 다시 채움(정본).
식(거창 25 설계서 단가산출 1308~1347행 꼴 · 끝수 = 소수 둘째 자리 반올림)
q = T / rt × f · n = q / (qs × k) · t1 = Cms × n / (60 × Es)
t2 = (L1/V1 + L1/V2 + L2/V3 + L2/V4) × 60 · Cm = t1 + t2 + t3 + t4 + t5 + t6
L1 = 거리이정표 그 행 포장 계(2차 + 1차 + 포장) · L2 = 비포장 · 속도 0 = 그 항 0.
로직 입력 채움(이름으로) — `Cm` · `사이클시간` = Cm · `t2` = t2 · `운반거리` = L1 + L2 ·
`own` = 사용자가 덮은 칸(L1 · L2 · t1 · 로직 입력 이름) — 그 값이 이김.
기본값 = 거창 설계서(혼합골재 덤프 15톤) · 속도 · t 표 = master_data CC000054~058(화면이 고름).
"""
from __future__ import annotations
import math
from typing import Any
DEFAULTS: dict[str, float] = {
"L1": 0.0,
"L2": 0.0,
"V1": 30.0,
"V2": 35.0,
"V3": 10.0,
"V4": 15.0,
"T": 15.0,
"rt": 1.7,
"f": 1.0,
"qs": 1.72,
"k": 1.0,
"Es": 0.6,
"Cms": 37.4,
"t3": 0.8,
"t4": 0.42,
"t5": 0.5,
"t6": 1.5,
}
#: 로직 입력 이름 → 셈 결과 칸
FILL = {"Cm": "cm", "사이클시간": "cm", "t2": "t2", "운반거리": "L"}
def r2(value: float) -> float:
"""소수 둘째 자리 반올림(0.5 올림 · TS `Math.round` 와 같음)."""
return math.floor(value * 100 + 0.5) / 100
def _div(a: float, b: float) -> float:
return a / b if b else 0.0
def _num(value: Any) -> float | None:
if isinstance(value, bool) or not isinstance(value, (int, float)):
return None
return float(value) if math.isfinite(value) else None
def cycle_time(inputs: dict[str, Any] | None) -> dict[str, float]:
"""사이클 입력(빈 칸 = 기본값 · `t1` 있으면 그 값) → {q, n, t1, t2, cm, L}."""
given = {k: _num(v) for k, v in (inputs or {}).items()}
v = {k: given[k] if given.get(k) is not None else d for k, d in DEFAULTS.items()}
q = r2(_div(v["T"], v["rt"]) * v["f"])
n = r2(_div(q, v["qs"] * v["k"]))
t1 = given.get("t1")
t1 = r2(_div(v["Cms"] * n, 60 * v["Es"])) if t1 is None else t1
l1, l2 = v["L1"], v["L2"]
t2 = r2((_div(l1, v["V1"]) + _div(l1, v["V2"]) + _div(l2, v["V3"]) + _div(l2, v["V4"])) * 60)
cm = r2(t1 + t2 + v["t3"] + v["t4"] + v["t5"] + v["t6"])
return {
"q": q,
"n": n,
"t1": t1,
"t2": t2,
"cm": cm,
"L": math.floor((l1 + l2) * 1000 + 0.5) / 1000,
}
def cycle_inputs(ref: dict[str, Any] | None, dist: dict[str, Any] | None) -> dict[str, Any]:
"""연결 `ref.cycle` + 거리이정표 거리(`dist{L1, L2}`) — 덮은 L1 · L2(`ref.own`)는 그대로."""
cycle = dict((ref or {}).get("cycle") or {})
own = set((ref or {}).get("own") or [])
for name in ("L1", "L2"):
if name not in own and _num((dist or {}).get(name)) is not None:
cycle[name] = dist[name]
if "t1" not in own:
cycle.pop("t1", None)
return cycle
def fill_given(
ref: dict[str, Any], names: list[str], dist: dict[str, Any] | None
) -> dict[str, Any]:
"""로직 입력값 다시 채움 — `names` = 그 로직 입력 이름 · 덮은 칸(`ref.own`)은 그대로."""
own = set(ref.get("own") or [])
got = cycle_time(cycle_inputs(ref, dist))
given = dict(ref.get("given") or {})
for name, slot in FILL.items():
if name in names and name not in own:
given[name] = got[slot]
return given