feat(core): rebar for 2·3주형 — shear bars per column, column bars per column (plan)

- Coping §9: C10 at each column centre (@300, k_max as for one column), C9 / C11
  outside, and the gaps between columns filled @250 from both C10 groups with the
  remaining length shared evenly (추천안, Q-K2). One column gives the T형 result.
- Column bars and couplers repeat per column (P1 230 × 2 for 2주형, × 3 for 3주형).
- Footings: each footing's bars are summed per name; the longest length governs.
- C14 is kept as the T형 layout with an RB-M01 note (per-column rule open, Q-K11).
- Tests: counts for 2주형 and 3주형; T형 unchanged; too-close columns refused.
- Not yet: the ③ shear-segment table for multi columns (still single column), the
  C14 per column, and a drawing for multi columns. Not verified in a browser.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-22 12:20:49 +09:00
1 parent 8ac5d2973c
commit 13318e9393
3 files changed
+139 -19

No files matched your search

+45
View File
@@ -0,0 +1,45 @@
import { describe, expect, it } from 'vitest';
import { buildPier } from '../src/core/geometry';
import { shearBarsMulti } from '../src/core/rebar/coping';
import { rebarSummary } from '../src/core/rebar/summary';
import { loadP1 } from './helpers';
// 2주형 and 3주형 on the P1 sheet with a 12 m coping (columns at L/5, 4L/5 and L/5, L/2, 4L/5).
const two = buildPier({ ...loadP1(), type: '2주형', columnCount: 2, copingLengthMm: 12000 });
const three = buildPier({ ...loadP1(), type: '3주형', columnCount: 3, copingLengthMm: 12000 });
const count = (rows: ReturnType<typeof rebarSummary>['rows'], name: string) => rows.find((r) => r.name === name)!.count;
describe('다주형 철근 (2주형·3주형, 코핑철근.md §9)', () => {
it('2주형: C10 2 × 9 = 18; C9 and C11 3 each outside; 18 between (추천안, Q-K2)', () => {
const rows = rebarSummary(two).rows;
expect(count(rows, 'C10')).toBe(18);
expect(count(rows, 'C9')).toBe(3);
expect(count(rows, 'C11')).toBe(3);
expect(count(rows, 'C9·C11 사이')).toBe(18);
});
it('3주형: C10 3 × 9 = 27; two gaps of 3 between', () => {
const rows = rebarSummary(three).rows;
expect(count(rows, 'C10')).toBe(27);
expect(count(rows, 'C9·C11 사이')).toBe(6);
});
it('column bars repeat per column: P1 230 × 2 and 230 × 3', () => {
expect(count(rebarSummary(two).rows, 'P1')).toBe(460);
expect(count(rebarSummary(three).rows, 'P1')).toBe(690);
});
it('a multi-column pier gets the RB-M01 note about C14', () => {
expect(rebarSummary(two).warnings.map((w) => w.code)).toContain('RB-M01');
});
it('the single column (T형) has no between row and no RB-M01', () => {
const t = rebarSummary(buildPier(loadP1()));
expect(t.rows.find((r) => r.name === 'C9·C11 사이')).toBeUndefined();
expect(t.warnings.map((w) => w.code)).not.toContain('RB-M01');
});
it('shear bars for a columns too close to share a Level are refused', () => {
expect(() => shearBarsMulti(12000, [3000, 3500])).toThrow('겹칩니다');
});
});