Files
Pier_v1/tests/seat-el.test.ts
T
ypshimandClaude Haiku 5.5 b84288c48a feat(check): 받침블럭 콘크리트 최소 높이 W11 (63 mm, 제안)
교각 받침블럭마다 콘크리트 높이(패드 제외)가 0보다 크고 63 mm(피복 50 + D13, 교대 I01과 같은 기준)보다
낮으면 W11 경고를 낸다. 교대는 기존 I01(블럭 철근을 교좌면 아래로)이 같은 경우를 다룬다.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-11-10 15:14:30 +09:00

92 lines
4.0 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 { validatePier } from '../src/core/validate';
import type { Issue, PierInput } from '../src/core/types';
import { loadP1, p1Pairs } from './helpers';
// Bridge context (A1 ↔ P1 girder pairs) as in the app, so the solplate slope is computed (2026-11-06).
const P1CTX = { pairs: p1Pairs() };
// 교좌면 EL of the P1 sheet (받침 1–10), 2026-11-03.
const SEAT = [43.411, 43.483, 43.555, 43.626, 43.698, 43.411, 43.483, 43.555, 43.626, 43.698];
function withSeat(input: PierInput, seats: number[]): PierInput {
return { ...input, bearings: input.bearings.map((b) => ({ ...b, seatEl: seats[b.no - 1] })) };
}
describe('교좌면 EL 입력 (2026-11-03)', () => {
it('the P1 교좌면 EL values reproduce the 두부보 상면 slope: the model does not change', () => {
const base = buildPier(loadP1(), P1CTX);
const seated = buildPier(withSeat(loadP1(), SEAT), P1CTX);
for (const b of base.blocks) {
const s = seated.blocks.find((x) => x.no === b.no)!;
expect(s.bottom).toBeCloseTo(b.bottom, 6);
expect(s.top).toBeCloseTo(b.top, 6);
}
});
it('an input 교좌면 EL sets the block bottom and so h1 = (EL.X − 50 mm) − 교좌면 EL', () => {
const m = buildPier(withSeat(loadP1(), [43.4, ...SEAT.slice(1)]), P1CTX);
const b1 = m.blocks.find((x) => x.no === 1)!;
expect(b1.bottom).toBeCloseTo(43.4, 6);
expect((b1.top - b1.bottom) * 1000).toBeCloseTo(111, 6);
});
it('without 교좌면 EL the seatCalc is the slope value (the check reference)', () => {
const m = buildPier(loadP1(), P1CTX);
expect(m.blocks.every((b) => Math.abs(b.seatCalc - b.bottom) < 1e-9)).toBe(true);
});
it('warns (W10) when the input 교좌면 EL differs from the slope by more than 5 mm, and keeps the input', () => {
const input = withSeat(loadP1(), [43.5, ...SEAT.slice(1)]);
const m = buildPier(input, P1CTX);
const issues: Issue[] = [];
validatePier(input, m, issues);
const w = issues.filter((i) => i.code === 'W10');
expect(w.length).toBe(1);
expect(w[0].message).toContain('1번');
expect(m.blocks.find((x) => x.no === 1)!.bottom).toBeCloseTo(43.5, 6);
});
it('no W10 for the P1 values', () => {
const input = withSeat(loadP1(), SEAT);
const m = buildPier(input, P1CTX);
const issues: Issue[] = [];
validatePier(input, m, issues);
expect(issues.filter((i) => i.code === 'W10')).toEqual([]);
});
it('an input 교좌면 EL also sets the coping top of that step, so the block sits on the coping (2026-11-10)', () => {
const m = buildPier(withSeat(loadP1(), [43.4, ...SEAT.slice(1)]), P1CTX);
const b1 = m.blocks.find((x) => x.no === 1 && x.row === '전열')!;
const seg = m.segments.find((s) => b1.g >= s.s0 && b1.g < s.s1)!;
expect(seg.top).toBeCloseTo(43.4, 6);
expect(b1.bottom).toBeCloseTo(seg.top, 9);
// seatCalc keeps the slope value (z − h1) as the W10 reference.
expect(b1.seatCalc).toBeCloseTo(43.411, 3);
});
it('W10 is information (I), not a warning, since the input builds the geometry', () => {
const input = withSeat(loadP1(), [43.5, ...SEAT.slice(1)]);
const m = buildPier(input, P1CTX);
const issues: Issue[] = [];
validatePier(input, m, issues);
expect(issues.filter((i) => i.code === 'W10').map((i) => i.level)).toEqual(['I']);
});
it('W11 when a block is thinner than 63 mm (피복 50 + D13), from its own 교좌면 EL; none for P1', () => {
const p1 = withSeat(loadP1(), SEAT);
const ok: Issue[] = [];
validatePier(p1, buildPier(p1, P1CTX), ok);
expect(ok.filter((i) => i.code === 'W11')).toEqual([]);
// Bearing 1: z 43.561 − pad 50 − 50 mm block → 교좌면 43.461.
const thin = withSeat(loadP1(), [43.461, ...SEAT.slice(1)]);
const m = buildPier(thin, P1CTX);
const issues: Issue[] = [];
validatePier(thin, m, issues);
const w = issues.filter((i) => i.code === 'W11');
expect(w.length).toBe(1);
expect(w[0].message).toContain('받침 1번');
});
});