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.3 KiB
TypeScript
52 lines
2.3 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { buildPier } from '../src/core/geometry';
|
|
import { DEFAULT_MATERIAL } from '../src/core/rebar/common';
|
|
import { buildQuantity, quantityRows, unitWeight } from '../src/core/rebar/quantity';
|
|
import { rebarSummary } from '../src/core/rebar/summary';
|
|
import { loadP1 } from './helpers';
|
|
|
|
const model = buildPier(loadP1());
|
|
const rows = rebarSummary(model).rows;
|
|
|
|
describe('철근재료표 (승인 2026-10-23)', () => {
|
|
it('unit weight is 0.00617 · d² on the nominal diameter (H19 19.1 → 2.25 kg/m)', () => {
|
|
expect(unitWeight(19.1)).toBeCloseTo(2.25, 2);
|
|
});
|
|
|
|
it('groups by 강종 then diameter; the group totals add up to the total', () => {
|
|
const q = buildQuantity(rows, DEFAULT_MATERIAL);
|
|
expect(q.groups.map((g) => g.grade)).toEqual([300, 400, 500].filter((g) => q.groups.some((x) => x.grade === g)));
|
|
expect(q.groups.reduce((s, g) => s + g.kg, 0)).toBeCloseTo(q.kg, 6);
|
|
for (const g of q.groups) {
|
|
expect(g.diameters.reduce((s, d) => s + d.kg, 0)).toBeCloseTo(g.kg, 6);
|
|
}
|
|
});
|
|
|
|
it('bars with no length yet are listed as missing and kept out of the totals', () => {
|
|
const q = buildQuantity(rows, DEFAULT_MATERIAL);
|
|
expect(q.missing).toContain('C9');
|
|
expect(q.missing).toContain('C11');
|
|
expect(q.groups.flatMap((g) => g.diameters.flatMap((d) => d.lines.map((l) => l.name)))).not.toContain('C9');
|
|
});
|
|
|
|
it('couplers are counted, not weighed', () => {
|
|
const q = buildQuantity(rows, DEFAULT_MATERIAL);
|
|
expect(q.couplers.find((c) => c.name === '주철근 커플러')!.count).toBe(368);
|
|
expect(q.couplers.find((c) => c.name === '띠철근 커플러')!.count).toBe(35);
|
|
});
|
|
|
|
it('할증 is 0% by default and multiplies the total when set', () => {
|
|
const q0 = buildQuantity(rows, DEFAULT_MATERIAL);
|
|
expect(q0.kgWithWaste).toBeCloseTo(q0.kg, 6);
|
|
const q10 = buildQuantity(rows, { ...DEFAULT_MATERIAL, waste: 10 });
|
|
expect(q10.kgWithWaste).toBeCloseTo(q0.kg * 1.1, 6);
|
|
expect(q10.ton).toBeCloseTo(q0.kg * 1.1 / 1000, 9);
|
|
});
|
|
|
|
it('the Excel rows start with the header and end with the couplers', () => {
|
|
const aoa = quantityRows(buildQuantity(rows, DEFAULT_MATERIAL));
|
|
expect(aoa[0][0]).toBe('강종');
|
|
expect(aoa[aoa.length - 1][0]).toBe('커플러 (개수만)');
|
|
});
|
|
});
|