Files
Pier_v1/tests/rebar-coping-main.test.ts
T
ypshimandClaude Haiku 5.5 3cfbdf62f6 feat(rebar): 철근표 간격·실간격을 입력과 연동, 근거는 기본값/입력
- C1–C8: 간격 2 × 주철근 기본간격, 실간격 기본간격
- C9·C11 · C10 · C12·C13 · C14: 전단·측면·C14 간격 입력
- S1·S2: 블록 철근 간격 입력
- 근거: 관련 입력이 모두 기본값이면 '기본값', 하나라도 바뀌면 '입력'
- 입력이 없는 행(C15·C16, P3~P5, 커플러)은 기존 고정값 유지

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-26 15:54:47 +09:00

86 lines
4.1 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 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 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);
});
});