feature: In-App Simulation Runner (Backend)
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
public sealed class SimulationRunState
|
||||
{
|
||||
private readonly object _gate = new();
|
||||
private DateTimeOffset? _completedAt;
|
||||
|
||||
public Guid RunId { get; init; }
|
||||
public string ScenarioId { get; init; } = null!;
|
||||
public string ScenarioName { get; init; } = null!;
|
||||
public double Speed { get; init; }
|
||||
public string StartedByUserId { get; init; } = null!;
|
||||
public DateTimeOffset StartedAt { get; init; }
|
||||
public double TotalOffsetMinutes { get; init; }
|
||||
public string PatientDisplayName { get; init; } = null!;
|
||||
|
||||
public SimulationRunStatus Status { get; private set; } = SimulationRunStatus.Pending;
|
||||
public Guid? PatientId { get; private set; }
|
||||
public Guid? EncounterId { get; private set; }
|
||||
public int ObservationsSent { get; private set; }
|
||||
public int MedicationsSent { get; private set; }
|
||||
public int OrdersPlaced { get; private set; }
|
||||
public double LastOffsetMinutes { get; private set; }
|
||||
public double ProgressPercent { get; private set; }
|
||||
public string? FailureReason { get; private set; }
|
||||
|
||||
public double ElapsedRealSeconds
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
var end = _completedAt ?? DateTimeOffset.UtcNow;
|
||||
return (end - StartedAt).TotalSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void MarkRunning()
|
||||
{
|
||||
lock (_gate) Status = SimulationRunStatus.Running;
|
||||
}
|
||||
|
||||
public void SetIds(Guid? patientId, Guid? encounterId)
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
if (patientId.HasValue) PatientId = patientId;
|
||||
if (encounterId.HasValue) EncounterId = encounterId;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateOffset(double offsetMinutes)
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
LastOffsetMinutes = offsetMinutes;
|
||||
ProgressPercent = TotalOffsetMinutes <= 0
|
||||
? 100
|
||||
: Math.Clamp(offsetMinutes / TotalOffsetMinutes * 100.0, 0, 100);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyResultCounters(int observationsSent, int medicationsSent, int ordersPlaced)
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
ObservationsSent = observationsSent;
|
||||
MedicationsSent = medicationsSent;
|
||||
OrdersPlaced = ordersPlaced;
|
||||
}
|
||||
}
|
||||
|
||||
public void NoteEvent(string description)
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
if (description.StartsWith("MEDICATION", StringComparison.Ordinal))
|
||||
MedicationsSent++;
|
||||
else if (description.StartsWith("ORDER ", StringComparison.Ordinal))
|
||||
OrdersPlaced++;
|
||||
else if (!description.StartsWith("ORDER_RESULT", StringComparison.Ordinal)
|
||||
&& !description.StartsWith("ACK ", StringComparison.Ordinal))
|
||||
ObservationsSent++;
|
||||
}
|
||||
}
|
||||
|
||||
public void MarkTerminal(SimulationRunStatus status, string? failureReason = null)
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
Status = status;
|
||||
FailureReason = failureReason;
|
||||
_completedAt = DateTimeOffset.UtcNow;
|
||||
if (status == SimulationRunStatus.Completed)
|
||||
ProgressPercent = 100;
|
||||
}
|
||||
}
|
||||
|
||||
public SimulationRunState Snapshot()
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
var copy = new SimulationRunState
|
||||
{
|
||||
RunId = RunId,
|
||||
ScenarioId = ScenarioId,
|
||||
ScenarioName = ScenarioName,
|
||||
Speed = Speed,
|
||||
StartedByUserId = StartedByUserId,
|
||||
StartedAt = StartedAt,
|
||||
TotalOffsetMinutes = TotalOffsetMinutes,
|
||||
PatientDisplayName = PatientDisplayName,
|
||||
};
|
||||
copy.Status = Status;
|
||||
copy.PatientId = PatientId;
|
||||
copy.EncounterId = EncounterId;
|
||||
copy.ObservationsSent = ObservationsSent;
|
||||
copy.MedicationsSent = MedicationsSent;
|
||||
copy.OrdersPlaced = OrdersPlaced;
|
||||
copy.LastOffsetMinutes = LastOffsetMinutes;
|
||||
copy.ProgressPercent = ProgressPercent;
|
||||
copy.FailureReason = FailureReason;
|
||||
copy._completedAt = _completedAt;
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user