Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013rJwJMVL4EE31y77TB11AP
66 lines
3.2 KiB
TypeScript
66 lines
3.2 KiB
TypeScript
/* =============================================================================
|
|
* common_util_masonry_slope.ts
|
|
* 벽 전면 기울기(1:n 의 n) — 품셈 13-4-4 [주]⑪ 표준경사 표(원문 L7185~7191)를 읽음.
|
|
*
|
|
* ⚠ **파이썬과 짝**(CLAUDE.md 5장 ①) — `B08_Quantity_Engine_UnitQuantity_StoneSpec.face_slope_ratio`
|
|
* + `common_util_structure_face_role.structure_face_role_of`. 거울 시험
|
|
* `resources/tester/test_b06_wall_lean_table.py` 가 네 갈래(직고 × 성토/절토 × 메/찰 + 사용자 칸)를
|
|
* 한 칸씩 대조. 한쪽만 고치면 횡단도 벽과 B08 수량이 갈림(2026-09-14 브레인 판정 「양쪽 다 이 표를」).
|
|
* ⚠ 표는 부르는 쪽이 넘김 — 이 파일은 아무것도 import 하지 않음(거울 시험이 단독으로 돌림).
|
|
* ========================================================================== */
|
|
|
|
/** 표준경사 표 — `resources/data_masonry/masonry_slope_*.json` 의 모양. */
|
|
export interface MasonrySlopeTable {
|
|
steps_m?: number[];
|
|
table?: Record<string, Record<string, number[]>>;
|
|
}
|
|
|
|
/** 벽 한 매의 기울기 입력 — B08 이 그 벽을 셀 때 보는 칸과 같음. */
|
|
export interface WallLeanInput {
|
|
/** 형태 — 「돌쌓기(찰)」·「돌쌓기(메)」만 표를 읽음(나머지는 종전 0.3). */
|
|
form?: string | null;
|
|
/** 직고(m) — 순수 높이. */
|
|
height_m: number;
|
|
/** 측점 단면유형 `design.section_mode` — 기울기 판정에 안 씀(91-3 · 칸 · 성토 기본). */
|
|
section_mode?: string | null;
|
|
/** 설치 측 — 기울기 판정에 안 씀(91-3). */
|
|
side?: string | null;
|
|
/** 성토/절토 칸 — 고르면 이김. */
|
|
face_role?: string | null;
|
|
/** 전면 기울기 칸 — 수(>0)면 이김(파이썬 `_num` 과 같이 글은 안 봄). */
|
|
face_slope_ratio?: number | string | null;
|
|
}
|
|
|
|
/** 표를 못 고를 때의 종전값 — 파이썬 `LEGACY_FACE_SLOPE_RATIO`. */
|
|
export const LEGACY_LEAN_RATIO = 0.3;
|
|
|
|
const FILL = "성토";
|
|
const CUT = "절토";
|
|
/** 형태 → 찰(true)/메(false) — 파이썬 `REVETMENT_STONE_FORMS`. */
|
|
const STONE_FORMS: Record<string, boolean> = { "돌쌓기(찰)": true, "돌쌓기(메)": false };
|
|
/** 성토/절토 — 칸이 이기고, 비면 성토(흙막이 · 사면안정 흙막이 · 옹벽 모두 · 원지반 자동판정 안 씀 · 91-3). */
|
|
export function faceRoleOf(faceRole?: string | null): string {
|
|
const picked = String(faceRole ?? "").trim();
|
|
return picked === CUT ? CUT : FILL;
|
|
}
|
|
|
|
/** 벽 전면 기울기 n — 표를 못 고르면 종전 0.3. */
|
|
export function wallLeanRatio(table: MasonrySlopeTable, input: WallLeanInput): number {
|
|
const wet = STONE_FORMS[String(input.form ?? "").trim()];
|
|
if (wet === undefined) return LEGACY_LEAN_RATIO;
|
|
const given = input.face_slope_ratio;
|
|
if (typeof given === "number" && Number.isFinite(given) && given > 0) return given;
|
|
const face = faceRoleOf(input.face_role);
|
|
const row = table.table?.[wet ? "찰쌓기" : "메쌓기"]?.[face];
|
|
if (!row?.length) return LEGACY_LEAN_RATIO;
|
|
const steps = table.steps_m ?? [];
|
|
let index = steps.length;
|
|
for (let i = 0; i < steps.length; i += 1) {
|
|
if (input.height_m <= steps[i]) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
return row[Math.min(index, row.length - 1)];
|
|
}
|