feat(core): haunch-and-Level-300 coping underside, steel pile 609.6, W03/W04 checks

- Multi-column coping (2·3주형): underside between columns drops 300 below
  Level with 300 × 300 haunches (spec §4.5, Q3 추천안).
- Steel pipe pile diameter 609.6 mm (spec §4.5, Q5 추천안).
- Direct foundation keeps the 100 mm blinding concrete (Q4 추천안, test added).
- W03: bearing centre closer than half a block width to a step boundary.
- W04: block footprint outside the coping plan.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-22 08:58:57 +09:00
1 parent 112f460f1f
commit 5466b3522e
3 files changed
+100 -7

No files matched your search

+54
View File
@@ -44,6 +44,35 @@ describe('foundation types', () => {
expect(m.piles).toHaveLength(0);
});
it('직접기초: blinding concrete under the footing (Q4 추천안, 적용)', () => {
const m = buildPier({ ...loadP1(), foundationType: '직접기초' });
expect(m.blindings).toHaveLength(1);
expect(m.blindings[0].thickness).toBeCloseTo(0.1, 6);
});
it('말뚝기초: steel pipe pile 609.6 mm (Q5 추천안)', () => {
const m = buildPier(loadP1());
expect(m.piles.length).toBeGreaterThan(0);
expect(m.piles[0].diameter).toBeCloseTo(0.6096, 6);
});
it('2주형: underside between columns drops 300 below Level, T형 has no such point (Q3 추천안)', () => {
const t = buildPier(loadP1());
const dip = t.levelBottom - 0.3;
expect(t.profile.some(([, z]) => Math.abs(z - dip) < 1e-9)).toBe(false);
const two = buildPier({ ...loadP1(), type: '2주형', columnCount: 2 });
expect(two.profile.some(([, z]) => Math.abs(z - dip) < 1e-9)).toBe(true);
const outlineLow = Math.min(...two.profile.map(([, z]) => z));
expect(outlineLow).toBeCloseTo(dip, 9);
});
it('3주형 builds with two gaps of haunches', () => {
const m = buildPier({ ...loadP1(), type: '3주형', columnCount: 3 });
const dips = m.profile.filter(([, z]) => Math.abs(z - (m.levelBottom - 0.3)) < 1e-9);
expect(dips).toHaveLength(4);
});
it('현장타설말뚝: no footing, one pile of column diameter per column, tip = bottom EL − length', () => {
const m = buildPier({ ...loadP1(), foundationType: '현장타설말뚝' });
expect(m.footings).toHaveLength(0);
@@ -52,3 +81,28 @@ describe('foundation types', () => {
expect(m.piles[0].bottom).toBeCloseTo(26.208 - 24, 6);
});
});
describe('bearing and block checks (spec §10 W03, W04)', () => {
it('P1 has no W03 or W04', () => {
const codes = run(loadP1()).map((i) => i.code);
expect(codes).not.toContain('W03');
expect(codes).not.toContain('W04');
});
it('W03 when a bearing centre is closer than half a block width to a step boundary', () => {
const m = buildPier(loadP1());
const boundary = m.segments[1].s0;
const bearings = m.bearings.map((b, k) => (k === 0 ? { ...b, s: boundary + 0.3 } : b));
const issues: Issue[] = [];
validatePier(loadP1(), { ...m, bearings }, issues);
expect(issues.map((i) => i.code)).toContain('W03');
});
it('W04 when a block footprint extends past the coping end', () => {
const m = buildPier(loadP1());
const blocks = m.blocks.map((b, k) => (k === 0 ? { ...b, s: 0.1 } : b));
const issues: Issue[] = [];
validatePier(loadP1(), { ...m, blocks }, issues);
expect(issues.map((i) => i.code)).toContain('W04');
});
});