- 새 파일 — Words(식 풀기 · 장비 갈래 · 조건 낱말) · Finger(블록 글 · STmate 자원 → 지문 · 기계 줄 · 직접 줄 호표) · Shares(절 몫 벡터) · Ours(마스터 판 열쇠 · 우리 지문 캐시 tmp/m02_hopyo · 엔진 셈 캐시 · 자재 값 찾기 건너뜀) · Option(옵션 공간 · 거꾸로 찾기 · 견줌) · Fit(손잡이 한 곳 · 순위 · 뒤 셈 · 맞춤셈 캐시) · Combine(조합 · 섞인 줄 몫 먼저) · Verdict(블록 셈 · 맞음 / 다른 점 / 후보) - Match — b_order(이름 · 근거 차례 · 같음 근거 검사 · 옛 판 글 · 조항 오타) · clause(윗마디 0.9 · 나 창 Basis.clause 있으면 그것) · 이름 후보 로직은 접지 않음 - 정답 표 fixtures/m02_hopyo_golden.json(사람 136 · 새 파일 51) · 골든 도우미 - 북부청 92 줄 실측 — 1순위 87 · 다섯 안 91 · 맞음 41 틀림 0 · 다른 점 28 틀림 0 · 조합 맞음 57/66 · 우리 지문 셈 37 초 · 캐시 읽기 0.05 초 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
148 lines
6.7 KiB
Python
148 lines
6.7 KiB
Python
"""338-1 엑셀 지문(`M02_Hopyo_Finger` · `_Words` · `_Shares`) — 식 풀기 일곱 꼴 · 합판 지문 · 고임돌
|
||
섞음 ·
|
||
몫 · STmate 자원 · 기계 줄 · 직접 줄 호표. 실물 = 북부청 임도(읽기만)."""
|
||
|
||
import pytest
|
||
|
||
from M02_MasterTemplete import M02_Hopyo_Finger as finger
|
||
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 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 = {"번": 1, "이름": "시험", "단위": "㎥", "글": [" 특별인부 : 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(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_자원_지문():
|
||
block = {
|
||
"글": ["잔토처리 (기계100%) 건설표준품셈9-3", "q = 0.7 , K = 0.9"],
|
||
"자원": [
|
||
{"갈래": "L", "코드": "L00002", "이름": "보통인부", "규격": "", "품": 0.2},
|
||
*[
|
||
{
|
||
"갈래": "X",
|
||
"코드": "X00205",
|
||
"이름": "굴삭기(무한궤도)",
|
||
"규격": "0.7㎥",
|
||
"품": 0.0229,
|
||
}
|
||
]
|
||
* 3,
|
||
{"갈래": "M", "코드": "M00001", "이름": "모래", "규격": "", "품": 1.2},
|
||
],
|
||
}
|
||
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 # 노임 없으면 호표 통째 아님
|