- 삽도 2개 (src/view/abut-wall-svg.ts): 교대축 직각 단면(① 구간, "300 + 500 + 1600 = 2400", 흉벽 상단·브라켓 상면·교좌면·저판 EL)과 정면·배면도(교좌면 계단, 흉벽 상단 경사, 받침, 수축줄눈). 생성본 값, 가로·세로 같은 축척 - 벽체 두께는 자동 (= 브라켓 폭 + 흉벽 두께 + 교좌면 폭). 입력은 브라켓 폭(기본 300). 예전 저장 파일의 벽체 두께는 브라켓 폭으로 바꿔 읽음 (normalizeShape) - 인접 무시 기준(기본 5 mm) 입력: 이웃 받침의 교좌면 EL 차이가 이 값보다 작으면 한 구간으로 묶음 (A1 단차 71 mm, 변화 없음) - 카드 구성: 벽체 형식(기본형만, QA-8) → 삽도 → 입력 격자(시안 순서, QA-4 표시) → 자동 값(벽체 두께, 흉벽 상단 IP3/IP1, 교대축) → 구간 표 → 확인 필요 → 시안 메모 - 저판·말뚝 입력 5개를 새 "확대기초 · 말뚝" 카드로 분리. 부재 목록 6행(시안 순서), 변경 표시도 카드별로 나눔 - 테스트 갱신·추가. 전체 655건 통과, 타입 검사·빌드 통과. 브라우저 시각 확인은 미실시 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
2.5 KiB
TypeScript
57 lines
2.5 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', '교좌면 44.367', '벽체 2.372', '상면 41.995', '기초 하단 40.895', '교대축', '← 배면', '전면 →']) {
|
|
expect(svg).toContain(s);
|
|
}
|
|
expect(svg).toMatch(/흉벽 상단 4[67]\.\d{3}/);
|
|
expect(svg).toMatch(/브라켓 상면 4[56]\.\d{3}/);
|
|
});
|
|
|
|
it('정면·배면도: five steps, five bearings, the sloped 흉벽 top (IP3 46.835 → IP1 47.180) and the 수축줄눈', () => {
|
|
const svg = abutWallElevationSvg(d);
|
|
for (const s of ['IP3', 'IP1', `${model.length.toFixed(3)} m`, '수축줄눈 1', '46.835', '47.180', '①', '⑤']) expect(svg).toContain(s);
|
|
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);
|
|
});
|
|
});
|