import { describe, expect, it } from 'vitest'; import { abutBlockRebar, abutBarDepths } from '../src/core/abut/rebar/block'; // 교대 받침블럭 (교대 기획서 §10 · 받침블럭철근.md §6.6): 블럭 5개, 1200 × 1200, 높이 125 (패드 50 포함, 콘크리트 75). const blocks = [1, 2, 3, 4, 5].map((no, i) => ({ no, s: 1 + i * 2, t: 0.2, rotDeg: 0, seatEl: 44.367, blockHeightMm: 125 })); const bottom = 40.895; const A1 = abutBlockRebar(blocks, bottom); const bar = (r: typeof A1, m: 'S1' | 'S2') => r.bars.find((b) => b.mark === m)!; describe('교대 받침블럭 배근 A1 (AD6, 교대 기획서 §10)', () => { it('블럭 콘크리트 75 (블럭 125 − 패드 50), 깊이: S2 50 · S1 62.7 (H13 두 개)', () => { expect(A1.concreteH).toBe(75); expect(abutBarDepths(A1.settings)).toEqual({ S2: 50, S1: 50 + 6.35 + 6.35 }); }); it('본수: 블럭마다 8본 (7@125, 끝 162.5), 5개 → S1 40 · S2 40', () => { expect(bar(A1, 'S1').count).toBe(40); expect(bar(A1, 'S2').count).toBe(40); expect(A1.paths.filter((p) => p.mark === 'S1' && p.block === 1).length).toBe(8); // 블럭 1 (s = 1000 mm): S2 본은 블럭 모서리에서 162.5, 125 간격 → 첫 본 s = 1000 − 600 + 162.5 = 562.5. const s2 = A1.paths.filter((p) => p.mark === 'S2' && p.block === 1).map((p) => p.pts[0][0]).sort((a, b) => a - b); expect(s2[0]).toBeCloseTo(562.5, 6); expect(s2[1] - s2[0]).toBeCloseTo(125, 6); expect(s2.length).toBe(8); }); it('길이 2500 (1100 직선 + 다리 700 × 2), 묻힘: S2 675 · S1 688', () => { expect([bar(A1, 'S1').length, bar(A1, 'S2').length]).toEqual([2500, 2500]); expect(Math.round(A1.embedment.S2)).toBe(675); expect(Math.round(A1.embedment.S1)).toBe(688); }); it('간섭 (Q-S4, 경고만): S1 다리가 W2 층을 지남 → RB-AK01 (W), 다른 오류 없음', () => { const codes = A1.issues.map((i) => `${i.code}:${i.level}`); expect(codes).toContain('RB-AK01:W'); expect(A1.issues.filter((i) => i.level === 'E')).toEqual([]); }); it('간격 수정 → RB-AK03 "수정됨"', () => { const r = abutBlockRebar(blocks, bottom, { spacingS1: 150 }); expect(r.issues.map((i) => i.code)).toContain('RB-AK03'); expect(bar(r, 'S1').modified).toBe(true); expect(bar(r, 'S2').modified).toBe(false); }); it('회전 (방위각): 블럭 축이 돌면 경로 점도 같이 돈다 (교대축 방향 길이 보존)', () => { const r = abutBlockRebar([{ ...blocks[0], rotDeg: 30 }], bottom); const p = r.paths.find((q) => q.mark === 'S1')!; const len = Math.hypot(p.pts[2][0] - p.pts[1][0], p.pts[2][1] - p.pts[1][1]); expect(len).toBeCloseTo(1100, 6); }); });