Spaces:
Running
Running
| import { PatientDataForRiskAssessment, RiskDetectionResult, RiskFactor } from "./types"; | |
| import { RISK_FACTORS, RISK_THRESHOLDS } from "./config"; | |
| function checkRedFlags(data: PatientDataForRiskAssessment): { isRedFlag: boolean; reasons: string[] } { | |
| const reasons: string[] = []; | |
| if (data.bloodPressureSystolic && data.bloodPressureDiastolic) { | |
| if (data.bloodPressureSystolic >= 160 || data.bloodPressureDiastolic >= 110) { | |
| reasons.push("Severely elevated blood pressure (≥160/110 mmHg)"); | |
| } | |
| } else if (data.bloodPressureSystolic && data.bloodPressureSystolic >= 160) { | |
| reasons.push("Severely elevated systolic blood pressure (≥160 mmHg)"); | |
| } else if (data.bloodPressureDiastolic && data.bloodPressureDiastolic >= 110) { | |
| reasons.push("Severely elevated diastolic blood pressure (≥110 mmHg)"); | |
| } | |
| if (data.hasConvulsions) { | |
| reasons.push("Convulsions present"); | |
| } | |
| if (data.hasLossOfConsciousness) { | |
| reasons.push("Loss of consciousness"); | |
| } | |
| if (data.hasHeavyVaginalBleeding) { | |
| reasons.push("Heavy vaginal bleeding"); | |
| } | |
| if (data.hasAbsentFetalMovement) { | |
| reasons.push("Absent fetal movement"); | |
| } | |
| return { isRedFlag: reasons.length > 0, reasons }; | |
| } | |
| function evaluateRiskFactors(data: PatientDataForRiskAssessment): { | |
| contributingFactors: RiskFactor[]; | |
| totalScore: number; | |
| reasons: string[]; | |
| } { | |
| const contributingFactors: RiskFactor[] = []; | |
| const reasons: string[] = []; | |
| let totalScore = 0; | |
| if (data.age !== undefined && data.age >= 35) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "advanced-maternal-age"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } else if (data.age !== undefined && data.age < 18) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "teen-pregnancy"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.bmi !== undefined && data.bmi >= 35) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "bmi-over-35"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.parity !== undefined && data.parity >= 5) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "grand-multiparity"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousCaesareans && data.previousCaesareans > 0) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-caesarean"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousStillbirths && data.previousStillbirths > 0) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-stillbirth"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousIufd) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-iufd"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousPreeclampsia) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-preeclampsia"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousEclampsia) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-eclampsia"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.gestationalHypertension) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "gestational-hypertension"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.chronicHypertension || data.chronicHypertensionBeforePregnancy) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "chronic-hypertension"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.diabetesMellitus) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "diabetes-mellitus"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.kidneyDisease) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "kidney-disease"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.heartDisease) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "heart-disease"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousPlacentalAbruption) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-placental-abruption"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousPlacentaPrevia) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "placenta-previa"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousMultiplePregnancy) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "twin-pregnancy"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousGestationalDiabetes) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-gestational-diabetes"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.familyPreeclampsia) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "family-preeclampsia"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.familyHypertension) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "family-hypertension"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousPretermBirth) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-preterm-birth"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousLowBirthWeight) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-low-birth-weight"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.previousPostpartumHemorrhage) { | |
| const factor = RISK_FACTORS.find((f) => f.id === "previous-postpartum-hemorrhage"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.smokingStatus === "CURRENT") { | |
| const factor = RISK_FACTORS.find((f) => f.id === "current-smoking"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| if (data.alcoholUse === "REGULAR") { | |
| const factor = RISK_FACTORS.find((f) => f.id === "current-alcohol"); | |
| if (factor) { | |
| contributingFactors.push(factor); | |
| reasons.push(factor.description); | |
| totalScore += factor.points; | |
| } | |
| } | |
| return { contributingFactors, totalScore, reasons }; | |
| } | |
| function calculateRiskLevel(score: number): "LOW" | "MODERATE" | "HIGH" | "EMERGENCY" { | |
| for (const threshold of RISK_THRESHOLDS) { | |
| if (threshold.maxPoints === null) { | |
| if (score >= threshold.minPoints) return threshold.level; | |
| } else { | |
| if (score >= threshold.minPoints && score <= threshold.maxPoints) { | |
| return threshold.level; | |
| } | |
| } | |
| } | |
| return "LOW"; | |
| } | |
| function collectRecommendations(factors: RiskFactor[]): string[] { | |
| const recommendations = new Set<string>(); | |
| factors.forEach((factor) => { | |
| factor.recommendations.forEach((rec) => recommendations.add(rec)); | |
| }); | |
| return Array.from(recommendations); | |
| } | |
| export function detectRisks(data: PatientDataForRiskAssessment): RiskDetectionResult { | |
| const { isRedFlag, reasons: redFlagReasons } = checkRedFlags(data); | |
| const { contributingFactors, totalScore, reasons: riskFactorReasons } = evaluateRiskFactors(data); | |
| let riskLevel = calculateRiskLevel(totalScore); | |
| const recommendations = collectRecommendations(contributingFactors); | |
| if (isRedFlag) { | |
| riskLevel = "EMERGENCY"; | |
| } | |
| return { | |
| riskLevel, | |
| score: totalScore, | |
| reasons: isRedFlag ? redFlagReasons : riskFactorReasons, | |
| contributingFactors, | |
| recommendations, | |
| isRedFlag, | |
| redFlagReasons: isRedFlag ? redFlagReasons : undefined, | |
| }; | |
| } | |