Merge remote-tracking branch 'origin/dev' into main_laptop_1
This commit is contained in:
@@ -1945,7 +1945,7 @@
|
||||
"default": null,
|
||||
"required": false,
|
||||
"phase": "detail",
|
||||
"empty_means": "비우면 돌쌓기 기본값으로 서고 「기본값으로 섰음」이 줄로 뜸 — 돌이 아닌 형태도 있어 필수로 못 검"
|
||||
"empty_means": "비우면 품셈 13-4-4 [주]⑩ 뒷길이 표준 하한(높이·찰/메로 · 범위 안 가장 작은 규격 — 예 메쌓기 1.5~3m 는 36~45㎝ 라 45㎝)으로 서고 그 사실이 줄로 뜸 — 돌이 아닌 형태도 있어 필수로 못 검"
|
||||
},
|
||||
{
|
||||
"key": "stone_kind",
|
||||
|
||||
@@ -27,7 +27,7 @@ from __future__ import annotations
|
||||
from typing import Any
|
||||
|
||||
from B08_Quantity.B08_Quantity_Engine_Pipe import NOTE_DEFAULT_WALL
|
||||
from B08_Quantity.B08_Quantity_Engine_StructureSheet import slope_of
|
||||
from B08_Quantity.B08_Quantity_Engine_StructureSheet import sheet_is_wet, slope_of
|
||||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import (
|
||||
_back_length,
|
||||
back_length_default_note,
|
||||
@@ -94,9 +94,14 @@ def back_length_cm(sheet: dict[str, Any]) -> tuple[int, str | None]:
|
||||
양식 장은 양식이 푼 값(`formula_sheet.vars.L3`), 전개 장은 `_back_length` — 표와 한 벌.
|
||||
"""
|
||||
options = sheet.get("options") or {}
|
||||
wet, height = sheet_is_wet(sheet), float(sheet.get("height_m") or 0.0)
|
||||
solved = ((sheet.get("formula_sheet") or {}).get("vars") or {}).get("L3")
|
||||
back = int(float(solved)) if isinstance(solved, (int, float)) else _back_length(options)
|
||||
return back, back_length_default_note(options, back)
|
||||
back = (
|
||||
int(float(solved))
|
||||
if isinstance(solved, (int, float))
|
||||
else _back_length(options, wet=wet, height_m=height)
|
||||
)
|
||||
return back, back_length_default_note(options, back, wet=wet, height_m=height)
|
||||
|
||||
|
||||
def figure_reason(sheet: dict[str, Any]) -> str | None:
|
||||
|
||||
@@ -103,23 +103,28 @@ SLOPE_TYPE_IDS: frozenset[str] = frozenset(
|
||||
REVETMENT_STONE_FORMS: dict[str, bool] = {"돌쌓기(찰)": True, "돌쌓기(메)": False}
|
||||
|
||||
|
||||
def slope_of(sheet: dict[str, Any]) -> tuple[float, str]:
|
||||
"""장 하나의 전면 기울기와 근거 문구 — **판정은 B08 한 벌**을 그대로 쓴다.
|
||||
def sheet_is_wet(sheet: dict[str, Any]) -> bool:
|
||||
"""장의 메/찰 — 표준경사·뒷길이 표준이 같은 갈래로 읽음.
|
||||
|
||||
메/찰은 종류에서 온다. 큰돌쌓기는 `bond` 칸(메쌓기/찰쌓기)이 그것이고, 안 고르면
|
||||
찰쌓기로 본다 — 품셈 13-6 은 둘 다 「1:0.3 **이상**」이라 그림 기울기가 갈리지 않는다.
|
||||
큰돌쌓기는 `bond` 칸(메쌓기/찰쌓기)이 그것이고, 안 고르면 찰쌓기로 본다 — 품셈 13-6 은
|
||||
둘 다 「1:0.3 **이상**」이라 그림 기울기가 갈리지 않는다.
|
||||
"""
|
||||
options = sheet.get("options") or {}
|
||||
type_id = str(sheet.get("type_id") or "")
|
||||
if type_id == "masonry_dry":
|
||||
wet = False
|
||||
elif type_id == "boulder_masonry":
|
||||
wet = options.get("bond") != "메쌓기"
|
||||
elif type_id == "revetment":
|
||||
return False
|
||||
if type_id == "boulder_masonry":
|
||||
return options.get("bond") != "메쌓기"
|
||||
if type_id == "revetment":
|
||||
# 표(기슭막이 전개)가 넘긴 그 갈래 — 형태 「돌쌓기(메)」만 메.
|
||||
wet = REVETMENT_STONE_FORMS.get(str(options.get("form") or "").strip(), True)
|
||||
else:
|
||||
wet = True
|
||||
return REVETMENT_STONE_FORMS.get(str(options.get("form") or "").strip(), True)
|
||||
return True
|
||||
|
||||
|
||||
def slope_of(sheet: dict[str, Any]) -> tuple[float, str]:
|
||||
"""장 하나의 전면 기울기와 근거 문구 — **판정은 B08 한 벌**을 그대로 쓴다."""
|
||||
options = sheet.get("options") or {}
|
||||
wet = sheet_is_wet(sheet)
|
||||
return face_slope_ratio(
|
||||
options,
|
||||
wet=wet,
|
||||
|
||||
@@ -16,7 +16,11 @@ import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity_StoneSpec import standard_back_length
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
#: 양식 칸 `default_from` — 빈 뒷길이를 뒷길이 표준표 하한으로(전개와 한 벌).
|
||||
STANDARD_BACK_LENGTH = "standard_back_length"
|
||||
TEMPLATE_DIR = ROOT / "resources" / "library_structure"
|
||||
|
||||
#: 사용자가 고친 식이 사는 칸 — B08 산출 조건 구획(`project_settings.json` 의 `quantity`).
|
||||
@@ -75,6 +79,12 @@ def template_vars(
|
||||
raw = options.get(spec["option"])
|
||||
else:
|
||||
raw = (settings or {}).get(spec.get("setting"))
|
||||
if raw in (None, "") and spec.get("default_from") == STANDARD_BACK_LENGTH:
|
||||
# 안 고른 뒷길이 — 전개와 같은 표준표 하한(`standard_back_length`, 브레인 판정 ㉮).
|
||||
wet = template.get("type_id") != "masonry_dry"
|
||||
height = float(structure.get("height_m") or 0.0)
|
||||
values[name] = float(standard_back_length(wet=wet, height_m=height)[0])
|
||||
continue
|
||||
values[name] = default if raw in (None, "") else _typed(raw, default)
|
||||
return values
|
||||
|
||||
|
||||
@@ -260,14 +260,14 @@ def stone_masonry(
|
||||
if height_m <= 0 or length_m <= 0:
|
||||
return [], ["높이·연장이 없어 전개하지 않음"]
|
||||
|
||||
back_cm = _back_length(options)
|
||||
back_cm = _back_length(options, wet=wet, height_m=height_m)
|
||||
if back_cm not in STONE_BACK_LENGTH_TABLE:
|
||||
# ⚠ 접지 않는다 — 다른 규격 계수가 조용히 도는 것보다 「없다」가 낫다.
|
||||
return [], [
|
||||
f"뒷길이 {back_cm}㎝ 는 품셈 표(25·30·35·45·55·60·75㎝)에 없어 물량이 서지 않습니다"
|
||||
]
|
||||
table = dict(STONE_BACK_LENGTH_TABLE[back_cm])
|
||||
default_note = back_length_default_note(options, back_cm)
|
||||
default_note = back_length_default_note(options, back_cm, wet=wet, height_m=height_m)
|
||||
if default_note:
|
||||
notes.append(default_note)
|
||||
# ⚠ **돌 종류로 계수가 갈린다** (품셈 13-4-3 · 13-4-4 [주]① · 교본 7-3).
|
||||
|
||||
@@ -444,8 +444,57 @@ def wants_blinding(options: dict[str, Any]) -> bool:
|
||||
BACK_LENGTH_KEYS = ("back_len_cm", "stone_back_length_cm")
|
||||
|
||||
|
||||
def _back_length(options: dict[str, Any]) -> int:
|
||||
"""저장된 뒷길이(㎝)를 **그대로** 돌려준다. 안 정했으면 기본 45.
|
||||
#: 뒷길이 표준표 — 품셈 13-4-4 [주]⑩. 안 고른 돌쌓기는 붙박이 45 가 아니라 이 표의 하한
|
||||
#: (2026-09-14 브레인 판정 ㉮ 「범위 안에 드는 규격 중 가장 작은 것」). 파일이 없으면 종전 45.
|
||||
BACK_LENGTH_PREFIX = "masonry_back_length_"
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def load_back_length_table() -> dict[str, Any]:
|
||||
"""뒷길이 표준표. 없으면 빈 표 — 그때는 종전 기본 45㎝ 로 돎."""
|
||||
files = sorted(SLOPE_DIR.glob(BACK_LENGTH_PREFIX + "*.json")) if SLOPE_DIR.is_dir() else []
|
||||
return json.loads(files[-1].read_text(encoding="utf-8")) if files else {}
|
||||
|
||||
|
||||
def standard_back_length(*, wet: bool, height_m: float) -> tuple[int, str]:
|
||||
"""(제안 뒷길이 ㎝, 근거) — 높이·메/찰 칸 범위 안 품셈 규격 중 가장 작은 것.
|
||||
|
||||
⚠ 하한이 규격(25·30·35·45·55·60·75)에 없으면 **그 위 첫 규격** — 메쌓기 ~3m 하한 36 은 45.
|
||||
내리면 품셈 범위 밖이 됨. 경계값은 표준경사표와 같이 **앞 칸**(높이 3.0m → `~3`).
|
||||
"""
|
||||
table = load_back_length_table()
|
||||
steps = table.get("steps_m") or []
|
||||
bond = "찰쌓기" if wet else "메쌓기"
|
||||
rows = (table.get("table_cm") or {}).get(bond) or []
|
||||
if not rows:
|
||||
return DEFAULT_BACK_LENGTH_CM, f"뒷길이 표준표를 못 읽어 종전 {DEFAULT_BACK_LENGTH_CM}㎝"
|
||||
index = next((i for i, limit in enumerate(steps) if height_m <= float(limit)), len(steps))
|
||||
low, high = rows[min(index, len(rows) - 1)]
|
||||
label = f"직고 {height_m:g}m" + (f" ≤{steps[index]:g}m" if index < len(steps) else " 7m 초과")
|
||||
span = f"{low}~{high}㎝" if high is not None else f"{low}㎝ 이상"
|
||||
picked = next(
|
||||
(
|
||||
size
|
||||
for size in sorted(STONE_BACK_LENGTH_TABLE)
|
||||
if size >= low and (high is None or size <= high)
|
||||
),
|
||||
None,
|
||||
)
|
||||
head = f"품셈 13-4-4 [주]⑩ 뒷길이 표준(원문 L7172~7181) · {bond} {label} {span}"
|
||||
if picked is None:
|
||||
return (
|
||||
DEFAULT_BACK_LENGTH_CM,
|
||||
f"{head} 안에 품셈 규격이 없어 종전 {DEFAULT_BACK_LENGTH_CM}㎝",
|
||||
)
|
||||
tail = "" if picked == low else f"(하한 {low}㎝ 는 규격 일곱(원문 L7152)에 없어 그 위 첫 규격)"
|
||||
return picked, f"{head} → 하한 {picked}㎝{tail}"
|
||||
|
||||
|
||||
def _back_length(
|
||||
options: dict[str, Any], *, wet: bool | None = None, height_m: float | None = None
|
||||
) -> int:
|
||||
"""저장된 뒷길이(㎝)를 **그대로** 돌려준다. 안 정했으면 뒷길이 표준표 하한(메/찰·높이를 받으면),
|
||||
못 받는 자리(골막이 등)는 종전 기본 45.
|
||||
|
||||
⚠ **접지 않는다.** 품셈 13-4-3·13-4-4 [주]① 이 25·30·35·45·55·60·75 **일곱 규격**을
|
||||
다 주므로 접을 까닭이 없다. 그 밖의 값(40 등)은 **계수가 없다고 드러낸다** —
|
||||
@@ -463,13 +512,26 @@ def _back_length(options: dict[str, Any]) -> int:
|
||||
# 45㎝ 계수로 **조용히** 돌고 999㎝ 도 60㎝ 로 접혔다(2026-09-08 실측).
|
||||
# 표에 없으면 그 값을 그대로 돌려주고, 계수를 고르는 쪽이 「없다」고 드러낸다.
|
||||
return value
|
||||
return DEFAULT_BACK_LENGTH_CM
|
||||
if wet is None or height_m is None:
|
||||
return DEFAULT_BACK_LENGTH_CM
|
||||
return standard_back_length(wet=wet, height_m=height_m)[0]
|
||||
|
||||
|
||||
def back_length_default_note(options: dict[str, Any], back_cm: int) -> str | None:
|
||||
def back_length_default_note(
|
||||
options: dict[str, Any],
|
||||
back_cm: int,
|
||||
*,
|
||||
wet: bool | None = None,
|
||||
height_m: float | None = None,
|
||||
) -> str | None:
|
||||
"""뒷길이를 안 골라 기본으로 섰을 때의 한 줄 — 표 사유·구조물도 그림이 **같은 말**을 씀."""
|
||||
if any(options.get(key) not in (None, "") for key in BACK_LENGTH_KEYS):
|
||||
return None
|
||||
if wet is not None and height_m is not None:
|
||||
return (
|
||||
f"⚠ 뒷길이를 안 골라 {standard_back_length(wet=wet, height_m=height_m)[1]} 로 섰습니다 "
|
||||
"— 구조물 상세에서 고르면 바뀜 · 그 값이 두께식·고임돌·돌 무게·채움콘크리트 계수를 모두 가릅니다"
|
||||
)
|
||||
return (
|
||||
f"⚠ 뒷길이를 안 골라 기본 {back_cm}㎝ 로 섰습니다 "
|
||||
"— 그 값이 두께식·고임돌·돌 무게·채움콘크리트 계수를 모두 가릅니다"
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"dataset_id": "masonry_back_length_standard",
|
||||
"effective_date": "2026-01-01",
|
||||
"note": "돌쌓기 뒷길이 표준 — **높이 × 메/찰** 로 범위가 갈린다. 뒷길이를 안 고른 돌쌓기는 붙박이 45㎝ 로 서고 있었는데, 그 자리를 이 표의 **하한**으로 바꿈(2026-09-14 브레인 판정). 사용자가 칸에서 고르면 그 값이 이김.",
|
||||
"source": {
|
||||
"doc": "산림사업 표준품셈(산림청고시 제2025-82호) 13-4-4 [주]⑩ <뒷길이 표준>",
|
||||
"line": "원문 L7172~7181",
|
||||
"quote": "높은 메쌓기는 밑으로 내려갈수록 뒷길이를 길게 하는 것이 원칙이다 · 높이는 첨단으로부터 기준 한다 · 특수한 조건에서는 본 기준과 달리 적용할 수 있다"
|
||||
},
|
||||
"policy": {
|
||||
"suggestion": "⭐ 제안값 = **범위 안에 드는 품셈 규격 중 가장 작은 것**(브레인 판정 ㉮). 하한이 규격(25·30·35·45·55·60·75)에 없으면 그 위 첫 규격 — 메쌓기 ~3m·~5m 하한 36㎝ 는 45㎝. 35 로 내리면 품셈 범위 아래로 나가 안 됨.",
|
||||
"boundary": "⚠ 원문 표기 `∼1.5 · ∼3 · ∼5 · ∼7 · 7이상` — 표준경사 표(`masonry_slope`)와 같이 「∼」를 **이하**로 읽어 경계값은 앞 칸(높이 3.0m → `~3` 칸).",
|
||||
"no_write_back": "⚠ 제안값을 저장에 박지 않음 — 「안 고름」과 「45 로 고름」이 구별돼야 함(표준경사와 같은 자리)."
|
||||
},
|
||||
"steps_m": [1.5, 3.0, 5.0, 7.0],
|
||||
"table_cm": {
|
||||
"메쌓기": [
|
||||
[25, 35],
|
||||
[36, 45],
|
||||
[36, 60],
|
||||
[45, 75],
|
||||
[75, null]
|
||||
],
|
||||
"찰쌓기": [
|
||||
[25, 35],
|
||||
[30, 35],
|
||||
[35, 45],
|
||||
[35, 55],
|
||||
[45, 60]
|
||||
]
|
||||
},
|
||||
"not_here": {
|
||||
"note": "이 표가 쓰지 않는 칸.",
|
||||
"items": [
|
||||
"돌붙이기 열(메 25~60 · 찰 20~40)은 높이로 안 갈림 — 바닥막이 돌붙임은 뒷길이가 붙박이(`_UnitQuantity_Revetment.BED_SILL_FORMS`)라 여기서 안 씀",
|
||||
"골막이는 뒷길이 기본이 종전대로 45㎝ — 이 표의 대상(돌쌓기 13-4)이 아님"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,13 @@
|
||||
"source": "judged_face_slope",
|
||||
"note": "사용자 값이 있으면 그 값, 없으면 품셈 13-4-4 [주]⑪ 표준경사를 전개가 판정해 넘김"
|
||||
},
|
||||
"L3": { "label": "뒷길이(㎝)", "option": "back_len_cm", "default": 45 },
|
||||
"L3": {
|
||||
"label": "뒷길이(㎝)",
|
||||
"option": "back_len_cm",
|
||||
"default": 45,
|
||||
"default_from": "standard_back_length",
|
||||
"note": "안 고르면 품셈 13-4-4 [주]⑩ 뒷길이 표준 하한(높이·메/찰 · 범위 안 가장 작은 규격) — 전개와 한 벌(2026-09-14 브레인 판정 ㉮). 45 는 표를 못 읽을 때만"
|
||||
},
|
||||
"돌종류": { "label": "돌 종류", "option": "stone_kind", "default": "" },
|
||||
"계수기준": { "label": "야면석 계수", "option": "stone_coeff_basis", "default": "" },
|
||||
"TOP_IN": {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""뒷길이 표준(품셈 13-4-4 [주]⑩) — 안 고른 돌쌓기의 뒷길이는 **표의 하한** (2026-09-14 브레인 판정 ㉮).
|
||||
|
||||
앞서 붙박이 45㎝ 로 섰음. 표는 높이 × 메/찰 로 범위를 줌 — 하한이 규격(25·30·35·45·55·60·75)에
|
||||
없으면 **범위 안 그 위 첫 규격**(메쌓기 ~3m·~5m 하한 36 → 45). 경계값은 앞 칸(표준경사와 같음).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity_StoneSpec import ( # noqa: E402
|
||||
_back_length,
|
||||
back_length_default_note,
|
||||
standard_back_length,
|
||||
)
|
||||
|
||||
# (높이, 메쌓기 제안, 찰쌓기 제안) — 원문 L7174~7177
|
||||
CELLS = [
|
||||
(1.0, 25, 25),
|
||||
(1.5, 25, 25), # 경계값은 앞 칸
|
||||
(2.5, 45, 30), # 메 36~45 → 45 · 찰 30~35 → 30
|
||||
(3.0, 45, 30),
|
||||
(4.0, 45, 35), # 메 36~60 → 45 · 찰 35~45 → 35
|
||||
(6.0, 45, 35), # 메 45~75 · 찰 35~55
|
||||
(7.5, 75, 45), # 메 75이상 · 찰 45~60
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("height, dry, wet", CELLS)
|
||||
def test_표_하한(height: float, dry: int, wet: int) -> None:
|
||||
assert standard_back_length(wet=False, height_m=height)[0] == dry
|
||||
assert standard_back_length(wet=True, height_m=height)[0] == wet
|
||||
|
||||
|
||||
def test_하한이_규격에_없으면_그_위_첫_규격_사유() -> None:
|
||||
cm, basis = standard_back_length(wet=False, height_m=2.5)
|
||||
assert cm == 45
|
||||
assert "36~45㎝" in basis and "하한 36㎝ 는 규격 일곱(원문 L7152)에 없어" in basis
|
||||
assert "원문 L7172~7181" in basis # 사용자가 되짚을 줄 번호(브레인 2026-09-14)
|
||||
|
||||
|
||||
def test_고른_값이_이긴다() -> None:
|
||||
assert _back_length({"back_len_cm": "55"}, wet=True, height_m=2.5) == 55
|
||||
assert back_length_default_note({"back_len_cm": 55}, 55, wet=True, height_m=2.5) is None
|
||||
|
||||
|
||||
def test_메찰_높이를_모르는_자리는_종전_45() -> None:
|
||||
assert _back_length({}) == 45
|
||||
assert "기본 45㎝" in (back_length_default_note({}, 45) or "")
|
||||
@@ -38,6 +38,9 @@ def _structures() -> list[dict]:
|
||||
"length_m": 10,
|
||||
"foundation": "기초유",
|
||||
"stone_kind": "야면석·호박돌",
|
||||
# 2026-09-14 — 안 고르면 뒷길이 표준 하한(찰 ≤3m 30㎝)이라 야면석 관측 무게(35·45·55)가
|
||||
# 없어 돌 줄이 안 섬. 돌 줄을 보는 시험이라 45 로 고름 · 빈 칸 길은 아래 시험.
|
||||
"back_len_cm": 45,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -76,6 +79,21 @@ def test_양식_갈음은_값을_안_움직인다() -> None:
|
||||
assert stone["source"] == "uljin_library"
|
||||
|
||||
|
||||
def test_뒷길이_안_고르면_양식도_전개와_같은_표준_하한() -> None:
|
||||
"""품셈 13-4-4 [주]⑩ 하한(찰 ≤3m 30㎝)을 전개와 양식이 한 벌로 씀(브레인 판정 ㉮)."""
|
||||
structures = _structures()[:1]
|
||||
structures[0]["options"].pop("back_len_cm")
|
||||
structures[0]["options"].pop("stone_kind")
|
||||
names = {"masonry_wet": "돌쌓기(찰)"}
|
||||
before = build_table(structures, names, None, None, 0.2, use_templates=False)["structures"][0]
|
||||
after = build_table(structures, names, None, None, 0.2)["structures"][0]
|
||||
assert after["library_item"] == "돌쌓기(찰)"
|
||||
assert [c["name"] for c in after["components"]] == [c["name"] for c in before["components"]]
|
||||
for got, want in zip(after["components"], before["components"]):
|
||||
assert got["amount"] == pytest.approx(want["amount"], rel=1e-9, abs=1e-12), got["name"]
|
||||
assert any("하한 30㎝" in note for note in before["notes"])
|
||||
|
||||
|
||||
def test_자재총괄_갈래와_배합_성분() -> None:
|
||||
names = {"masonry_wet": "돌쌓기(찰)", "masonry_dry": "돌쌓기(메)"}
|
||||
before = build_material_table(
|
||||
|
||||
@@ -89,7 +89,9 @@ def test_기본값으로_그린_장은_표_사유와_같은_말을_적는다() -
|
||||
options = {"height_m": 2.0}
|
||||
_rows, table_notes = stone_masonry(2.0, 1.0, options, wet=False)
|
||||
table_default = [note for note in table_notes if "뒷길이를 안 골라" in note]
|
||||
assert table_default == [back_length_default_note(options, 45)]
|
||||
# 2026-09-14 — 기본은 뒷길이 표준 하한(메 ≤3m 36~45㎝ → 45) · 표·그림이 같은 말.
|
||||
assert table_default == [back_length_default_note(options, 45, wet=False, height_m=2.0)]
|
||||
assert "하한 36㎝ 는 규격 일곱" in table_default[0]
|
||||
|
||||
texts = _texts(build_figure(_sheet()))
|
||||
assert table_default[0] in texts
|
||||
|
||||
@@ -61,7 +61,16 @@ CASES = [
|
||||
dict(height=2.0, length=7.5, back_len_cm=45, face_slope_ratio=0.35, foundation="기초유"),
|
||||
dict(height=2.0, length=10.0, back_len_cm=55, thickness_top_m=0.9, foundation="기초버림"),
|
||||
dict(height=2.0, length=10.0, back_len_cm=45, thickness_bottom_m="1.4", stone_kind="깬잡석"),
|
||||
dict(height=2.0, length=10.0, stone_kind="야면석·호박돌", stone_coeff_basis="실무 관행"),
|
||||
# 뒷길이 45 — 안 고르면 표준 하한 30㎝ 라 야면석 관측 무게(35·45·55)가 없어 양식만 오류 줄(명세 13장 Ⓐ)
|
||||
dict(
|
||||
height=2.0,
|
||||
length=10.0,
|
||||
back_len_cm=45,
|
||||
stone_kind="야면석·호박돌",
|
||||
stone_coeff_basis="실무 관행",
|
||||
),
|
||||
# 뒷길이 안 고름 — 전개·양식이 같은 표준 하한(찰 ≤3m 30㎝, 브레인 판정 ㉮)
|
||||
dict(height=2.0, length=10.0, stone_kind="깬돌", foundation="기초유"),
|
||||
dict(height=1.5, length=10.0, back_len_cm=35, weep_hole_area_m2=3, foundation="기초유"),
|
||||
dict(height=2.5, length=12.0, back_len_cm=60, stone_kind="견치돌", rubble=0.3),
|
||||
# 줄이 안 서는 갈래 — `when`
|
||||
|
||||
@@ -125,7 +125,8 @@ def test_실무_시트_m당_값_재현() -> None:
|
||||
품셈 1-2-2 의 소수 자리는 표기 규칙이고 계산은 전정밀로 둔다(PLAN 8-16).
|
||||
맞추려고 식을 비틀지 않는다 — 허용오차를 그 차이만큼 둔다.
|
||||
"""
|
||||
result = expand(돌쌓기찰(height=1.5, length=1.0))
|
||||
# 실무 시트가 뒷길이 45 — 2026-09-14 부터 안 고르면 표준 하한(찰 ≤1.5m 25㎝)이라 고름.
|
||||
result = expand(돌쌓기찰(height=1.5, length=1.0, back_len_cm=45))
|
||||
assert result.height_m == 1.5
|
||||
assert result.length_m == 1.0
|
||||
assert 성분(result, "터파기").amount == pytest.approx(1.55, abs=0.02)
|
||||
@@ -135,7 +136,7 @@ def test_실무_시트_m당_값_재현() -> None:
|
||||
|
||||
def test_평균두께는_전정밀로() -> None:
|
||||
"""실무가 0.83 으로 반올림해 재계산한 자리 — 우리는 0.825 를 그대로 쓴다."""
|
||||
result = expand(돌쌓기찰(height=1.5, length=1.0))
|
||||
result = expand(돌쌓기찰(height=1.5, length=1.0, back_len_cm=45))
|
||||
# 터파기 = 높이 × (평균두께 + 0.2) × 연장 = 1.5 × 1.025 = 1.5375
|
||||
assert 성분(result, "터파기").amount == pytest.approx(1.5375)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user