Files
Aislo/resources/tester/test_794_2a2_m01_add.py
eomsangdonandClaude Opus 5.5 c5067aa2b6 feat(809-1a): 일위대가 불러오기 = 경쟁사 로직 인정 · 요소만 연결 · [수정] 모달 = 일위대가 컨테이너 부품 · 기초 판정 걷음
- [수정] 모달 = Labor_Table(읽기 · 덧칸 표지 · 엑셀 금액) · 줄 = 로직(단가산출 · 일위대가) / 요소(연결됨 · 후보 · 못 이음) · 단가산출 줄 = 가져온 식 SK 수식 탭 모달(Labor_SkEdit) · 서버 hopyo-view(M02_Hopyo_View)
- 엑셀 보기 목록 · 칠 = 줄 표지(View.listing) · 단가산출 탭 = 블록 목록 + [가져온 식으로 열기] · [내 단가산출로]
- 걷음(요구 703): 판정 체계 785(Judge · Solve · Bind · San_Basis 다섯 · Make.Move · Row 1차 판정 · 화면 Check · CheckRows · Rows · Block · JudgeApi · Picks · Judge.css) · [우리 기초로 바꾸기](to-base) · 근거 기초 제안 · Clause 기초 판정
- 시험 지움: 642_2(Bind · Solve) · 642_3(Row 1차 판정) · 642_5(옮기기 Move) · 642_6(판정 화면) · 786_2(옛 [수정] 모달) · 793_3a(근거 → 기초 제안) — 모두 걷은 기초 판정 길 몫
- 시험 고침: 642_1 · 794_2a2 · 794_2b(근거 제안 부분만 뺌) · 793_2 · 793_3b(기초 바꾸기 기대 → 없음) · 627 · 779_2 · 785_4 · 807_1 · m02_hopyo_excel · grid · stmate(judge 길 → view 길)
- 새 시험 test_809_1_import_labor(기초 길 0 · 표지 1,350 줄 · 가져온 식 SK · 모달 = Labor_Table · 금액 = 엑셀)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:17:58 +09:00

