- 양식 갈음의 종류 이름 치환(_downstream_name) 삭제 · 돌쌓기·골막이·바닥막이(메) 전개도 「돌」+규격 - 자재총괄 줄에 spec·supply_key — 관급구분 열쇠는 이름+규격, 옛 열쇠(이름만·종류 이름)도 받음 - 화면 자재총괄 이름 칸·원단위 성분 칸에 규격 표시, 관급 선택은 supply_key 로 저장 - 원단위 합계 열쇠에 규격 포함 · 종류 이름 DESTINATION 항목 정리 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
136 lines
6.0 KiB
Python
136 lines
6.0 KiB
Python
"""계수 갈래·채움콘 강도·돌 중량 근거 (2026-09-08 사용자 확정 2차 ⑤·⑨·⑩).
|
||
|
||
⚠ 겨누는 것 여섯
|
||
① **빈 칸은 「안 정함」**이다 — 기본값은 등록부가 아니라 계산 쪽이 갖는다
|
||
② ⑨ 기본은 **품셈 열**(야면석 고임돌 0.11 · 채움 0.15)
|
||
③ ⑨ 「실무 관행」으로 두면 건설품셈 참고자료 열(0.15 · 0.20)로 덮이고 사유가 뜬다
|
||
④ ⑩ 강도 기본은 **210**, 180 을 고르면 그 값이 이긴다
|
||
⑤ ⚠ 아는 값이 아니면 **조용히 넘어가지 않는다**
|
||
⑥ ⑤ 돌 중량은 값을 그대로 두되 **어디서 온 값인지**가 줄에 적힌다
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parents[2]
|
||
sys.path.insert(0, str(ROOT))
|
||
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import ( # noqa: E402
|
||
FILL_CONCRETE_MPA_DEFAULT,
|
||
fill_concrete_mpa,
|
||
stone_masonry,
|
||
wants_practice_coefficients,
|
||
)
|
||
|
||
|
||
def 성분(**options: object) -> tuple[dict, list[str]]:
|
||
components, notes = stone_masonry(
|
||
2.5, 10.0, {"height_m": 2.5, "length_m": 10.0, "back_len_cm": 45, **options}, wet=True
|
||
)
|
||
return {c.name: c for c in components}, notes
|
||
|
||
|
||
def test_빈_칸은_안_정함이다() -> None:
|
||
assert wants_practice_coefficients({}) is False
|
||
assert fill_concrete_mpa({})[0] == FILL_CONCRETE_MPA_DEFAULT == "210"
|
||
|
||
|
||
def test_기본은_품셈_열이다() -> None:
|
||
"""야면석을 고르면 품셈 계수(고임돌 0.11 · 채움 0.15)가 선다 — 확정 ⑨."""
|
||
got, _ = 성분(stone_kind="야면석·호박돌")
|
||
돌쌓기 = got["돌쌓기"].amount
|
||
assert abs(got["고임돌"].amount - 돌쌓기 * 0.11) < 0.01
|
||
assert abs(got["채움콘크리트"].amount - 돌쌓기 * 0.15) < 0.01
|
||
|
||
|
||
def test_실무_관행으로_두면_덮이고_사유가_뜬다() -> None:
|
||
"""⚠ 값이 조용히 바뀌면 안 된다 — 덮어썼다는 사실이 사유로 나온다."""
|
||
got, notes = 성분(stone_kind="야면석·호박돌", stone_coeff_basis="실무 관행")
|
||
돌쌓기 = got["돌쌓기"].amount
|
||
assert abs(got["고임돌"].amount - 돌쌓기 * 0.15) < 0.01
|
||
assert abs(got["채움콘크리트"].amount - 돌쌓기 * 0.20) < 0.01
|
||
assert any("실무 관행" in n for n in notes)
|
||
|
||
|
||
def test_강도는_기본_210이고_고르면_그_값() -> None:
|
||
기본, _ = 성분()
|
||
assert 기본["채움콘크리트"].spec == "210"
|
||
assert "확정 ⑩" in 기본["채움콘크리트"].basis
|
||
고름, _ = 성분(fill_concrete_mpa="180")
|
||
assert 고름["채움콘크리트"].spec == "180"
|
||
assert "고른 값" in 고름["채움콘크리트"].basis
|
||
|
||
|
||
def test_모르는_강도는_조용히_넘어가지_않는다() -> None:
|
||
강도, basis = fill_concrete_mpa({"fill_concrete_mpa": "240"})
|
||
assert 강도 == "210"
|
||
assert "240" in basis
|
||
|
||
|
||
def test_돌_중량은_값을_두고_근거를_남긴다() -> None:
|
||
"""⚠ 품셈·교본에 돌중량표가 없다 — 값은 그대로 두고 출처를 줄에 단다(확정 ⑤).
|
||
|
||
⚠ 2026-09-09 확정 5차 큰 것 7 로 **관측표를 보는 자리가 야면석 계열로 좁아졌다** —
|
||
종류를 안 고르면 계산식(뒷길이 × 0.77 × 2.65)으로 선다. 출처를 다는 못은 그대로이되
|
||
**어느 조건에서 다는지**가 달라졌으므로 조건을 명시한다.
|
||
"""
|
||
got, _ = 성분(stone_kind="야면석·호박돌")
|
||
야면석 = got["돌"] # 이름 「돌」 + 규격에 종류(명세 13장 Ⓒ)
|
||
assert 야면석.spec == "야면석·호박돌"
|
||
assert abs(야면석.amount - got["돌쌓기"].amount * 0.88) < 1e-9
|
||
assert "울진" in 야면석.basis and "품셈·교본에는 돌중량표가 없음" in 야면석.basis
|
||
assert 야면석.source == "uljin_library"
|
||
|
||
|
||
def test_안_고르면_계산식으로_서고_그_사실이_적힌다() -> None:
|
||
"""⚠ 값이 서는 것으로 끝나면 **관측값인지 계산값인지**를 화면에서 못 가른다."""
|
||
got, notes = 성분()
|
||
돌 = got["돌"]
|
||
assert 돌.source == "" # 관측 출처가 아니다
|
||
assert "0.77" in 돌.basis and "2.65" in 돌.basis
|
||
assert any("계산식" in n for n in notes)
|
||
|
||
|
||
def test_두께_칸이_비면_식으로_돈다() -> None:
|
||
"""확정 2차 ② 후반 「사용자가 값을 바꿀 수 있게」 — 빈 칸은 「안 정함」이다."""
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import wall_thickness
|
||
|
||
top, bottom, basis = wall_thickness({}, back_cm=45, height_m=2.5)
|
||
assert abs(top - 0.75) < 1e-9 # 뒷길이 0.45 + 0.30
|
||
assert abs(bottom - 1.20) < 1e-9 # 상부 + 0.30 × (2.5 − 1.0)
|
||
assert "뒷길이" in basis and "사용자 입력" not in basis
|
||
|
||
|
||
def test_넣은_두께가_식을_이긴다() -> None:
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import wall_thickness
|
||
|
||
top, bottom, basis = wall_thickness(
|
||
{"thickness_top_m": 0.6, "thickness_bottom_m": "1.0"}, back_cm=45, height_m=2.5
|
||
)
|
||
assert (top, bottom) == (0.6, 1.0)
|
||
assert basis.count("사용자 입력") == 2
|
||
|
||
|
||
def test_상부만_넣으면_하부는_그_위에서_식을_잇는다() -> None:
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import wall_thickness
|
||
|
||
top, bottom, _ = wall_thickness({"thickness_top_m": 0.6}, back_cm=45, height_m=2.5)
|
||
assert (top, abs(bottom - 1.05) < 1e-9) == (0.6, True) # 0.6 + 0.30 × 1.5
|
||
|
||
|
||
def test_두께가_입적까지_닿는다() -> None:
|
||
"""칸만 만들고 계산이 안 읽으면 「값이 안 닿는」 옛 사고와 같아진다."""
|
||
기본, _ = 성분()
|
||
두꺼움, _ = 성분(thickness_top_m=1.2, thickness_bottom_m=1.6)
|
||
assert 두꺼움["입적"].amount > 기본["입적"].amount
|
||
|
||
|
||
def test_이상한_값은_식으로_돌린다() -> None:
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import wall_thickness
|
||
|
||
for bad in ("", None, "두꺼움", -1, 0):
|
||
top, _, basis = wall_thickness({"thickness_top_m": bad}, back_cm=45, height_m=2.5)
|
||
assert abs(top - 0.75) < 1e-9 and "사용자 입력" not in basis, bad
|