The quantity table sits below the 철근표 for the whole pier. Lines group by grade and nominal diameter, with subtotals, unit weight 0.00617·d² (kg/m), the total in kg and ton, and a 할증 total. 할증 is an input in 공통 설정, default 0 as an assumption. Couplers are counted, not weighed. Bars with no length yet (C9, C10, C11, C12, P1, P2) are listed as missing and kept out of the totals. The table exports to Excel with SheetJS. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
52 lines
2.5 KiB
TypeScript
52 lines
2.5 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
||
import { buildPier } from '../src/core/geometry';
|
||
import { DEFAULT_BEND, DEFAULT_MATERIAL, fyOf, isAssumedMaterial, materialFrom } from '../src/core/rebar/common';
|
||
import { rebarSummary } from '../src/core/rebar/summary';
|
||
import { loadP1 } from './helpers';
|
||
|
||
describe('③ 철근 강도: 규격 접두어별 입력 (승인 2026-10-23)', () => {
|
||
it('defaults: D = SD300, H = SD400, S = SD500, the same as the P1 values', () => {
|
||
expect(DEFAULT_MATERIAL.grade).toEqual({ D: 300, H: 400, S: 500 });
|
||
expect(fyOf(DEFAULT_MATERIAL, 'H19')).toBe(400);
|
||
expect(fyOf(DEFAULT_MATERIAL, 'S32')).toBe(500);
|
||
expect(fyOf(DEFAULT_MATERIAL, 'D22')).toBe(300);
|
||
});
|
||
|
||
it('only fck is assumed now; the grades are confirmed inputs', () => {
|
||
expect(isAssumedMaterial(DEFAULT_MATERIAL)).toBe(true);
|
||
expect(isAssumedMaterial({ ...DEFAULT_MATERIAL, fck: 35 })).toBe(false);
|
||
expect(isAssumedMaterial({ ...DEFAULT_MATERIAL, grade: { D: 300, H: 400, S: 400 } })).toBe(true);
|
||
});
|
||
|
||
it('an older file that stored fyH / fyS is read into the grade map', () => {
|
||
expect(materialFrom({ fck: 35, fyH: 400, fyS: 400 })).toEqual({ fck: 35, grade: { D: 300, H: 400, S: 400 }, bend: DEFAULT_BEND, waste: 0 });
|
||
});
|
||
|
||
it('a value outside SD300 · SD400 · SD500 falls back to the default for its prefix', () => {
|
||
expect(materialFrom({ fck: 27, grade: { S: 600 } }).grade.S).toBe(500);
|
||
expect(materialFrom(undefined)).toEqual(DEFAULT_MATERIAL);
|
||
});
|
||
|
||
it('the P1 values do not change with the defaults (S = SD500 gives the same C7 length)', () => {
|
||
const model = buildPier(loadP1());
|
||
const base = rebarSummary(model).rows.find((r) => r.name === 'C7')!.length;
|
||
const same = rebarSummary(model, materialFrom({ fck: 27, grade: { D: 300, H: 400, S: 500 } })).rows.find((r) => r.name === 'C7')!.length;
|
||
expect(same).toBe(base);
|
||
});
|
||
});
|
||
|
||
import { bendDeduction, bendRadius } from '../src/core/rebar/common';
|
||
|
||
describe('굽힘 반경 (승인 2026-10-23, 입력)', () => {
|
||
it('centre-line radius = inner factor × d + d/2, by size class', () => {
|
||
expect(bendRadius(25.4, DEFAULT_BEND)).toBeCloseTo(3 * 25.4 + 12.7, 6); // H25: main25
|
||
expect(bendRadius(28.6, DEFAULT_BEND)).toBeCloseTo(4 * 28.6 + 14.3, 6); // H29: main35
|
||
expect(bendRadius(15.9, DEFAULT_BEND)).toBeCloseTo(2 * 15.9 + 7.95, 6); // H16: small16
|
||
});
|
||
|
||
it('a 90° bend loses (2 − π/2)·R of centre line against the sharp corner', () => {
|
||
const R = 100;
|
||
expect(bendDeduction(Math.PI / 2, R)).toBeCloseTo((2 - Math.PI / 2) * R, 6);
|
||
});
|
||
});
|