import type { CaseState } from "./caseModel"; export const PUMP_ROD_MISMATCH_M = 15; export type EngineeringIssue = { severity: "warning" | "error"; code: string; message: string; }; export type EngineeringChecks = { issues: EngineeringIssue[]; hasBlockingError: boolean; }; export function runEngineeringChecks(state: CaseState): EngineeringChecks { const issues: EngineeringIssue[] = []; const activeTaper = state.taper.filter((t) => Number.isFinite(t.length) && t.length > 0); const rodTotal = activeTaper.reduce((acc, t) => acc + t.length, 0); const pumpDepth = state.pumpDepth; if (rodTotal > 0 && pumpDepth > 0) { const diff = Math.abs(pumpDepth - rodTotal); if (diff > PUMP_ROD_MISMATCH_M) { issues.push({ severity: "error", code: "PUMP_ROD_MISMATCH_15M", message: `Pump depth (${pumpDepth.toFixed(1)}) and total rod length (${rodTotal.toFixed( 1 )}) differ by ${diff.toFixed(1)} m (> ${PUMP_ROD_MISMATCH_M} m limit).` }); } } if (state.survey.length < 2) { issues.push({ severity: "error", code: "SURVEY_TOO_SHORT", message: "Trajectory needs at least 2 survey stations." }); } else { let nonMonotonic = false; for (let i = 1; i < state.survey.length; i += 1) { if (state.survey[i].md <= state.survey[i - 1].md) nonMonotonic = true; } if (nonMonotonic) { issues.push({ severity: "error", code: "SURVEY_MD_NON_MONOTONIC", message: "Measured depth must strictly increase between survey stations." }); } const maxMd = state.survey[state.survey.length - 1].md; if (pumpDepth > 0 && maxMd > 0 && maxMd < pumpDepth - 10) { issues.push({ severity: "warning", code: "SURVEY_BELOW_PUMP_MISSING", message: `Trajectory ends at MD ${maxMd.toFixed( 1 )}, shallower than pump depth ${pumpDepth.toFixed(1)}.` }); } } return { issues, hasBlockingError: issues.some((issue) => issue.severity === "error") }; }