/** * 교대 지반·지층 (2026-11-04, 시안 ② 지반·지층 카드 = 교각과 같은 카드). 순수 함수. * * - 입력은 교각과 같은 이름이다: 위치(육상 · 하상 · 해상), 지하수위, 설계홍수위 · 세굴, 고조위 · 저조위, 지층 행. * 지반고는 엑셀 입력(①에서 수정)이다. 표시만 하고 형상 계산에는 쓰지 않는다. * - 검사는 교각과 같다(G01–G14, 말뚝 근입 G04). 지반고가 저판 하면보다 낮으면 흙덮개가 없다는 정보 AI01을 더한다. */ import { SUPPORT_STRATUM, validateGround, validatePileEmbedment, validateStrataNValues, type GroundCheckInput } from '../ground'; import type { Issue, PierInput } from '../types'; import type { AbutMembers } from './members'; import type { AbutRecord } from './parse'; export type AbutGround = Pick; /** 말뚝 두께 (mm): spec_abut 말뚝 Φ600 × 12T. Used only by the 해상 부식 여유 check. */ const ABUT_PILE_THICKNESS_MM = 12; /** The check input of an abutment: its 지반 values, 지반고 and 저판 하면 (기초 하단 when the 저판 is not built). */ export function abutGroundCheckInput(rec: AbutRecord, members?: AbutMembers): GroundCheckInput { return { name: rec.name, groundEl: rec.groundEl, footingBottomEl: members?.footingBottomEl ?? rec.foundationBottomEl, pileThicknessMm: ABUT_PILE_THICKNESS_MM, ...(rec.ground ?? {}), }; } /** 연암 상면 EL: the bottom of the row above the 연암 row (지반고 for the first row); undefined without a 연암 row. */ export function supportTopEl(groundEl: number, rows: { name: string; bottomEl: number }[] | undefined): number | undefined { const list = rows ?? []; const k = list.findIndex((r) => r.name === SUPPORT_STRATUM); if (k < 0) return undefined; return k === 0 ? groundEl : list[k - 1].bottomEl; } /** Issues of the 지반·지층 card: the pier checks plus AI01 (지반고 below the 저판 하면). */ export function abutGroundIssues(rec: AbutRecord, members?: AbutMembers): Issue[] { const input = abutGroundCheckInput(rec, members); const issues: Issue[] = []; validateGround(input, issues); validateStrataNValues(input, issues); if (members && members.pileBottomEl !== undefined && members.piles.length > 0) { validatePileEmbedment(input, { piles: [{ bottom: members.pileBottomEl, diameter: members.shape.pileDiameterM }] }, issues); } if (rec.groundEl < input.footingBottomEl) { issues.push({ code: 'AI01', level: 'I', pier: rec.name, message: `지반고 ${rec.groundEl.toFixed(3)}이 저판 하면 ${input.footingBottomEl.toFixed(3)}보다 ${(input.footingBottomEl - rec.groundEl).toFixed(3)} 낮아 흙덮개가 없습니다.`, }); } return issues; } /** True when any 지반 value differs from the default (육상, 지하수위 없음, 지층 행 없음). */ export function abutGroundChanged(ground: AbutGround | undefined): boolean { if (!ground) return false; return Object.entries(ground).some(([key, v]) => { if (v === undefined) return false; if (key === 'groundPosition') return v !== '육상'; if (key === 'groundWaterOn') return v === true; if (key === 'strataRows') return (v as unknown[]).length > 0; return true; }); }