fix(B08): 돌쌓기 면적이 기울기 몫을 두 번 먹던 것 수정
㉘ 자기 감사 후속. 실무 시트의 「돌쌓기 = 정면적 × 1.04」에서 그 1.04 가 곧 기울기 몫임(1:0.3 → √(1+0.3²) = 1.0440). 시트가 반올림해 적은 것을 별도 계수로 오해해 hypot 위에 또 곱하고 있었음. - 돌쌓기·큰돌쌓기 모두 기울기 몫을 한 번만 곱함 - 상수는 지우지 않고 `sheet_check_factor_at_0_3` 으로 성격을 바꿈 — 1:0.3 에서 시트값과 맞는지 대조하는 검산 참고값 - 하드코딩 금지 이유를 주석에 남김: 큰돌쌓기는 「1:0.3 이상」이라 기울기가 바뀌면 1.04 는 틀린 값이 되지만 hypot 은 따라감 값 변화 (실노선): 고임돌 -3.85 % · 야면석 -3.85 % · 물구멍 -3.85 % 막자갈 +3.20 % (입적에서 빼는 몫이 줄어 늘어남 — 식대로임) 시험 - 옛 시험이 덧곱을 계약으로 못 박고 있어 정정 - 거울 시험 추가: 기울기 0.3·0.5·1.0 에서 정면적 × hypot 과 일치 - 시트 대조 추가: 정면적 18.87 → 돌쌓기 19.62, 오차 0.5 % 안 - NULLABLE_SETTING_KEYS 계약 시험 추가 (홑 숫자 칸만 좁게 봄) 곁들여 타설 방식 안내 한 줄 — 고른 값이 아직 금액에 안 닿는다는 사실을 화면에 적음. 인계에 타설 공종 줄을 세울지는 이중계상 확인 뒤 결정. 시험: 666 passed · 24 skipped (B05 코리도 1건 기존 깨짐, 무관) · tsc 오류 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -58,7 +58,14 @@ DEFAULT_BACK_LENGTH_CM = 45
|
|||||||
|
|
||||||
# 돌쌓기 전개식의 상수 — 실무 수식에 박혀 있던 값을 뺀 것.
|
# 돌쌓기 전개식의 상수 — 실무 수식에 박혀 있던 값을 뺀 것.
|
||||||
STONE_MASONRY = {
|
STONE_MASONRY = {
|
||||||
"face_to_slope_factor": 1.04, # 돌쌓기 면적 = 정면적 × 1.04 (비탈 기울기 몫)
|
# ⚠ **곱하는 값이 아니라 검산 참고값이다** (2026-09-08 ㉘ 에서 고침).
|
||||||
|
# 실무 시트의 「돌쌓기 = 정면적 × 1.04」에서 그 1.04 가 **곧 기울기 몫**이다
|
||||||
|
# (1:0.3 → √(1+0.3²) = 1.0440 ≈ 1.04). 시트가 반올림해 적은 것을 우리가
|
||||||
|
# **별도 계수로 오해해 `hypot` 위에 또 곱하고 있었다** — 면적이 4 % 부풀었고
|
||||||
|
# 그 면적이 고임돌·야면석·채움콘크리트·모르터·물구멍 **전부의 밑수**였다.
|
||||||
|
# ⚠ 하드코딩하면 안 되는 값이다 — 큰돌쌓기는 「1:0.3 **이상**」이라 기울기가
|
||||||
|
# 바뀔 수 있고, 그때 1.04 는 틀린 값이 되지만 `hypot` 은 따라간다.
|
||||||
|
"sheet_check_factor_at_0_3": 1.04, # 1:0.3 에서 시트값과 맞는지 대조하는 자리
|
||||||
"thickness_base_m": 0.45, # 평균두께 식의 밑돌 두께
|
"thickness_base_m": 0.45, # 평균두께 식의 밑돌 두께
|
||||||
"thickness_top_coeff": 0.10, # 상부 두께 계수 (0.45 + 0.10·H)
|
"thickness_top_coeff": 0.10, # 상부 두께 계수 (0.45 + 0.10·H)
|
||||||
"thickness_bottom_coeff": 0.40, # 하부 두께 계수 (0.45 + 0.40·H)
|
"thickness_bottom_coeff": 0.40, # 하부 두께 계수 (0.45 + 0.40·H)
|
||||||
@@ -178,7 +185,9 @@ BOULDER_DIAMETERS = ("40~60", "60~80", "80~100")
|
|||||||
#: 큰돌쌓기 전개 상수. **재료 원단위는 품셈에 없다** — 13-6 [주]⑦ 「재료량은 설계수량을 적용한다」.
|
#: 큰돌쌓기 전개 상수. **재료 원단위는 품셈에 없다** — 13-6 [주]⑦ 「재료량은 설계수량을 적용한다」.
|
||||||
#: 그래서 여기서 내는 것은 **면적과 터파기 계열까지**이고 큰돌 자체는 미확보로 둔다.
|
#: 그래서 여기서 내는 것은 **면적과 터파기 계열까지**이고 큰돌 자체는 미확보로 둔다.
|
||||||
BOULDER_MASONRY = {
|
BOULDER_MASONRY = {
|
||||||
"face_to_slope_factor": 1.04, # 돌쌓기 면적 = 정면적 × 1.04 (13-4 와 같은 기울기 몫)
|
# ⚠ 검산 참고값 — 곱하지 않는다. 까닭은 `STONE_MASONRY` 의 같은 칸 주석을 볼 것.
|
||||||
|
# 큰돌쌓기는 전면 기울기가 「1:0.3 **이상**」이라 특히 하드코딩하면 안 된다.
|
||||||
|
"sheet_check_factor_at_0_3": 1.04,
|
||||||
"excavation_extra_m": 0.2, # 터파기 폭 여유
|
"excavation_extra_m": 0.2, # 터파기 폭 여유
|
||||||
"backfill_thickness_m": 0.2, # 되메우기 두께
|
"backfill_thickness_m": 0.2, # 되메우기 두께
|
||||||
}
|
}
|
||||||
@@ -221,8 +230,8 @@ def boulder_masonry(
|
|||||||
slope_ratio = _num(options.get("face_slope_ratio"), 0.3) # 레지스트리에 칸 없음 — 기본 0.3
|
slope_ratio = _num(options.get("face_slope_ratio"), 0.3) # 레지스트리에 칸 없음 — 기본 0.3
|
||||||
constants = BOULDER_MASONRY
|
constants = BOULDER_MASONRY
|
||||||
face_area = height_m * length_m
|
face_area = height_m * length_m
|
||||||
slope_area = face_area * math.hypot(1.0, slope_ratio)
|
# 기울기 몫은 **한 번만** — 13-4 와 같은 자리다(㉘).
|
||||||
masonry_area = slope_area * constants["face_to_slope_factor"]
|
masonry_area = face_area * math.hypot(1.0, slope_ratio)
|
||||||
|
|
||||||
components = [
|
components = [
|
||||||
Component(
|
Component(
|
||||||
@@ -230,7 +239,7 @@ def boulder_masonry(
|
|||||||
"㎡",
|
"㎡",
|
||||||
masonry_area,
|
masonry_area,
|
||||||
DESTINATION["돌쌓기"],
|
DESTINATION["돌쌓기"],
|
||||||
f"비탈면적 × 1.04 · 직경 {diameter}㎝ (품셈 13-6)",
|
f"정면적 × √(1+{slope_ratio}²) · 직경 {diameter}㎝ (품셈 13-6)",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -300,9 +309,9 @@ def stone_masonry(
|
|||||||
constants = STONE_MASONRY
|
constants = STONE_MASONRY
|
||||||
|
|
||||||
face_area = height_m * length_m # 정면적
|
face_area = height_m * length_m # 정면적
|
||||||
# 비탈면적 = 정면적 × √(1+n²) — 기울어진 만큼 길어진다.
|
# 돌쌓기 면적 = 정면적 × √(1+n²) — 기울어진 만큼 길어진다. **기울기 몫은 한 번만.**
|
||||||
slope_area = face_area * math.hypot(1.0, slope_ratio)
|
# 실무 시트의 「정면적 × 1.04」가 바로 이 값이다(1:0.3 에서 1.0440 ≈ 1.04).
|
||||||
masonry_area = slope_area * constants["face_to_slope_factor"]
|
masonry_area = face_area * math.hypot(1.0, slope_ratio)
|
||||||
thickness = (
|
thickness = (
|
||||||
(constants["thickness_base_m"] + constants["thickness_top_coeff"] * height_m)
|
(constants["thickness_base_m"] + constants["thickness_top_coeff"] * height_m)
|
||||||
+ (constants["thickness_base_m"] + constants["thickness_bottom_coeff"] * height_m)
|
+ (constants["thickness_base_m"] + constants["thickness_bottom_coeff"] * height_m)
|
||||||
@@ -310,7 +319,13 @@ def stone_masonry(
|
|||||||
volume = face_area * thickness # 입적
|
volume = face_area * thickness # 입적
|
||||||
|
|
||||||
components = [
|
components = [
|
||||||
Component("돌쌓기", "㎡", masonry_area, DESTINATION["돌쌓기"], "비탈면적 × 1.04"),
|
Component(
|
||||||
|
"돌쌓기",
|
||||||
|
"㎡",
|
||||||
|
masonry_area,
|
||||||
|
DESTINATION["돌쌓기"],
|
||||||
|
f"정면적 × √(1+{slope_ratio}²) — 비탈면적",
|
||||||
|
),
|
||||||
Component(
|
Component(
|
||||||
"고임돌",
|
"고임돌",
|
||||||
"㎥",
|
"㎥",
|
||||||
|
|||||||
@@ -352,6 +352,13 @@ function buildQuantitySidePanel(
|
|||||||
placing.is_default ? `${label} (${L("B08_Quantity_Placing_Default_Tag")})` : label,
|
placing.is_default ? `${label} (${L("B08_Quantity_Placing_Default_Tag")})` : label,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
// ⚠ 고른 값이 **아직 금액에 안 닿는다**는 사실을 숨기지 않는다(2026-09-08 ㉘).
|
||||||
|
// 인계가 타설 공종 줄을 아직 안 세운다 — B09 일위대가가 타설 품을 이미 갖고 있는지
|
||||||
|
// 확인되기 전까지는 세우면 같은 콘크리트를 두 번 센다(이중계상 ㉢ 과 같은 자리).
|
||||||
|
const pending = document.createElement("p");
|
||||||
|
pending.className = "b08-quantity__note";
|
||||||
|
pending.textContent = L("B08_Quantity_Placing_NotApplied");
|
||||||
|
panel.append(pending);
|
||||||
}
|
}
|
||||||
// ⚠ 「정하면 얼마나 달라지는지」까지 보여야 사용자가 판단한다. 이 값은 **참고 표시 전용**이고
|
// ⚠ 「정하면 얼마나 달라지는지」까지 보여야 사용자가 판단한다. 이 값은 **참고 표시 전용**이고
|
||||||
// B08 의 어떤 계산에도 안 들어간다(금액은 B09 몫).
|
// B08 의 어떤 계산에도 안 들어간다(금액은 B09 몫).
|
||||||
|
|||||||
@@ -628,6 +628,10 @@ export const ui_locales_b2 = {
|
|||||||
B08_Quantity_Method_Unset: ["안 정함", "Not set"],
|
B08_Quantity_Method_Unset: ["안 정함", "Not set"],
|
||||||
B08_Quantity_Method_Ripping: ["긁어내기(암절취)", "Ripping"],
|
B08_Quantity_Method_Ripping: ["긁어내기(암절취)", "Ripping"],
|
||||||
B08_Quantity_Method_Blasting: ["터뜨리기(발파암)", "Blasting"],
|
B08_Quantity_Method_Blasting: ["터뜨리기(발파암)", "Blasting"],
|
||||||
|
B08_Quantity_Placing_NotApplied: [
|
||||||
|
"⚠ 이 선택은 아직 금액에 반영되지 않습니다 — 견적의 일위대가가 타설 품을 이미 갖고 있는지 확인 중입니다.",
|
||||||
|
"Not yet applied to cost — checking whether the unit-price already covers placing labour.",
|
||||||
|
],
|
||||||
B08_Quantity_Side_Topsoil: ["표토제거", "Topsoil Removal"],
|
B08_Quantity_Side_Topsoil: ["표토제거", "Topsoil Removal"],
|
||||||
B08_Quantity_Side_Topsoil_Label: ["표토 두께(m)", "Topsoil thickness (m)"],
|
B08_Quantity_Side_Topsoil_Label: ["표토 두께(m)", "Topsoil thickness (m)"],
|
||||||
B08_Quantity_Unset_Placeholder: ["안 정함", "Not set"],
|
B08_Quantity_Unset_Placeholder: ["안 정함", "Not set"],
|
||||||
|
|||||||
Reference in New Issue
Block a user