private void Aggregate(ref AggregatedAlert?aggregatedAlert, StatusNotificationWriter writer, DateTime start, StatusResultsOrganizer child, float ignoreRatingsBetterThan) { // does this child have children? if (child.ChildrenCount > 0) { System.Diagnostics.Debug.Assert(child.NatureOfSystem == StatusNatureOfSystem.ChildrenIrrelevant || child.ChildrenCount > 1); // recurse for this level too RenderTargetedResults(writer, start, child, ignoreRatingsBetterThan); } else { // can we aggregate this one? if (aggregatedAlert != null && aggregatedAlert.CanBeAggregated(child.Target, child.OverallReport)) { aggregatedAlert.Aggregate(child.Source, child.Target, child.MostRecentTime, child.OverallReport); } else // this one can't be aggregated with previous ones, so we need to flush the previously-aggregated alerts and start a new aggregation { if (aggregatedAlert != null) { writer.WriteAggregatedAlert(aggregatedAlert); } aggregatedAlert = new AggregatedAlert(child.Source, child.Target, child.MostRecentTime, child.OverallReport); } } }
/// <summary> /// Writes a notification for the specified <see cref="AggregatedAlert"/>. /// </summary> /// <param name="aggregatedAlert">An <see cref="AggregatedAlert"/> that should be written to the notification.</param> public void WriteAggregatedAlert(AggregatedAlert aggregatedAlert) { if (_tabLevel <= 1) { throw new InvalidOperationException("A status range must be entered before aggregated alerts can be written!"); } StatusAuditAlert auditAlert = aggregatedAlert.CommonAlert ?? StatusAuditAlert.None; StatusRatingRange range = StatusRating.FindRange(auditAlert.Rating); string rangeName = StatusRating.GetRangeName(range); string rangeColor = StatusRating.GetRangeForegroundColor(auditAlert.Rating); string rgbColor = StatusRating.GetRatingRgbForegroundColor(aggregatedAlert.RatingSum / aggregatedAlert.Sources.Count); List <StatusPropertyRange> propertyRanges = aggregatedAlert.PropertyRanges; OpenHeader(_details, _terse, _tabLevel, (StatusRatingRange)(-1), rgbColor); _terse.Append(aggregatedAlert.Target + ": " + aggregatedAlert.TerseSources + "->"); #if RAWRATINGS _details.Append("[RATING=" + auditAlert.Rating.ToString(DebugRatingFloatFormat) + "] "); #endif _details.Append(aggregatedAlert.Target + ": " + aggregatedAlert.DetailsSources + " reporting: "); // multi-line alert details or properties to list? if ((aggregatedAlert.CommonAlert?.Details != null && (aggregatedAlert.CommonAlert.Details.Contains("<br/>", StringComparison.Ordinal) || aggregatedAlert.CommonAlert.Details.Contains("</div>", StringComparison.Ordinal))) || (propertyRanges != null && propertyRanges.Count > 0)) { CloseHeader(_details, _terse, _tabLevel); EnterTabLevel(); OpenHeader(_details, _terse, _tabLevel, (StatusRatingRange)(-1), rgbColor); _terse.Append(RenderTerse(auditAlert.Terse).Replace("\n", "\n" + new string(' ', _tabLevel), StringComparison.Ordinal)); _details.AppendLine(RenderDetails(auditAlert.Details)); CloseHeader(_details, _terse, _tabLevel); // are there properties? if (propertyRanges != null && propertyRanges.Count > 0) { _details.Append(" because"); foreach (StatusPropertyRange propertyRange in aggregatedAlert.PropertyRanges) { OpenHeader(_details, _terse, _tabLevel, (StatusRatingRange)(-1), rgbColor); _terse.Append(propertyRange.ToString()); _details.AppendLine(propertyRange.ToString()); CloseHeader(_details, _terse, _tabLevel); } } LeaveTabLevel(); } else { _terse.Append(RenderTerse(auditAlert.Terse)); _details.Append(' '); _details.Append(RenderDetails(auditAlert.Details)); CloseHeader(_details, _terse, _tabLevel); } }