Files
Pier_v1/tests/rebar-stairs.test.ts
ypshimandClaude Opus 5.5 2b26b7c095 fix(rebar): 측면 수평 C12 = 상단 · C13 = 하단 변화구간 (엑셀 Pier B357–G358)
T형과 다주형 모두 엑셀 Pier 시트 철근표(C12 상단, C13 하단(변화구간))에 맞춰
측면 수평철근 번호를 서로 바꾼다 (사용자 결정 2026-11-06).
- 경사 하면에서 끊기는 아래 단 → C13, 끝면까지 가는 위 단 → C12
- 철근표 위치·비고 문구, 3D, 다주형 생성기가 같은 원천(sideRows)을 따른다
- C14 높이 순서를 유지하도록 측면 단을 아래(C13) → 위(C12) 순서로 넘김
- 테스트 기대값의 번호를 교환 (P1: C12 2단 8개, C13 5단 20개)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:29:50 +09:00

77 lines
3.3 KiB
TypeScript
Raw Permalink 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 { buildPier } from '../src/core/geometry';
import { c14Bars, c14Length, copingSideBars, stairBars, undersideAt } from '../src/core/rebar/coping';
import { loadP1 } from './helpers';
const m = buildPier(loadP1());
const L = m.copingL * 1000;
const B = m.copingB * 1000;
const side = copingSideBars(L, 41.288, 42.538);
const rows = [...side.c13, ...side.c12];
const under = (x: number) => undersideAt(L, x, m.endBottom, m.levelBottom);
describe('C14 / C15 / C16 (코핑철근.md §7–8)', () => {
it('C14: 2 upper lines of 11 (C2, C3) and lower rows 5 / 6 / 3 / 2 = 38', () => {
const bars = c14Bars(L, m.copingRefTop, rows, under);
const count = (line: number) => bars.filter((b) => b.line === line).length;
expect(count(1)).toBe(11);
expect(count(2)).toBe(11);
expect([3, 4, 5, 6].map(count)).toEqual([5, 6, 3, 2]);
expect(bars.length).toBe(38);
});
it('C14 heights: upper 43.208 / 43.108, lower 42.810 / 42.310 / 41.810 / 41.310 (상면 단 간격 100)', () => {
const bars = c14Bars(L, m.copingRefTop, rows, under);
const z = (line: number) => bars.find((b) => b.line === line)!.z;
expect(z(1)).toBeCloseTo(43.208, 3);
expect(z(2)).toBeCloseTo(43.108, 3);
expect([3, 4, 5, 6].map(z)).toEqual([42.81, 42.31, 41.81, 41.31].map((v) => expect.closeTo(v, 2)));
});
it('C14 length 3447.5 (2855.5 run + 2 × 296 legs)', () => {
expect(c14Length(B)).toBeCloseTo(3447.5, 0);
});
it('C15: 11 bars, z 43.598, length 3852 (2088 + 2 × 882)', () => {
const { c15 } = stairBars(L, B, m.copingRefTop);
expect(c15.length).toBe(11);
expect(c15[0].z).toBeCloseTo(43.598, 3);
expect(c15[0].length).toBeCloseTo(3852, 0);
expect(c15[0].x0).toBeCloseTo(9812, 0);
});
it('C16: 22 bars (3·4구간), z 43.436 / 43.507, lengths 4070 / 4069', () => {
const { c16 } = stairBars(L, B, m.copingRefTop);
expect(c16.length).toBe(22);
expect(c16[0].z).toBeCloseTo(43.436, 3);
expect(c16[11].z).toBeCloseTo(43.507, 3);
expect(c16[0].length).toBeCloseTo(4070, 0);
expect(c16[11].length).toBeCloseTo(4069, 0);
});
it('C15 / C16 across positions: 137 from the cover line, then @250, 11 bars', () => {
const { c15 } = stairBars(L, B, m.copingRefTop);
expect(c15[0].n).toBeCloseTo(-B / 2 + 237, 0);
expect(c15[10].n - c15[0].n).toBeCloseTo(2500, 0);
});
});
describe('C14 연직 발 (코핑철근.md §8)', () => {
it('upper lines keep their legs; a lower bar keeps its legs only if they end above the underside', () => {
const bars = c14Bars(L, m.copingRefTop, rows, under);
expect(bars.filter((b) => b.line <= 2).every((b) => b.legs)).toBe(true);
// The leg of the C12 5단 bar (line 4) at the ends (x 1 m, 11 m) would end below the sloped underside, so it is left out.
const omitted = bars.filter((b) => !b.legs).map((b) => [b.line, Math.round(b.x / 1000)]);
expect(omitted).toEqual([[4, 1], [4, 11]]);
});
});
describe('C15 간격 = 2 × 주철근 기본간격 (승인 2026-10-26)', () => {
it('the default pitch is 250, and a larger pitch moves the 11 C15 bars apart', () => {
const { c15 } = stairBars(L, B, m.copingRefTop);
expect(c15[1].n - c15[0].n).toBe(250);
const wider = stairBars(L, B, m.copingRefTop, undefined, 280).c15;
expect(wider[1].n - wider[0].n).toBe(280);
});
});