Files
Aislo/resources/tester/test_m02_hopyo_fit.py
T
eomsangdonandClaude Opus 5.5 022d6375e1 refactor(776-3): 지문 형식 모름 — 단위 줄 투영 한 벌 · 몫 한 벌 · 블록 단가 = 항목 · clause 대체 몸 · 오타 정규식 걷음 · 맞춤 캐시 = HP 지문 칸
- 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>
2026-11-04 13:20:17 +09:00

136 lines
5.4 KiB
Python

"""338-1 순위 · 판정 · 조합 · 뒤 셈(`M02_Hopyo_Fit` · `_Verdict` · `_Combine`) — 같음 규칙 · 딱
맞음이
같음을 이김 · 맞음 · 다른 점 · 후보 · 철근 둘 · 고임돌 인력 10% · 맞춤셈 캐시 · 「셈 중」.
실물 = 북부청 임도 · 사방(읽기만) · 층 · 캐시 폴더는 임시."""
import queue
import shutil
import time
import pytest
from M02_MasterTemplete import M02_Hopyo_Fit as fit
from M02_MasterTemplete import M02_Hopyo_Match as hm
from M02_MasterTemplete import M02_Hopyo_Ours as ours
from M02_MasterTemplete import M02_Hopyo_Store as hopyo_store
from M02_MasterTemplete import M02_Hopyo_Verdict as verdict
from resources.tester.helper_m02_hopyo_golden import line_of, read
from resources.tester.test_m02_hopyo_excel import master_hash
@pytest.fixture(scope="module")
def got():
if not ours.ready():
ours.build()
return hm.targets()
def _block(lid: str, got: dict, **change) -> dict:
block, line = line_of(lid)
if change:
line = {**line, "근거": {}}
block = {**block, "출처": []}
return verdict.block(block, line, got)
def test_같음_규칙_이름_같음_1위_고정(got):
r = _block("N014", got)
assert r["B"] == "같음" and r["차례"][0] == "GC000214" and r["판정"]["상태"] == "맞음"
def test_딱_맞음이_같음을_이김(got):
r = _block("N001", got, 근거=None) # 인용 조항을 지우면 이름 같음 = 산림 GF000160
assert r["B"] == "같음" and hm.b_order(line_of("N001")[1], got)["상태"] == "후보"
assert r["차례"][0] == "GC000211" and r["판정"]["상태"] == "맞음"
def test_판정_셋(got):
a = _block("N000", got)
assert a["판정"]["상태"] == "맞음" and "소량감률 50" in a["판정"]["글"]
assert a["후보"][0]["판정"] == "맞음" and a["후보"][0]["근거"]["까닭"].startswith("조항 같음")
b = _block("N008", got)
assert b["판정"]["상태"] == "다른 점" and b["차례"][0] == "GC000083"
assert "특별인부 엑셀 0.3542 · 우리 0.3704" in b["판정"]["꼬리표"]
c = _block("S084", got)
assert c["판정"]["상태"] == "후보" and len(c["후보"]) == 5
def test_합판_맞음_못_가름_꼬리표(got):
r = _block("N001", got)
assert r["판정"]["상태"] == "맞음"
assert any(
t.endswith("못 가름") and {"측압", "폼타이규격"} <= set(t.split())
for t in r["판정"]["꼬리표"]
)
def test_조합_철근_가공_조립(got):
r = _block("N003", got)
assert {c["로직"] for c in r["조합"] if c["체크"]} == {"GC000206", "GC000207"}
def test_조합_고임돌_인력_몫_먼저(got):
r = _block("N005", got)
assert r["차례"][0] == "GF000211"
labor = next(c for c in r["조합"] if c["로직"] == "GF000211")
assert labor["몫"] == 0.1 and labor["체크"]
assert all(not c["체크"] for c in r["조합"] if c["로직"] in ("GC000267", "GC000268"))
def test_조합_근거_안_닿은_덧은_후보(got):
r = _block("N009", got) # 구조물되메우기(인력100%) — 훈증더미 인력 제거(개)는 덧 아님
assert r["차례"][0] == "GF000113" and not r["조합"]
assert any(c["로직"] == "GF000083" and c["글"].startswith("덧 후보") for c in r["후보"])
r = _block("N017", got) # 다웰바(EA) — PSC빔 쉬즈관(m) 덧 아님
assert r["차례"][0] == "GC000226" and not r["조합"]
def test_숫자_없음_옛_HP(got):
block, line = line_of("N000")
r = verdict.block({**block, "글": [], "항목": []}, line, got) # 단위 줄 · 글 없음
assert r["판정"]["상태"] == "후보" and r["판정"]["글"] == fit.NO_NUMBER
assert r["차례"][0] == "GC000198" # 이름 · 근거 차례 그대로
@pytest.fixture
def layer(tmp_path, monkeypatch, got):
cache = tmp_path / "cache"
cache.mkdir()
shutil.copy(ours.path_of(), cache / ours.path_of().name)
monkeypatch.setenv("AISLO_HOPYO_CACHE", str(cache))
book = read("북부청임도")
small = {**book, "호표": book["호표"][:3]}
brief = hopyo_store.save(tmp_path, "북부청.xls", small, {"id": "t"})
return tmp_path, brief["키"], cache
def test_뒤_셈_캐시_셈_중(layer, monkeypatch):
folder, key, cache = layer
# 앞 시험들의 올리기가 쌓은 일감(북부청 통째)을 기다리지 않게 — 이 시험만의 일감 줄 · 일꾼
monkeypatch.setattr(fit, "_JOBS", queue.Queue())
monkeypatch.setattr(fit, "_PENDING", set())
monkeypatch.setattr(fit, "_WORKER", {"스레드": None})
before = master_hash()
assert fit.result(folder, key) is None
first = fit.ensure(folder, key)
assert first["끝"] is False and first["한"] == 0
for _ in range(300):
if fit.status(folder, key)["끝"]:
break
time.sleep(0.2)
done = fit.status(folder, key)
assert done["끝"] and done["한"] == done["모두"] > 0
got = fit.result(folder, key)
assert got["판"] == ours.version() and len(got["블록"]) == done["모두"]
assert fit.cache_path(folder, key).parent == cache
assert fit.ensure(folder, key)["끝"] # 두 번째는 캐시만 봄
assert master_hash() == before
def test_셈_단위_열쇠(got):
book = read("북부청임도")
units = fit.units({**book, "호표": book["호표"][:3]})
keys = [k for k, _, _ in units]
assert len(keys) == len(set(keys)) and keys[0].startswith("단산:")
assert all(k.startswith(("단산:", "줄:", "호표:")) for k in keys)