import { describe, expect, it } from 'vitest'; import { assemblyBars, bottomBars, crossBars, grid, layers, legB2, shearB9, sideBars } from '../src/core/rebar/footing'; // P1 footing: L 10400 × W 8150 × H 2000. const L = 10400; const W = 8150; const H = 2000; describe('확대기초 철근 (확대기초철근 (1).md, plan C5)', () => { it('grid across W: n 61, G 7625, e 162.5, 62 positions (§3.3)', () => { const g = grid(W); expect(g.n).toBe(61); expect(g.G).toBe(7625); expect(g.e).toBeCloseTo(162.5, 6); expect(g.positions).toBe(62); }); it('배근도 재현 grid: W 7800 → n 58, e 175', () => { const g = grid(7800); expect(g.n).toBe(58); expect(g.e).toBeCloseTo(175, 6); }); it('layer heights: B5 1900, B1 1873, B2·B4 150, B6·B8 177, B3 250, B7 277', () => { const z = layers(H); expect(z.B5).toBe(1900); expect(z.B1).toBeCloseTo(1873, 6); expect(z.B24).toBe(150); expect(z.B68).toBeCloseTo(177, 6); expect(z.B3).toBe(250); expect(z.B7).toBeCloseTo(277, 6); }); it('B2 leg 1723, B2 length 13646 (over the 12000 bar, splice needed)', () => { expect(legB2(H)).toBeCloseTo(1723, 6); const b2 = bottomBars(L, W, H).find((b) => b.name === 'B2')!; expect(b2.length).toBeCloseTo(13646, 0); expect(b2.count).toBe(31); }); it('B1–B4 counts 31 / 31 / 31 / 31 and B4 length 10200', () => { const bars = bottomBars(L, W, H); expect(bars.map((b) => b.count)).toEqual([31, 31, 31, 31]); expect(bars.find((b) => b.name === 'B4')!.length).toBeCloseTo(10200, 6); }); it('B5–B8 counts 40 each (grid along L: n 79), B8 length 7950, B6 length 11396', () => { const bars = crossBars(L, W, H); expect(bars.map((b) => b.count)).toEqual([40, 40, 40, 40]); expect(bars.find((b) => b.name === 'B8')!.length).toBeCloseTo(7950, 6); expect(bars.find((b) => b.name === 'B6')!.length).toBeCloseTo(11396, 0); }); it('B10-1 18 bars ≈ 10748, B10-2 18 bars ≈ 8494', () => { const [b101, b102] = sideBars(L, W, H); expect(b101.count).toBe(18); expect(b101.length).toBeCloseTo(10748, 0); expect(b102.count).toBe(18); expect(b102.length).toBeCloseTo(8494, 0); }); it('B10 levels from the height: H 2000 → m 8 (9 levels), H 2200 → m 9 (10 levels), as in the document', () => { expect(b10Levels(2000)).toBe(9); expect(b10Levels(2200)).toBe(10); expect(assemblyJs(2000)).toEqual([2, 4, 6]); expect(assemblyJs(2200)).toEqual([2, 4, 6, 8]); }); it('B11 60 bars (20 / 20 / 20) ≈ 8359, B12 47 bars (16 / 15 / 16) ≈ 10613', () => { const [b11, b12] = assemblyBars(L, W, H); expect(b11.count).toBe(60); expect(b11.length).toBeCloseTo(8359, 0); expect(b12.count).toBe(47); expect(b12.length).toBeCloseTo(10612.5, 1); // the document prints ≈ 10613 }); it('B9 shear: 16 rows, 20 per row on the grid, 320 in all, length ≈ 2128 (l_v 1750 + 2 × 189)', () => { const b9 = shearB9(L, W, H, []); expect(b9.rows).toBe(16); expect(b9.perRow.every((c) => c === 20)).toBe(true); expect(b9.count).toBe(320); expect(b9.length).toBeCloseTo(2128, 0); }); it('B9 column zone: bars whose centre is within D/2 + d/2 of a column axis are left out (P1: 14 bars)', () => { const b9 = shearB9(L, W, H, [0], 2000); expect(b9.count).toBe(306); for (const b of b9.bars) expect(Math.hypot(b.x, b.n)).toBeGreaterThan(1000 + 7.95); }); }); import { assemblyHeights, assemblyJs, b10Levels, legOffsets } from '../src/core/rebar/footing'; describe('확대기초 배근도 재현 (확대기초철근 (1).md §13)', () => { it('leg offsets: B1 +25.4, B3 +22.25, B5 +28.6, B7 +23.85', () => { const o = legOffsets(); expect(o.B1).toBeCloseTo(25.4, 6); expect(o.B3).toBeCloseTo(22.25, 6); expect(o.B5).toBeCloseTo(28.6, 6); expect(o.B7).toBeCloseTo(23.85, 6); }); it('B11 at 550 / 950 / 1350 and B12 at 569.1 / 969.1 / 1369.1', () => { const h = assemblyHeights(H); expect(h.B11).toEqual([550, 950, 1350]); expect(h.B12.map((z) => Math.round(z * 10) / 10)).toEqual([569.1, 969.1, 1369.1]); }); it('배근도 재현 W 7800 → B4 30, B2 29 (odd count split)', () => { const bars = bottomBars(10400, 7800, 2000); expect(bars.find((b) => b.name === 'B4')!.count).toBe(30); expect(bars.find((b) => b.name === 'B2')!.count).toBe(29); }); it('배근도 재현 L 9350 → B8 36, B6 35', () => { const bars = crossBars(9350, 8150, 2000); expect(bars.find((b) => b.name === 'B8')!.count).toBe(36); expect(bars.find((b) => b.name === 'B6')!.count).toBe(35); }); it('variables: W 8000 with s 150 → 50 grid steps, e 150, B4 26 / B2 25; W 12000 → 92 steps, e 150', () => { const g = grid(8000, 150); expect(g.n).toBe(50); expect(g.e).toBeCloseTo(150, 6); expect(grid(12000).n).toBe(92); expect(grid(12000).e).toBeCloseTo(150, 6); }); it('splice cases: L 8700 → B2 11946 (no splice); L 12400 → B4 12200; W 8800 → B6 12046', () => { expect(bottomBars(8700, 8150, 2000).find((b) => b.name === 'B2')!.length).toBeCloseTo(11946, 0); expect(bottomBars(12400, 8150, 2000).find((b) => b.name === 'B4')!.length).toBeCloseTo(12200, 0); expect(crossBars(10400, 8800, 2000).find((b) => b.name === 'B6')!.length).toBeCloseTo(12046, 0); }); });