using Spectre.Console; public static class SimulatorConsole { public static void Header(string title, string? description = null) { AnsiConsole.Write(new Rule($"[bold]{title}[/]").LeftJustified()); if (description is not null) AnsiConsole.MarkupLine($"[dim]{description}[/]"); AnsiConsole.WriteLine(); } public static void Event(string simTime, string message) => AnsiConsole.MarkupLine($"[green][[{simTime}]][/] {Markup.Escape(message)}"); public static void Warn(string message) => AnsiConsole.MarkupLine($"[yellow]{Markup.Escape(message)}[/]"); public static void Error(string message) => AnsiConsole.MarkupLine($"[red]{Markup.Escape(message)}[/]"); public static void Info(string message) => AnsiConsole.MarkupLine($"[blue]{Markup.Escape(message)}[/]"); public static void DryRun(string message) => AnsiConsole.MarkupLine($"[dim]DRY-RUN:[/] {Markup.Escape(message)}"); public static void Success(string message) => AnsiConsole.MarkupLine($"[bold green]{Markup.Escape(message)}[/]"); public static void Wait(double deltaMinutes, int delayMs) => AnsiConsole.MarkupLine( $"[dim] ⏳ waiting {deltaMinutes:F0}m simulated ({delayMs / 1000.0:F1}s real)...[/]"); public static void Divider() => AnsiConsole.Write(new Rule().RuleStyle(Style.Parse("dim"))); public static void Summary(ReplayResult r) { AnsiConsole.WriteLine(); var table = new Table().AddColumn("Metric").AddColumn("Value"); table.AddRow("Scenario", r.ScenarioId); table.AddRow("Observations sent", r.ObservationsSent.ToString()); table.AddRow("Medications sent", r.MedicationsSent.ToString()); if (r.MedicationsSkipped > 0) table.AddRow("Medications skipped", r.MedicationsSkipped.ToString()); table.AddRow("Orders placed", r.OrdersPlaced.ToString()); table.AddRow("Orders resulted", r.OrdersResulted.ToString()); table.AddRow("Wall-clock time", $"{r.Duration.TotalSeconds:F1}s"); AnsiConsole.Write(table); } public static void BatchSummary(List results) { AnsiConsole.WriteLine(); AnsiConsole.Write(new Rule("[bold]Batch Summary[/]").LeftJustified()); var table = new Table() .AddColumn("Scenario") .AddColumn("Observations") .AddColumn("Medications") .AddColumn("Time"); foreach (var r in results) table.AddRow(r.ScenarioId, r.ObservationsSent.ToString(), r.MedicationsSent.ToString(), $"{r.Duration.TotalSeconds:F1}s"); AnsiConsole.Write(table); } public static void PollResults(string simTime, PollResult poll) { if (poll.News2 is not null) AnsiConsole.MarkupLine( $"[cyan][[{simTime}]][/] NEWS2 = {poll.News2.TotalScore} ({poll.News2.RiskLevel})"); foreach (var alert in poll.NewAlerts) AnsiConsole.MarkupLine( $"[red][[{simTime}]][/] ALERT {alert.AlertType} ({alert.Severity})"); if (poll.SepsisBundle is not null) AnsiConsole.MarkupLine( $"[cyan][[{simTime}]][/] SEPSIS BUNDLE {poll.SepsisBundle.ComplianceStatus} " + $"({poll.SepsisBundle.ElementsCompleted}/4)"); } }