Preserve local abutment, cast-in-place rebar and compact header features alongside remote drawing, ground-link and quantity workspaces. Adapt drawing and takeoff consumers to generated solplate plans, retain current P1 regression coverage, and resolve bearing-detail annotation collisions. Validation: 122 test files / 975 tests passed; production build passed; 10 browser integration checks passed.
49 lines
2.3 KiB
TypeScript
49 lines
2.3 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
||
import { fileURLToPath } from 'node:url';
|
||
import * as XLSX from 'xlsx';
|
||
import { parseWorkbook } from '../src/core/parseWorkbook';
|
||
import type { PierInput } from '../src/core/types';
|
||
import { parseAbutments } from '../src/core/abut/parse';
|
||
import { type BearingPair, girderPairs } from '../src/core/bearing-pair';
|
||
import { buildPier, type PierModel } from '../src/core/geometry';
|
||
|
||
/** Spec workbook (RAG/Pier ui_xxx.xlsx, sheet intent.PR, all tables on one sheet). Used by single-sheet tests. */
|
||
const SPEC_PATH = fileURLToPath(new URL('../도면추출/samples/P1.xlsx', import.meta.url));
|
||
/** User input (RAG/운곡교P1입력.xlsx, three sheets 교각 · IP · 받침). This is the P1 input used by the app and tests. */
|
||
const INPUT_PATH = fileURLToPath(new URL('../도면추출/samples/운곡교P1입력.xlsx', import.meta.url));
|
||
|
||
export function loadWorkbook(path: string = SPEC_PATH): XLSX.WorkBook {
|
||
return XLSX.read(readFileSync(path), { type: 'buffer' });
|
||
}
|
||
|
||
export function loadInputWorkbook(): XLSX.WorkBook {
|
||
return loadWorkbook(INPUT_PATH);
|
||
}
|
||
|
||
export function loadP1(): PierInput {
|
||
const { piers, issues } = parseWorkbook(loadInputWorkbook());
|
||
if (issues.length) throw new Error(`P1 parse issues: ${JSON.stringify(issues)}`);
|
||
const p1 = piers.find((p) => p.name === 'P1');
|
||
if (!p1) throw new Error('P1 not found');
|
||
return p1;
|
||
}
|
||
|
||
/**
|
||
* P1 with its bridge context (2026-11-06): the girder pairs A1 ①–⑤ ↔ P1 ①–⑤ from the same input workbook, so the
|
||
* solplate slope S is computed (−1.908 … −1.902 %, T 30) as in the app where A1 is loaded with P1.
|
||
*/
|
||
export function p1Pairs(): BearingPair[] {
|
||
const a1 = parseAbutments(loadInputWorkbook()).abutments.find((a) => a.name === 'A1');
|
||
if (!a1) throw new Error('A1 not found');
|
||
const p1 = loadP1();
|
||
return girderPairs([
|
||
{ name: 'A1', bearings: a1.bearings.map((b) => ({ no: b.no, x: b.pos.e, y: b.pos.n, z: b.z, azimuthDeg: b.azimuthDeg! })) },
|
||
{ name: p1.name, bearings: p1.bearings.map((b) => ({ no: b.no, x: b.x, y: b.y, z: b.z, azimuthDeg: b.azimuthDeg })) },
|
||
]);
|
||
}
|
||
|
||
/** buildPier for P1 (with changes) in its bridge context. */
|
||
export function buildP1(changes: Partial<PierInput> = {}): PierModel {
|
||
return buildPier({ ...loadP1(), ...changes }, { pairs: p1Pairs() });
|
||
}
|