Files
Aislo/resources/tester/test_b08_collected_stone.py
eomsangdonandClaude Opus 5 d7cb14f416 test(B08): tmp/tests 중 tester 에 없던 47 개를 resources/tester 로 옮김
tmp/ 가 창끼리 안 건너가는 것이 확정돼(랩탑이 시간 두고 두 번 확인) 시험·예외가
저절로 건너가도록 git 안으로 옮김. 사용자 확정.

- 내용은 하나도 안 고침 — 자리만 옮김. tmp/tests 는 남겨 둠.
- 같은 이름이 이미 있던 64 개는 랩탑 것을 그대로 두고 건너뜀.
- helper_b05_*.js 둘은 랩탑이 .cjs 로 이미 올린 것과 **줄바꿈만 다른 같은 내용**이라
  복사본을 도로 뺌(시험이 .cjs 를 부름).
- resources/tester/ 에서 전체 1176 통과 · 29 건너뜀 · 실패 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 17:15:57 +09:00

105 lines
3.7 KiB
Python
Raw Permalink 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.
"""채집석 공제 — 캐서 쓴 돌만큼 사토가 준다 (2026-09-09 사용자 확정 ②).
⚠⚠ **공제는 사토에서 한 번만 한다.** B08 은 소요량(㎥ **양수**)을 내기만 하고 빼지 않는다.
빼는 자리는 유토곡선의 사토뿐이다 — 실어 내는 몫에서 먼저 빼고 모자라면 자연방토에서.
⚠ 겨누는 것 다섯
① 기본은 「캔다」 — 정한 적 없으면 공제가 선다(법이 「가급적 현장 채취」)
② 「구입」으로 둔 구조물은 **공제 없음** — 구조물마다 갈린다
③ ⚠ **부호를 안 넘긴다** — 양수로 준다(음수로 주면 받는 쪽에서 두 번 뒤집힌다)
④ 자재총괄에 **안 섞인다** — 자재는 `material` 만 모은다
⑤ 인계 맨 위에 **한 값으로** 실린다(구조물마다 갈리므로 합산해서 하나로)
"""
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_Handoff import build_handoff # noqa: E402
from B08_Quantity.B08_Quantity_Engine_MaterialSummary import ( # noqa: E402
build_table as build_material_table,
)
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import ( # noqa: E402
COLLECTED_STONE_KEY,
build_table,
is_collected_stone,
stone_masonry,
)
def 구조물(**options: object) -> dict:
return {
"structure_id": "s1",
"type_id": "masonry_wet",
"start_m": 0.0,
"end_m": 10.0,
"options": {"height_m": 2.5, "length_m": 10.0, "back_len_cm": 45, **options},
}
def 성분(**options: object) -> dict:
components, _ = 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}
def test_기본은_캔다() -> None:
"""법이 그쪽을 권한다 — 별표2 「야면석 등은 **가급적 현장에서 채취·사용**」."""
assert is_collected_stone({}) is True
assert "채집석" in 성분()
def test_구입으로_두면_공제가_없다() -> None:
for value in ("구입", "purchase", "buy"):
assert is_collected_stone({"stone_supply": value}) is False, value
assert "채집석" not in 성분(stone_supply="구입")
def test_양수로_낸다() -> None:
"""⚠ 실무 시트가 `274.66` 이라 부호를 넘기면 **두 번 뒤집힌다.**"""
got = 성분()["채집석"]
assert got.unit == "㎥"
assert got.amount > 0
def test_여기서_빼지_않는다는_것이_근거에_적힌다() -> None:
basis = 성분()["채집석"].basis
assert "사토에서 한 번만" in basis
def test_자재총괄에_안_섞인다() -> None:
"""⚠ 자재는 `material` 만 모은다 — 채집석이 자재로 서면 같은 돌을 두 번 센다."""
unit = build_table([구조물()])
material = build_material_table(unit)
assert all(row["name"] != "채집석" for row in material["rows"])
def test_구조물마다_갈리고_합산해서_하나로_간다() -> None:
unit = build_table(
[
구조물(),
{
"structure_id": "s2",
"type_id": "masonry_dry",
"start_m": 20.0,
"end_m": 30.0,
"options": {
"height_m": 2.0,
"length_m": 10.0,
"back_len_cm": 35,
"stone_supply": "구입",
},
},
]
)
only_collected = 성분()["채집석"].amount
assert unit[COLLECTED_STONE_KEY] == round(only_collected, 3)
assert build_handoff(unit_quantity_table=unit)["collected_stone_deduction_m3"] == round(
only_collected, 3
)