Files
Pier_v1/tests/abut-wall-svg.test.ts
T
ypshimandClaude Haiku 5.5 5e64a4f2ed feat(abut): 벽체 높이 H_w = 받침 ① 교좌면 ~ 흉벽 상단 연직 (기본 3326)
- 사용자 도면(2026-11-04): 받침 ① 위치에서 받침 ① 교좌면부터 흉벽 상단까지 연직 거리. 모든 교대 기본값 3326 (QA-4 가정 2500 대체)
- 입력 이름 "벽체 높이 · 받침 ① 기준 연직", ② 정면도에 받침 ① 기준선과 H_w 치수
- ③ 흉벽 철근표 대표 단면 = 받침 ① 위치 (P1–P3는 그 단면에서 정확히 계산)
- 테스트: 흉벽 상단 IP1 48.006 / IP3 47.661 등 + 0.826 반영, 교대흉벽철근.md §11 재현은 2500을 넣어 유지, 3326 기본 확인 (P1 3945)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-11-04 17:20:05 +09:00

58 lines
2.6 KiB
TypeScript

import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import * as XLSX from 'xlsx';
import { describe, expect, it } from 'vitest';
import { buildAbut } from '../src/core/abut/geometry';
import { parseAbutments, toAbutInput } from '../src/core/abut/parse';
import { buildMembers } from '../src/core/abut/members';
import { abutWallElevationSvg, abutWallSectionSvg, type AbutWallDrawing } from '../src/view/abut-wall-svg';
const RAG = fileURLToPath(new URL('../../../RAG/운곡교P1입력.xlsx', import.meta.url));
const rec = parseAbutments(XLSX.read(readFileSync(RAG), { type: 'buffer' })).abutments[0];
const input = toAbutInput(rec);
const model = buildAbut(input);
const m = buildMembers(model, { bottomEl: input.foundationBottomEl, pileLengthMm: input.pileLengthMm });
const d: AbutWallDrawing = {
lengthM: model.length,
segments: m.wallSegments,
bearings: model.bearings,
footingTopEl: m.footingTopEl,
footingBottomEl: m.footingBottomEl!,
parapetTopStartEl: m.parapetTopStartEl,
parapetTopEndEl: m.parapetTopEndEl,
wallFrontM: m.shape.wallFrontM,
parapetBackM: m.shape.parapetBackM,
wallBackM: m.shape.wallBackM,
footingFrontM: m.shape.footingFrontM,
footingBackM: m.shape.footingBackM,
bracketHeightM: m.shape.bracketHeightM,
shrinkJointCount: 1,
bracketWidthMm: 300,
parapetThicknessMm: 500,
seatWidthMm: 1600,
};
describe('교대 벽체·흉벽 삽도 (시안 ② 벽체·흉벽 카드)', () => {
it('단면 (① 구간): the width line and the levels of the generated model', () => {
const svg = abutWallSectionSvg(d);
for (const s of ['300 + 500 + 1600 = 2400', '교좌면 EL.44.367', '벽체 2.372', '상면 EL.41.995', '기초 하단 EL.40.895', '교대축', '← 배면', '전면 →']) {
expect(svg).toContain(s);
}
expect(svg).toMatch(/흉벽 상단 EL\.4[78]\.\d{3}/);
expect(svg).toMatch(/브라켓 상면 EL\.4[56]\.\d{3}/);
});
it('정면·배면도: five steps, five bearings, the sloped 흉벽 top (IP3 47.661 → IP1 48.006) and the 수축줄눈', () => {
const svg = abutWallElevationSvg(d);
for (const s of ['IP3', 'IP1', `${model.length.toFixed(3)} m`, '수축줄눈 1', 'EL.47.661', 'EL.48.006', '①', '⑤']) expect(svg).toContain(s);
expect(svg).toContain('H_w 3326'); // 받침 ① 기준선의 벽체 높이 (사용자 도면 2026-11-04)
expect(svg).toContain('교좌면 계단 5구간');
});
it('the 수축줄눈 count follows the input', () => {
const svg = abutWallElevationSvg({ ...d, shrinkJointCount: 2 });
expect(svg).toContain('수축줄눈 2');
expect(svg.match(/stroke-dasharray="5 3"/g)).toHaveLength(2);
});
});