/// <summary> /// Summarizes an enumerable of double messages into summarized doubles. /// </summary> /// <typeparam name="T">The type of messages to summarize.</typeparam> /// <param name="messages">Enumerable of double messages.</param> /// <param name="interval">The time interval each summary value should cover.</param> /// <returns>List of summarized doubles.</returns> internal static List <IntervalData <T> > Summarizer <T>(IEnumerable <Message <T> > messages, TimeSpan interval) { return(messages .OrderBy(msg => msg.OriginatingTime) .GroupBy(msg => Summarizer <T, T> .GetIntervalStartTime(msg.OriginatingTime, interval)) .Select( group => { var firstMessage = group.First(); var lastMessage = group.Last(); return IntervalData.Create( lastMessage.Data, // Take last value as representative value for plotting group.Min(m => m.Data), // Minimum value group.Max(m => m.Data), // Maximum value firstMessage.OriginatingTime, // First message's OT lastMessage.OriginatingTime - firstMessage.OriginatingTime); // Interval between first and last messages }).ToList()); }
/// <summary> /// Summarizes an enumerable of double messages into summarized doubles. /// </summary> /// <typeparam name="T">The type of messages to summarize.</typeparam> /// <param name="messages">Enumerable of double messages.</param> /// <param name="interval">The time interval each summary value should cover.</param> /// <returns>List of summarized doubles.</returns> internal static List <IntervalData <T> > Summarizer <T>(IEnumerable <Message <T> > messages, TimeSpan interval) { return(messages .OrderBy(msg => msg.OriginatingTime) .GroupBy(msg => Summarizer <T, T> .GetIntervalStartTime(msg.OriginatingTime, interval)) .Select( group => { var firstMessage = group.First(); var lastMessage = group.Last(); // Use the last value as representative for summarization, with the first message // originating time. return IntervalData.Create( value: lastMessage.Data, minimum: group.Min(m => m.Data), maximum: group.Max(m => m.Data), originatingTime: firstMessage.OriginatingTime, interval: lastMessage.OriginatingTime - firstMessage.OriginatingTime); }).ToList()); }
/// <summary> /// Summarizes an enumerable of double messages into summarized doubles. /// </summary> /// <typeparam name="TKey">The type of the series key.</typeparam> /// <typeparam name="T">The type of messages to summarize.</typeparam> /// <param name="messages">Enumerable of double messages.</param> /// <param name="interval">The time interval each summary value should cover.</param> /// <returns>List of summarized doubles.</returns> internal static List <IntervalData <Dictionary <TKey, T> > > SeriesSummarizer <TKey, T>(IEnumerable <Message <Dictionary <TKey, T> > > messages, TimeSpan interval) { return(messages .OrderBy(msg => msg.OriginatingTime) .GroupBy(msg => Summarizer <T, T> .GetIntervalStartTime(msg.OriginatingTime, interval)) .Select( group => { var firstMessage = group.First(); var lastMessage = group.Last(); var min = new Dictionary <TKey, T>(); var max = new Dictionary <TKey, T>(); foreach (var message in group) { foreach (var kvp in message.Data) { // Update min if (!min.ContainsKey(kvp.Key)) { min.Add(kvp.Key, kvp.Value); } else if (kvp.Value is IComparable <T> comparable) { if (comparable.CompareTo(min[kvp.Key]) == -1) { min[kvp.Key] = kvp.Value; } } else if (kvp.Value is IComparable untypedComparable) { if (untypedComparable.CompareTo(min[kvp.Key]) == -1) { min[kvp.Key] = kvp.Value; } } else { throw new InvalidOperationException("Cannot summarize over values that are not comparable."); } // Update max if (!max.ContainsKey(kvp.Key)) { max.Add(kvp.Key, kvp.Value); } else if (kvp.Value is IComparable <T> comparable) { if (comparable.CompareTo(max[kvp.Key]) == 1) { max[kvp.Key] = kvp.Value; } } else if (kvp.Value is IComparable untypedComparable) { if (untypedComparable.CompareTo(max[kvp.Key]) == 1) { max[kvp.Key] = kvp.Value; } } else { throw new InvalidOperationException("Cannot summarize over values that are not comparable."); } } } // Use the last value as representative for summarization, with the first message // originating time. return IntervalData.Create( value: lastMessage.Data, minimum: min, maximum: max, originatingTime: firstMessage.OriginatingTime, interval: lastMessage.OriginatingTime - firstMessage.OriginatingTime); }).ToList()); }