Files
Pier_v1/tests/rebar-coping-main.test.ts
T
ypshimandClaude Haiku 5.5 72053be420 feat(rebar): C15·C16 폭 간격을 2 × 주철근 기본간격에 연동
- stairBars가 pitch를 받는다 (기본 2 × 기본간격 = 250, P1 그대로)
- 3D와 철근표가 같은 pitch를 쓴다
- 철근표 간격·실간격: 2 × 기본간격, 근거는 기본값/입력

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-26 16:04:31 +09:00

90 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from 'vitest';
import { developmentLength, hookLength, NOMINAL_DIAMETER, spliceLength } from '../src/core/rebar/common';
import { bottomPiece, topBarLength, topRowEl, widthLayout } from '../src/core/rebar/coping-main';
import { buildPier } from '../src/core/geometry';
import { rebarSummary } from '../src/core/rebar/summary';
import { DEFAULT_COPING_REBAR } from '../src/core/rebar/coping-settings';
import { loadP1 } from './helpers';
describe('C1–C8 상·하면 주철근 (코핑철근.md §5, plan C3)', () => {
it('nominal diameters: H29 28.6, S32 31.8 (documents use these, not the round numbers)', () => {
expect(NOMINAL_DIAMETER.H29).toBe(28.6);
expect(NOMINAL_DIAMETER.S32).toBe(31.8);
});
it('width layout for B 3100: edge 127, ends 110.5, 21@125, 24 bars (12 + 12)', () => {
const w = widthLayout(3100);
expect(w.yE).toBe(127);
expect(w.S).toBe(2846);
expect(w.n).toBe(21);
expect(w.g).toBe(110.5);
expect(w.count).toBe(24);
expect(w.cyclePerKind).toBe(12);
expect(w.text).toBe('127 · 110.5 · 21@125 · 110.5 · 127');
});
it('주철근 기본간격 input drives the layout: 140 → 19@140 (22 bars, even), 120 → 22@120 (25, odd)', () => {
const w140 = widthLayout(3100, { ...DEFAULT_COPING_REBAR, mainSpacing: 140 });
expect(w140.spacing).toBe(140);
expect(w140.n).toBe(19);
expect(w140.count).toBe(22);
expect(w140.text).toBe(`${w140.yE} · ${w140.g} · 19@140 · ${w140.g} · ${w140.yE}`);
const w120 = widthLayout(3100, { ...DEFAULT_COPING_REBAR, mainSpacing: 120 });
expect(w120.n).toBe(22);
expect(w120.count).toBe(25);
});
it('철근표 간격: P1 기본값은 250 / 125 · 기본값 근거, 기본간격 140이면 280 / 140 · 입력 근거', () => {
const base = rebarSummary(buildPier(loadP1())).rows;
const c1 = base.find((r) => r.name === 'C1')!;
expect([c1.spacing, c1.actual, c1.basis]).toEqual(['250', '125', 'default']);
const c12 = base.find((r) => r.name === 'C12')!;
expect(c12.basis).toBe('default');
const c15 = base.find((r) => r.name === 'C15')!;
expect([c15.spacing, c15.actual, c15.basis]).toEqual(['250', '250', 'default']);
const m = buildPier({ ...loadP1(), copingRebar: { mainSpacing: 140 }, blockRebar: { spacingS1: 130 } });
const rows = rebarSummary(m).rows;
const c8 = rows.find((r) => r.name === 'C8')!;
expect([c8.spacing, c8.actual, c8.basis]).toEqual(['280', '140', 'input']);
expect(rows.find((r) => r.name === 'C12')!.basis).toBe('default');
const c16 = rows.find((r) => r.name === 'C16')!;
expect([c16.spacing, c16.actual, c16.basis]).toEqual(['280', '280', 'input']);
const s1 = rows.find((r) => r.name === 'S1')!;
expect([s1.spacing, s1.actual, s1.basis]).toEqual(['130', '130', 'input']);
});
it('CP04: the default P1 has an even count (no warning); 기본간격 120 gives an odd count and a CP04 warning', () => {
const base = rebarSummary(buildPier(loadP1())).warnings.filter((w) => w.code === 'CP04');
expect(base).toEqual([]);
const odd = buildPier({ ...loadP1(), copingRebar: { mainSpacing: 120 } });
const warnings = rebarSummary(odd).warnings.filter((w) => w.code === 'CP04');
expect(warnings).toHaveLength(1);
expect(warnings[0].target).toBe('coping');
});
it('heights: 43.284 / 43.184 / 43.084 for the three top rows (상면 단 간격 100)', () => {
expect(topRowEl(43.284, 1)).toBe(43.284);
expect(topRowEl(43.284, 2)).toBe(43.184);
expect(topRowEl(43.284, 3)).toBe(43.084);
});
it('top bar lengths 12744 / 12686.8 / 12629.6 (path + 2 × 472 hook, 가로 단 간격 d = 28.6)', () => {
expect(topBarLength(12000, 1)).toBeCloseTo(12744, 0);
expect(topBarLength(12000, 2)).toBeCloseTo(12686.8, 1);
expect(topBarLength(12000, 3)).toBeCloseTo(12629.6, 1);
});
it('bottom piece ≈ 7448 with l_s = 1717.6 (1.3 × l_d of H29 at fck 27) — the document shows 1717', () => {
const b = bottomPiece();
expect(b.path).toBeCloseTo(12235.6, 6);
expect(b.ls).toBeCloseTo(1717.6, 0);
expect(b.piece).toBeCloseTo(7448, 0);
});
it('hook 472 (16.5 × 28.6) and splice from the same formula as C1', () => {
expect(hookLength('main90', NOMINAL_DIAMETER.H29)).toBeCloseTo(472, 0);
expect(spliceLength(NOMINAL_DIAMETER.H29, 400, 27)).toBeCloseTo(1.3 * developmentLength(NOMINAL_DIAMETER.H29, 400, 27), 9);
});
});