chore: 네 창 작업 269건 main 반영 (2026-09-09) #13

Merged
eomsangdon merged 269 commits from main_desktop_1 into main 2026-09-09 18:21:28 +09:00
2 changed files with 93 additions and 0 deletions
Showing only changes of commit d366970e1d - Show all commits
@@ -932,6 +932,10 @@ EXPANDERS = {
"masonry_dry": lambda h, l, o, f=None, r="": stone_masonry(h, l, o, False, f, r),
# 큰돌쌓기는 표준경사 표 대상이 아니라 성절토를 안 쓴다(교본 「1:0.3 이상」).
"boulder_masonry": lambda h, l, o, f=None, r="": boulder_masonry(h, l, o),
# 기슭막이는 **형태가 돌쌓기면 돌쌓기 식**이다 — 실무 정본 탭 제목이 「돌기슭막이(…찰쌓기…)」
# 이고 그 안의 계산이 같다. 갈래·사유는 `_UnitQuantity_Revetment` 가 든다(늦게 부른다 —
# 그쪽이 이 모듈의 `stone_masonry` 를 쓰므로 위에서 부르면 맞물린다).
"revetment": lambda h, l, o, f=None, r="": _revetment()(h, l, o, f, r),
# ⚠⚠ **큰돌쌓기(`boulder_masonry`)를 여기에 두지 않는다** (2026-09-07 발견).
# 큰돌쌓기는 품셈 **13-6** 이고 돌쌓기는 **13-4** 다 — **규격 축이 다르다.**
# 돌쌓기는 **뒷길이**(35·45·55·60㎝), 큰돌쌓기는 **직경**(40~60·60~80·80~100㎝).
@@ -941,6 +945,14 @@ EXPANDERS = {
# 전개식·관측 원단위가 설 때까지 **미확보로 드러낸다.**
}
def _revetment():
"""기슭막이 전개 함수를 늦게 가져온다 — 서로 부르는 것을 풀기 위한 자리."""
from B08_Quantity.B08_Quantity_Engine_UnitQuantity_Revetment import revetment
return revetment
#: 전개식을 일부러 안 두는 종류 — 왜 안 두는지 사람이 읽게 적는다.
EXPANDER_WITHHELD: dict[str, str] = {}
@@ -0,0 +1,81 @@
"""기슭막이 전개 — **형태로 갈라 돌쌓기 식을 그대로 쓴다**(3단계, 2026-09-09).
실무 정본이 근거다 — `구조물도/기슭막이/04.구조도(기슭막이).xls` 의 탭 제목이
**「돌기슭막이(H=2.0m, 찰쌓기, 기초유)」** 이고, 그 안의 계산이 돌쌓기와 **같은 식**이다.
정면적 → 비탈면적(×√(1+n²)) → 평균두께 → 입적 → 돌 · 막자갈 · 고임돌 →
터파기(기초 + 비탈) → 되메우기 → 잔토
⇒ **기슭막이는 새 식이 아니라 「형태가 돌쌓기면 돌쌓기 식」**이다. 여기서 식을 다시 짜면
같은 계산이 두 벌이 되어 돌쌓기와 갈린다(CLAUDE.md 5장).
⚠ **형태가 돌쌓기가 아닌 갈래는 식이 없다** — 콘크리트·돌망태·통나무/목재틀·바자.
지어내지 않고 **왜 없는지**를 줄로 남긴다.
⚠ **뒷길이·돌 종류 칸이 기슭막이 등록부에 아직 없다**(2026-09-09 실측). 돌쌓기 식은 그 둘로
계수가 갈리는데, 없으면 `_back_length` 가 **조용히 45㎝ 로 돈다**. 값이 나오므로 아무도
못 알아채는 자리라 **그 사실을 줄로 드러낸다** — 「값이 있기는 하니 안 보이는」 그것.
"""
from __future__ import annotations
from typing import Any
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import Component, stone_masonry
#: 형태 → 돌쌓기 갈래(찰이면 True). 여기 없는 형태는 전개식이 없다.
STONE_FORMS: dict[str, bool] = {
"돌쌓기(찰)": True,
"돌쌓기(메)": False,
}
#: 식이 없는 형태와 **왜 없는지**. 품셈 장이 다르거나 원단위가 원문에 없다.
WITHHELD_FORMS: dict[str, str] = {
"콘크리트": (
"콘크리트 기슭막이는 돌쌓기(품셈 13-4)가 아니라 콘크리트 구조물이라 전개식이 다름 "
"— 벽 두께·저판이 정본에 없어 물량이 서지 않음"
),
"돌망태": ("돌망태는 품셈 13-8 이고 규격 축이 망태 치수라 돌쌓기 표를 못 씀 — 원단위 미확보"),
"통나무·목재틀": (
"목재틀은 품셈 13-13 이고 밑수가 ㎥당 목공 품이라 돌쌓기 표를 못 씀 "
"— 각재·판재 자재가 카탈로그에 없어 값이 모자람"
),
"바자": "바자얽기(품셈 5-15)는 별도 일위대가를 만들어 잇기로 확정(2026-09-09 ⑧-4)",
}
#: 돌쌓기 식이 계수를 가르는 데 쓰는 칸 — 기슭막이 등록부에 아직 없는 것을 알린다.
STONE_SPEC_KEYS: tuple[tuple[str, str], ...] = (
("back_len_cm", "뒷길이"),
("stone_kind", "돌 종류"),
)
def revetment(
height_m: float,
length_m: float,
options: dict[str, Any],
face: str | None = None,
face_reason: str = "",
) -> tuple[list[Component], list[str]]:
"""기슭막이 1구간 전개 — 형태가 돌쌓기면 그 식, 아니면 사유만."""
form = str(options.get("form") or "").strip()
if form not in STONE_FORMS:
why = WITHHELD_FORMS.get(form)
if why:
return [], [f"기슭막이 형태 「{form}」 — {why}"]
return [], [
f"기슭막이 형태가 정해지지 않았습니다(지금 「{form or '빈 값'}」) "
"— 형태를 골라야 물량이 섭니다"
]
components, notes = stone_masonry(
height_m, length_m, options, STONE_FORMS[form], face, face_reason
)
# ⚠ 계수를 가르는 칸이 없으면 **기본값으로 조용히 돈다** — 그 사실을 드러낸다.
missing = [label for key, label in STONE_SPEC_KEYS if not options.get(key)]
if missing and components:
notes.append(
f"⚠ 기슭막이 제원에 {' · '.join(missing)} 칸이 없어 **돌쌓기 기본값으로 섰음** "
"— 그 값이 고임돌·야면석·채움콘크리트 계수를 가름"
)
return components, notes