2025-04-14 12:55:28 -07:00

222 lines
9.6 KiB
C#

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<int, Aggregation> GetKeyValuePairs(Settings settings, Dictionary<int, List<Notification>> keyValuePairs)
{
Dictionary<int, Aggregation> results = new();
int value;
int? inverseValue;
double inverseAverage;
Aggregation aggregation;
double fibonacciAverage;
List<int> collection = new();
int averageFromInverseCeiling;
List<int> inverseCollection = new();
List<int> fibonacciCollection = new();
foreach (KeyValuePair<int, List<Notification>> 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<Notification> GetNotifications(Settings settings, string directory)
{
List<Notification> results = new();
string? key;
string text;
string[] files;
Notification? notification;
List<Notification>? collection;
Dictionary<string, List<Notification>> 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<string, List<Notification>> keyValuePair in keyValuePairs)
{
if (keyValuePair.Value.Count == 1)
results.Add(keyValuePair.Value[0]);
else
{
notification = keyValuePair.Value.Select(record => new KeyValuePair<string, Notification>(record.Time, record)).OrderBy(pair => pair.Key).Last().Value;
results.Add(notification);
}
}
}
return new(results);
}
private static ReadOnlyDictionary<int, Aggregation> GetKeyValuePairs(Settings settings, string directory)
{
ReadOnlyDictionary<int, Aggregation> results;
int id;
List<Notification>? collection;
Dictionary<int, List<Notification>> keyValuePairs = new();
ReadOnlyCollection<Notification> 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<string, ReadOnlyDictionary<int, Aggregation>> GetKeyValuePairsAndWriteFiles(Settings settings)
{
Dictionary<string, ReadOnlyDictionary<int, Aggregation>> results = new();
string json;
string jsonOld;
string jsonFile;
string directoryName;
ReadOnlyDictionary<int, Aggregation> 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<int, Aggregation> GetKeyValuePairs(Settings settings, Notification notification)
{
ReadOnlyDictionary<int, Aggregation> results;
if (string.IsNullOrEmpty(notification.Id) || !int.TryParse(notification.Id, out int id))
results = new(new Dictionary<int, Aggregation>());
else
{
Dictionary<int, List<Notification>> 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<int, Aggregation>))]
internal partial class AggregationReadOnlyDictionarySourceGenerationContext : JsonSerializerContext
{
}