Files
Pier_v1/tests/integrated-block.test.ts
T
ypshimandClaude Haiku 5.5 43a18182f3 feat(bearing): 일체 block as one stepped block per pair, with its rebar (승인 2026-10-26)
- integrated-block.ts: per pair (전열 k · 후열 k) one block centred on the
  pair midpoint, 2500 across the 교축 and 1200 along the 교각축, with a
  stepped top (each half to its own bearing row top). Only when 일체 is chosen
  and every pair is within 100 mm; otherwise 분리 is kept (B02).
- Rebar: S2 19 bars at 125 across the 2500 (10 front half, 9 back half), each
  leg from its half's top; S1 8 bars across the 1200, 3800 long, depth from
  the lower top. Totals per pier: S1 40, S2 95 (분리: 80 / 80).
- Scene and 3D rebar draw the stepped blocks instead of the per-bearing blocks.
- The per-bearing blocks stay for the solplate, the pads, and the body.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-26 12:02:33 +09:00

84 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, type BlockModel } from '../src/core/geometry';
import { buildIntegratedBlocks, INTEGRATED_BLOCK } from '../src/core/integrated-block';
import { bearingBlockRebar, integratedBlockBars, totals } from '../src/core/rebar/bearing-block';
import { loadP1 } from './helpers';
const input = { ...loadP1(), bearingLayout: '일체' as const };
const model = buildPier(input);
describe('일체 블록 모델 (승인 2026-10-26)', () => {
it('P1 with 일체: one stepped block per pair (5), 2500 along the 교축 and 1200 along the 교각축', () => {
expect(model.integratedBlocks).toHaveLength(5);
expect(INTEGRATED_BLOCK).toEqual({ length: 2500, depth: 1200 });
const first = model.integratedBlocks[0];
expect(first.frontNo).toBe(1);
expect(first.backNo).toBe(6);
});
it('the block is centred on the pair midpoint, and its two halves keep their own tops (단이 있는 블록)', () => {
const ib = model.integratedBlocks[0];
const f = model.blocks.find((b) => b.no === 1)!;
const b = model.blocks.find((x) => x.no === 6)!;
expect(ib.n).toBeCloseTo((f.n + b.n) / 2, 9);
expect(ib.s).toBeCloseTo((f.s + b.s) / 2, 9);
expect(ib.topFront).toBe(f.top);
expect(ib.topBack).toBe(b.top);
// the front and back tops differ on P1 (150 vs 200 mm), so the block is stepped
expect(Math.abs(ib.topFront - ib.topBack)).toBeGreaterThan(0.01);
});
it('the 2500 block covers the pair: the front and back bearings sit 600 mm inside each end (C1 600)', () => {
const ib = model.integratedBlocks[0];
const f = model.blocks.find((b) => b.no === 1)!;
const b = model.blocks.find((x) => x.no === 6)!;
const half = INTEGRATED_BLOCK.length / 2000;
expect(ib.n - half).toBeCloseTo(f.n - 0.6, 2);
expect(ib.n + half).toBeCloseTo(b.n + 0.6, 2);
});
it('분리 keeps no integrated blocks', () => {
expect(buildPier(loadP1()).integratedBlocks).toEqual([]);
});
it('a staggered pair blocks 일체: no integrated blocks, the model stays 분리', () => {
const blocks = [{ no: 1, row: '전열', s: 1, n: -0.7, top: 0.5, bottom: 0, rowSkewDeg: 0 }, { no: 1, row: '후열', s: 1.2, n: 0.6, top: 0.5, bottom: 0, rowSkewDeg: 0 }] as unknown as BlockModel[];
expect(buildIntegratedBlocks(blocks, true)).toEqual([]);
});
});
describe('일체 블록 철근 (승인 2026-10-26, 받침블럭철근.md 일체 a 2500)', () => {
it('S2: 19 bars across the 2500 length, 10 on the front half and 9 on the back half (the centre bar on the front)', () => {
const rows = integratedBlockBars(model.integratedBlocks[0]).filter((r) => r.name === 'S2');
expect(rows.reduce((s, r) => s + r.count, 0)).toBe(19);
expect(rows.map((r) => r.count)).toEqual([10, 9]);
expect(rows[0].length).toBe(2500);
});
it('S1: 8 bars across the 1200 depth, 3800 long (2500 − 100 + 2 × 700)', () => {
const s1 = integratedBlockBars(model.integratedBlocks[0]).find((r) => r.name === 'S1')!;
expect(s1.count).toBe(8);
expect(s1.length).toBe(3800);
});
it('a pier of five integrated blocks has S1 40 and S2 95 (per-bearing 분리 gives 80 and 80)', () => {
const t = totals(bearingBlockRebar(model));
expect(t).toEqual({ S1: 40, S2: 95 });
const sep = totals(bearingBlockRebar(buildPier(loadP1())));
expect(sep).toEqual({ S1: 80, S2: 80 });
});
});
describe('일체 블록 3D 철근과 장면', () => {
it('the 3D rebar and the scene build for a 일체 pier, with the S2 bars counted per pair (19 each)', async () => {
const { buildRebar3D } = await import('../src/view/rebar3d');
const { buildPierScene } = await import('../src/view/scene');
const rb = buildRebar3D(model);
expect(rb.group.children.length).toBeGreaterThan(0);
const scene = buildPierScene(model, undefined);
// the blocks group holds the stepped halves (2 per pair) and no per-bearing blocks
expect(scene.parts.blocks.children.length).toBeGreaterThan(0);
expect(scene.parts.blocks.children.length).toBe(model.integratedBlocks.length * 2);
});
});