- Finger — 풀이 두 벌(_text · _stmate) 걷고 블록 단위 줄 투영 하나(_units) · 글은 조건 · 옛 판 · 계수 · 「…의 N %」 만 · 셈 밖 줄 안 씀 - Shares — 몫 = 단위 줄을 절(제목 · 윗절)로 묶음 한 벌 · 식 다시 풀기(qty_of · sections_stm) 걷음 · trade = ReadEst.trade - Elem.prices = 단위 줄 단가(글 다시 안 풂 · machines 갈래 안 건드림) - Match.clause = Basis.clause 만 · 대체 몸 · _TYPO_CLAUSE 걷음(오타는 읽기 ReadEst.sources) · fix_typo = 사본(Line 이 부름) - Fit.cache_path — HP 지문 칸(올린 엑셀 sha256 + 판) · 파일 그대로면 다시 안 읽음(lru) · 붙여넣기 HP 만 파일 해시 - 지문 전후 = 셈 단위 275 중 150 같음 · 다름 = 장비 절 · 글(쓰는 곳 없음) 100 · 고침(STmate 기계 두 묶음 · 거창 자재 · 끝 점 직종 · 옛 몫 금액 ÷ 단가 엉터리 · 제외금액 줄) — 골든 1위 줄마다 · 불리는 블록 206 갈래 · 1위 · 상태 전후 같음(162/177 · 기초 80 · SK 37 · 대기 89) - S1 다시 굳힘 = 봉화 · 울진대흥 · 울진소광 자원(같은 코드 두 묶음 따로) · S2 다시 굳힘 125/275(위 까닭) - 시험 고침 — finger(블록 = ReadEst.items · STmate 단위 줄 · 셈 밖) · fit 옛 HP(항목 · 글 없음) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
147 lines
7.0 KiB
Python
147 lines
7.0 KiB
Python
"""338-1 엑셀 지문(`M02_Hopyo_Finger` · `_Words` · `_Shares`) — 식 풀기 일곱 꼴 · 합판 지문 · 고임돌
|
||
섞음 · 몫 · STmate 단위 줄 · 기계 줄 · 직접 줄 호표. 지문 = 블록 단위 줄 투영(776-3 · 형식 모름).
|
||
실물 = 북부청 임도(읽기만)."""
|
||
|
||
import pytest
|
||
|
||
from M02_MasterTemplete import M02_Hopyo_Finger as finger
|
||
from M02_MasterTemplete import M02_Hopyo_ReadEst as est
|
||
from M02_MasterTemplete import M02_Hopyo_Shares as shares
|
||
from M02_MasterTemplete.M02_Hopyo_Words import conds, mtypes, parse_rhs
|
||
from resources.tester.helper_m02_hopyo_golden import line_of
|
||
|
||
approx = pytest.approx
|
||
|
||
|
||
def _est(text: list[str]) -> dict:
|
||
"""EST 글 → 블록(단위 줄 = 어댑터 `ReadEst.items`)."""
|
||
return {"번": 1, "이름": "시험", "단위": "㎥", "글": text, "항목": est.items(text)}
|
||
|
||
|
||
# ── 식 풀기 ────────────────────────────────────────────────────────────
|
||
def test_식_단가_떼고_품():
|
||
got = parse_rhs("273,540 × 3인 ÷ 55㎥ × 2 = 29,840.7")
|
||
assert got["단가"] == 273540 and got["품"] == approx(0.10909, abs=1e-5) and got["율"] == []
|
||
|
||
|
||
def test_식_퍼센트_율():
|
||
got = parse_rhs("59,020 ÷ 23.1 × 90% = 2,299.5")
|
||
assert got["품"] == approx(0.03896, abs=1e-5)
|
||
assert got["밑품"] == approx(1 / 23.1) and got["율"] == [[0.9, "%"]]
|
||
|
||
|
||
def test_식_인당_단위_섞음():
|
||
got = parse_rhs("172,068 × 0.3인/㎥ × 10% = 5,162")
|
||
assert got["품"] == approx(0.03) and got["밑품"] == approx(0.3)
|
||
|
||
|
||
def test_식_바꿔_쓴_식은_앞_율을_이어받음():
|
||
got = parse_rhs("215,907 × 4인 ÷ P × 1.2(할증) = 215,907 × 0.104 × 1.2 = 26,945")
|
||
assert got["품"] == approx(0.1248) and got["밑품"] == approx(0.104)
|
||
assert got["율"] == [[1.2, "할증"]]
|
||
|
||
|
||
def test_식_횟수_품할증():
|
||
got = parse_rhs("172,068 × 0.05인 × 2회 = 17,206")
|
||
assert got["품"] == approx(0.1) and got["밑품"] == approx(0.05) and got["율"] == [[2.0, "회"]]
|
||
got = parse_rhs("273,540 × 0.1 × 1.2(품할증) = 32,824")
|
||
assert got["밑품"] == approx(0.1) and got["율"] == [[1.2, "품할증"]]
|
||
|
||
|
||
def test_식_못_풀면_역산():
|
||
assert parse_rhs("273,540 × P = 30,000") is None
|
||
block = _est([" 특별인부 : 273,540 × P = 27,354"])
|
||
fp = finger.excel(block, {"이름": "시험", "규격": "", "단위": "㎥"})
|
||
assert fp["인력"]["특별인부"]["품"] == approx(0.1) and fp["인력"]["특별인부"]["어떻게"] == [
|
||
"역산"
|
||
]
|
||
|
||
|
||
def test_장비_갈래_조건_낱말():
|
||
assert mtypes("유압식 백호우 0.7㎥") == {"굴착기"} and mtypes("펌프카 41m") == {"콘크리트펌프"}
|
||
assert conds("합판거푸집 4회 보통")["횟수"] == {"4회"}
|
||
assert conds("구조물터파기(암)")["토질"] == {"암"}
|
||
|
||
|
||
# ── 실물 지문 ──────────────────────────────────────────────────────────
|
||
def test_합판_4회_지문():
|
||
block, line = line_of("N001")
|
||
fp = finger.excel(block, line)
|
||
assert fp["인력"]["형틀목공"]["품"] == approx(0.1111, abs=1e-4)
|
||
assert fp["인력"]["보통인부"]["품"] == approx(0.0444, abs=1e-4)
|
||
assert "4회" in fp["조건"]["횟수"] and fp["출처"] == [["건설품셈", "6-3-1"]]
|
||
assert {m["이름"][:4] for m in fp["자재"] if m["품"]} >= {"내수합판"}
|
||
|
||
|
||
def test_레미콘_소량_지문_장비_시간():
|
||
block, line = line_of("N000")
|
||
fp = finger.excel(block, line)
|
||
assert fp["인력"]["콘크리트공"]["품"] == approx(0.10909, abs=1e-5)
|
||
assert [(m["갈래"], round(m["시간"], 2)) for m in fp["장비"]] == [(["굴착기"], 0.29)]
|
||
|
||
|
||
def test_고임돌_섞음_율과_몫():
|
||
block, line = line_of("N005")
|
||
fp = finger.excel(block, line)
|
||
labor = fp["인력"]["보통인부"]
|
||
assert labor["밑품"] == approx(0.3, abs=1e-3) and labor["품"] == approx(0.03, abs=1e-3)
|
||
assert any(note in ("%", "섞음") and v == approx(0.1) for v, note in labor["율"])
|
||
parts = fp["몫"]
|
||
assert any(p["노임"] and not p["장비"] for p in parts) # 인력 몫
|
||
assert any(p["장비"] and not p["노임"] for p in parts) # 장비 몫
|
||
|
||
|
||
def test_몫_절마다_노임_장비():
|
||
texts = [
|
||
" 1. 굴착기 0.6㎥ 채집(90%)",
|
||
" 노무비 : 59,020 ÷ 23.1 × 90% = 2,299",
|
||
" 2. 인력채집(10%)",
|
||
" 보통인부 : 172,068 × 0.3인/㎥ × 10% = 5,162",
|
||
" 3. 합 계",
|
||
" 보통인부 : 172,068 × 1 = 172,068",
|
||
]
|
||
parts = shares.sections(est.items(texts))
|
||
assert [p["제목"] for p in parts] == ["굴착기 0.6㎥ 채집(90%)", "인력채집(10%)"]
|
||
assert parts[0]["장비"] == {"굴착기|0.6": approx(0.9 / 23.1)}
|
||
assert parts[1]["노임"] == {"보통인부": approx(0.03)}
|
||
|
||
|
||
def test_STmate_단위_줄_지문():
|
||
qty = {"율": [], "인자": [], "어떻게": "QTY"}
|
||
block = {
|
||
"글": ["잔토처리 (기계100%) 건설표준품셈9-3", "q = 0.7 , K = 0.9"],
|
||
"항목": [
|
||
{"묶음": "L", "이름": "보통인부", "규격": "", "직종": "보통인부", "품": 0.2, **qty},
|
||
{"묶음": "X", "이름": "굴삭기(무한궤도)", "규격": "0.7㎥", "품": 0.0229, **qty},
|
||
{"묶음": "M", "이름": "모래", "규격": "", "품": 1.2, "밑품": 1.2, **qty},
|
||
{"묶음": "L", "이름": "보통인부", "규격": "", "품": 0.5, "밖": True, **qty},
|
||
],
|
||
}
|
||
fp = finger.excel(block, {"이름": "잔토처리", "규격": "토사", "단위": "M3"})
|
||
assert fp["인력"] == {"보통인부": {"품": 0.2, "밑품": 0.2, "율": [], "어떻게": ["QTY"]}}
|
||
assert [(m["갈래"], m["규격"], m["시간"]) for m in fp["장비"]] == [(["굴착기"], [0.7], 0.0229)]
|
||
assert fp["자재"] == [{"이름": "모래", "품": 1.2, "밑품": 1.2}] and fp["계수"]["K"] == 0.9
|
||
|
||
|
||
def test_기계_줄_블록_없음():
|
||
fp = finger.excel(None, {"이름": "콘크리트 펌프차", "규격": "41m,80~95㎥/hr", "단위": "hr"})
|
||
assert [(m["갈래"], m["시간"]) for m in fp["장비"]] == [(["콘크리트펌프"], 1.0)]
|
||
assert 41.0 in fp["장비"][0]["규격"] and fp["인력"] == {}
|
||
|
||
|
||
def test_직접_줄_호표():
|
||
hopyo = {
|
||
"이름": "돌붙임",
|
||
"규격": "",
|
||
"단위": "㎡",
|
||
"줄": [
|
||
{"이름": "석 공", "규격": "", "수량": 0.1, "단위": "인", "갈래": "기타"},
|
||
{"이름": "보통인부", "규격": "", "수량": 0.05, "단위": "인", "갈래": "기타"},
|
||
{"이름": "굴착기", "규격": "0.6㎥", "수량": 0.2, "단위": "hr", "갈래": "기계"},
|
||
],
|
||
}
|
||
fp = finger.direct(hopyo)
|
||
assert fp["인력"]["석공"]["품"] == 0.1 and fp["인력"]["보통인부"]["품"] == 0.05
|
||
assert [(m["갈래"], m["시간"]) for m in fp["장비"]] == [(["굴착기"], 0.2)]
|
||
assert finger.direct({**hopyo, "줄": hopyo["줄"][2:]}) is None # 노임 없으면 호표 통째 아님
|