Files
ClubPenguinClient/MareSynchronos/Services/CharacterAnalyzer.cs
2023-07-10 13:23:44 +02:00

98 lines
4.1 KiB
C#

using MareSynchronos.API.Data;
using MareSynchronos.FileCache;
using MareSynchronos.Services.Mediator;
using MareSynchronos.UI;
using MareSynchronos.Utils;
using Microsoft.Extensions.Logging;
namespace MareSynchronos.Services;
public sealed class CharacterAnalyzer : MediatorSubscriberBase, IDisposable
{
private readonly FileCacheManager _fileCacheManager;
private CharacterData? _lastCreatedData;
private CancellationTokenSource? _analysisCts;
public CharacterAnalyzer(ILogger<CharacterAnalyzer> logger, MareMediator mediator, FileCacheManager fileCacheManager) : base(logger, mediator)
{
Mediator.Subscribe<CharacterDataCreatedMessage>(this, (msg) =>
{
_lastCreatedData = msg.CharacterData.DeepClone();
});
_fileCacheManager = fileCacheManager;
}
public bool IsAnalysisRunning => _analysisCts != null;
public void CancelAnalyze()
{
_analysisCts?.CancelDispose();
_analysisCts = null;
}
public async Task Analyze()
{
_analysisCts = _analysisCts?.CancelRecreate() ?? new();
var cancelToken = _analysisCts.Token;
if (_lastCreatedData == null) return;
Logger.LogInformation("=== Calculating Character Analysis, this may take a while ===");
foreach (var obj in _lastCreatedData.FileReplacements)
{
Logger.LogInformation("=== File Calculation for {obj} ===", obj.Key);
Dictionary<string, List<DataEntry>> data = new(StringComparer.OrdinalIgnoreCase);
var totalFiles = obj.Value.Count(c => !string.IsNullOrEmpty(c.Hash));
var currentFile = 1;
foreach (var hash in obj.Value.Select(c => c.Hash))
{
var fileCacheEntry = _fileCacheManager.GetFileCacheByHash(hash);
if (fileCacheEntry == null) continue;
Logger.LogInformation("Computing File {x}/{y}: {hash}", currentFile, totalFiles, hash);
Logger.LogInformation(" File Path: {path}", fileCacheEntry.ResolvedFilepath);
var filePath = fileCacheEntry.ResolvedFilepath;
FileInfo fi = new(filePath);
var ext = fi.Extension;
if (!data.ContainsKey(ext)) data[ext] = new List<DataEntry>();
(_, byte[] fileLength) = await _fileCacheManager.GetCompressedFileData(hash, cancelToken).ConfigureAwait(false);
Logger.LogInformation(" Original Size: {size}, Compressed Size: {compr}",
UiSharedService.ByteToString(fi.Length), UiSharedService.ByteToString(fileLength.LongLength));
data[ext].Add(new DataEntry(fi.FullName, fi.Length, fileLength.LongLength));
currentFile++;
cancelToken.ThrowIfCancellationRequested();
}
Logger.LogInformation("=== Summary by file type for {obj} ===", obj.Key);
foreach (var entry in data)
{
Logger.LogInformation("{ext} files: {count}, size extracted: {size}, size compressed: {sizeComp}", entry.Key, entry.Value.Count,
UiSharedService.ByteToString(entry.Value.Sum(v => v.OriginalSize)), UiSharedService.ByteToString(entry.Value.Sum(v => v.CompressedSize)));
}
Logger.LogInformation("=== Total summary for {obj} ===", obj.Key);
Logger.LogInformation("Total files: {count}, size extracted: {size}, size compressed: {sizeComp}", data.Values.Sum(c => c.Count),
UiSharedService.ByteToString(data.Values.Sum(v => v.Sum(c => c.OriginalSize))), UiSharedService.ByteToString(data.Values.Sum(v => v.Sum(c => c.CompressedSize))));
Logger.LogInformation("IMPORTANT NOTES:\n\r- For Mare up- and downloads only the compressed size is relevant.\n\r- An unusually high total files count beyond 200 and up will also increase your download time to others significantly.");
}
_analysisCts.CancelDispose();
_analysisCts = null;
}
public void Dispose()
{
_analysisCts.CancelDispose();
}
private sealed record DataEntry(string filePath, long OriginalSize, long CompressedSize);
}