185 lines
8.2 KiB
Python
Raw Permalink 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.
"""794-2a2 M01 보강 지킴 — 자재 운반 GF 둘(산림 10-1 · 10-2) · 기계 채집 자체 GX · 덤프 조합 GF000284 넓힘.
① 새 줄 셋 엔진 셈 — 운임 = 자재 구역화물(톤급 · 거리 줄 하나) ÷ 1.1 ÷ 적재 톤 · 하차 품 = 입력(기본값 없음) ·
채집 = 실무 봉화#3 식(q = 4/16 · Q 12.38 · 소운반 Q 9.44) · 견본 자동값으로 멈추지 않음.
② GF000284 — 고르기 첫째(굴착기 0.7㎥ · 15ton) = 넓히기 전 식(원문 수 0.7 · 15 · 20 · 0.85 · 22초) 그대로 ·
다른 고름 = 건설 공통 8-2-3 싸이클 · 8-2-5 로더 cm(거창#27 1.8 × 8 + 6 + 14 = 34.4) · 덤프 T.
③ 근거 제안 시험은 809-1 에서 지움(근거 → 기초 제안 길 걷음 · 요구 703).
마스터 = 지금 M01(읽기만).
"""
from __future__ import annotations
import importlib
import itertools
from decimal import Decimal as D
from functools import lru_cache
import pytest
from M01_MasterData import M01_MasterData_Store as m01 # scripts 길을 둠
ma = importlib.import_module("master_auto")
mcut = importlib.import_module("master_cut")
mf = importlib.import_module("master_formula")
CEMENT, REBAR, GATHER, DUMP = "GF000335", "GF000336", "GX000004", "GF000284"
@lru_cache(maxsize=1)
def whole():
return m01.loaded()[1]
def run(key: str, given: dict) -> dict:
w = whole()
auto = {k: v for k, v in ma.values(w, w.logic(key)).items() if v is not None}
return mcut.engine(w, key, mf.run(w, key, {**auto, **given}))
def near(a: D, b: D) -> bool:
"""줄 단가 = 하위 로직 계(끝수 셈이 원 미만을 끊음)."""
return abs(a - b) < 1
def line(got: dict, name: str) -> dict:
return next(x for x in got["줄"] if x["이름"] == name)
# ── ① 새 줄 ────────────────────────────────────────────────────────────
def test_새_줄_셋_자리():
w = whole()
for key, no, unit in (
(CEMENT, "10-1", "원/포"),
(REBAR, "10-2", "원/ton"),
(GATHER, "13-2-4", "원/㎡"),
):
row = w.logic(key)
assert row["원문번호"] == no and row["결과단위"] == unit and row["소유"] == "공용"
got = run(key, {}) # 견본 자동값 — 멈추지 않음
assert got["계"] >= 0
def test_철근운반_실무_북부청임도36():
got = run(REBAR, {"톤급": "10.5톤", "거리": "20km", "하차품": D(2) * 11 / 450})
fr = line(got, "구역화물 운임")
assert fr["품목"]["규격"] == "10.5톤, 20km" and fr["비목"].keys() == {"경비"}
assert fr["수량"] == 1 / (D("1.1") * D("10.5"))
assert fr["금액"] == (fr["단가"] / D("1.1") / D("10.5")).quantize(
D("0.1"), "ROUND_DOWN"
) # 줄 0.1 원 버림
labor = line(got, "보통인부(하차)")
assert labor["수량"] == D(2) * 11 / 450 and labor["비목"].keys() == {"노무비"}
# 엑셀 「구역화물(10.5톤,20km) 111,240 ÷ 1.1 ÷ 10.5 = 9,631.1」 — 같은 단가면 같은 금액
if fr["단가"] == 111240:
assert round(fr["금액"], 1) == D("9631.1")
def test_시멘트운반_포당():
got = run(CEMENT, {"톤급": "5.0톤", "거리": "20km", "하차품": D("0.31")})
fr = line(got, "구역화물 운임")
assert fr["품목"]["규격"] == "5.0톤, 20km"
assert fr["수량"] == 1 / (D("1.1") * D("5.0") * 25) # 40kg 포대 · 25 포/ton(원문 주)
assert line(got, "보통인부(하차)")["수량"] == D("0.31") / 25
def test_구역화물_톤급_거리_줄_하나씩():
w = whole()
spec = {s["이름"]: s["고르기"] for s in w.logic(REBAR)["입력"] if "고르기" in s}
assert spec["톤급"][0] == "10.5톤" and len(spec["톤급"]) == 20 and len(spec["거리"]) == 24
for ton, km in itertools.product(spec["톤급"], spec["거리"]):
got = run(REBAR, {"톤급": ton, "거리": km, "하차품": D(0)})
fr = line(got, "구역화물 운임")
assert fr["품목"]["규격"] == f"{ton}, {km}", (ton, km)
assert fr["수량"] == 1 / (D("1.1") * D(ton.removesuffix("톤")))
def test_하차품_기본값_없음():
w = whole()
for key in (CEMENT, REBAR):
assert ma.defaults(w, w.logic(key))["하차품"] is None
assert line(run(key, {}), "보통인부(하차)")["금액"] == 0
def test_기계채집_실무_봉화3():
w = whole()
got = run(GATHER, w.logic(GATHER)["시험입력"])
mid = got["중간"]
assert mid["q"] == D("0.25") and mid["K"] == D("0.55") and mid["E"] == D("0.45")
assert mid["cm"] == 18 and mid["Q"] == D("12.375") # 엑셀 Q = 12.38
assert round(mid["Q2"], 2) == D("9.44") # 엑셀 소운반 Q = 9.44(덤프 2.5톤 · L 0.2)
names = [x["이름"] for x in got["줄"]]
assert names == ["굴착기(채집)", "굴착기(상차)", "덤프트럭(소운반)"]
assert got["줄"][0]["수량"] == got["줄"][1]["수량"] == 1 / mid["Q"]
off = run(GATHER, {**w.logic(GATHER)["시험입력"], "상차": "안 함", "운반거리": D(0)})
assert [x["수량"] for x in off["줄"][1:]] == [0, 0]
# ── ② GF000284 넓힘 ───────────────────────────────────────────────────
OLD = { # 넓히기 전 식 — 원문 수
"Q1": "반올림(3600 * 0.7 * K * (1 / L) * E0 / 찾기(QF000336, 구분='㎝(초)').값, 3)",
"q": "15 / 감마 * L",
"n": "q / (0.7 * K)",
"t1": "20 * n / (60 * 0.85)",
}
def _old(mid: dict, name: str) -> D:
return mf.evaluate(mf.parse(OLD[name]), dict(mid), whole(), 0)
@pytest.mark.parametrize("재료", ["토사", "암절취", "발파암"])
def test_덤프운반_기본_고름_옛_식_그대로(재료):
w = whole()
row = w.logic(DUMP)
assert [s["이름"] for s in row["입력"][:4]] == ["재료", "운반거리", "지역", "보정작업"]
assert (
ma.defaults(w, row)["적재기계"] == "0201-0070"
and ma.defaults(w, row)["덤프"] == "0602-0150"
)
for dist, rock in itertools.product(
(D("0.3"), D("23.877")), ("해당 없음", "암석작업(연암・보통암・경암)")
):
got = run(DUMP, {"재료": 재료, "운반거리": dist, "지역": "전국평균", "보정작업": rock})
mid = got["중간"]
assert (
mid["Q1"] == _old(mid, "Q1")
and mid["q"] == _old(mid, "q")
and mid["n"] == _old(mid, "n")
)
assert mid["Cms"] * mid["n"] / (60 * mid["Es"]) == _old(mid, "t1")
dig, truck = got["줄"]
assert [dig["이름"], truck["이름"]] == [
"굴착기(무한궤도) 0.7㎥(적재)",
"덤프트럭 15ton(운반)",
]
base = {"지역": "전국평균", "보정작업": rock}
assert near(dig["단가"], mf.run(w, "GC000267", {"기계": "0201-0070", **base})["계"])
assert near(truck["단가"], mf.run(w, "GC000269", {"기계": "0602-0150", **base})["계"])
def test_덤프운반_넓힌_고름():
g = {"재료": "토사", "운반거리": D(1), "지역": "전국평균", "보정작업": "해당 없음"}
small = run(DUMP, {**g, "적재기계": "0201-0020"})["중간"]
assert (small["q0"], small["Cm"], small["Cms"]) == (
D("0.2"),
20,
18,
) # 8-2-3 0.12∼0.4 · 180° · 135°
big = run(DUMP, {**g, "적재기계": "0201-0100"})["중간"]
assert (big["q0"], big["Cm"], big["Cms"]) == (D("1.0"), 23, 21)
loader = run(DUMP, {**g, "적재기계": "0302-0134"})
mid = loader["중간"]
assert (
mid["q0"] == D("1.34") and mid["Cms"] == D("34.4") == mid["Cm"]
) # 거창#27 1.8 × 8 + 6 + 14
assert mid["K"] == 1 and mid["Es"] == mid["E0"] == D("0.6") # 거창#27 K 1 · Es 0.6
rock = run(DUMP, {**g, "보정작업": "암석작업(연암・보통암・경암)", "적재기계": "0302-0134"})
plain = {"기계": "0302-0134", "지역": "전국평균", "보정작업": "해당 없음"}
assert near(
rock["줄"][0]["단가"], mf.run(whole(), "GC000267", plain)["계"]
) # 타이어 로더 = 손료 보정 없음
for dump, ton in (("0602-0080", 8), ("0602-0240", 24)):
mid = run(DUMP, {**g, "덤프": dump})["중간"]
assert mid["덤프T"] == ton and mid["q"] == ton / mid["감마"] * mid["L"]