public static class SofaCalculator { public static readonly IReadOnlyList SofaObservationCodes = new[] { "PAO2_MMHG", "FIO2_PCT", "PLATELET_K_UL", "BILIRUBIN_MG_DL", "CREATININE_MG_DL", "URINE_OUTPUT_ML_H", "SYSTOLIC_BP", "DIASTOLIC_BP", "SPO2", "SUPPLEMENTAL_O2" }; public static readonly IReadOnlySet SofaCodeSet = new HashSet(SofaObservationCodes); public static bool IsSofaCode(string observationCode) => SofaCodeSet.Contains(observationCode); // GCS components and gcs.scored also trigger SOFA re-score (CNS organ system) public static bool TriggersRescore(string observationCode) => IsSofaCode(observationCode) || GcsCalculator.IsGcsCode(observationCode); public static string CacheKey(Guid encounterId, string code) => $"sofa:{encounterId}:{code}"; // --- 1. Respiratory: PaO2/FiO2 ratio --- public static int ScoreRespiratory(decimal? pao2, decimal? fio2, bool onMechanicalVent) { if (pao2 is null || fio2 is null || fio2 == 0) return 0; var ratio = pao2.Value / (fio2.Value / 100m); return ratio switch { >= 400 when onMechanicalVent => 0, >= 400 => 0, >= 300 => 1, >= 200 => 2, >= 100 when onMechanicalVent => 3, >= 100 => 2, _ when onMechanicalVent => 4, _ => 3 }; } // SpO2/FiO2 proxy when PaO2 unavailable (Rice et al. 2007) public static int ScoreRespiratoryFromSpo2(decimal? spo2, decimal? fio2, bool onMechanicalVent) { if (spo2 is null || fio2 is null || fio2 == 0) return 0; var sfRatio = spo2.Value / (fio2.Value / 100m); return sfRatio switch { >= 315 => 0, >= 235 => 1, >= 150 => 2, >= 67 when onMechanicalVent => 3, >= 67 => 2, _ when onMechanicalVent => 4, _ => 3 }; } // --- 2. Coagulation: Platelet count (k/µL) --- public static int ScoreCoagulation(decimal? platelets) { if (platelets is null) return 0; return platelets.Value switch { >= 150 => 0, >= 100 => 1, >= 50 => 2, >= 20 => 3, _ => 4 }; } // --- 3. Liver: Bilirubin (mg/dL) --- public static int ScoreLiver(decimal? bilirubin) { if (bilirubin is null) return 0; return bilirubin.Value switch { < 1.2m => 0, < 2.0m => 1, < 6.0m => 2, < 12.0m => 3, _ => 4 }; } // --- 4. Cardiovascular: MAP and vasopressor dose --- public static int ScoreCardiovascular(decimal? map, VasopressorInfo? vasopressor) { if (vasopressor is not null) { return vasopressor.DrugName.ToUpperInvariant() switch { "DOPAMINE" when vasopressor.DoseUgKgMin > 15m => 4, "EPINEPHRINE" when vasopressor.DoseUgKgMin > 0.1m => 4, "NOREPINEPHRINE" when vasopressor.DoseUgKgMin > 0.1m => 4, "DOPAMINE" when vasopressor.DoseUgKgMin > 5m => 3, "EPINEPHRINE" => 3, "NOREPINEPHRINE" => 3, "DOPAMINE" => 2, "DOBUTAMINE" => 2, _ => 1 }; } if (map is null) return 0; return map.Value < 70m ? 1 : 0; } // --- 5. CNS: Glasgow Coma Scale (from Phase 25) --- public static int ScoreCns(int? gcsTotal) => GcsCalculator.ToSofaCnsScore(gcsTotal ?? 15); // --- 6. Renal: Creatinine (mg/dL) or urine output (mL/day) --- public static int ScoreRenal(decimal? creatinine, decimal? urineOutputMlPerDay) { var creatScore = creatinine switch { null => 0, < 1.2m => 0, < 2.0m => 1, < 3.5m => 2, < 5.0m => 3, _ => 4 }; var urineScore = urineOutputMlPerDay switch { null => 0, < 200m => 4, < 500m => 3, _ => 0 }; return Math.Max(creatScore, urineScore); } public static SofaResult ComputeTotal( int respiratory, int coagulation, int liver, int cardiovascular, int cns, int renal) => new( Total: respiratory + coagulation + liver + cardiovascular + cns + renal, Respiratory: respiratory, Coagulation: coagulation, Liver: liver, Cardiovascular: cardiovascular, Cns: cns, Renal: renal); // Count organ systems with component data for baseline eligibility public static int CountPopulatedOrganSystems( bool hasRespiratory, bool hasCoagulation, bool hasLiver, bool hasCardiovascular, bool hasCns, bool hasRenal) => new[] { hasRespiratory, hasCoagulation, hasLiver, hasCardiovascular, hasCns, hasRenal } .Count(hasData => hasData); }