feat(rebar): 코핑 배근 입력 12개 · CP01·CP02 검사 · 적용 버튼

- core/rebar/coping-settings.ts: 입력 정의, 기본값(코핑철근.md), 범위(코핑_입력범위_제안.md), 검사 함수
- 다리 수는 4·6·8 목록으로 두고 홀수는 CP02로 막음
- 값은 적용 버튼을 누를 때만 draft에 쓰고 다시 생성 (범위 밖이면 반영하지 않음)
- PierInput.copingRebar, 모델 copingRebar, 변경 추적 키 추가

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-26 15:26:20 +09:00
1 parent ec402e22d7
commit 9c93a6aa01
6 files changed
+212 -1

No files matched your search

+2 -1
View File
@@ -23,7 +23,7 @@ export const EDITABLE_FIELDS = [
] as const;
/** Inputs tracked for overrides and pending changes: the numeric cards plus 열별 본수 (an array, compared by value). */
export const TRACKED_KEYS = [...EDITABLE_FIELDS.map((f) => f.key), 'pileRows', 'groundPosition', 'groundWaterOn', 'groundWaterEl', 'floodLevelEl', 'scourDepthM', 'highWaterEl', 'lowWaterEl', 'strataRows', 'bearingType', 'bearingLayout', 'blockRebar'] as const;
export const TRACKED_KEYS = [...EDITABLE_FIELDS.map((f) => f.key), 'pileRows', 'groundPosition', 'groundWaterOn', 'groundWaterEl', 'floodLevelEl', 'scourDepthM', 'highWaterEl', 'lowWaterEl', 'strataRows', 'bearingType', 'bearingLayout', 'blockRebar', 'copingRebar'] as const;
export type EditableKey = (typeof TRACKED_KEYS)[number];
@@ -54,6 +54,7 @@ export const FIELD_LABELS: Record<EditableKey, string> = {
bearingType: '받침 종류·용량',
bearingLayout: '받침 배치',
blockRebar: '받침블럭 철근 설정',
copingRebar: '코핑 배근 입력',
strataRows: '지층 행',
};
+4
View File
@@ -1,6 +1,7 @@
import { buildAxis, copingSpan, fromAxis, kinkArc, nearKink, toAxis } from './axis';
import { buildIntegratedBlocks, type IntegratedBlock } from './integrated-block';
import { type BlockRebarSettings, DEFAULT_BLOCK_REBAR } from './rebar/bearing-block';
import { type CopingRebarSettings, DEFAULT_COPING_REBAR } from './rebar/coping-settings';
import { layoutText, resolveRowCounts, rowLayout, type PileGeometry } from './piles';
import type { PierInput, Row } from './types';
import { type CopingGeom, P1_COPING_GEOM } from './coping-geom';
@@ -176,6 +177,8 @@ export interface PierModel {
integratedBlocks: IntegratedBlock[];
/** 받침블럭 철근 설정 used by the rebar (승인 2026-10-26). */
blockRebar: BlockRebarSettings;
/** 코핑 배근 입력 used by the coping rebar (승인 2026-10-26). */
copingRebar: CopingRebarSettings;
columns: ColumnModel[];
footings: FootingModel[];
blindings: BlindingModel[];
@@ -464,6 +467,7 @@ export function buildPier(input: PierInput): PierModel {
blocks,
integratedBlocks: buildIntegratedBlocks(blocks, input.bearingLayout === '일체'),
blockRebar: { ...DEFAULT_BLOCK_REBAR, ...input.blockRebar },
copingRebar: { ...DEFAULT_COPING_REBAR, ...input.copingRebar },
columns,
footings,
blindings,
+86
View File
@@ -0,0 +1,86 @@
/**
* 코핑 배근 입력 (승인 2026-10-26, 제안 = RAG/코핑_입력범위_제안.md). The 12 numbers of the ③ 코핑 배근 입력 panel.
* Defaults are the 코핑철근.md values; the ranges are the proposal's, pending the design-standard check.
*/
export interface CopingRebarSettings {
/** 피복 (철근 중심, mm). */
cover: number;
/** 주철근 기본간격 (mm). */
mainSpacing: number;
/** 주철근 끝단 최소 여유 (mm). */
mainEndGap: number;
/** 상면 주철근 단 간격 (mm). */
mainLayerGap: number;
/** 첫 전단철근 최소 여유 (피복 다음, mm). */
firstShearGap: number;
/** 전단철근 다리 수 (짝수). */
shearLegs: number;
/** 전단철근 간격 · 경사 (mm). */
spacingS: number;
/** 전단철근 간격 · Level (mm). */
spacingL: number;
/** 측면 수평 간격 (mm). */
sideSpacing: number;
/** 측면 위 끝 아래 최소 여유 (mm). */
sideEndGap: number;
/** C14 간격 위 2줄 (mm). */
c14UpperSpacing: number;
/** C14 간격 아래 줄 (mm). */
c14LowerSpacing: number;
}
export const DEFAULT_COPING_REBAR: CopingRebarSettings = {
cover: 100,
mainSpacing: 125,
mainEndGap: 80,
mainLayerGap: 57.2,
firstShearGap: 200,
shearLegs: 6,
spacingS: 250,
spacingL: 300,
sideSpacing: 250,
sideEndGap: 400,
c14UpperSpacing: 1000,
c14LowerSpacing: 2000,
};
/** Allowed range per input (inclusive, mm). The shear legs are checked for evenness separately (CP02). */
export const COPING_REBAR_RANGES: Record<keyof CopingRebarSettings, [number, number]> = {
cover: [80, 150],
mainSpacing: [100, 150],
mainEndGap: [60, 100],
mainLayerGap: [50, 70],
firstShearGap: [100, 300],
shearLegs: [4, 8],
spacingS: [200, 350],
spacingL: [200, 350],
sideSpacing: [200, 300],
sideEndGap: [300, 500],
c14UpperSpacing: [800, 1200],
c14LowerSpacing: [1500, 2500],
};
export interface CopingSettingsIssue {
code: 'CP01' | 'CP02';
key: keyof CopingRebarSettings;
message: string;
}
/**
* Checks the settings against the ranges. CP01: a value is not a finite number or is out of range (W).
* CP02: the shear leg count is odd (the 폐합 bars come in pairs of legs).
*/
export function copingSettingsIssues(s: CopingRebarSettings): CopingSettingsIssue[] {
const out: CopingSettingsIssue[] = [];
for (const key of Object.keys(COPING_REBAR_RANGES) as (keyof CopingRebarSettings)[]) {
const v = s[key];
const [lo, hi] = COPING_REBAR_RANGES[key];
if (!Number.isFinite(v) || v < lo || v > hi) {
out.push({ code: 'CP01', key, message: `CP01 ${key} ${v} 범위 밖 (${lo}–${hi})` });
}
}
if (Number.isFinite(s.shearLegs) && s.shearLegs % 2 !== 0) {
out.push({ code: 'CP02', key: 'shearLegs', message: `CP02 전단철근 다리 수 ${s.shearLegs}는 홀수 (짝수만 허용)` });
}
return out;
}
+4
View File
@@ -1,3 +1,5 @@
import type { CopingRebarSettings } from './rebar/coping-settings';
export type PierType = 'T형' | '2주형' | '3주형';
export type FoundationType = '말뚝기초' | '직접기초' | '현장타설말뚝';
export type Row = '전열' | '후열';
@@ -74,6 +76,8 @@ export interface PierInput {
blockRebar?: Partial<{ coverTop: number; coverSide: number; firstGap: number; spacingS1: number; spacingS2: number; legLength: number }>;
/** 받침 배치 (승인 2026-10-26): 분리 (default) or 일체. 일체 is allowed only when every front–back pair is within 100 mm. */
bearingLayout?: '분리' | '일체';
/** 코핑 배근 입력 (승인 2026-10-26): the 12 numbers of ③ 코핑 배근. Absent = the 코핑철근.md defaults. */
copingRebar?: Partial<CopingRebarSettings>;
strataRows?: StrataRow[];
}