feature: Simulator Scenarios + Clinical Validation: SOFA/GCS
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
public record GcsResponse(
|
||||
int EyeScore, int VerbalScore, int MotorScore,
|
||||
int TotalScore, string Classification, DateTimeOffset CalculatedAt);
|
||||
@@ -0,0 +1 @@
|
||||
public record QsofaResponse(int ActiveCriteria);
|
||||
@@ -0,0 +1,7 @@
|
||||
public record SofaResponse(
|
||||
int TotalScore,
|
||||
int RespiratoryScore, int CoagulationScore, int LiverScore,
|
||||
int CardiovascularScore, int CnsScore, int RenalScore,
|
||||
bool IsBaseline, int? DeltaFromBaseline,
|
||||
SofaStalenessResponse? Staleness,
|
||||
DateTimeOffset CalculatedAt);
|
||||
@@ -0,0 +1,4 @@
|
||||
public record SofaStalenessResponse(
|
||||
IReadOnlyList<string> StaleComponents,
|
||||
IReadOnlyList<string> MissingComponents,
|
||||
bool UsedSpO2Fallback);
|
||||
@@ -119,4 +119,28 @@ public class VigilCareApiClient
|
||||
.ReadFromJsonAsync<ApiResponse<SepsisBundleResponse>>();
|
||||
return envelope?.Data;
|
||||
}
|
||||
|
||||
public async Task<GcsResponse?> GetCurrentGcsAsync(Guid encounterId)
|
||||
{
|
||||
var response = await _http.GetAsync($"/api/v1/encounters/{encounterId}/gcs");
|
||||
if (!response.IsSuccessStatusCode) return null;
|
||||
var envelope = await response.Content.ReadFromJsonAsync<ApiResponse<GcsResponse>>();
|
||||
return envelope?.Data;
|
||||
}
|
||||
|
||||
public async Task<SofaResponse?> GetCurrentSofaAsync(Guid encounterId)
|
||||
{
|
||||
var response = await _http.GetAsync($"/api/v1/encounters/{encounterId}/sofa");
|
||||
if (!response.IsSuccessStatusCode) return null;
|
||||
var envelope = await response.Content.ReadFromJsonAsync<ApiResponse<SofaResponse>>();
|
||||
return envelope?.Data;
|
||||
}
|
||||
|
||||
public async Task<QsofaResponse?> GetCurrentQsofaAsync(Guid encounterId)
|
||||
{
|
||||
var response = await _http.GetAsync($"/api/v1/encounters/{encounterId}/qsofa/current");
|
||||
if (!response.IsSuccessStatusCode) return null;
|
||||
var envelope = await response.Content.ReadFromJsonAsync<ApiResponse<QsofaResponse>>();
|
||||
return envelope?.Data;
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,22 @@ public static class SimulatorConsole
|
||||
AnsiConsole.MarkupLine(
|
||||
$"[cyan][[{simTime}]][/] NEWS2 = {poll.News2.TotalScore} ({poll.News2.RiskLevel})");
|
||||
|
||||
if (poll.Gcs is not null)
|
||||
AnsiConsole.MarkupLine(
|
||||
$"[cyan][[{simTime}]][/] GCS = {poll.Gcs.TotalScore}/15 ({poll.Gcs.Classification}) " +
|
||||
$"E{poll.Gcs.EyeScore} V{poll.Gcs.VerbalScore} M{poll.Gcs.MotorScore}");
|
||||
|
||||
if (poll.Sofa is not null)
|
||||
{
|
||||
var delta = poll.Sofa.DeltaFromBaseline is int d ? $" Δ+{d}" : "";
|
||||
AnsiConsole.MarkupLine(
|
||||
$"[cyan][[{simTime}]][/] SOFA = {poll.Sofa.TotalScore}/24{delta}");
|
||||
}
|
||||
|
||||
if (poll.Qsofa is not null)
|
||||
AnsiConsole.MarkupLine(
|
||||
$"[cyan][[{simTime}]][/] qSOFA screen = {poll.Qsofa.ActiveCriteria}/3");
|
||||
|
||||
foreach (var alert in poll.NewAlerts)
|
||||
AnsiConsole.MarkupLine(
|
||||
$"[red][[{simTime}]][/] ALERT {alert.AlertType} ({alert.Severity})");
|
||||
@@ -78,6 +94,7 @@ public static class SimulatorConsole
|
||||
if (poll.SepsisBundle is not null)
|
||||
AnsiConsole.MarkupLine(
|
||||
$"[cyan][[{simTime}]][/] SEPSIS BUNDLE {poll.SepsisBundle.ComplianceStatus} " +
|
||||
$"({poll.SepsisBundle.ElementsCompleted}/4)");
|
||||
$"({poll.SepsisBundle.ElementsCompleted}/4) " +
|
||||
$"trigger={poll.SepsisBundle.TriggeringAlertType}");
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,16 @@ public class ApiPoller
|
||||
public async Task PollAndDisplayAsync(Guid encounterId, string simTime)
|
||||
{
|
||||
var news2 = await _client.GetCurrentNews2Async(encounterId);
|
||||
var gcs = await _client.GetCurrentGcsAsync(encounterId);
|
||||
var sofa = await _client.GetCurrentSofaAsync(encounterId);
|
||||
var qsofa = await _client.GetCurrentQsofaAsync(encounterId);
|
||||
|
||||
var allAlerts = await _client.GetAlertsAsync(encounterId);
|
||||
var newAlerts = allAlerts.Where(a => _seenAlertIds.Add(a.Id)).ToList();
|
||||
|
||||
var bundle = await _client.GetSepsisBundleAsync(encounterId);
|
||||
|
||||
var result = new PollResult(news2, newAlerts, bundle);
|
||||
var result = new PollResult(news2, gcs, sofa, qsofa, newAlerts, bundle);
|
||||
SimulatorConsole.PollResults(simTime, result);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
public record PollResult(
|
||||
News2Response? News2,
|
||||
List<AlertResponse> NewAlerts,
|
||||
GcsResponse? Gcs,
|
||||
SofaResponse? Sofa,
|
||||
QsofaResponse? Qsofa,
|
||||
IReadOnlyList<AlertResponse> NewAlerts,
|
||||
SepsisBundleResponse? SepsisBundle);
|
||||
@@ -99,6 +99,36 @@
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_EYE",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_VERBAL",
|
||||
"value": 5,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_MOTOR",
|
||||
"value": 6,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 15,
|
||||
"type": "observation",
|
||||
|
||||
@@ -101,6 +101,36 @@
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_EYE",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_VERBAL",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_MOTOR",
|
||||
"value": 6,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 2,
|
||||
"type": "observation",
|
||||
|
||||
@@ -110,6 +110,37 @@
|
||||
},
|
||||
"note": "Nasal cannula 2L/min started on arrival"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 1,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_EYE",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 1,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_VERBAL",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 1,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_MOTOR",
|
||||
"value": 5,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
},
|
||||
"note": "GCS 13 — sluggish, confused from hypothermia"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "order",
|
||||
|
||||
@@ -56,6 +56,21 @@
|
||||
"type": "observation",
|
||||
"data": { "code": "AVPU", "value": 0, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_EYE", "value": 4, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_VERBAL", "value": 5, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_MOTOR", "value": 6, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"scenario": {
|
||||
"id": "neurological-decline-gcs-01",
|
||||
"name": "Traumatic Brain Injury — Progressive GCS Decline",
|
||||
"description": "Post-trauma patient with initial GCS 14 (E4V4M6). Over 3 hours, GCS declines to 6. Triggers GCS_WARNING then GCS_CRITICAL. Vitals remain stable — neuro-specific deterioration, not sepsis.",
|
||||
"durationMinutes": 180,
|
||||
"tags": ["gcs", "neurological", "no-sepsis", "news2"]
|
||||
},
|
||||
"patient": {
|
||||
"firstName": "David",
|
||||
"lastName": "Okonkwo",
|
||||
"dateOfBirth": "1981-07-22",
|
||||
"gender": "Male"
|
||||
},
|
||||
"encounter": {
|
||||
"department": "Icu",
|
||||
"encounterType": "Inpatient",
|
||||
"attendingPhysician": "Dr. Amara Singh",
|
||||
"roomBed": "ICU-1A-3",
|
||||
"admissionReason": "TBI — motor vehicle collision, GCS 14 on arrival"
|
||||
},
|
||||
"events": [
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "HEART_RATE", "value": 72, "unit": "bpm", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "RESP_RATE", "value": 16, "unit": "/min", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "SYSTOLIC_BP", "value": 135, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "DIASTOLIC_BP", "value": 82, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "TEMP_C", "value": 36.9, "unit": "°C", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "SPO2", "value": 99, "unit": "%", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "SUPPLEMENTAL_O2", "value": 0, "unit": "flag", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_EYE", "value": 4, "unit": "score", "source": "Manual" },
|
||||
"note": "GCS 14 — confused speech"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_VERBAL", "value": 4, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_MOTOR", "value": 6, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 60,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_EYE", "value": 3, "unit": "score", "source": "Manual" },
|
||||
"note": "GCS 12 → GCS_WARNING"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 60,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_VERBAL", "value": 3, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 60,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_MOTOR", "value": 6, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 60,
|
||||
"type": "observation",
|
||||
"data": { "code": "HEART_RATE", "value": 68, "unit": "bpm", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 60,
|
||||
"type": "observation",
|
||||
"data": { "code": "SYSTOLIC_BP", "value": 142, "unit": "mmHg", "source": "Device" },
|
||||
"note": "Cushing response — HTN with bradycardia developing"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_EYE", "value": 2, "unit": "score", "source": "Manual" },
|
||||
"note": "GCS 9 — still GCS_WARNING band"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_VERBAL", "value": 3, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_MOTOR", "value": 4, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "HEART_RATE", "value": 58, "unit": "bpm", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "SYSTOLIC_BP", "value": 168, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 150,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_EYE", "value": 1, "unit": "score", "source": "Manual" },
|
||||
"note": "GCS 6 → GCS_CRITICAL"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 150,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_VERBAL", "value": 2, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 150,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_MOTOR", "value": 3, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 155,
|
||||
"type": "order",
|
||||
"data": {
|
||||
"orderType": "Imaging",
|
||||
"orderCode": "CT_HEAD",
|
||||
"description": "STAT CT head — GCS decline from 14 to 6",
|
||||
"orderedBy": "Dr. Amara Singh"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectedOutcomes": [
|
||||
{
|
||||
"afterOffsetMinutes": 60,
|
||||
"type": "alert",
|
||||
"alertType": "GCS_WARNING",
|
||||
"description": "GCS 12 in 9–12 band"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 150,
|
||||
"type": "alert",
|
||||
"alertType": "GCS_CRITICAL",
|
||||
"description": "GCS 6 ≤ 8"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -110,6 +110,36 @@
|
||||
},
|
||||
"note": "Nasal cannula 2L/min \u2014 standard post-op order"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 1,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_EYE",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 1,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_VERBAL",
|
||||
"value": 5,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 1,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_MOTOR",
|
||||
"value": 6,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 20,
|
||||
"type": "observation",
|
||||
@@ -718,6 +748,37 @@
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_EYE",
|
||||
"value": 3,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
},
|
||||
"note": "GCS 11 \u2014 hemorrhagic shock, declining consciousness"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_VERBAL",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_MOTOR",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 121,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "SUPPLEMENTAL_O2",
|
||||
"value": 1,
|
||||
@@ -726,7 +787,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"offsetMinutes": 121,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "LACTATE_MMOL_L",
|
||||
|
||||
@@ -98,6 +98,36 @@
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_EYE",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_VERBAL",
|
||||
"value": 5,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_MOTOR",
|
||||
"value": 6,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "order",
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
{
|
||||
"scenario": {
|
||||
"id": "sepsis-sofa-progression-01",
|
||||
"name": "Pneumonia → Multi-Organ Dysfunction (SOFA Pathway)",
|
||||
"description": "ICU patient with community-acquired pneumonia. Initial SOFA baseline ~2. Over 4 hours, respiratory failure, thrombocytopenia, and renal impairment develop. qSOFA screen fires early; SOFA delta ≥ 2 triggers sepsis bundle. GCS remains 15 until late decline to 13.",
|
||||
"durationMinutes": 240,
|
||||
"tags": ["sofa", "sepsis", "multi-organ", "gcs", "qsofa-screen"]
|
||||
},
|
||||
"patient": {
|
||||
"firstName": "Margaret",
|
||||
"lastName": "Torres",
|
||||
"dateOfBirth": "1954-03-18",
|
||||
"gender": "Female"
|
||||
},
|
||||
"encounter": {
|
||||
"department": "Icu",
|
||||
"encounterType": "Inpatient",
|
||||
"attendingPhysician": "Dr. Elena Vasquez",
|
||||
"roomBed": "ICU-2A-6",
|
||||
"admissionReason": "Community-acquired pneumonia, worsening dyspnea"
|
||||
},
|
||||
"events": [
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "HEART_RATE", "value": 88, "unit": "bpm", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "RESP_RATE", "value": 18, "unit": "/min", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "SYSTOLIC_BP", "value": 128, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "DIASTOLIC_BP", "value": 78, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "TEMP_C", "value": 38.2, "unit": "°C", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "SPO2", "value": 94, "unit": "%", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "SUPPLEMENTAL_O2", "value": 1, "unit": "flag", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_EYE", "value": 4, "unit": "score", "source": "Manual" },
|
||||
"note": "Baseline GCS 15 — fully alert"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_VERBAL", "value": 5, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_MOTOR", "value": 6, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 5,
|
||||
"type": "observation",
|
||||
"data": { "code": "PAO2_MMHG", "value": 85, "unit": "mmHg", "source": "Lab" },
|
||||
"note": "ABG baseline — P/F ~283 at FiO2 30%"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 5,
|
||||
"type": "observation",
|
||||
"data": { "code": "FIO2_PCT", "value": 30, "unit": "%", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 5,
|
||||
"type": "observation",
|
||||
"data": { "code": "PLATELET_K_UL", "value": 185, "unit": "k/µL", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 5,
|
||||
"type": "observation",
|
||||
"data": { "code": "BILIRUBIN_MG_DL", "value": 0.9, "unit": "mg/dL", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 5,
|
||||
"type": "observation",
|
||||
"data": { "code": "CREATININE_MG_DL", "value": 1.0, "unit": "mg/dL", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 5,
|
||||
"type": "observation",
|
||||
"data": { "code": "LACTATE_MMOL_L", "value": 1.8, "unit": "mmol/L", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 60,
|
||||
"type": "observation",
|
||||
"data": { "code": "HEART_RATE", "value": 102, "unit": "bpm", "source": "Device" },
|
||||
"note": "Mild tachycardia; qSOFA RR ≥ 22"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 60,
|
||||
"type": "observation",
|
||||
"data": { "code": "RESP_RATE", "value": 24, "unit": "/min", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 60,
|
||||
"type": "observation",
|
||||
"data": { "code": "SYSTOLIC_BP", "value": 105, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 60,
|
||||
"type": "observation",
|
||||
"data": { "code": "TEMP_C", "value": 38.9, "unit": "°C", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "RESP_RATE", "value": 28, "unit": "/min", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "SYSTOLIC_BP", "value": 92, "unit": "mmHg", "source": "Device" },
|
||||
"note": "SBP ≤ 100 → qSOFA ≥ 2 → QSOFA_SCREEN"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "DIASTOLIC_BP", "value": 58, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "SPO2", "value": 89, "unit": "%", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "observation",
|
||||
"data": { "code": "PAO2_MMHG", "value": 62, "unit": "mmHg", "source": "Lab" },
|
||||
"note": "Repeat ABG — P/F 155 at FiO2 40% → SOFA Resp 2"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "observation",
|
||||
"data": { "code": "FIO2_PCT", "value": 40, "unit": "%", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "observation",
|
||||
"data": { "code": "PLATELET_K_UL", "value": 88, "unit": "k/µL", "source": "Lab" },
|
||||
"note": "Thrombocytopenia → SOFA Coag 1"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "observation",
|
||||
"data": { "code": "CREATININE_MG_DL", "value": 2.3, "unit": "mg/dL", "source": "Lab" },
|
||||
"note": "AKI → SOFA Renal 2"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "observation",
|
||||
"data": { "code": "LACTATE_MMOL_L", "value": 3.1, "unit": "mmol/L", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 130,
|
||||
"type": "medication",
|
||||
"data": {
|
||||
"drugName": "Norepinephrine",
|
||||
"dose": 0.05,
|
||||
"doseUnit": "mcg/kg/min",
|
||||
"route": "IV",
|
||||
"administeredBy": "RN-Torres"
|
||||
},
|
||||
"note": "Vasopressor → SOFA CV 3; delta ≥ 2 → SOFA_SEPSIS + bundle"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 180,
|
||||
"type": "observation",
|
||||
"data": { "code": "PAO2_MMHG", "value": 55, "unit": "mmHg", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 180,
|
||||
"type": "observation",
|
||||
"data": { "code": "FIO2_PCT", "value": 60, "unit": "%", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 180,
|
||||
"type": "observation",
|
||||
"data": { "code": "PLATELET_K_UL", "value": 42, "unit": "k/µL", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 180,
|
||||
"type": "observation",
|
||||
"data": { "code": "CREATININE_MG_DL", "value": 3.8, "unit": "mg/dL", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 200,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_EYE", "value": 3, "unit": "score", "source": "Manual" },
|
||||
"note": "GCS 13 — SOFA CNS 1"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 200,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_VERBAL", "value": 4, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 200,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_MOTOR", "value": 6, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 210,
|
||||
"type": "order",
|
||||
"data": {
|
||||
"orderType": "Lab",
|
||||
"orderCode": "BLOOD_CULTURE",
|
||||
"description": "Blood cultures x2 — sepsis workup",
|
||||
"orderedBy": "Dr. Elena Vasquez"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 210,
|
||||
"type": "order",
|
||||
"data": {
|
||||
"orderType": "Lab",
|
||||
"orderCode": "SERUM_LACTATE",
|
||||
"description": "Repeat lactate",
|
||||
"orderedBy": "Dr. Elena Vasquez"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectedOutcomes": [
|
||||
{
|
||||
"afterOffsetMinutes": 120,
|
||||
"type": "alert",
|
||||
"alertType": "QSOFA_SCREEN",
|
||||
"description": "qSOFA ≥ 2 — bedside screen positive, recommend SOFA labs"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 130,
|
||||
"type": "alert",
|
||||
"alertType": "SOFA_SEPSIS",
|
||||
"description": "SOFA delta ≥ 2 from baseline after labs + vasopressor"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 130,
|
||||
"type": "bundle",
|
||||
"description": "Sepsis bundle auto-created; triggeringAlertType = SOFA_SEPSIS"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
{
|
||||
"scenario": {
|
||||
"id": "sofa-partial-spo2-fallback-01",
|
||||
"name": "Ward Patient — Partial SOFA with SpO₂/FiO₂ Proxy",
|
||||
"description": "General medicine patient with worsening pneumonia. No ABG — SpO₂/FiO₂ used for respiratory SOFA. Partial scoring when labs missing; carry-forward and staleness flags when data ages.",
|
||||
"durationMinutes": 360,
|
||||
"tags": ["sofa", "partial-scoring", "spo2-fallback", "carry-forward", "ward"]
|
||||
},
|
||||
"patient": {
|
||||
"firstName": "Priya",
|
||||
"lastName": "Sharma",
|
||||
"dateOfBirth": "1970-01-14",
|
||||
"gender": "Female"
|
||||
},
|
||||
"encounter": {
|
||||
"department": "GeneralMedicine",
|
||||
"encounterType": "Inpatient",
|
||||
"attendingPhysician": "Dr. Noah Chen",
|
||||
"roomBed": "GM-8B-2",
|
||||
"admissionReason": "Worsening pneumonia, transferred from ED"
|
||||
},
|
||||
"events": [
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "HEART_RATE", "value": 92, "unit": "bpm", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "RESP_RATE", "value": 20, "unit": "/min", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "SYSTOLIC_BP", "value": 118, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "DIASTOLIC_BP", "value": 72, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "SPO2", "value": 93, "unit": "%", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "FIO2_PCT", "value": 28, "unit": "%", "source": "Manual" },
|
||||
"note": "Nasal cannula 2L — S/F ~332, SOFA Resp 0"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "SUPPLEMENTAL_O2", "value": 1, "unit": "flag", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "TEMP_C", "value": 38.5, "unit": "°C", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_EYE", "value": 4, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_VERBAL", "value": 5, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": { "code": "GCS_MOTOR", "value": 6, "unit": "score", "source": "Manual" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 30,
|
||||
"type": "observation",
|
||||
"data": { "code": "CREATININE_MG_DL", "value": 1.1, "unit": "mg/dL", "source": "Lab" },
|
||||
"note": "Partial SOFA — no platelets/bilirubin yet"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "PLATELET_K_UL", "value": 165, "unit": "k/µL", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
"type": "observation",
|
||||
"data": { "code": "BILIRUBIN_MG_DL", "value": 0.8, "unit": "mg/dL", "source": "Lab" },
|
||||
"note": "Baseline SOFA now more complete"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 180,
|
||||
"type": "observation",
|
||||
"data": { "code": "SPO2", "value": 88, "unit": "%", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 180,
|
||||
"type": "observation",
|
||||
"data": { "code": "FIO2_PCT", "value": 40, "unit": "%", "source": "Manual" },
|
||||
"note": "S/F 220 → SOFA Resp ~1; usedSpO2Fallback true"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 180,
|
||||
"type": "observation",
|
||||
"data": { "code": "RESP_RATE", "value": 26, "unit": "/min", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 240,
|
||||
"type": "observation",
|
||||
"data": { "code": "SPO2", "value": 84, "unit": "%", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 240,
|
||||
"type": "observation",
|
||||
"data": { "code": "FIO2_PCT", "value": 60, "unit": "%", "source": "Manual" },
|
||||
"note": "S/F 140 → SOFA Resp 2"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 240,
|
||||
"type": "observation",
|
||||
"data": { "code": "CREATININE_MG_DL", "value": 1.9, "unit": "mg/dL", "source": "Lab" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 240,
|
||||
"type": "observation",
|
||||
"data": { "code": "PLATELET_K_UL", "value": 110, "unit": "k/µL", "source": "Lab" },
|
||||
"note": "SOFA Coag 1"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 300,
|
||||
"type": "observation",
|
||||
"data": { "code": "SYSTOLIC_BP", "value": 88, "unit": "mmHg", "source": "Device" }
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 300,
|
||||
"type": "observation",
|
||||
"data": { "code": "DIASTOLIC_BP", "value": 52, "unit": "mmHg", "source": "Device" },
|
||||
"note": "MAP 64 → SOFA CV 1"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 300,
|
||||
"type": "observation",
|
||||
"data": { "code": "CREATININE_MG_DL", "value": 2.5, "unit": "mg/dL", "source": "Lab" },
|
||||
"note": "SOFA Renal 2; delta may reach ≥ 2"
|
||||
}
|
||||
],
|
||||
"expectedOutcomes": [
|
||||
{
|
||||
"afterOffsetMinutes": 180,
|
||||
"type": "score",
|
||||
"scoreType": "SOFA",
|
||||
"description": "SOFA computed with usedSpO2Fallback in staleness flags"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 300,
|
||||
"type": "alert",
|
||||
"alertType": "SOFA_SEPSIS",
|
||||
"description": "Multi-organ decline — delta ≥ 2 from baseline"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -99,6 +99,36 @@
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_EYE",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_VERBAL",
|
||||
"value": 5,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_MOTOR",
|
||||
"value": 6,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 30,
|
||||
"type": "observation",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"scenario": {
|
||||
"id": "uti-sepsis-elderly-01",
|
||||
"name": "UTI Progressing to Sepsis in Elderly Patient",
|
||||
"description": "72-year-old female presenting with UTI symptoms who deteriorates into sepsis over 4 hours, triggering SIRS, qSOFA, and NEWS2 alerts with sepsis bundle compliance.",
|
||||
"description": "72-year-old female with UTI progressing to sepsis over 4 hours. qSOFA screen fires first; SOFA delta \u2265 2 triggers sepsis bundle. NEWS2 and bundle compliance still exercised.",
|
||||
"durationMinutes": 240,
|
||||
"tags": [
|
||||
"sepsis",
|
||||
@@ -98,6 +98,36 @@
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_EYE",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_VERBAL",
|
||||
"value": 4,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 0,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "GCS_MOTOR",
|
||||
"value": 6,
|
||||
"unit": "score",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 20,
|
||||
"type": "observation",
|
||||
@@ -281,6 +311,56 @@
|
||||
"source": "Lab"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 45,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "PAO2_MMHG",
|
||||
"value": 92,
|
||||
"unit": "mmHg",
|
||||
"source": "Lab"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 45,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "FIO2_PCT",
|
||||
"value": 28,
|
||||
"unit": "%",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 45,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "PLATELET_K_UL",
|
||||
"value": 210,
|
||||
"unit": "k/\u00b5L",
|
||||
"source": "Lab"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 45,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "BILIRUBIN_MG_DL",
|
||||
"value": 0.7,
|
||||
"unit": "mg/dL",
|
||||
"source": "Lab"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 45,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "CREATININE_MG_DL",
|
||||
"value": 1.0,
|
||||
"unit": "mg/dL",
|
||||
"source": "Lab"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 40,
|
||||
"type": "order",
|
||||
@@ -450,7 +530,7 @@
|
||||
"unit": "bpm",
|
||||
"source": "Device"
|
||||
},
|
||||
"note": "SIRS criteria met: Temp >38.3 + HR >90 \u2192 SEPSIS_WARNING"
|
||||
"note": "Temp >38.3 + HR >90 \u2014 early sepsis physiology"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 90,
|
||||
@@ -627,7 +707,7 @@
|
||||
"unit": "bpm",
|
||||
"source": "Device"
|
||||
},
|
||||
"note": "NEWS2 = 6, SIRS 3 of 4 criteria met (Temp, HR, RR)"
|
||||
"note": "NEWS2 = 6, continued deterioration"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
@@ -698,7 +778,7 @@
|
||||
"unit": "\u00d710\u00b3/\u00b5L",
|
||||
"source": "Lab"
|
||||
},
|
||||
"note": "Repeat labs \u2014 WBC elevated, lactate rising, SIRS 4/4"
|
||||
"note": "Repeat labs \u2014 WBC elevated, lactate rising"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 120,
|
||||
@@ -730,6 +810,48 @@
|
||||
"source": "Lab"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "PAO2_MMHG",
|
||||
"value": 68,
|
||||
"unit": "mmHg",
|
||||
"source": "Lab"
|
||||
},
|
||||
"note": "Worsening gas exchange \u2014 SOFA Resp \u2191"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "FIO2_PCT",
|
||||
"value": 40,
|
||||
"unit": "%",
|
||||
"source": "Manual"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "PLATELET_K_UL",
|
||||
"value": 95,
|
||||
"unit": "k/\u00b5L",
|
||||
"source": "Lab"
|
||||
}
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "observation",
|
||||
"data": {
|
||||
"code": "CREATININE_MG_DL",
|
||||
"value": 2.1,
|
||||
"unit": "mg/dL",
|
||||
"source": "Lab"
|
||||
},
|
||||
"note": "AKI \u2014 SOFA Renal \u2191; delta \u2265 2 \u2192 SOFA_SEPSIS"
|
||||
},
|
||||
{
|
||||
"offsetMinutes": 125,
|
||||
"type": "medication",
|
||||
@@ -1308,46 +1430,34 @@
|
||||
"description": "HR enters warning range (91 bpm)"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 90,
|
||||
"afterOffsetMinutes": 105,
|
||||
"type": "alert",
|
||||
"alertType": "SEPSIS_WARNING",
|
||||
"description": "SIRS criteria met: Temp 38.4\u00b0C (>38.3) + HR 96 (>90) = 2 of 4"
|
||||
"alertType": "QSOFA_SCREEN",
|
||||
"description": "qSOFA \u2265 2 \u2014 screen positive, recommend SOFA labs"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 90,
|
||||
"afterOffsetMinutes": 125,
|
||||
"type": "alert",
|
||||
"alertType": "SOFA_SEPSIS",
|
||||
"description": "SOFA delta \u2265 2 from baseline after repeat labs"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 125,
|
||||
"type": "bundle",
|
||||
"description": "Sepsis bundle auto-created with 4 orders: blood cultures, serum lactate, broad-spectrum antibiotics, IV fluid resuscitation"
|
||||
"description": "Sepsis bundle auto-created; triggeringAlertType = SOFA_SEPSIS"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 105,
|
||||
"type": "score",
|
||||
"scoreType": "NEWS2",
|
||||
"expectedMinimum": 5,
|
||||
"description": "NEWS2 reaches 5 (HR=1, RR=2, Temp=1, SpO2=1) \u2192 WARNING threshold"
|
||||
"description": "NEWS2 reaches medium risk"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 135,
|
||||
"type": "alert",
|
||||
"alertType": "NEWS2_EMERGENCY",
|
||||
"description": "NEWS2 reaches 8 (HR=2, RR=2, SBP=1, Temp=2, SpO2=1) \u22657 \u2192 EMERGENCY"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 135,
|
||||
"type": "score",
|
||||
"scoreType": "NEWS2",
|
||||
"expectedMinimum": 7,
|
||||
"description": "NEWS2 \u22657 sustained through peak deterioration"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 150,
|
||||
"type": "alert",
|
||||
"alertType": "QSOFA_WARNING",
|
||||
"description": "qSOFA 3/3: RR 24 (\u226522) + SBP 98 (\u2264100) + AVPU 1 (\u22651)"
|
||||
},
|
||||
{
|
||||
"afterOffsetMinutes": 130,
|
||||
"type": "bundle",
|
||||
"description": "Sepsis bundle COMPLIANT \u2014 all 4 orders completed within 40 minutes (blood cultures T+92, lactate T+95, ceftriaxone T+125, IV fluids T+130)"
|
||||
"description": "NEWS2 \u2265 7 at peak deterioration"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,7 +4,12 @@ public static class ScenarioValidator
|
||||
{
|
||||
"HEART_RATE", "RESP_RATE", "SYSTOLIC_BP", "DIASTOLIC_BP",
|
||||
"TEMP_C", "SPO2", "AVPU", "SUPPLEMENTAL_O2",
|
||||
"WBC_K_UL", "POTASSIUM_MEQ_L", "LACTATE_MMOL_L", "GLUCOSE_MG_DL"
|
||||
"WBC_K_UL", "POTASSIUM_MEQ_L", "LACTATE_MMOL_L", "GLUCOSE_MG_DL",
|
||||
// Phase 25 — GCS components
|
||||
"GCS_EYE", "GCS_VERBAL", "GCS_MOTOR",
|
||||
// Phase 26 — SOFA lab / respiratory inputs
|
||||
"PAO2_MMHG", "FIO2_PCT", "PLATELET_K_UL",
|
||||
"BILIRUBIN_MG_DL", "CREATININE_MG_DL", "URINE_OUTPUT_ML_H",
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> ValidSources = new()
|
||||
@@ -67,15 +72,15 @@ public static class ScenarioValidator
|
||||
}
|
||||
|
||||
var placedOrders = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
double lastOffset = -1;
|
||||
for (int i = 0; i < scenario.Events.Count; i++)
|
||||
var indexedEvents = scenario.Events
|
||||
.Select((evt, i) => (evt, i))
|
||||
.OrderBy(x => x.evt.OffsetMinutes)
|
||||
.ThenBy(x => x.i);
|
||||
|
||||
foreach (var (evt, i) in indexedEvents)
|
||||
{
|
||||
var evt = scenario.Events[i];
|
||||
if (evt.OffsetMinutes < 0)
|
||||
errors.Add($"events[{i}]: offsetMinutes cannot be negative");
|
||||
if (evt.OffsetMinutes < lastOffset)
|
||||
errors.Add($"events[{i}]: offsetMinutes goes backwards ({evt.OffsetMinutes} < {lastOffset})");
|
||||
lastOffset = evt.OffsetMinutes;
|
||||
|
||||
if (!ValidEventTypes.Contains(evt.Type))
|
||||
errors.Add($"events[{i}]: unknown type '{evt.Type}'");
|
||||
@@ -123,7 +128,7 @@ public static class ScenarioValidator
|
||||
{
|
||||
errors.Add(
|
||||
$"events[{i}]: order_result '{orderDescription}' has no matching prior 'order' event " +
|
||||
"(sepsis bundle orders are auto-created when SEPSIS_WARNING or QSOFA_WARNING fires)");
|
||||
"(sepsis bundle orders are auto-created when SOFA_SEPSIS or QSOFA_SCREEN fires)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,20 @@
|
||||
"description": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"observationCodes": {
|
||||
"type": "array",
|
||||
"description": "Valid observation codes",
|
||||
"items": {
|
||||
"enum": [
|
||||
"HEART_RATE", "RESP_RATE", "SYSTOLIC_BP", "DIASTOLIC_BP",
|
||||
"TEMP_C", "SPO2", "AVPU", "SUPPLEMENTAL_O2",
|
||||
"WBC_K_UL", "POTASSIUM_MEQ_L", "LACTATE_MMOL_L", "GLUCOSE_MG_DL",
|
||||
"GCS_EYE", "GCS_VERBAL", "GCS_MOTOR",
|
||||
"PAO2_MMHG", "FIO2_PCT", "PLATELET_K_UL",
|
||||
"BILIRUBIN_MG_DL", "CREATININE_MG_DL", "URINE_OUTPUT_ML_H"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user