Files
Pier_v1/tests/footing-section-svg.test.ts
T
ypshimandClaude Haiku 5.5 99db6a1f52 Revert "feat(rebar): B1–B4와 B5–B8 방향 교환 (B1–B4는 W 방향, B5–B8은 L 방향)"
이 교환은 9,350 방향이 L이라는 가정에서 적용됐으나, 단면 삽도(B5–B8 선, 교각축 직각 단면)와 재료표가 원래 배치(B1–B4 L 방향, B5–B8 W 방향)와 맞는 것으로 확인되어 되돌림.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-27 09:48:05 +09:00

75 lines
3.8 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 { buildPier } from '../src/core/geometry';
import { assemblyBars, assemblyGridIndices, assemblyJs, b9Bars, bottomBars, crossBars, sideBars } from '../src/core/rebar/footing';
import { DEFAULT_FOOTING_REBAR } from '../src/core/rebar/footing-settings';
import { footingSectionSvg } from '../src/view/footing-section-svg';
import { loadP1 } from './helpers';
const countMark = (svg: string, cls: string, bar: string) => svg.split(`class="${cls}" data-bar="${bar}"`).length - 1;
describe('확대기초 교각축 직각 단면 (폭 W) (승인 2026-10-26, 추천안 1단계)', () => {
const m = buildPier(loadP1());
const foot = m.footings[0];
const L = foot.length * 1000;
const W = foot.width * 1000;
const H = (foot.top - foot.bottom) * 1000;
const fs = DEFAULT_FOOTING_REBAR;
const svg = footingSectionSvg(m);
it('point and line counts match the rebar table families', () => {
const bottom = bottomBars(L, W, H, fs);
expect(countMark(svg, 'b1', 'B1')).toBe(bottom.find((b) => b.name === 'B1')!.count);
expect(countMark(svg, 'b2', 'B2')).toBe(bottom.find((b) => b.name === 'B2')!.count);
expect(countMark(svg, 'b4', 'B4')).toBe(bottom.find((b) => b.name === 'B4')!.count);
expect(countMark(svg, 'b9', 'B9')).toBe(b9Bars(L, W, [], 2000, fs).rows);
expect(countMark(svg, 'b10', 'B10-1')).toBe(sideBars(L, W, H, fs).find((b) => b.name === 'B10-1')!.count);
expect(countMark(svg, 'b11', 'B11')).toBe(assemblyJs(H, fs).length);
expect(countMark(svg, 'b12', 'B12')).toBe(assemblyBars(L, W, H, fs).find((b) => b.name === 'B12')!.count);
for (const name of ['B5', 'B6', 'B7', 'B8']) expect(countMark(svg, 'b5', name)).toBe(1);
expect(crossBars(L, W, H, fs).length).toBe(4);
});
it('shows the width, the grid string, and the B10 levels as dimensions', () => {
expect(svg).toContain('폭 8150');
expect(svg).toContain('8@200=1600');
expect(svg).toContain(`${fs.cBottom}`);
});
it('has one bubble per highlighted bar family', () => {
for (const name of ['B1', 'B2', 'B3', 'B4', 'B5', 'B11', 'B10-1']) expect(svg).toContain(`data-bubble="${name}"`);
});
it('조립 철근은 격자 가운데에 놓임: 양끝 여유 차이 ≤ 1칸 (B11 n 79, B12 n 61, k 8, 엇갈림 2칸 유지)', () => {
const levels = assemblyJs(H, fs).length;
for (const [n, k] of [[79, 8], [61, 8]] as const) {
const all = Array.from({ length: levels }, (_, idx) => assemblyGridIndices(n, k, idx)).flat();
const left = Math.min(...all);
const right = n - Math.max(...all);
expect(Math.abs(left - right)).toBeLessThanOrEqual(1);
}
expect(assemblyGridIndices(61, 8, 1)[0] - assemblyGridIndices(61, 8, 0)[0]).toBe(2);
});
it('조립 철근(B11·B12)은 짝수 격자에 놓여 B9(홀수 격자)와 겹치지 않음 (확대기초철근 (1).md §9.1)', () => {
const levels = assemblyJs(H, fs).length;
for (const [n, k] of [[79, 8], [61, 8]] as const) {
for (let idx = 0; idx < levels; idx++) {
for (const i of assemblyGridIndices(n, k, idx)) expect(i % 2).toBe(0);
}
}
});
it('2단계: B6 다리 주석 1723, 범례 5항목, 기둥과 말뚝 맥락 표시, 탭 4개 중 첫 탭만 작동', () => {
expect(svg).toContain('B6 다리 → B5');
expect(svg).toContain('높이 1723');
for (const label of ['주철근 (B5–B8)', '직각·보조 (B1–B4)', '전단·띠 (B9)', '측면 수평 (B10-1 · B10-2)', '조립 (B11·B12)']) expect(svg).toContain(label);
expect(svg).toContain('class="column"');
expect(svg.split('class="pile"').length - 1).toBeGreaterThan(0);
});
it('최외측 열: B1–B4 연장선과 측면 피복 다리선 (승인 2026-10-26)', () => {
expect(svg.split('class="leg"').length - 1).toBe(2);
expect(svg.split('class="ext"').length - 1).toBeGreaterThan(0);
});
});