"""812-9 지킴 — 가져온 기계 잇기(`M02_Machine_Find` · 요구 718 · 719). (a) 기계표 전체에서 찾음 — 낱말표 밖 기종(로우더 · 공기 압축기 · 램 머 · 라인마커 …) · 후보 여럿이던 것 (물탱크 · 크레인(무한궤도) · 머캐덤 · 콘크리트 펌프차 …) · 지어 맞추기 없음(3.0Ton = 우리 표에 없음) (b) 표기 정규화 · 괄호 낱말(무한궤도 · 타이어 · 일반용 · 표에 없는 낱말 발파 = 안 봄) · 범위 · 복수 규격 (c) 조합 기계 = 둘(대형브레이카 +굴착기 · 0.7+브레이카 · +부착용집게 · +진동콤팩터 · 덤프트럭(자동덮개)) (d) 별칭 먼저 — M01 기계 줄 「별칭」 칸(815-1 · 시험 안 임시 별칭) · 이름 + 규격 통째 = 그 EQ · 이름만 = 그 기종으로 · 후보 여럿 표지(옛 층 장부 쓰기 `learn` = 815-2 장부 걷기로 지움) (e) 금액 전후 같음 — 조합 줄 둘(첫 줄 엑셀 값 · 다음 줄 0) · 원파일 저장 금액 그대로 """ from __future__ import annotations import sys from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] HERE = Path(__file__).resolve().parent for p in (ROOT, HERE): if str(p) not in sys.path: sys.path.insert(0, str(p)) from M02_MasterTemplete import M02_Elem_Alias as ea # noqa: E402 from M02_MasterTemplete import M02_Machine_Find as mf # noqa: E402 from test_815_1_import_link import aliases, no_aliases # noqa: E402 — M01 별칭 칸 임시 @pytest.fixture(autouse=True) def _blank_aliases(): """진짜 마스터 기계 별칭 내용 · 수와 무관 — 별칭이 필요한 시험은 스스로 넣음.""" with no_aliases("EQ"): yield def one(name: str, spec: str = "") -> tuple[str, str, str]: got = mf.find(name, spec) first = got["후보"][0] if got["후보"] else {} return got["판정"], str(first.get("이름") or ""), str(first.get("규격") or "") LINKED = [ # 낱말 모름 · 후보 여럿이던 예(812-8) → 하나 ("로우더(타이어)", "0.57㎥", "로더(타이어)", "0.57㎥"), ("로우더(타이어)", "1.72㎥", "로더(타이어)", "1.72㎥"), ("공기 압축기", "21.0㎥/min", "공기압축기(이동식)", "21.0㎥/min"), ("공기 압축기", "7.1㎥/min", "공기압축기(이동식)", "7.1㎥/min"), ("라인마커", "10Km/hr", "라인 마커", "10km/hr"), ("램 머", "80kg", "래 머", "80㎏"), ("진동파일해머", "60kW", "진동파일 해머(전동식)", "60㎾"), ("진동파일해머", "45kW", "진동파일 해머(전동식)", "45㎾"), ("진동파일해머", "40kW", "진동파일 해머(전동식)", "40㎾"), ("노면파쇄기", "2.0m", "노면파쇄기", "2.0m"), ("아스팔트 디스트리뷰터", "3800ℓ", "아스팔트 디스트리뷰터", "3,800ℓ"), ("고소작업차", "3Ton", "고소작업차", "3ton"), ("고소작업차", "5Ton", "고소작업차", "5ton"), ("취부기(녹생토)", "18.65kW", "취부기(녹생토 암절개면 보호식재용)", "18.65㎾"), ("아스팔트 스프레이어", "400ℓ", "아스팔트 스프레이어", "400ℓ"), ("커 터", "320~400mm", "커터(콘크리트 및 아스팔트용)", "320~400"), ("경운기", "1000kg", "경운기", "1,000㎏"), ("건설용펌프(자흡식)", "50mm", "건설용펌프(자흡식)", "50(1.49×10)"), ("강연선인장기", "120Ton", "강연선인장기", "120ton"), ("물탱크", "5500ℓ", "물탱크(살수차)", "5,500ℓ"), ("물탱크", "16000ℓ", "물탱크(살수차)", "16,000ℓ"), ("콘크리트 펌프차", "32m,80~95㎥/hr", "콘크리트 펌프차", "32 [80∼95]"), ("머캐덤 로울러(자주식)", "10~12Ton", "머캐덤 롤러(자주식)", "10∼12"), ("타이어 로울러(자주식)", "8~15Ton", "타이어 롤러(자주식)", "8∼15"), ("크레인(무한궤도)", "40Ton", "크레인(무한궤도)", "40 (1.53)"), ("크레인(무한궤도)", "35Ton", "크레인(무한궤도)", "35 (1.33)"), ("크로울러 드릴(공기식)", "17㎥/min", "크롤러드릴(공기식)", "17 (120㎜)"), ("모터 그레이더", "3.6m(일반용)", "모터그레이더(일반용)", "3.6m"), ("콘크리트 믹서", "0.3㎥", "콘크리트 믹서", "0.30㎥"), ("진동 로울러(자주식)", "12Ton", "진동롤러(자주식)", "12ton"), ("굴삭기(무한궤도)", "0.7㎥", "굴착기(무한궤도)", "0.7㎥"), ("굴착기(타이어형)", "0.6㎥", "굴착기(타이어)", "0.6㎥"), ("굴착기(무한궤도)", "0.4㎥(발파)", "굴착기(무한궤도)", "0.4㎥"), ("불도우저(무한궤도)", "32Ton", "불도저(무한궤도)", "32ton"), ] @pytest.mark.parametrize("name,spec,our,size", LINKED) def test_linked(name: str, spec: str, our: str, size: str) -> None: kind, *got = one(name, spec) assert kind in (mf.LINKED, mf.ALIAS) and got == [our, size] # 승인 별칭(디젤 엔진) = 별칭 MASTER = [ # 마스터 층 승인 별칭(요구 735-5 · 736) — 이름 별칭 + 규격은 수로 맞댐 ("아스팔트페이버(피니셔)", "3.0m", "EQ000193"), ("아스팔트페이버(피니셔)", "1.7m", "EQ000192"), ("디젤 엔진", "11.19kW", "EQ000500"), ("디젤 엔진", "26.11kW", "EQ000503"), ("디젤 엔진", "52.22kW", "EQ000504"), ("워터제트", "96kW", "EQ000400"), ("버킷준설기", "7.46kW", "EQ000425"), ("바이브레이트", "봉상후렉시블", "EQ000248"), ] # 마스터 기계 별칭 다섯(815-2 가 기계 줄 「별칭」 칸으로 옮김) — 칸이 비었으면 시험 동안만 넣음 FIVE = {"EQ000193": "아스팔트페이버(피니셔)", "EQ000500": "디젤 엔진", "EQ000400": "워터제트", "EQ000425": "버킷준설기", "EQ000248": '"바이브레이트 봉상후렉시블"'} # fmt: skip @pytest.mark.parametrize("name,spec,eq", MASTER) def test_master_alias(name: str, spec: str, eq: str) -> None: rows = ea.book()["줄"]["EQ"] with aliases("EQ", {k: v for k, v in FIVE.items() if not rows[k].get("별칭")}): got = mf.find(name, spec) assert got["키"] == eq and got["판정"] in (mf.LINKED, mf.ALIAS) def test_no_guess() -> None: """우리 표에 없는 규격 = 못 찾음(가까운 규격으로 안 이음) · 기종 모름 = 별칭 몫 · 여럿 = 여럿.""" got = mf.find("덤프트럭", "3.0Ton") assert got["판정"] == mf.NONE and got["까닭"] == "우리 표에 없음(규격)" and got["키"] is None assert got["후보"][0]["규격"] == "2.5ton" # 보여주기만 — 가까운 규격 먼저 for name, spec in ( ("진공흡입기", "5kW"), ("스키드로더", "0.3㎥"), ): # 우리 표에 없는 기종 = 별칭 몫 got = mf.find(name, spec) assert (got["판정"], got["까닭"]) == (mf.NONE, "기종 모름 — 별칭") got = mf.find("크레인(트럭)", "10Ton") # 「트럭」 = 기계표 괄호에 없는 낱말 → 안 봄 assert got["판정"] == mf.MANY and got["수"] == 2 assert mf.mark(got, "크레인(트럭)", "10Ton").startswith("참고 · 기계 후보 2 — 고르기") assert "기계 못 찾음" in mf.mark(mf.find("덤프트럭", "3.0Ton"), "덤프트럭", "3.0Ton") assert mf.mark(mf.find("물탱크", "5500ℓ"), "물탱크", "5500ℓ") is None def test_norm_paren_spec() -> None: assert mf.norm("로우더") == mf.norm("로더") and mf.norm("로울러") == mf.norm("롤러") assert mf.norm("브레이카") == mf.norm("브레이커") and mf.norm("굴삭기") == mf.norm("굴착기") assert mf.norm("불도우저") == mf.norm("불도저") and mf.norm("램 머") == mf.norm("래 머") assert mf.tokens("10~12Ton") == [(10.0, 12.0, "ton")] assert mf.tokens("32m,80~95㎥/hr") == [(32.0, 32.0, "m"), (80.0, 95.0, "m3/hr")] assert mf.tokens("5,500ℓ") == [(5500.0, 5500.0, "l")] assert mf.spec_fit(mf.tokens("0.7㎥"), mf.tokens("0.6∼0.8")) == "안" assert one("굴착기(타이어)", "0.6㎥")[1] == "굴착기(타이어)" # 괄호 낱말이 가름 assert one("굴착기(무한궤도)", "0.6㎥")[1] == "굴착기(무한궤도)" COMBO = [ # 조합 기계 = 둘 · 규격 없는 쪽 = 앞 규격 ("굴삭기(무한궤도)", "0.7+브레이카", [("굴착기(무한궤도)", "0.7㎥"), ("대형 브레이커", "0.7㎥")]), ("대형브레이카", "+굴착기(0.7㎥)", [("대형 브레이커", "0.7㎥"), ("굴착기(무한궤도)", "0.7㎥")]), ("대형브레이카", "+굴착기(0.4㎥)", [("대형 브레이커", "0.4㎥"), ("굴착기(무한궤도)", "0.4㎥")]), ("굴삭기+진동콤팩터", "0.7㎥", [("굴착기(무한궤도)", "0.7㎥"), ("유압식 진동콤팩터(굴착기 부착용)", "0.7㎥")]), ("굴삭기(무한궤도)", "0.2㎥+부착용집게", [("굴착기(무한궤도)", "0.2㎥"), ("부착용 집게", "0.2㎥")]), ("굴삭기(무한궤도)", "0.6㎥+부착용집게", [("굴착기(무한궤도)", "0.6㎥"), ("부착용 집게", "0.6∼0.8")]), ("로우더(타이어)+소형노면파쇄기", "0.95㎥", [("로더(타이어)", "0.95㎥"), ("소형노면파쇄기", "0.95㎥")]), ("덤프트럭(자동덮개)", "15Ton", [("덤프트럭", "15ton"), ("덤프트럭 자동덮개시설", "15톤용")]), ("굴삭기(무한궤도)", "0.7㎥,(브레이커조합)", [("굴착기(무한궤도)", "0.7㎥"), ("대형 브레이커", "0.7㎥")]), ] # fmt: skip @pytest.mark.parametrize("name,spec,want", COMBO) def test_combo_two(name: str, spec: str, want: list) -> None: got = mf.find_all(name, spec) assert [g["판정"] for g in got] == [mf.LINKED, mf.LINKED] assert [(g["후보"][0]["이름"], g["후보"][0]["규격"]) for g in got] == want def test_combo_many_part() -> None: """대형브레이카 +굴착기(1.0㎥) — 굴착기 무한궤도 · 타이어 둘 다 1.0 = 그 쪽만 후보 여럿(사용자 고름).""" got = mf.find_all("대형브레이카", "+굴착기(1.0㎥)") assert [g["판정"] for g in got] == [mf.LINKED, mf.MANY] assert mf.find_all("덤프트럭", "15Ton") == [{**mf.find("덤프트럭", "15Ton"), "이름": "덤프트럭", "규격": "15Ton"}] # fmt: skip def test_alias_first_master_column() -> None: """마스터 기계 줄 「별칭」 칸(815-2 옮김) — 이름만 별칭 = 그 기종 → 규격으로 하나 · 통째 별칭 · 할증 글 · 후보 여럿 = `test_815_1_import_link.test_alias_machine`.""" with aliases("EQ", FIVE): # 다섯만 넣음(더 있어도 비워져 있음) got = mf.find("아스팔트페이버(피니셔)", "3.0m") assert (got["판정"], got["후보"][0]["이름"], got["후보"][0]["규격"]) == ( mf.ALIAS, "아스팔트 피니셔", "3m") # fmt: skip assert mf.find("크레인(트럭)", "10Ton")["판정"] == mf.MANY # 크레인 별칭은 비움 · 여럿 def test_combo_money_same() -> None: """원파일 거창 측구터파기 연암 — 「굴삭기(무한궤도) 0.7+브레이카」 = 줄 둘 · 금액 = 원파일 저장 그대로.""" from test_810_2_native_doc import doc_and_money, native from M02_MasterTemplete import M02_Doc_FromNative as fn saved = native("EST", "거창") blk = fn.numbers(saved)[2] sk, doc, money = doc_and_money(fn.emit(saved, 2)) names = [(m["이름"], m.get("규격")) for m in doc["금액"]] assert ("굴삭기(무한궤도)", "0.7") in names and ( "대형 브레이커", "0.7㎥", ) in names # 첫 줄 규격 = 그 기계(814-1) assert float(money["계"]) == pytest.approx(float(blk["저장"]["T"]), abs=1) found = {x["원래"]["이름"]: x for x in doc["가져온"]["기계"]} assert found["브레이카"]["조합"] is True and found["브레이카"]["찾기어"] == "대형 브레이커" assert any("조합 기계 — 경비는 한 덩이" in m for m in doc["가져온"]["표지"]) from M02_MasterTemplete import M02_Doc_NativeLayout as lay from test_812_3_native_layout import _show groups = [(g[0], g[2]) for g in _show(doc)] # 조합 기계 = 기계마다 항목(요구 738-3) assert ("굴착기(무한궤도) 0.7㎥", ["=Q", "굴삭기(무한궤도)"]) in groups assert ("대형 브레이커 0.7㎥", ["대형 브레이커"]) in groups owned = lay.owned_of(doc) # 못 이은 기계 줄(시간당 자료 없음 = 숫자 묶음)도 기계 = 이름 단추 at = next(i for i, m in enumerate(doc["금액"]) if m["이름"] == "대형 브레이커") assert owned.get(at) == found["브레이카"]["기호"]