Files
Pier_v1/tests/rebar-grade.test.ts
T
ypshimandClaude Haiku 5.5 b6bf087334 feat(rebar): 철근재료표 by 강종 → 직경 → 번호 with unit weights, 할증 and Excel export
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>
2026-10-23 10:16:56 +09:00

52 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
});
});