확정 2차 ② 후반 「사용자가 값을 바꿀 수 있게」. 식은 이미 있었고 없던 것은 덮어쓸 칸이었음. - 등록부(돌쌓기 계열 다섯 종류)에 `thickness_top_m`·`thickness_bottom_m` 칸을 둠. 큰돌쌓기는 두께 식이 달라 뺐고 화면에서도 그 장에는 안 뜸. - 빈 칸은 「안 정함」 — 자동값을 저장에 박지 않음. 상부만 넣으면 하부는 그 위에서 식을 이음. - 근거 문구가 어디서 온 값인지 적음(「사용자 입력」 / 「뒷길이 45㎝ + 0.3」). 화면 실측(랩탑_보조, 표준도 3장 돌쌓기(찰)) — 0.60 넣고 저장하니 2개소 반영, 입적 24.375 → 20.625㎥ 로 움직였고 칸을 비워 되돌리니 24.375 로 복귀함. 시험 다섯 추가, 전체 1203 통과·실패 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
135 lines
5.9 KiB
Python
135 lines
5.9 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["야면석·호박돌"]
|
||
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
|