feat(rebar): range checks for the block rebar settings (승인 2026-10-26)

- RB01 a setting outside its range (cover 50–100, side cover 50–100, first gap
  0–150, spacing S1/S2 100–200, leg 500–1000); RB02 S1 depth at or above the
  block height; RB03 the legs do not reach into the coping.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-26 14:10:49 +09:00
1 parent e1497176ea
commit a6f362df56
3 files changed
+78

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
import type { PierModel } from '../geometry';
import type { Issue, PierInput } from '../types';
import { barDepths, DEFAULT_BLOCK_REBAR, type BlockRebarSettings } from './bearing-block';
/**
* 받침블럭 철근 입력 범위 (승인 2026-10-26, 제안 범위 확인).
* RB01: a setting outside its range. RB02: the S2 bar sits at or below the block top-to-bottom height.
* RB03: the bar legs do not reach into the coping (묻힘 < 0).
*/
export const BLOCK_REBAR_RANGES: Record<keyof BlockRebarSettings, [number, number]> = {
coverTop: [50, 100],
coverSide: [50, 100],
firstGap: [0, 150],
spacingS1: [100, 200],
spacingS2: [100, 200],
legLength: [500, 1000],
};
const LABELS: Record<keyof BlockRebarSettings, string> = {
coverTop: '상면 피복',
coverSide: '측면 피복',
firstGap: '첫 철근 최소 여유',
spacingS1: '간격 S1',
spacingS2: '간격 S2',
legLength: '다리 길이',
};
export function checkBlockRebar(input: PierInput, model: PierModel): Issue[] {
const s: BlockRebarSettings = { ...DEFAULT_BLOCK_REBAR, ...input.blockRebar };
const out: Issue[] = [];
const add = (code: string, message: string) => out.push({ code, level: 'W', pier: input.name, message });
for (const key of Object.keys(BLOCK_REBAR_RANGES) as (keyof BlockRebarSettings)[]) {
const [lo, hi] = BLOCK_REBAR_RANGES[key];
if (s[key] < lo || s[key] > hi) add('RB01', `${LABELS[key]} ${s[key]} mm가 범위 ${lo}–${hi} mm를 벗어납니다.`);
}
const depth = barDepths(s);
for (const b of model.blocks) {
const height = (b.top - b.bottom) * 1000;
if (depth.S1 >= height) {
add('RB02', `블럭 높이 ${height.toFixed(0)} mm보다 S1 깊이 ${depth.S1.toFixed(1)} mm가 깊습니다.`);
break;
}
}
for (const b of model.blocks) {
const height = (b.top - b.bottom) * 1000;
if (s.legLength - (height - depth.S1) < 0) {
add('RB03', `다리 끝이 코핑 안에 묻히지 않습니다 (블럭 ${b.no}).`);
break;
}
}
return out;
}
+2
View File
@@ -2,6 +2,7 @@ import { DIM, type PierModel } from './geometry';
import type { Issue, PierInput, PierType } from './types';
import { validateGround, validatePileEmbedment, validateStrataNValues } from './ground';
import { integratedCheck } from './bearing-layout';
import { checkBlockRebar } from './rebar/block-check';
const EXPECTED_COLUMNS: Record<PierType, number> = { 'T형': 1, '2주형': 2, '3주형': 3 };
@@ -94,6 +95,7 @@ export function validatePier(input: PierInput, model: PierModel, issues: Issue[]
validateGround(input, issues);
validatePileEmbedment(input, model, issues);
validateStrataNValues(input, issues);
issues.push(...checkBlockRebar(input, model));
// 일체 (승인 2026-10-26): the model builds one stepped block per pair when allowed; otherwise it keeps 분리.
if (input.bearingLayout === '일체') {
const check = integratedCheck(model.blocks);