Run initial test for Climate Resilience Verification Suite
Add first part of Alert Quality Analytics
This commit is contained in:
@@ -20,25 +20,43 @@ public class ReplayEngine
|
||||
// --- Phase 1: Setup ---
|
||||
SimulatorConsole.Header(scenario.Scenario.Name, scenario.Scenario.Description);
|
||||
|
||||
PatientResponse patient;
|
||||
EncounterResponse encounter;
|
||||
|
||||
if (options.DryRun)
|
||||
{
|
||||
SimulatorConsole.DryRun("Would register patient: " +
|
||||
$"{scenario.Patient.FirstName} {scenario.Patient.LastName}");
|
||||
SimulatorConsole.DryRun("Would open encounter: " +
|
||||
$"{scenario.Encounter.Department} / {scenario.Encounter.EncounterType}");
|
||||
if (options.ExistingEncounterId.HasValue)
|
||||
{
|
||||
result.EncounterId = options.ExistingEncounterId.Value;
|
||||
if (options.Target == ReplayTarget.Gateway)
|
||||
SimulatorConsole.DryRun($"Gateway mode — would use existing encounter {result.EncounterId}");
|
||||
else
|
||||
SimulatorConsole.DryRun($"Would use existing encounter {result.EncounterId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
SimulatorConsole.DryRun("Would register patient: " +
|
||||
$"{scenario.Patient.FirstName} {scenario.Patient.LastName}");
|
||||
SimulatorConsole.DryRun("Would open encounter: " +
|
||||
$"{scenario.Encounter.Department} / {scenario.Encounter.EncounterType}");
|
||||
}
|
||||
}
|
||||
else if (options.Target == ReplayTarget.Gateway && options.ExistingEncounterId.HasValue)
|
||||
{
|
||||
result.EncounterId = options.ExistingEncounterId.Value;
|
||||
SimulatorConsole.Info($"Gateway mode — using existing encounter {result.EncounterId}");
|
||||
}
|
||||
else if (options.ExistingEncounterId.HasValue)
|
||||
{
|
||||
result.EncounterId = options.ExistingEncounterId.Value;
|
||||
SimulatorConsole.Info($"Using existing encounter {result.EncounterId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
patient = await _client.RegisterPatientAsync(new RegisterPatientRequest(
|
||||
var patient = await _client.RegisterPatientAsync(new RegisterPatientRequest(
|
||||
scenario.Patient.FirstName,
|
||||
scenario.Patient.LastName,
|
||||
DateOnly.Parse(scenario.Patient.DateOfBirth),
|
||||
scenario.Patient.Gender));
|
||||
|
||||
encounter = await _client.OpenEncounterAsync(patient.Id, new OpenEncounterRequest(
|
||||
var encounter = await _client.OpenEncounterAsync(patient.Id, new OpenEncounterRequest(
|
||||
scenario.Encounter.EncounterType,
|
||||
DepartmentMapper.ToApiDepartment(scenario.Encounter.Department),
|
||||
scenario.Encounter.AttendingPhysician,
|
||||
@@ -91,6 +109,9 @@ public class ReplayEngine
|
||||
case "order_result":
|
||||
await ReplayOrderResult(evt, simTimestamp, options, result);
|
||||
break;
|
||||
case "alert_ack":
|
||||
await ReplayAlertAck(evt, simTimestamp, options, result, ct);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +136,9 @@ public class ReplayEngine
|
||||
{
|
||||
var observations = new List<IngestObservationRequest>();
|
||||
var offsetMinutes = cluster[0].OffsetMinutes;
|
||||
var recordedAt = _scenarioStartTime.AddMinutes(offsetMinutes);
|
||||
var recordedAt = options.Target == ReplayTarget.Gateway
|
||||
? DateTimeOffset.UtcNow
|
||||
: _scenarioStartTime.AddMinutes(offsetMinutes);
|
||||
|
||||
foreach (var evt in cluster)
|
||||
{
|
||||
@@ -135,7 +158,7 @@ public class ReplayEngine
|
||||
}
|
||||
|
||||
if (!options.DryRun && observations.Count > 0)
|
||||
await _client.SendObservationBatchAsync(result.EncounterId, observations);
|
||||
await _client.SendObservationBatchAsync(result.EncounterId, observations, options.Target);
|
||||
}
|
||||
|
||||
private async Task ReplayMedication(
|
||||
@@ -238,4 +261,30 @@ public class ReplayEngine
|
||||
"Lab" or "LAB" or "lab" => "LAB",
|
||||
_ => throw new InvalidOperationException($"Unknown observation source: '{source}'")
|
||||
};
|
||||
|
||||
private async Task ReplayAlertAck(
|
||||
ScenarioEvent evt, string simTime, ReplayOptions options, ReplayResult result,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var alertType = evt.Data.GetProperty("alertType").GetString()!;
|
||||
var clinicianId = evt.Data.GetProperty("clinicianId").GetString()!;
|
||||
var note = evt.Data.TryGetProperty("note", out var n) ? n.GetString() : null;
|
||||
|
||||
if (options.DryRun)
|
||||
{
|
||||
SimulatorConsole.DryRun($"[{simTime}] ACK {alertType} by {clinicianId}");
|
||||
return;
|
||||
}
|
||||
|
||||
var waitForAlert = options.Target == ReplayTarget.Central
|
||||
? TimeSpan.FromSeconds(30)
|
||||
: (TimeSpan?)null;
|
||||
|
||||
var ok = await _client.TryAcknowledgeAlertAsync(
|
||||
result.EncounterId, alertType, clinicianId, note, waitForAlert, ct);
|
||||
if (ok)
|
||||
SimulatorConsole.Event(simTime, $"ACK {alertType} by {clinicianId}");
|
||||
else
|
||||
SimulatorConsole.Warn($"[{simTime}] ACK failed — no open {alertType} alert found");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user