103 lines
3.7 KiB
TypeScript
103 lines
3.7 KiB
TypeScript
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 14862 (= C3 43.170 − 0.1, e_P1 485), P2 top ≈ 14539 (l_d of S32 at fck 27, 1836.9 ≈ the document 1836)', () => {
|
||
expect(c.zTop1).toBe(14862);
|
||
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, 39 ties from 2.340 at @300, top at the coping middle level 14.025 (승인 2026-10-23)', () => {
|
||
expect(c.zTopT).toBe(14025);
|
||
expect(c.lE).toBe(2340);
|
||
expect(c.p3Count).toBe(39);
|
||
expect(c.p3[0]).toBe(2340);
|
||
expect(c.p3[c.p3.length - 1]).toBe(13740);
|
||
});
|
||
|
||
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 / 2862', () => {
|
||
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, 2862]);
|
||
});
|
||
|
||
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);
|
||
});
|
||
});
|