using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; namespace Adaptation.FileHandlers.Priority; #nullable enable public class Aggregation { [JsonConstructor] public Aggregation(double inverseAverage, int valueCount, double fibonacciAverage, int? inverseValue, int valueMaximum, int valueMinimum, Notification[] notifications, int valueSum) { InverseAverage = inverseAverage; ValueCount = valueCount; FibonacciAverage = fibonacciAverage; InverseValue = inverseValue; ValueMaximum = valueMaximum; ValueMinimum = valueMinimum; Notifications = notifications; ValueSum = valueSum; } public double InverseAverage { get; } // [JsonPropertyName("InverseAverage")] public int ValueCount { get; } // [JsonPropertyName("ValueCount")] public double FibonacciAverage { get; } // [JsonPropertyName("Fibonacci")] public int? InverseValue { get; } // [JsonPropertyName("InverseValue")] public int ValueMaximum { get; } // [JsonPropertyName("ValueMaximum")] public int ValueMinimum { get; } // [JsonPropertyName("ValueMinimum")] public Notification[] Notifications { get; } // [JsonPropertyName("Notifications")] public int ValueSum { get; } // [JsonPropertyName("ValueSum")] private static ReadOnlyDictionary GetKeyValuePairs(Settings settings, Dictionary> keyValuePairs) { Dictionary results = new(); int value; int? inverseValue; double inverseAverage; Aggregation aggregation; double fibonacciAverage; List collection = new(); int averageFromInverseCeiling; List inverseCollection = new(); List fibonacciCollection = new(); foreach (KeyValuePair> keyValuePair in keyValuePairs) { collection.Clear(); inverseCollection.Clear(); fibonacciCollection.Clear(); foreach (Notification notification in keyValuePair.Value) { if (!int.TryParse(notification.Value, out value)) continue; collection.Add(value); if (notification.Inverse is null) continue; inverseCollection.Add(notification.Inverse.Value); if (notification.Fibonacci is null) continue; fibonacciCollection.Add(notification.Fibonacci.Value); } if (inverseCollection.Count == 0 || fibonacciCollection.Count == 0) continue; inverseAverage = Math.Round(inverseCollection.Average(), settings.Digits); averageFromInverseCeiling = (int)Math.Ceiling(inverseAverage); inverseValue = Notification.GetInverse(averageFromInverseCeiling.ToString()); fibonacciAverage = Math.Round(fibonacciCollection.Average(), settings.Digits); aggregation = new(inverseAverage: inverseAverage, valueCount: collection.Count, fibonacciAverage: fibonacciAverage, inverseValue: inverseValue, valueMaximum: collection.Max(), valueMinimum: collection.Min(), notifications: keyValuePair.Value.ToArray(), valueSum: collection.Sum()); results.Add(keyValuePair.Key, aggregation); } return new(results); } private static ReadOnlyCollection GetNotifications(Settings settings, string directory) { List results = new(); string? key; string text; string[] files; Notification? notification; List? collection; Dictionary> keyValuePairs = new(); string[] directories = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly); foreach (string subDirectory in directories) { keyValuePairs.Clear(); files = Directory.GetFiles(subDirectory, settings.SourceFileFilter, SearchOption.TopDirectoryOnly); foreach (string file in files) { text = File.ReadAllText(file); if (string.IsNullOrEmpty(text) || text[0] == '[') continue; notification = JsonSerializer.Deserialize(text, NotificationSourceGenerationContext.Default.Notification); if (notification is null || string.IsNullOrEmpty(notification.Id)) continue; key = !string.IsNullOrEmpty(notification.Username) ? notification.Username : throw new Exception(); if (string.IsNullOrEmpty(key)) continue; if (!keyValuePairs.TryGetValue(key, out collection)) { keyValuePairs.Add(key, new()); if (!keyValuePairs.TryGetValue(key, out collection)) throw new Exception(); } collection.Add(notification); } foreach (KeyValuePair> keyValuePair in keyValuePairs) { if (keyValuePair.Value.Count == 1) results.Add(keyValuePair.Value[0]); else { notification = keyValuePair.Value.Select(record => new KeyValuePair(record.Time, record)).OrderBy(pair => pair.Key).Last().Value; results.Add(notification); } } } return new(results); } private static ReadOnlyDictionary GetKeyValuePairs(Settings settings, string directory) { ReadOnlyDictionary results; int id; List? collection; Dictionary> keyValuePairs = new(); ReadOnlyCollection notifications = GetNotifications(settings, directory); foreach (Notification notification in notifications) { if (!int.TryParse(notification.Id, out id)) continue; if (!keyValuePairs.TryGetValue(id, out collection)) { keyValuePairs.Add(id, new()); if (!keyValuePairs.TryGetValue(id, out collection)) throw new Exception(); } collection.Add(notification); } results = GetKeyValuePairs(settings, keyValuePairs); return results; } internal static ReadOnlyDictionary> GetKeyValuePairsAndWriteFiles(Settings settings) { Dictionary> results = new(); string json; string jsonOld; string jsonFile; string directoryName; ReadOnlyDictionary keyValuePairs; if (!Directory.Exists(settings.SourceFileLocation)) _ = Directory.CreateDirectory(settings.SourceFileLocation); if (!Directory.Exists(settings.TargetFileLocation)) _ = Directory.CreateDirectory(settings.TargetFileLocation); string[] directories = Directory.GetDirectories(settings.SourceFileLocation, "*", SearchOption.TopDirectoryOnly); foreach (string directory in directories) { directoryName = Path.GetFileName(directory); keyValuePairs = GetKeyValuePairs(settings, directory); jsonFile = Path.Combine(settings.TargetFileLocation, $"{directoryName}.json"); json = JsonSerializer.Serialize(keyValuePairs, AggregationReadOnlyDictionarySourceGenerationContext.Default.ReadOnlyDictionaryInt32Aggregation); // keyValuePairs = JsonSerializer.Deserialize(json, AggregationReadOnlyDictionarySourceGenerationContext.Default.ReadOnlyDictionaryInt32Aggregation); jsonOld = File.Exists(jsonFile) ? File.ReadAllText(jsonFile) : string.Empty; if (json != jsonOld) File.WriteAllText(jsonFile, json); results.Add(directoryName, keyValuePairs); } return new(results); } internal static ReadOnlyDictionary GetKeyValuePairs(Settings settings, Notification notification) { ReadOnlyDictionary results; if (string.IsNullOrEmpty(notification.Id) || !int.TryParse(notification.Id, out int id)) results = new(new Dictionary()); else { Dictionary> keyValuePairs = new() { { id, new Notification[] { notification }.ToList() } }; results = GetKeyValuePairs(settings, keyValuePairs); } return results; } } [JsonSourceGenerationOptions(WriteIndented = true)] [JsonSerializable(typeof(Aggregation))] internal partial class AggregationSourceGenerationContext : JsonSerializerContext { } [JsonSourceGenerationOptions(WriteIndented = true)] [JsonSerializable(typeof(Aggregation[]))] internal partial class AggregationCollectionSourceGenerationContext : JsonSerializerContext { } [JsonSourceGenerationOptions(WriteIndented = true)] [JsonSerializable(typeof(ReadOnlyDictionary))] internal partial class AggregationReadOnlyDictionarySourceGenerationContext : JsonSerializerContext { }