feat(bearing): 받침별 받침높이로 h3를 정한다 (교각·교대, AP07 폐지)
받침 시트의 받침높이_mm(9열)를 받침마다 읽어 h3 = H − T_ref로 쓴다. 거더 하면 = z + H가 받침마다 지켜진다. 솔플레이트 입력에 h3를 적으면 그 값이 모든 받침에 우선한다. 받침높이가 없으면 기존 기본값(교각 181, 교대 교대 값 − T_ref). 교대는 받침마다 달라도 받침별 값을 쓰므로 AP07(첫 값 사용) 경고를 없앤다. 교각 받침높이가 T_ref 이하이면 S01(E). 입력 양식 받침 표에 받침높이_mm 열을 추가한다. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8aedc9b969
commit
d7a61df7a9
10 files changed
+121
-13
No files matched your search
@@ -0,0 +1,83 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { buildPier } from '../src/core/geometry';
|
||||
import { validateInput } from '../src/core/validate';
|
||||
import { parseAbutments, toAbutInput } from '../src/core/abut/parse';
|
||||
import { buildAbut } from '../src/core/abut/geometry';
|
||||
import { abutSoles, resolveBearingRule } from '../src/core/abut/bearing-table';
|
||||
import type { Issue, PierInput } from '../src/core/types';
|
||||
import { loadInputWorkbook, loadP1, p1Pairs } from './helpers';
|
||||
|
||||
// 받침별 받침높이 (2026-11-10): h3 = 그 받침의 받침높이 H − T_ref, 거더 하면 = z + H.
|
||||
const CTX = { pairs: p1Pairs() };
|
||||
const withHeights = (input: PierInput, h: Record<number, number | undefined>): PierInput => ({
|
||||
...input,
|
||||
bearings: input.bearings.map((b) => ({ ...b, heightMm: b.no in h ? h[b.no] : b.heightMm })),
|
||||
});
|
||||
|
||||
describe('교각 받침별 받침높이', () => {
|
||||
it('reads 받침높이 from the bearing sheet (P1: 211 for every bearing, so h3 stays 181)', () => {
|
||||
const p1 = loadP1();
|
||||
expect(p1.bearings.map((b) => b.heightMm)).toEqual(Array(10).fill(211));
|
||||
expect(buildPier(p1, CTX).blocks.every((b) => b.plan.h3 === 181)).toBe(true);
|
||||
});
|
||||
|
||||
it('each bearing gets h3 = its H − T_ref; the block (z − pad − drop) does not move', () => {
|
||||
const base = buildPier(loadP1(), CTX);
|
||||
const m = buildPier(withHeights(loadP1(), { 3: 174, 8: 188 }), CTX);
|
||||
const h3 = (no: number) => m.blocks.find((b) => b.no === no)!.plan.h3;
|
||||
expect(h3(3)).toBe(144);
|
||||
expect(h3(8)).toBe(158);
|
||||
expect(h3(1)).toBe(181);
|
||||
for (const b of m.blocks) {
|
||||
const o = base.blocks.find((x) => x.no === b.no)!;
|
||||
expect(b.top).toBeCloseTo(o.top, 9);
|
||||
expect(b.bottom).toBeCloseTo(o.bottom, 9);
|
||||
}
|
||||
});
|
||||
|
||||
it('girder underside = z + H: pad top + h3 + T − (T − T_ref) − … equals z + H for every bearing', () => {
|
||||
const input = withHeights(loadP1(), { 2: 176, 7: 183 });
|
||||
const m = buildPier(input, CTX);
|
||||
for (const b of m.blocks) {
|
||||
const H = input.bearings.find((x) => x.no === b.no)!.heightMm!;
|
||||
const z = input.bearings.find((x) => x.no === b.no)!.z;
|
||||
expect(b.padTop + (b.plan.h3 + b.plan.T) / 1000).toBeCloseTo(z + H / 1000, 9);
|
||||
}
|
||||
});
|
||||
|
||||
it('a typed h3 (솔플레이트 입력) wins over the bearing heights', () => {
|
||||
const input = { ...withHeights(loadP1(), { 3: 174 }), sole: { h3Mm: 200 } };
|
||||
expect(buildPier(input, CTX).blocks.every((b) => b.plan.h3 === 200)).toBe(true);
|
||||
});
|
||||
|
||||
it('without 받침높이 the default h3 181 is used', () => {
|
||||
const input = { ...loadP1(), bearings: loadP1().bearings.map(({ heightMm: _h, ...b }) => b) };
|
||||
expect(buildPier(input, CTX).blocks.every((b) => b.plan.h3 === 181)).toBe(true);
|
||||
});
|
||||
|
||||
it('S01 (E) when a 받침높이 is not above T_ref, so no body could be built', () => {
|
||||
const issues: Issue[] = [];
|
||||
expect(validateInput(withHeights(loadP1(), { 4: 30 }), issues)).toBe(false);
|
||||
expect(issues.filter((i) => i.code === 'S01').map((i) => i.message)).toEqual([expect.stringContaining('받침 4번')]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('교대 받침별 받침높이', () => {
|
||||
const a1 = () => parseAbutments(loadInputWorkbook()).abutments.find((a) => a.name === 'A1')!;
|
||||
|
||||
it('different heights per bearing give different h3 and no AP07 warning', () => {
|
||||
const wb = loadInputWorkbook();
|
||||
wb.Sheets['받침']['I16'] = { t: 'n', v: 260 };
|
||||
const { abutments, issues } = parseAbutments(wb);
|
||||
expect(issues.some((i) => i.code === 'AP07')).toBe(false);
|
||||
const rec = abutments.find((a) => a.name === 'A1')!;
|
||||
const soles = abutSoles(buildAbut(toAbutInput(rec)), resolveBearingRule(), rec.bearingHeightMm);
|
||||
expect(soles.map((s) => s.h3)).toEqual([245, 245, 230, 245, 245]);
|
||||
});
|
||||
|
||||
it('a typed h3 wins for every bearing', () => {
|
||||
const rec = a1();
|
||||
const soles = abutSoles(buildAbut(toAbutInput(rec)), resolveBearingRule({ h3Mm: 200 }), rec.bearingHeightMm);
|
||||
expect(soles.every((s) => s.h3 === 200)).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user