feat(abut): 흉벽 배근 입력 저장
- AbutRecord.rebar.parapet (바꾼 값만), applyParapetRebar, 프로젝트 파일 검증 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
25a4a84138
commit
ba71911edc
4 files changed
+34
-1
No files matched your search
@@ -10,6 +10,7 @@ import { resolveSlab, slabIssues, type AbutSlab, type SlabForm } from './slab';
|
||||
import type { AbutGround } from './ground';
|
||||
import { footingRebarIssues, resolveFootingRebar, type AbutFootingRebarSettings } from './rebar/footing';
|
||||
import { resolveWallRebar, wallRebarIssues, type AbutWallRebarSettings } from './rebar/wall';
|
||||
import { parapetRebarIssues, resolveParapetRebar, type AbutParapetRebarSettings } from './rebar/parapet';
|
||||
import { abutBearingRuleIssues, resolveBearingRule, type AbutBearingRule } from './bearing-table';
|
||||
|
||||
export type AbutEditKey = 'seatEl' | 'foundationBottomEl' | 'groundEl' | 'pileLengthMm' | 'skewDeg' | 'slopeI';
|
||||
@@ -189,6 +190,16 @@ export function applyWallRebar(rec: AbutRecord, patch: Partial<AbutWallRebarSett
|
||||
return { ...rec, rebar: { ...(rec.rebar ?? {}), wall } };
|
||||
}
|
||||
|
||||
/** Changes ③ 흉벽 · 브라켓 배근 values (only the changed ones are kept; undefined clears one), refused with a Korean message. */
|
||||
export function applyParapetRebar(rec: AbutRecord, patch: Partial<AbutParapetRebarSettings>): AbutRecord {
|
||||
for (const v of Object.values(patch)) if (typeof v === 'number' && !Number.isFinite(v)) throw new Error('숫자를 입력하세요.');
|
||||
const parapet: Partial<AbutParapetRebarSettings> = { ...(rec.rebar?.parapet ?? {}), ...patch };
|
||||
for (const key of Object.keys(parapet) as (keyof AbutParapetRebarSettings)[]) if (parapet[key] === undefined) delete parapet[key];
|
||||
const issues = parapetRebarIssues(resolveParapetRebar(parapet));
|
||||
if (issues.length > 0) throw new Error(issues[0]);
|
||||
return { ...rec, rebar: { ...(rec.rebar ?? {}), parapet } };
|
||||
}
|
||||
|
||||
/** Changes one 접속슬래브 dim, refused with a Korean message when the slab would not build. */
|
||||
export function applySlabEdit(rec: AbutRecord, key: (typeof SLAB_EDIT_FIELDS)[number]['key'], value: number): AbutRecord {
|
||||
if (!Number.isFinite(value)) throw new Error('숫자를 입력하세요.');
|
||||
|
||||
@@ -17,6 +17,7 @@ import type { AbutSlab } from './slab';
|
||||
import type { AbutGround } from './ground';
|
||||
import type { AbutFootingRebarSettings } from './rebar/footing';
|
||||
import type { AbutWallRebarSettings } from './rebar/wall';
|
||||
import type { AbutParapetRebarSettings } from './rebar/parapet';
|
||||
|
||||
type Cell = string | number | null | undefined;
|
||||
type Grid = Cell[][];
|
||||
@@ -68,7 +69,7 @@ export interface AbutRecord {
|
||||
/** 지반·지층 입력 (② 지반·지층 카드, 교각과 같은 필드). Absent = 육상, 지하수위 없음, 지층 행 없음. */
|
||||
ground?: AbutGround;
|
||||
/** ③ 배근 입력 (부재별, 바꾼 값만). Absent = 엑셀 Abut 시트 기본값. */
|
||||
rebar?: { footing?: Partial<AbutFootingRebarSettings>; wall?: Partial<AbutWallRebarSettings> };
|
||||
rebar?: { footing?: Partial<AbutFootingRebarSettings>; wall?: Partial<AbutWallRebarSettings>; parapet?: Partial<AbutParapetRebarSettings> };
|
||||
/** 예전 "좌우 같게" 값 (2026-11-04 이전 파일). 지금은 읽기만 하고 쓰지 않는다. */
|
||||
wingsLinked?: boolean;
|
||||
}
|
||||
|
||||
@@ -171,6 +171,9 @@ export function checkStoredAbutments(list: unknown): void {
|
||||
for (const [key, v] of Object.entries(a.rebar.wall ?? {})) {
|
||||
if (!finite(v)) throw new Error(`${who}: 벽체 배근 값 ${key}이(가) 맞지 않습니다.`);
|
||||
}
|
||||
for (const [key, v] of Object.entries(a.rebar.parapet ?? {})) {
|
||||
if (!finite(v)) throw new Error(`${who}: 흉벽 배근 값 ${key}이(가) 맞지 않습니다.`);
|
||||
}
|
||||
}
|
||||
if (a.wingsLinked !== undefined && typeof a.wingsLinked !== 'boolean') throw new Error(`${who}: 좌우 같게 값이 맞지 않습니다.`);
|
||||
if (a.wings !== undefined) {
|
||||
|
||||
@@ -140,3 +140,21 @@ describe('교대 흉벽 · 브라켓 배근 A1 (AD5, 교대흉벽철근.md §11)
|
||||
expect(bar(r, 'P1').modified).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
import { applyParapetRebar, applyWallRebar } from '../src/core/abut/edit';
|
||||
import { checkStoredAbutments } from '../src/core/project';
|
||||
|
||||
describe('③ 흉벽 배근 입력 저장', () => {
|
||||
it('stores only the changed values next to the 벽체 ones; undefined links a group back; refuses bad values', () => {
|
||||
const a = applyParapetRebar(applyWallRebar(rec, { sL: 150 }), { sHoriz: 150, s10: 350 });
|
||||
expect(a.rebar).toEqual({ wall: { sL: 150 }, parapet: { sHoriz: 150, s10: 350 } });
|
||||
expect(applyParapetRebar(a, { sHoriz: undefined }).rebar?.parapet).toEqual({ s10: 350 });
|
||||
expect(() => applyParapetRebar(rec, { k67V: 0 })).toThrow('P6 · P7 배수');
|
||||
expect(() => applyParapetRebar(rec, { L10: -1 })).toThrow();
|
||||
});
|
||||
|
||||
it('the project file keeps the 흉벽 input and refuses a non-number', () => {
|
||||
expect(() => checkStoredAbutments([applyParapetRebar(rec, { c: 80 })])).not.toThrow();
|
||||
expect(() => checkStoredAbutments([{ ...rec, rebar: { parapet: { c: 'x' } } as never }])).toThrow('흉벽 배근');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user