import { describe, expect, it } from 'vitest'; import { columnRebar } from '../src/core/rebar/column'; const c = columnRebar(); describe('기둥 철근 C4 (기둥철근.md, plan C4)', () => { it('P1 radius 875, P2 radius 843.2 (touching; centre gap = d_P1)', () => { expect(c.r1).toBe(875); expect(c.r2).toBe(843.2); expect(c.angleStepDeg).toBeCloseTo(360 / 46, 9); }); it('heights: P1 top 15147, P2 top ≈ 14539 (l_d of S32 at fck 27, 1836.9 ≈ the document 1836)', () => { expect(c.zTop1).toBe(15147); expect(Math.abs(c.zTop2 - 14539)).toBeLessThan(1); }); it('couplers P1 at +3 / 6 / 9 / 12 m, P2 at +150 above each', () => { expect(c.couplerP1).toEqual([3000, 6000, 9000, 12000]); expect(c.couplerP2).toEqual([3150, 6150, 9150, 12150]); }); it('main bar pieces 230 + 230, couplers 4 × 46 × 2 = 368', () => { expect(c.mainP1).toBe(230); expect(c.mainP2).toBe(230); expect(c.couplers).toBe(368); }); it('tie radius 900.45, circumference ≈ 5657.7', () => { expect(c.tieRadius).toBe(900.45); expect(c.tieCircumference).toBeCloseTo(5657.7, 1); }); it('P3: l_e = 2340, 38 ties from 2.340 at @300 (top 13.440)', () => { expect(c.zTopT).toBe(13724); expect(c.lE).toBe(2340); expect(c.p3Count).toBe(38); expect(c.p3[0]).toBe(2340); expect(c.p3[c.p3.length - 1]).toBe(13440); }); it('P5: 19 ties @120 from 2.220 down to 0.060', () => { expect(c.p5Count).toBe(19); expect(c.p5[0]).toBe(2220); expect(c.p5[c.p5.length - 1]).toBe(60); }); it('P4: 8 ties @120 from −0.060 to −0.900 (none removed in the example)', () => { expect(c.p4Count).toBe(8); expect(c.p4[0]).toBe(-60); expect(c.p4[c.p4.length - 1]).toBe(-900); }); it('P4 semicircle ≈ 2828.9', () => { expect(c.p4SemicircleLength).toBeCloseTo(2828.9, 0); }); it('P6: 8 levels from −0.060 to 12.540, 4 bars each = 32, length ≈ 2071', () => { expect(c.p6Levels).toEqual([-60, 1740, 3540, 5340, 7140, 8940, 10740, 12540]); expect(c.p6Count).toBe(32); expect(c.p6Length).toBeCloseTo(2071, 0); }); }); import { deleteInterferingP4, footingTopBars } from '../src/core/rebar/column'; describe('RB-C07 P4 삭제 규칙 (기둥철근.md §6.2)', () => { it('the example: no P4 interferes with the top bars (B5 −100, B1 −127): 8 kept, 0 deleted', () => { expect(c.p4Count).toBe(8); expect(c.p4Deleted).toEqual([]); const r = deleteInterferingP4([-60, -180], footingTopBars(2000)); expect(r.deleted).toEqual([]); }); it('hypothetical: B5 moved to −70 deletes the P4 at −60 (|−60 + 70| = 10 < 23.85)', () => { const bars = [{ name: 'B5', z: -70, d: 28.6 }]; const r = deleteInterferingP4([-60, -180, -300], bars); expect(r.deleted).toEqual([{ z: -60, bar: 'B5' }]); expect(r.kept).toEqual([-180, -300]); }); it('a P4 just outside the limit is kept: |−60 + 84| = 24 ≥ 23.85', () => { const r = deleteInterferingP4([-60], [{ name: 'B5', z: -84, d: 28.6 }]); expect(r.kept).toEqual([-60]); }); }); describe('기둥철근 P1·P2 마디와 바닥 (기둥철근.md §3.2)', () => { it('bottom at −1697.5 (−H_f + z_B7 + (d_B7 + d_P1)/2), P1 pieces 4697.5 + 525 / 3000 ×3 / 3147', () => { expect(c.zBot).toBeCloseTo(-1697.55, 1); expect(c.p1Hook).toBe(525); expect(c.p1Pieces.map((v) => Math.round(v))).toEqual([5223, 3000, 3000, 3000, 3147]); }); it('P2 pieces 4847.5 / 3000 ×3 / 2389', () => { expect(c.p2Pieces.map((v) => Math.round(v))).toEqual([4848, 3000, 3000, 3000, 2389]); }); it('P6 hook 135 each, so the length is 2071 (1800.9 + 2 × 135)', () => { expect(c.p6Length).toBeCloseTo(2070.9, 1); }); });