Files
vigilcare-records/VigilCareRecordsAPI/Services/PlausibilityValidator.cs
T
2026-06-26 05:04:39 +08:00

53 lines
2.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
public static class PlausibilityValidator
{
// Plausible ranges define the outer boundary of physically possible values.
// These are NOT clinical alert thresholds — they catch device malfunctions,
// transcription errors, and misread handwriting from paper charts.
// A heart rate of 300 is clinically extreme but not impossible during VT;
// 400 is physically impossible and indicates a data entry mistake.
private static readonly Dictionary<string, (decimal Min, decimal Max)> _ranges = new()
{
["HEART_RATE"] = (1, 300), // beats per minute; ceiling allows extreme tachycardia (e.g. VT)
["TEMP_C"] = (15, 50), // core body temperature in °C
["POTASSIUM_MEQ_L"] = (0.1m, 12), // serum potassium mEq/L; catches decimal misplacement (5.2 vs 52)
["SPO2"] = (50, 100), // peripheral oxygen saturation %
["RESP_RATE"] = (1, 80), // respirations per minute
["WBC_K_UL"] = (0.1m, 500), // white blood cell count ×10³/µL
["GLUCOSE_MG_DL"] = (10, 1000), // blood glucose mg/dL
["LACTATE_MMOL_L"] = (0.1m, 30), // blood lactate mmol/L
["BP_SYSTOLIC"] = (40, 300), // systolic blood pressure mmHg
["BP_DIASTOLIC"] = (20, 200), // diastolic blood pressure mmHg
};
/// <summary>
/// Returns true if the value falls within the plausible range for the given code.
/// Unknown observation codes pass plausibility — the code is validated elsewhere.
/// </summary>
public static bool IsPlausible(string observationCode, decimal value, out string? reason)
{
if (!_ranges.TryGetValue(observationCode, out var range))
{
// Unknown codes pass plausibility — the observation code itself
// is validated at the business rule layer, not here.
reason = null;
return true;
}
if (value < range.Min || value > range.Max)
{
reason = $"Value {value} is outside the plausible range " +
$"[{range.Min}{range.Max}] for {observationCode}.";
return false;
}
reason = null;
return true;
}
/// <summary>
/// Returns all known observation codes and their plausible ranges.
/// Used by the frontend to display valid input boundaries.
/// </summary>
public static IReadOnlyDictionary<string, (decimal Min, decimal Max)> GetAllRanges() =>
_ranges;
}