feat(bearing): 교량받침 ELEVATION TABLE과 솔플레이트 TABLE을 모델값으로 추가

- 모델값만 사용 (도면값 없음). A·B 열은 제거
- ELEVATION: EL.X(엑셀 z), h1 블록, h2 몰탈, h3 받침, h4 솔플(T), E, C1–C6,
  S1·S2 (블록 철근의 본수·길이, 전열 행에 일체 쌍 표시)
- 솔플레이트: S, L, W, T, T1, T2 (소수 한 자리), 검산 T1−T2 ≈ L·|S|/100
- 계산은 core/bearing-table.ts 순수 함수, 테스트 포함

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-11-03 11:22:45 +09:00
1 parent 6cbda0e126
commit b1b2ad1ddb
3 files changed
+231

No files matched your search

+47
View File
@@ -48,6 +48,7 @@ import { footingPlanSvg, footingSideSvg } from './view/footing-svg';
import { P1_COPING_GEOM } from './core/coping-geom';
import { SOLPLATE_RULE_DEFAULT, solplatePlan, solplateRuleIssues } from './core/solplate-rule';
import type { SolplateRule } from './core/types';
import { type BarSummary, elevationRows, solplateRows } from './core/bearing-table';
/** 지반 모델 (ground_model.json) for the project. Its values reach a pier's 지반고 only when the user applies them. */
let groundModel: GroundModelFile | null = null;
@@ -2436,9 +2437,55 @@ function renderBearingRef(box: HTMLDivElement, pier: Pier): void {
wrap.appendChild(typeInput);
renderBearingLayout(wrap, pier);
renderSolplateRule(wrap, pier);
renderElevationTable(wrap, pier);
renderSolplateTable(wrap, pier);
box.appendChild(wrap);
}
/** 교량받침 ELEVATION TABLE (모델값, mm · EL m, 2026-11-03): one row per bearing, from the model only. */
function renderElevationTable(wrap: HTMLDivElement, pier: Pier): void {
if (!pier.model) return;
wrap.appendChild(el('p', '교량받침 ELEVATION TABLE (모델값 · mm · EL m)', 'lbl'));
const table = el('table', undefined, 'grid-table rebar-table');
const head = el('thead');
const hr = el('tr');
for (const h of ['No', '열', 'EL.X', 'h1 블록', 'h2 몰탈', 'h3 받침', 'h4 솔플', 'E', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'S1 (본수·길이)', 'S2 (본수·길이)']) hr.appendChild(el('th', h));
head.appendChild(hr);
table.appendChild(head);
const body = el('tbody');
const dash = (v: number | null) => (v === null ? '—' : String(v));
const bars = (b: BarSummary | null) => (b === null ? '—' : `${b.count} · ${b.length}`);
for (const r of elevationRows(pier.model)) {
const tr = el('tr');
const cells = [String(r.no), r.row, r.elx.toFixed(3), String(r.h1), String(r.h2), String(r.h3), String(r.h4), String(r.E), String(r.C1), dash(r.C2), dash(r.C3), String(r.C4), String(r.C5), String(r.C6), bars(r.S1), bars(r.S2)];
for (const c of cells) tr.appendChild(el('td', c));
body.appendChild(tr);
}
table.appendChild(body);
wrap.appendChild(el('div', undefined, 'table-scroll')).appendChild(table);
}
/** 솔플레이트 TABLE (모델값, mm, 2026-11-03): S, L, W, T, T1, T2 and the check T1 − T2 ≈ L·|S|/100. */
function renderSolplateTable(wrap: HTMLDivElement, pier: Pier): void {
if (!pier.model) return;
wrap.appendChild(el('p', '솔플레이트 TABLE (모델값 · mm)', 'lbl'));
const table = el('table', undefined, 'grid-table rebar-table');
const head = el('thead');
const hr = el('tr');
for (const h of ['No', 'S (%)', 'L (교직)', 'W (교축)', 'T (중심)', 'T1 (−측)', 'T2 (+측)', '검산 T1 − T2 ≈ L·|S|/100']) hr.appendChild(el('th', h));
head.appendChild(hr);
table.appendChild(head);
const body = el('tbody');
for (const r of solplateRows(pier.model)) {
const tr = el('tr');
const cells = [String(r.no), r.S.toFixed(2), String(r.L), String(r.W), String(r.T), r.T1.toFixed(1), r.T2.toFixed(1), `${r.checkLhs.toFixed(1)} ≈ ${r.checkRhs.toFixed(1)} ${r.ok ? '일치' : '불일치'}`];
for (const c of cells) tr.appendChild(el('td', c));
body.appendChild(tr);
}
table.appendChild(body);
wrap.appendChild(el('div', undefined, 'table-scroll')).appendChild(table);
}
/** Sets one pier's solplate rule (C안, 2026-11-03) and rebuilds that pier. */
function setSolplateRule(name: string, rule: SolplateRule): void {
const p = state.piers.find((q) => q.input.name === name);