Files
Pier_v1/tests/abut-members.test.ts
T
ypshimandClaude Haiku 5.5 1d31d2f3a9 feat(abut): 교대 형상·입력 패널과 교각 받침·솔플레이트 개편
- 교대 형상(src/core/abut, 3D 장면, 목록·카메라·맞춤)과 교대 입력 패널 추가
- 교각 받침 기준 카드 제거, 솔플레이트 규칙을 교각별 입력으로 변경
- 받침 ELEVATION·솔플레이트 TABLE을 모델값으로 연결
- 교대 입력값 카드: 형식 행에 시점·종점 표시, 제목을 "A1 입력값 [입력]"으로 변경
- 테스트 614건 통과, 타입 검사 통과

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-11-03 14:51:34 +09:00

60 lines
2.6 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 { 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';
const RAG = fileURLToPath(new URL('../../../RAG/운곡교P1입력.xlsx', import.meta.url));
// 운곡교 A1, 기준 입력 파일에서 읽음 (spec_abut §10.1).
const input = toAbutInput(parseAbutments(XLSX.read(readFileSync(RAG), { type: 'buffer' })).abutments[0]);
const model = buildAbut(input);
const m = buildMembers(model, { bottomEl: input.foundationBottomEl, pileLengthMm: input.pileLengthMm });
describe('교대 A1 벽체 · 흉벽 · 저판 · 말뚝 (AA3, spec_abut §10.1)', () => {
it('저판 상면 41.995 (기초 하단 40.895 + 두께 1.1)', () => {
expect(m.footingTopEl).toBeCloseTo(41.995, 3);
});
it('wall height ① 구간 2.372 m, five segments with the seat EL of each bearing', () => {
expect(m.wallSegments).toHaveLength(5);
const first = m.wallSegments.find((w) => Math.abs(w.seatEl - 44.367) < 1e-6)!;
expect(first.heightM).toBeCloseTo(2.372, 3);
});
it('wall segments tile the axis from 0 to L with the step boundaries', () => {
const w = m.wallSegments;
expect(w[0].sFrom).toBeCloseTo(0, 9);
expect(w[w.length - 1].sTo).toBeCloseTo(model.length, 9);
expect(w[0].sTo).toBeCloseTo(model.stepBounds[0], 9);
for (let i = 1; i < w.length; i++) expect(w[i].sFrom).toBeCloseTo(w[i - 1].sTo, 9);
});
it('흉벽 상단 EL 47.180 at IP1 end and 46.835 at IP3 end; slope −2.829 %', () => {
expect(m.parapetTopStartEl).toBeCloseTo(47.18, 2);
expect(m.parapetTopEndEl).toBeCloseTo(46.835, 2);
expect(m.parapetSlope * 100).toBeCloseTo(-2.829, 2);
});
it('말뚝 3열 × 6본 = 18, rows at t −1.15 / +0.85 / +2.15, spacing ≈ 2.179 m', () => {
expect(m.piles.map((r) => r.t)).toEqual([-1.15, 0.85, 2.15]);
expect(m.piles.every((r) => r.s.length === 6)).toBe(true);
const gap = m.piles[0].s[1] - m.piles[0].s[0];
expect(gap).toBeCloseTo(2.179, 2);
expect(m.piles[0].s[0]).toBeCloseTo(0.65, 6);
});
it('말뚝 선단 EL 19.295 (40.895 − 21.6 m)', () => {
expect(m.pileBottomEl).toBeCloseTo(19.295, 3);
});
it('without a foundation the footing and piles have no EL (no crash)', () => {
const bare = buildMembers(model);
expect(bare.footingBottomEl).toBeUndefined();
expect(bare.pileBottomEl).toBeUndefined();
expect(bare.piles[0].s).toHaveLength(6);
});
});