feat(B08): 큰돌쌓기 메/찰 자동 판정 + 전면 기울기 근거

랩탑이 B06 에서 상세 제원을 받게 하고 `bond` 칸을 더해 준 것을 받음.

- `bond`(메쌓기/찰쌓기) → 품셈 `FP-13-06-01`/`FP-13-06-02` 자동 판정.
  미입력이면 `blocked_kind: input_missing` 과 사람 말 사유로 드러냄 —
  랩탑이 「빈 값을 미확보로 계속 드러내 달라」고 한 그대로. 첫 항목을 슬쩍
  고르면 근거 없는 값이 수량·단가로 흘러감.
- `pending_user` 에서 큰돌쌓기를 뺌 — 칸이 생겨 자동으로 갈림.

전면 기울기 1:0.3 의 근거를 찾아 데이터·주석에 적음. 지어낸 값이 아니라
**교본 7-3 돌흙막이 기준**임 — 「돌 찰쌓기 3.0m 이하 1:0.3 / 돌 메쌓기 2.0m 이하
1:0.3 / 큰돌쌓기 1:0.3 이상(전도 방지)」(지식DB 돌쌓기.md §1).
⚠ 큰돌쌓기는 「1:0.3 **이상**」이라 더 완만하게 잡을 수 있음 — 칸을 만든다면
그 범위를 보여야 한다는 것도 데이터에 적음.

검증 — 전체 642 passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-08 04:43:58 +09:00
co-authored by Claude Opus 5
parent 56ab6d9598
commit d0978d2422
4 changed files with 47 additions and 11 deletions
+15 -2
View File
@@ -602,9 +602,22 @@ def _structure_rows(
type_id = str(structure.get("type_id") or "")
entry = mapping.for_structure(type_id) or {}
code = entry.get("work_item_code")
# 돌쌓기는 **뒷길이 갈래**로 단가가 갈린다 — 저장 제원에서 자동으로 고른다.
# 돌쌓기는 **뒷길이 갈래**로, 큰돌쌓기는 **메/찰**로 단가가 갈린다 —
# 둘 다 저장 제원에서 자동으로 고른다(사용자 칸을 따로 만들지 않는다).
class_key: str | None = None
class_basis = ""
if entry.get("class_from") == "bond":
bond = str((structure.get("options") or {}).get("bond") or "").strip()
bond_codes = entry.get("bond_codes") or {}
if bond in bond_codes:
code = bond_codes[bond]
class_key = bond
class_basis = f"쌓기 방식 「{bond}」 → 품셈 13-6 {code.split('-')[-1]}"
else:
class_basis = (
"큰돌쌓기 쌓기 방식이 아직 입력되지 않았습니다 — 구조물 상세 입력에서 "
"메쌓기·찰쌓기 중 하나를 고르면 공종이 정해집니다"
)
if code and entry.get("class_from") == "back_length":
class_key, class_basis = masonry_class(structure.get("options") or {})
if class_key:
@@ -618,7 +631,7 @@ def _structure_rows(
blocked_kind, blocked_reason = blocked_of(structure, class_basis)
if code is None and composite is None:
unmatched.append(f"{wording_type_label(type_id)} — 품셈 공종을 아직 못 이었습니다")
elif entry.get("class_from") == "back_length" and class_key is None:
elif entry.get("class_from") in ("back_length", "bond") and class_key is None:
unmatched.append(f"{wording_type_label(type_id)}{class_basis}")
length = float(structure.get("length_m") or 0.0)
rows.append(
@@ -293,6 +293,9 @@ def stone_masonry(
# ⚠ `face_slope_ratio` 는 **레지스트리에 없는 키**다 — 즉 지금은 늘 기본 0.3 으로 돈다.
# 상수로 두는 것이 아니라 「칸이 생기면 바로 받는다」는 뜻으로 남겨 둔다.
# (키 이름 어긋남으로 저장값이 안 닿던 `back_len_cm` 사고와 구별할 것 — 이쪽은 **칸 자체가 없다**.)
# **기본 0.3 의 근거** — 교본 7-3 돌흙막이 기준: 「돌 찰쌓기 3.0m 이하 **1:0.3** /
# 돌 메쌓기 2.0m 이하 **1:0.3** / 큰돌쌓기 **1:0.3 이상**(전도 방지)」
# (`지식DB 02_상세설계/구조물/돌쌓기.md §1`, 값은 `data_masonry` 의 `face_slope`).
slope_ratio = _num(options.get("face_slope_ratio"), 0.3) # 전면 기울기 1:0.3 (교본 7-3)
constants = STONE_MASONRY
@@ -31,5 +31,24 @@
"60~80",
"80~100"
]
},
"face_slope": {
"note": "전면 기울기(1:n) — **교본 7-3 돌흙막이 기준**이 형식별로 정해 둔다. 코드의 기본 0.3 은 지어낸 값이 아니라 이 표에서 온 것이다.",
"source": "resources/knowledge/technical_info/01_임도/02_상세설계/구조물/돌쌓기.md §1 (교본 7-3)",
"quote": "돌 찰쌓기 3.0m 이하 1:0.3 / 돌 메쌓기 2.0m 이하 1:0.3 / 큰돌쌓기 1:0.3 이상(전도 방지)",
"by_type": {
"masonry_wet": 0.3,
"masonry_dry": 0.3,
"boulder_masonry": 0.3
},
"pending": "⚠ 큰돌쌓기는 「1:0.3 **이상**」이라 더 완만하게 잡을 수 있음 — 칸을 만든다면 그 범위를 보여야 함. 지금은 하한 0.3 으로 감."
},
"bond": {
"note": "큰돌쌓기 쌓기 방식 — 저장 제원 `bond`. 품셈 13-6-1(메)·13-6-2(찰)로 그대로 갈린다.",
"option_key": "bond",
"codes": {
"메쌓기": "FP-13-06-01",
"찰쌓기": "FP-13-06-02"
}
}
}
@@ -139,6 +139,16 @@
"type_id": "ford_pavement",
"work_item_code": "FP-12-06",
"master_name": "콘크리트 포장(인력시공)"
},
{
"type_id": "boulder_masonry",
"work_item_code": null,
"class_from": "bond",
"bond_codes": {
"메쌓기": "FP-13-06-01",
"찰쌓기": "FP-13-06-02"
},
"class_note": "저장 제원 `bond`(메쌓기/찰쌓기)로 품셈 13-6-1·13-6-2 를 고름 — 자동 판정"
}
],
"pending_user": {
@@ -160,15 +170,6 @@
"FP-09-05 발파암"
],
"why": "설계자가 넣는 암 갈래 이름(풍화암·연암·보통암·경암)이 리핑이냐 발파냐를 말하지 않음. 갈래마다 시공법을 지정하는 칸이 필요함"
},
{
"type_id": "boulder_masonry",
"candidates": [
"FP-13-06-01 메쌓기",
"FP-13-06-02 찰쌓기"
],
"why": "저장 제원(`boulder_masonry`)에 **메/찰 구분 칸이 없어** 어느 쪽인지 못 고름. 레지스트리(`B05_Profile_Structure_Types.json`)는 다른 창 소관이라 여기서 못 고침 — 칸이 생기면 `structure` 에 옮긴다.",
"class_axis": "직경(`stone_cm`) 40~60·60~80·80~100 — 품셈 13-6 축과 글자까지 같음"
}
]
},