feature: Explainable Alerts
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
public static class AlertExplanationBuilder
|
||||
{
|
||||
public static AlertExplanation Build(
|
||||
string scoringLabel,
|
||||
int? totalScore,
|
||||
List<ScoreContributor> contributors,
|
||||
TrendContext? trend = null,
|
||||
MedicationContext? medication = null)
|
||||
{
|
||||
return new AlertExplanation
|
||||
{
|
||||
ScoreContributors = contributors,
|
||||
Trend = trend,
|
||||
MedicationContext = medication,
|
||||
NarrativeSummary = BuildNarrative(scoringLabel, totalScore, contributors, trend, medication)
|
||||
};
|
||||
}
|
||||
|
||||
private static string BuildNarrative(
|
||||
string scoringLabel,
|
||||
int? totalScore,
|
||||
List<ScoreContributor> contributors,
|
||||
TrendContext? trend,
|
||||
MedicationContext? medication)
|
||||
{
|
||||
var elevated = contributors.Where(c => c.Points > 0).ToList();
|
||||
if (elevated.Count == 0)
|
||||
elevated = contributors;
|
||||
|
||||
var headline = totalScore.HasValue
|
||||
? $"{scoringLabel} {totalScore} — "
|
||||
: $"{scoringLabel} — ";
|
||||
|
||||
var contributorText = string.Join(", ",
|
||||
elevated.Select(c => $"{c.Parameter.ToLowerInvariant()} (+{c.Points})"));
|
||||
|
||||
var parts = new List<string> { headline + contributorText };
|
||||
|
||||
if (trend is not null)
|
||||
{
|
||||
parts.Add(
|
||||
$"{trend.Parameter} {trend.Direction.ToLowerInvariant()} " +
|
||||
$"{trend.PercentChange:F0}% over {FormatDuration(trend.Duration)}.");
|
||||
}
|
||||
|
||||
if (medication is not null)
|
||||
{
|
||||
var minutesAgo = (int)(DateTimeOffset.UtcNow - medication.AdministeredAt).TotalMinutes;
|
||||
var medLine =
|
||||
$"{medication.DrugName} {medication.Dose} {medication.Route} " +
|
||||
$"administered {minutesAgo} minutes ago";
|
||||
if (!string.IsNullOrEmpty(medication.RelevanceNote))
|
||||
medLine += $" ({medication.RelevanceNote})";
|
||||
parts.Add(medLine);
|
||||
}
|
||||
|
||||
return string.Join(" ", parts);
|
||||
}
|
||||
|
||||
private static string FormatDuration(TimeSpan duration)
|
||||
{
|
||||
if (duration.TotalHours >= 1)
|
||||
{
|
||||
var hours = (int)duration.TotalHours;
|
||||
return $"{hours} hour{(hours == 1 ? "" : "s")}";
|
||||
}
|
||||
|
||||
var minutes = (int)duration.TotalMinutes;
|
||||
return $"{minutes} minute{(minutes == 1 ? "" : "s")}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user