Merge remote-tracking branch 'origin/sub_laptop_1' into sub_laptop_8
This commit is contained in:
@@ -11,6 +11,7 @@ from __future__ import annotations
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import warnings
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
@@ -24,6 +25,7 @@ from M02_MasterTemplete import M02_Hopyo_Excel as hx # noqa: E402
|
||||
from M02_MasterTemplete import M02_Hopyo_Match as hm # noqa: E402
|
||||
from M02_MasterTemplete import M02_Hopyo_Verdict as verdict # noqa: E402
|
||||
|
||||
warnings.filterwarnings("ignore", category=UserWarning, module="openpyxl")
|
||||
DOCS = ROOT / "resources/knowledge/original/실무문서"
|
||||
FIXTURE = Path(__file__).resolve().parent / "fixtures/m02_hopyo_golden.json"
|
||||
FILES = {
|
||||
@@ -84,15 +86,24 @@ def read(tag: str) -> dict[str, Any] | None:
|
||||
return book
|
||||
|
||||
|
||||
def _key(line: dict[str, Any]) -> tuple:
|
||||
def _keys(line: dict[str, Any]) -> list[tuple]:
|
||||
"""줄 → 짝 열쇠 후보 — (이름 · 규격 · 단위 · 이음) · 이음 = 단산 번 · 줄 코드 · 없음."""
|
||||
ref = line.get("참조") or {}
|
||||
no = ref.get("번") if ref.get("종류") == "단산" else None
|
||||
code = str(ref.get("코드") or line.get("코드") or "")
|
||||
return line.get("이름"), line.get("규격") or "", line.get("단위") or "", no, code[:6]
|
||||
head = (line.get("이름"), line.get("규격") or "", line.get("단위") or "")
|
||||
code = str(ref.get("코드") or line.get("코드") or "")[:6]
|
||||
out = [(*head, ("단산", ref["번"]))] if ref.get("종류") == "단산" else []
|
||||
return out + ([(*head, ("코드", code))] if code else []) + [(*head, None)]
|
||||
|
||||
|
||||
def _lab_key(lab: dict[str, Any]) -> tuple:
|
||||
return lab["이름"], lab["규격"], lab["단위"], lab.get("단산"), str(lab.get("코드") or "")[:6]
|
||||
head = (lab["이름"], lab["규격"], lab["단위"])
|
||||
if lab.get("단산") is not None:
|
||||
return (*head, ("단산", lab["단산"]))
|
||||
return (*head, ("코드", str(lab["코드"])[:6]) if lab.get("코드") else None)
|
||||
|
||||
|
||||
def _find(want: dict[tuple, dict], line: dict[str, Any]) -> dict | None:
|
||||
return next((want[k] for k in _keys(line) if k in want), None)
|
||||
|
||||
|
||||
def line_of(lid: str) -> tuple[dict | None, dict[str, Any]]:
|
||||
@@ -102,9 +113,7 @@ def line_of(lid: str) -> tuple[dict | None, dict[str, Any]]:
|
||||
blocks = {int(b["번"]): b for b in book.get("단산") or []}
|
||||
for h in book["호표"]:
|
||||
for line in h["줄"]:
|
||||
if _key(line) == _lab_key(lab) or (
|
||||
not line.get("참조") and _key(line)[:3] == _lab_key(lab)[:3]
|
||||
):
|
||||
if _find({_lab_key(lab): lab}, line):
|
||||
ref = line.get("참조") or {}
|
||||
return (blocks.get(int(ref["번"])) if ref.get("종류") == "단산" else None), line
|
||||
raise KeyError(lid)
|
||||
@@ -123,7 +132,6 @@ def evaluate(tags: tuple[str, ...] | None = None) -> dict[str, Any]:
|
||||
continue
|
||||
out["읽음"].append(tag)
|
||||
want = {_lab_key(lab): lab for lab in labs if lab["파일"] == tag}
|
||||
loose = {k[:3]: lab for k, lab in want.items()}
|
||||
blocks = {int(b["번"]): b for b in book.get("단산") or []}
|
||||
t0 = time.time()
|
||||
for h in book["호표"]:
|
||||
@@ -132,7 +140,7 @@ def evaluate(tags: tuple[str, ...] | None = None) -> dict[str, Any]:
|
||||
ref = line.get("참조") or {}
|
||||
if ref.get("종류") == "일위" and ref.get("번"):
|
||||
refs.append(int(ref["번"]))
|
||||
lab = want.get(_key(line)) or (loose.get(_key(line)[:3]) if not ref else None)
|
||||
lab = _find(want, line)
|
||||
if lab is None:
|
||||
continue
|
||||
ids.append(lab["id"])
|
||||
@@ -141,6 +149,15 @@ def evaluate(tags: tuple[str, ...] | None = None) -> dict[str, Any]:
|
||||
block = blocks.get(int(ref["번"])) if ref.get("종류") == "단산" else None
|
||||
out["줄"][lab["id"]] = {"lab": lab, "셈": verdict.block(block, line, got)}
|
||||
out["호표"][f"{tag}|{h['번']}"] = (list(dict.fromkeys(ids)), refs)
|
||||
by_code = {str(b.get("코드") or "")[:6]: b for b in blocks.values() if b.get("코드")}
|
||||
for lab in want.values(): # 호표 줄이 안 부르는 블록(실험 C6 = 블록마다) — 블록 머리로 줄
|
||||
block = blocks.get(lab.get("단산") or -1) or by_code.get(str(lab.get("코드"))[:6])
|
||||
if lab["id"] in out["줄"] or block is None:
|
||||
continue
|
||||
basis = {"출처": block.get("출처") or [], "직종": block.get("직종") or []}
|
||||
line = {**{k: lab[k] for k in ("이름", "규격", "단위")}, "갈래": "단가산출"}
|
||||
line.update(참조={"종류": "단산", "번": block["번"]}, 근거=basis)
|
||||
out["줄"][lab["id"]] = {"lab": lab, "셈": verdict.block(block, line, got)}
|
||||
out["시간"][tag] = round(time.time() - t0, 1)
|
||||
return out
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ def test_출처_글():
|
||||
|
||||
|
||||
def _top(book: dict, no: int) -> list[dict]:
|
||||
got = hm.match_line(_line(book, no), [], hm.units_of(book))
|
||||
assert got["상태"] == "후보" and got["들어감"] is False # 자동 확정 없음
|
||||
got = hm.b_order(_line(book, no)) # 338 — 이름 · 근거 차례(숫자 판정의 덤)
|
||||
assert got["상태"] == "후보" # 자동 확정 없음
|
||||
return got["후보"]
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ def test_근거_후보(north):
|
||||
assert "GC000143" in [c["로직"] for c in _top(north, 64)[:2]]
|
||||
assert _top(north, 49)[0]["로직"] == "GC000085"
|
||||
soil = next(x for x in north["호표"][2]["줄"] if x["이름"].startswith("잔토처리"))
|
||||
names = [c["이름"] for c in hm.match_line(soil, [], {})["후보"]]
|
||||
names = [c["이름"] for c in hm.b_order(soil)["후보"]]
|
||||
assert not any("철골재" in n for n in names)
|
||||
assert master_hash() == before
|
||||
|
||||
@@ -106,7 +106,7 @@ def test_근거_없는_줄_그대로(north):
|
||||
assert bare
|
||||
for line in bare:
|
||||
plain = {k: v for k, v in line.items() if k != "근거"}
|
||||
assert hm.match_line(line, [], {}) == hm.match_line(plain, [], {})
|
||||
assert hm.b_order(line) == hm.b_order(plain)
|
||||
|
||||
|
||||
def test_길_응답_근거_칸(client):
|
||||
|
||||
@@ -46,7 +46,7 @@ def test_딱_맞음이_같음을_이김(got):
|
||||
def test_판정_셋(got):
|
||||
a = _block("N000", got)
|
||||
assert a["판정"]["상태"] == "맞음" and "소량감률 50" in a["판정"]["글"]
|
||||
assert a["후보"][0]["판정"] == "맞음" and a["후보"][0]["근거"]["까닭"] == "조항 같음"
|
||||
assert a["후보"][0]["판정"] == "맞음" and a["후보"][0]["근거"]["까닭"].startswith("조항 같음")
|
||||
b = _block("N008", got)
|
||||
assert b["판정"]["상태"] == "다른 점" and b["차례"][0] == "GC000083"
|
||||
assert "특별인부 엑셀 0.3542 · 우리 0.3704" in b["판정"]["꼬리표"]
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
"""338-1 골든(느림 · 2~4 분) — 정답 표(사람 136 · 새 파일 51)를 실물 엑셀 여덟 파일(읽기만)로 맞춰
|
||||
설계 7-3 기준 수치 · master_data 원본 그대로 · 셈 무게. 우리 지문 캐시가 없으면 처음 ≈ 40 초 더."""
|
||||
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from M02_MasterTemplete import M02_Hopyo_Match as hm
|
||||
from M02_MasterTemplete import M02_Hopyo_Ours as ours
|
||||
from resources.tester import helper_m02_hopyo_golden as golden
|
||||
from resources.tester.test_m02_hopyo_excel import master_hash
|
||||
|
||||
LABELED = ("북부청임도", "북부청사방", "동부청영월")
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def run():
|
||||
before = master_hash()
|
||||
if not ours.ready():
|
||||
ours.build()
|
||||
t0 = time.time()
|
||||
res = golden.evaluate()
|
||||
return {"결과": res, "시간": time.time() - t0, "원본": before}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def no_seeds():
|
||||
keep = hm._seeds
|
||||
hm._seeds = lambda: {}
|
||||
hm._targets.cache_clear()
|
||||
try:
|
||||
yield golden.evaluate(LABELED)
|
||||
finally:
|
||||
hm._seeds = keep
|
||||
hm._targets.cache_clear()
|
||||
|
||||
|
||||
def test_모든_파일_모든_줄(run):
|
||||
res = run["결과"]
|
||||
assert not res["못읽음"] and len(res["읽음"]) == 8
|
||||
assert {lab["id"] for lab in golden.labels()} == set(res["줄"])
|
||||
|
||||
|
||||
def test_사람_126_순위(run):
|
||||
got = golden.metrics(run["결과"], {"사람"})
|
||||
assert got["줄"] == 126
|
||||
assert got["1순위"] >= 116 # 92%
|
||||
assert got["다섯 안"] >= 122 # 96%
|
||||
|
||||
|
||||
def test_북부청_92_조합_전(run):
|
||||
rows = [r for r in run["결과"]["줄"].values() if r["lab"]["파일"] in LABELED[:2]]
|
||||
have = [r for r in rows if r["lab"]["정답"]]
|
||||
ok = sum((r["셈"].get("지문차례") or [None])[0] in r["lab"]["정답"] for r in have)
|
||||
assert len(have) == 92 and ok >= 81 # 88%
|
||||
|
||||
|
||||
def test_판정_맞음_다른_점_옵션(run):
|
||||
got = golden.metrics(run["결과"], {"사람"})
|
||||
assert got["맞음"] >= 55 and got["맞음 틀림"] <= 2
|
||||
assert got["다른 점 틀림"] <= 2
|
||||
assert got["옵션까지"] >= 50
|
||||
|
||||
|
||||
def test_새_파일_맞음_틀림(run):
|
||||
got = golden.metrics(run["결과"], {"자동", "씨앗", "자동+씨앗"})
|
||||
assert got["줄"] == 51 and got["맞음 틀림"] <= 3
|
||||
|
||||
|
||||
def test_조합_맞음(run):
|
||||
got = golden.metrics(run["결과"], {"사람"})
|
||||
assert got["조합 호표"] == 83 and got["조합 맞음"] >= 60 # 72%
|
||||
|
||||
|
||||
def test_씨앗_끔_1순위(no_seeds):
|
||||
got = golden.metrics(no_seeds, {"사람"})
|
||||
assert got["줄"] == 126 and got["1순위"] >= 111 # 88%
|
||||
|
||||
|
||||
def test_원본_그대로_셈_무게(run):
|
||||
assert master_hash() == run["원본"]
|
||||
assert run["결과"]["시간"]["북부청임도"] <= 300 # 북부청 임도 맞춤 셈 ≤ 5 분
|
||||
@@ -2,9 +2,13 @@
|
||||
맞춤 차례 · 기억 우선 · 길(보기 · 미리 채움 · 확정) · master_data 원본 그대로. 층은 임시 폴더.
|
||||
"""
|
||||
|
||||
import shutil
|
||||
|
||||
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_Template_Layers as layers
|
||||
|
||||
# 올리기 길 시험의 `client` 마당을 같이 씀
|
||||
@@ -86,88 +90,124 @@ def test_규격에서_입력값():
|
||||
assert values == {} and unread == ["뒷길이"] # 고르기 밖 수 = 빈 값 + 표시
|
||||
|
||||
|
||||
# ── 맞춤 차례 ────────────────────────────────────────────────────────
|
||||
# ── 맞춤 응답(338 · 설계 3-3) ─────────────────────────────────────────
|
||||
@pytest.fixture(autouse=True)
|
||||
def calc(tmp_path, monkeypatch):
|
||||
"""맞춤셈 캐시 = 임시 폴더(우리 지문 사본) · 뒤 셈은 시험이 바로 돌림(`run_job`)."""
|
||||
if not ours.ready():
|
||||
ours.build()
|
||||
cache = tmp_path / "hopyo_cache"
|
||||
cache.mkdir()
|
||||
shutil.copy(ours.path_of(), cache / ours.path_of().name)
|
||||
monkeypatch.setenv("AISLO_HOPYO_CACHE", str(cache))
|
||||
monkeypatch.setattr(fit, "ensure", fit.status)
|
||||
|
||||
|
||||
def _hopyo(client, no, layer="personal"):
|
||||
res = client.get(f"{URL.format(layer)}/HP-000001/{no}")
|
||||
assert res.status_code == 200, res.text
|
||||
return {one["이름"]: one["맞춤"] for one in res.json()["호표"]["줄"]}
|
||||
|
||||
|
||||
def test_이름_같음_후보_호표_퍼센트(client):
|
||||
def _ready(client, layer="personal"):
|
||||
assert _post(client, layer).status_code == 200
|
||||
folder = layers.personal_dir(7, 42) if layer == "personal" else client.system
|
||||
before = _hopyo(client, 1, layer)["레미콘타설(장비사용)"]
|
||||
assert before["상태"] == "후보" and "셈 중" in before["꼬리표"] # 셈 전 = 이름 · 근거 후보
|
||||
fit.run_job(folder, "HP-000001")
|
||||
return folder
|
||||
|
||||
|
||||
def test_새_상태_체크_제안(client):
|
||||
before = master_hash()
|
||||
assert _post(client).status_code == 200
|
||||
_ready(client)
|
||||
first = _hopyo(client, 1)
|
||||
remicon = first["레미콘타설(장비사용)"]
|
||||
assert remicon["상태"] == "맞음" and remicon["체크"] is True and "들어감" not in remicon
|
||||
target = remicon["대상"][0]
|
||||
assert target["로직"] == "GC000198" and target["입력값"]["소량감률"] == 50
|
||||
assert target["출처"]["소량감률"] == "블록" and target["배"] == 1
|
||||
assert remicon["품"]["같음"]["콘크리트공"] and remicon["품"]["엑셀"]["인력"]["콘크리트공"]
|
||||
plywood = first["합판거푸집"]
|
||||
assert plywood["상태"] == "같음" and plywood["대상"]["로직"] == "GF000160"
|
||||
assert plywood["입력값"] == {"횟수": "4회사용시"} and plywood["들어감"] is True
|
||||
remicon = first["레미콘(25-21-120)"]
|
||||
assert remicon["상태"] == "후보" and remicon["들어감"] is False
|
||||
assert all(c["규격"] == "25-21-120" for c in remicon["후보"][:3]) # 규격 같은 자재 먼저
|
||||
assert plywood["상태"] == "맞음" and set(plywood["갈리는칸"]) == {"측압", "폼타이규격"}
|
||||
mat = first["레미콘(25-21-120)"]
|
||||
assert mat["상태"] == "후보" and mat["체크"] is False
|
||||
assert all(c["규격"] == "25-21-120" for c in mat["후보"][:3]) # 규격 같은 자재 먼저
|
||||
dig = _hopyo(client, 3)["구조물터파기(인력100%)"]
|
||||
assert dig["상태"] == "후보" and len(dig["후보"]) == 5
|
||||
assert dig["후보"][0]["이름"] == "굴착(인력/토사)" # 330-2 근거(건설 3-2-1 · 특별인부) 1순위
|
||||
assert any(c["이름"].startswith("구조물터파기") for c in dig["후보"]) # 이름 1순위 자리
|
||||
assert dig["상태"] == "다른 점" and dig["체크"] is False
|
||||
assert dig["대상"][0]["로직"] == "GC000083" and len(dig["후보"]) == 5
|
||||
assert "특별인부 엑셀 0.3542 · 우리 0.3704" in dig["꼬리표"]
|
||||
ref = _hopyo(client, 45)["고화매트재료비"]
|
||||
assert ref["상태"] == "호표" and ref["대상"] == {"호표": 46, "단위": "㎡"} and ref["들어감"]
|
||||
assert ref["상태"] == "호표" and ref["체크"] is False and ref["글"] == "제46호표 먼저 확인"
|
||||
assert ref["대상"][0]["호표"] == 46 and ref["대상"][0]["단위"] == "㎡"
|
||||
pct = _hopyo(client, 46)["잡재료비"]
|
||||
assert pct["상태"] == "%" and pct["들어감"] is False
|
||||
assert pct["상태"] == "%" and pct["체크"] is False
|
||||
whole = client.get(f"{URL.format('personal')}/HP-000001").json()
|
||||
assert whole["맞춤"][1] == 415 and 0 < whole["맞춤"][0] < 415
|
||||
assert whole["맞춤"][1] == 415 and 0 < whole["맞춤"][0] < 415 and whole["셈"]["끝"]
|
||||
assert next(h for h in whole["호표"] if h["번"] == 61)["맞춤"] == [0, 0]
|
||||
one = client.get(f"{URL.format('personal')}/HP-000001/1").json()["호표"]
|
||||
assert one["셈"]["끝"] and one["만든"] is None and one["맞춤"][0] >= 2
|
||||
assert master_hash() == before
|
||||
|
||||
|
||||
def test_미리_채움_확정_기억_우선(client):
|
||||
assert _post(client).status_code == 200
|
||||
url = f"{URL.format('personal')}/HP-000001/3/guess"
|
||||
got = client.post(url, json={"차례": 1, "대상": {"로직": "GF000101"}}).json()
|
||||
assert got["환산"] == {"배": 1, "갈래": "같음"} and got["대상"]["단위"] == "㎥"
|
||||
assert client.post(url, json={"차례": 1, "대상": {"로직": "XX"}}).status_code == 400
|
||||
key = _hopyo(client, 3)["구조물터파기(인력100%)"]["열쇠"]
|
||||
assert key == "구조물터파기(인력100%)|토사|m3"
|
||||
body = {"줄": {key: {"로직": "GF000101", "입력값": {"지역": "서울"}, "환산": 1}}}
|
||||
assert client.post("/api/m02/layers/personal/hopyo-memory", json=body).status_code == 200
|
||||
dig = _hopyo(client, 3)["구조물터파기(인력100%)"]
|
||||
assert (dig["상태"], dig["대상"]["로직"], dig["입력값"], dig["들어감"]) == (
|
||||
"기억",
|
||||
"GF000101",
|
||||
{"지역": "서울"},
|
||||
True,
|
||||
def _ledger(client, rows, layer="personal"):
|
||||
res = client.put(f"/api/m02/layers/{layer}/hopyo-ledger", json={"줄": rows})
|
||||
assert res.status_code == 200, res.text
|
||||
|
||||
|
||||
def test_별칭_체크_규칙(client):
|
||||
_ready(client)
|
||||
dig = "구조물터파기(인력100%)|토사|m3"
|
||||
remicon = "레미콘타설(장비사용)|철근구조물-소량타설|m3"
|
||||
_ledger(
|
||||
client,
|
||||
{
|
||||
dig: {"갈래": "짝", "짝": [{"로직": "GC000083", "배": 1}]},
|
||||
remicon: {"갈래": "짝", "짝": [{"로직": "GC000199", "배": 1}]},
|
||||
"합판거푸집|6회|m2": {"갈래": "짝", "짝": [{"로직": "GC000211", "배": 1}]},
|
||||
"면목|구멍|개": {"갈래": "우리에 없음"},
|
||||
},
|
||||
)
|
||||
# 이름 같음보다 기억이 앞섬 · 빼기
|
||||
plywood = _hopyo(client, 1)["합판거푸집"]["열쇠"]
|
||||
out = {"줄": {plywood: {"빼기": True}}}
|
||||
assert client.post("/api/m02/layers/personal/hopyo-memory", json=out).status_code == 200
|
||||
assert _hopyo(client, 1)["합판거푸집"]["상태"] == "빼기"
|
||||
clear = {"줄": {plywood: None}}
|
||||
assert client.post("/api/m02/layers/personal/hopyo-memory", json=clear).status_code == 200
|
||||
assert _hopyo(client, 1)["합판거푸집"]["상태"] == "같음"
|
||||
got = _hopyo(client, 3)["구조물터파기(인력100%)"]
|
||||
assert got["상태"] == "별칭" and got["체크"] is True and got["대상"][0]["출처"] == {}
|
||||
assert got["별칭"]["층"] == "personal" and not got["별칭"]["근거다름"]
|
||||
first = _hopyo(client, 1)
|
||||
other = first["레미콘타설(장비사용)"] # 숫자 판정 맞음 = GC000198 → 체크 안 함
|
||||
assert other["상태"] == "별칭" and other["체크"] is False
|
||||
assert "숫자 판정 맞음 = GC000198" in other["꼬리표"]
|
||||
loose = first["합판거푸집"] # 규격 4회 ↔ 장부 6회 — 느슨 열쇠
|
||||
assert loose["상태"] == "별칭" and loose["별칭"]["규격다름"] and loose["체크"] is False
|
||||
_ledger(client, {dig: {"갈래": "짝", "짝": [{"로직": "GF000101", "배": 1}]}})
|
||||
off = _hopyo(client, 3)["구조물터파기(인력100%)"] # 산림 로직 ↔ 엑셀 건설 3-2-1
|
||||
assert off["별칭"]["근거다름"] and off["체크"] is False and "근거 다름" in off["꼬리표"]
|
||||
|
||||
|
||||
def test_확정_검사와_위_층_기억(client):
|
||||
bad = [
|
||||
{"로직": "GC000422", "환산": 1}, # 돈 아닌 로직
|
||||
{"로직": "GF000101", "환산": 0},
|
||||
{"로직": "GF000101", "자재": "MT004258", "환산": 1},
|
||||
{"환산": 1},
|
||||
]
|
||||
for one in bad:
|
||||
res = client.post("/api/m02/layers/personal/hopyo-memory", json={"줄": {"a|b|c": one}})
|
||||
assert res.status_code == 400, one
|
||||
assert client.post("/api/m02/layers/system/hopyo-memory", json={"줄": {}}).status_code == 403
|
||||
def test_장부_뺌_위_층(client):
|
||||
client.who.update(role="SYSTEM_ADMIN")
|
||||
key = "구조물터파기(인력100%)|토사|m3"
|
||||
body = {"줄": {key: {"로직": "GF000103", "환산": 1}}}
|
||||
assert client.post("/api/m02/layers/system/hopyo-memory", json=body).status_code == 200
|
||||
_ledger(client, {key: {"갈래": "안 씀"}}, "system")
|
||||
client.who.update(role="USER")
|
||||
assert _post(client).status_code == 200
|
||||
assert _hopyo(client, 3)["구조물터파기(인력100%)"]["대상"]["로직"] == "GF000103" # 위 층
|
||||
mine = {"줄": {key: {"로직": "GF000101", "환산": 1}}}
|
||||
assert client.post("/api/m02/layers/personal/hopyo-memory", json=mine).status_code == 200
|
||||
assert _hopyo(client, 3)["구조물터파기(인력100%)"]["대상"]["로직"] == "GF000101" # 같은 층 먼저
|
||||
_ready(client)
|
||||
got = _hopyo(client, 3)["구조물터파기(인력100%)"]
|
||||
assert got["상태"] == "뺌" and got["뺌"] == "안 씀" and got["별칭"]["층"] == "system"
|
||||
assert hm.chain(layers.personal_dir(7, 42))[1] == layers.company_dir(7)
|
||||
|
||||
|
||||
def test_미리_셈_목록_낱개(client):
|
||||
folder = _ready(client)
|
||||
url = f"{URL.format('personal')}/HP-000001/1/guess"
|
||||
one = client.post(url, json={"차례": 1, "대상": {"로직": "GC000198"}})
|
||||
assert one.status_code == 200, one.text
|
||||
assert one.json()["대상"][0]["환산"] == {"배": 1, "갈래": "같음"}
|
||||
assert client.post(url, json={"차례": 1, "대상": {"로직": "XX"}}).status_code == 400
|
||||
body = [{"로직": "GC000198", "입력값": {"타설방법": "장비사용타설", "소량감률": 50}}]
|
||||
got = hm.guess(folder, "HP-000001", 1, 1, body)
|
||||
assert got["대상"][0]["출처"]["소량감률"] == "고름"
|
||||
assert got["품"]["같음"]["콘크리트공"] and got["품"]["엑셀"]["인력"]["콘크리트공"]
|
||||
plain = hm.guess(folder, "HP-000001", 1, 1, [{"로직": "GC000198", "입력값": {"소량감률": 0}}])
|
||||
assert not plain["품"]["같음"]["콘크리트공"] # 옵션을 바꾸면 우리 품이 바뀜
|
||||
|
||||
|
||||
def test_로직_추가_고르기_줄은_이_층과_위_층(client):
|
||||
client.who.update(role="SYSTEM_ADMIN")
|
||||
assert _post(client, "system").status_code == 200
|
||||
@@ -197,7 +237,7 @@ def test_뜻_낱말이_안_겹치면_후보_아님():
|
||||
assert hm.candidates(soil, "로직") == [] # 「처리」 두 글자만 겹침(소금처리 · 바탕처리)
|
||||
stone = {"이름": "임도표지석(받침,글새김포함)", "규격": "", "단위": "㎥", "갈래": "자재"}
|
||||
assert hm.candidates(stone, "자재") == [] # 속도표지판 · 도로표지용페인트
|
||||
got = hm.match_line(soil, [], {})
|
||||
assert got["상태"] == "없음" and got["후보"] == []
|
||||
got = hm.b_order(soil)
|
||||
assert got["상태"] == "없음" and got["top"] == []
|
||||
fill = {"이름": "구조물되메우기(인력100%)", "규격": "", "단위": "㎥", "갈래": "단가산출"}
|
||||
assert hm.candidates(fill, "로직")[0]["이름"] == "되메우기" # 한쪽 낱말에 듦 = 겹침
|
||||
|
||||
Reference in New Issue
Block a user