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 48.006 at IP1 end and 47.661 at IP3 end; slope −2.829 %', () => { expect(m.parapetTopStartEl).toBeCloseTo(48.006, 2); expect(m.parapetTopEndEl).toBeCloseTo(47.661, 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); }); });