Files
Aislo/resources/tester/test_812_9_machine_link.py
T
eomsangdonandClaude Opus 5.5 ae8d098a10 fix(815-3): 합친 뒤 시험 셋 가름 · 시간당 경비 식 조종원 차례 · 호표 기계 글 머리 꼬리 · 합친 판 요약 다시 잼
- 809_1 이름 = 진짜 흠 + 낡은 기대 — 읽기기(812-1)가 지은 율 줄 이름 「율」이 엑셀 글 머리로 안 바뀜 → `Import_Shape._MADE` 에 율 더함 · 합계 = 차림 글줄 · 기계 = 한 줄(이름 · 규격 칸) 은 낡은 기대 고침 · 금액 15,935 · 336 · 723 · 16,994 그대로
- 812_9 별칭 = 낡은 기대 — 815-2 가 아스팔트페이버 별칭을 마스터 기계 줄 칸으로 옮겨 「넣기 전 못 찾음」 이 안 맞음 · 시험은 마스터 칸으로 봄 · 부르는 곳 없는 `M02_Machine_Find.learn`(옛 장부 쓰기) · `by_code` · `same_kind`(걷은 연결 찾기 몫) 지움
- 804_2 hourly = 낡은 기대 — 814-1 이 GC000268 목록을 117 → 209 로 늘려 겹친 116 대 고름이 GC000269 로 뒤집힘(116 대 모두 원 단위 같음) · 같은 로직 줄만 대던 시험 → 같은 갈래 식(부착 · 손료만 · 조종원) 줄 모두 댐
- 진짜 흠(브레인 갈래 가) — GC000272 「조종원 없는 기종」 목록에 기계표 조종원 1 인 9 대가 겹쳐 목록 길이 차례로 고름 → `logic_of` = 기계표 조종원 > 0 이면 조종원 호표 든 식 먼저 · 불러오기 `hourly_link` 도 같은 길 · 바뀐 4 대 = 진동롤러(핸드가이드식) 0.7ton 6,557 → 41,969 · 래머 80kg 1,959 → 23,708 · 플레이트 콤팩터 1.5ton 2,855 → 24,604 · 발전기 100kW 45,535 → 67,284(M01 문서 금액 그대로) · 시험에 9 대 굳힘
- 778_5 기계 표 = 진짜 흠 — 812-9 찾기가 호표 기계 글 「운 반 : 덤프트럭(4.5Ton)」 · 「…[hr] : 90%」 · 「(90%)」 머리 꼬리를 안 뗌 → `Hopyo_Fixed._eqs` 쌍점 조각 · 율 꼬리 뗌 · 이어짐 187 · 고를 것 1 · 못 이음 2(조합 한 줄 · 괄호 깨짐) · 모두 이음 블록 161
- 721 단추 자리 = 낡은 기대(808-1 [단가 갱신][재생성] tools 더함)
- 815-1 보고 요약에 「합친 뒤」 열 — 기계 이음 95.7 % · 우리 값 원파일 1,891 · 0 원 줄 블록 147

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 16:32:28 +09:00

197 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""812-9 지킴 — 가져온 기계 잇기(`M02_Machine_Find` · 요구 718 · 719).
(a) 기계표 전체에서 찾음 — 낱말표 밖 기종(로우더 · 공기 압축기 · 램 머 · 라인마커 …) · 후보 여럿이던 것
(물탱크 · 크레인(무한궤도) · 머캐덤 · 콘크리트 펌프차 …) · 지어 맞추기 없음(1.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 # noqa: E402 — M01 별칭 칸 임시
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("덤프트럭", "1.0Ton")
assert got["판정"] == mf.NONE and got["까닭"] == "우리 표에 없음(규격)" and got["키"] is None
assert got["후보"][0]["규격"] == "2.5ton" # 보여주기만 — 가까운 규격 먼저
for name, spec in (("에어 호스", "1.91cm"), ("모노펌프", "5-20㎥/hr")): # 승인 전 = 별칭 몫
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("덤프트럭", "1.0Ton"), "덤프트럭", "1.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`."""
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["브레이카"]["기호"]