From 24879ccdb9abc4aa34ff674d66d082b0a993acda Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Mon, 21 Aug 2023 06:19:44 +0200 Subject: [PATCH] UI restructuring --- Influx/AllaganToolsIPC.cs | 1 - Influx/Configuration.cs | 1 + Influx/Influx/InfluxStatisticsClient.cs | 111 ++++++++++++++++++++++++ Influx/InfluxPlugin.cs | 109 +++++++---------------- Influx/StatisticsUpdate.cs | 8 ++ Influx/Windows/ConfigurationWindow.cs | 15 ++++ Influx/Windows/StatisticsWindow.cs | 79 +++++++++++++++++ 7 files changed, 244 insertions(+), 80 deletions(-) create mode 100644 Influx/Influx/InfluxStatisticsClient.cs create mode 100644 Influx/StatisticsUpdate.cs create mode 100644 Influx/Windows/ConfigurationWindow.cs create mode 100644 Influx/Windows/StatisticsWindow.cs diff --git a/Influx/AllaganToolsIPC.cs b/Influx/AllaganToolsIPC.cs index 8e94199..998e9c6 100644 --- a/Influx/AllaganToolsIPC.cs +++ b/Influx/AllaganToolsIPC.cs @@ -216,5 +216,4 @@ internal sealed class AllaganToolsIPC : IDisposable public long Sum(int itemId) => _items.Where(x => x.ItemId == itemId).Sum(x => x.Quantity); } - } diff --git a/Influx/Configuration.cs b/Influx/Configuration.cs index a491622..d0b2dc9 100644 --- a/Influx/Configuration.cs +++ b/Influx/Configuration.cs @@ -13,6 +13,7 @@ public sealed class Configuration : IPluginConfiguration public sealed class ServerConfiguration { + public bool Enabled { get; set; } public string Server { get; set; } = "http://localhost:8086"; public string Token { get; set; } = "xxx"; public string Organization { get; set; } = "org"; diff --git a/Influx/Influx/InfluxStatisticsClient.cs b/Influx/Influx/InfluxStatisticsClient.cs new file mode 100644 index 0000000..eca6a6a --- /dev/null +++ b/Influx/Influx/InfluxStatisticsClient.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Dalamud.Game.Gui; +using InfluxDB.Client; +using InfluxDB.Client.Api.Domain; +using InfluxDB.Client.Writes; + +namespace Influx.Influx; + +internal class InfluxStatisticsClient : IDisposable +{ + private const string MutexName = "Global\\c31c89b5-5efb-4c7e-bf87-21717a2814ef"; + + private readonly InfluxDBClient _influxClient; + private readonly ChatGui _chatGui; + private readonly Configuration _configuration; + private readonly Mutex _mutex; + private readonly bool _mutexCreated; + + public InfluxStatisticsClient(ChatGui chatGui, Configuration configuration) + { + _influxClient = new InfluxDBClient(configuration.Server.Server, configuration.Server.Token); + _chatGui = chatGui; + _configuration = configuration; + _mutex = new Mutex(true, MutexName, out _mutexCreated); + } + + public bool Enabled => _configuration.Server.Enabled; + + public void OnStatisticsUpdate(StatisticsUpdate update) + { + if (!Enabled || !_mutexCreated) + return; + + DateTime date = DateTime.UtcNow; + IReadOnlyDictionary stats = update.Currencies; + + var validFcIds = stats.Keys + .Where(x => x.CharacterType == AllaganToolsIPC.CharacterType.Character) + .Select(x => x.FreeCompanyId) + .ToList(); + Task.Run(async () => + { + try + { + List values = new(); + foreach (var (character, currencies) in stats) + { + if (character.CharacterType == AllaganToolsIPC.CharacterType.Character) + { + values.Add(PointData.Measurement("currency") + .Tag("id", character.CharacterId.ToString()) + .Tag("player_name", character.Name) + .Tag("type", character.CharacterType.ToString()) + .Field("gil", currencies.Gil) + .Field("ventures", currencies.Ventures) + .Field("ceruleum_tanks", currencies.CeruleumTanks) + .Field("repair_kits", currencies.RepairKits) + .Timestamp(date, WritePrecision.S)); + } + else if (character.CharacterType == AllaganToolsIPC.CharacterType.Retainer) + { + var owner = stats.Keys.First(x => x.CharacterId == character.OwnerId); + values.Add(PointData.Measurement("currency") + .Tag("id", character.CharacterId.ToString()) + .Tag("player_name", owner.Name) + .Tag("type", character.CharacterType.ToString()) + .Tag("retainer_name", character.Name) + .Field("gil", currencies.Gil) + .Field("ceruleum_tanks", currencies.CeruleumTanks) + .Field("repair_kits", currencies.RepairKits) + .Timestamp(date, WritePrecision.S)); + } + else if (character.CharacterType == AllaganToolsIPC.CharacterType.FreeCompanyChest && + validFcIds.Contains(character.CharacterId)) + { + values.Add(PointData.Measurement("currency") + .Tag("id", character.CharacterId.ToString()) + .Tag("fc_name", character.Name) + .Tag("type", character.CharacterType.ToString()) + .Field("gil", currencies.Gil) + .Field("fccredit", currencies.FcCredits) + .Field("ceruleum_tanks", currencies.CeruleumTanks) + .Field("repair_kits", currencies.RepairKits) + .Timestamp(date, WritePrecision.S)); + } + } + + var writeApi = _influxClient.GetWriteApiAsync(); + await writeApi.WritePointsAsync( + values, + _configuration.Server.Bucket, _configuration.Server.Organization); + + //_chatGui.Print($"Influx: {values.Count} points"); + } + catch (Exception e) + { + _chatGui.PrintError(e.ToString()); + } + }); + } + + public void Dispose() + { + _mutex.Dispose(); + _influxClient.Dispose(); + } +} diff --git a/Influx/InfluxPlugin.cs b/Influx/InfluxPlugin.cs index 63a0703..f7134dd 100644 --- a/Influx/InfluxPlugin.cs +++ b/Influx/InfluxPlugin.cs @@ -7,8 +7,12 @@ using System.Threading.Tasks; using Dalamud.Game.ClientState; using Dalamud.Game.Command; using Dalamud.Game.Gui; +using Dalamud.Interface.Windowing; +using Dalamud.Logging; using Dalamud.Plugin; using ECommons; +using Influx.Influx; +using Influx.Windows; using InfluxDB.Client; using InfluxDB.Client.Api.Domain; using InfluxDB.Client.Writes; @@ -24,9 +28,11 @@ public class InfluxPlugin : IDalamudPlugin private readonly Configuration _configuration; private readonly ClientState _clientState; private readonly CommandManager _commandManager; - private readonly ChatGui _chatGui; private readonly AllaganToolsIPC _allaganToolsIpc; - private readonly InfluxDBClient _influxClient; + private readonly InfluxStatisticsClient _influxStatisticsClient; + private readonly WindowSystem _windowSystem; + private readonly StatisticsWindow _statisticsWindow; + private readonly ConfigurationWindow _configurationWindow; private readonly Timer _timer; public InfluxPlugin(DalamudPluginInterface pluginInterface, ClientState clientState, @@ -38,12 +44,18 @@ public class InfluxPlugin : IDalamudPlugin _configuration = LoadConfig(); _clientState = clientState; _commandManager = commandManager; - _chatGui = chatGui; _allaganToolsIpc = new AllaganToolsIPC(pluginInterface, chatGui, _configuration); - _influxClient = new InfluxDBClient(_configuration.Server.Server, _configuration.Server.Token); + _influxStatisticsClient = new InfluxStatisticsClient(chatGui, _configuration); + + _windowSystem = new WindowSystem(typeof(InfluxPlugin).FullName); + _statisticsWindow = new StatisticsWindow(); + _windowSystem.AddWindow(_statisticsWindow); + _configurationWindow = new ConfigurationWindow(); + _windowSystem.AddWindow(_configurationWindow); _commandManager.AddHandler("/influx", new CommandInfo(ProcessCommand)); - _timer = new Timer(_ => CountGil(), null, TimeSpan.Zero, TimeSpan.FromMinutes(1)); + _timer = new Timer(_ => UpdateStatistics(), null, TimeSpan.Zero, TimeSpan.FromMinutes(1)); + _pluginInterface.UiBuilder.Draw += _windowSystem.Draw; } private Configuration LoadConfig() @@ -58,98 +70,37 @@ public class InfluxPlugin : IDalamudPlugin private void ProcessCommand(string command, string arguments) { - CountGil(true); + UpdateStatistics(); + _statisticsWindow.IsOpen = true; } - private void CountGil(bool printDebug = false) + private void UpdateStatistics() { if (!_clientState.IsLoggedIn) return; - DateTime date = DateTime.UtcNow; - IReadOnlyDictionary stats; try { - stats = _allaganToolsIpc.CountCurrencies(); + var update = new StatisticsUpdate + { + Currencies = _allaganToolsIpc.CountCurrencies(), + }; + _statisticsWindow.OnStatisticsUpdate(update); + _influxStatisticsClient.OnStatisticsUpdate(update); } catch (Exception e) { - _chatGui.PrintError(e.ToString()); - return; + PluginLog.LogError(e, "failed to update statistics"); } - - - var validFcIds = stats.Keys - .Where(x => x.CharacterType == AllaganToolsIPC.CharacterType.Character) - .Select(x => x.FreeCompanyId) - .ToList(); - Task.Run(async () => - { - - try - { - List values = new(); - foreach (var (character, currencies) in stats) - { - if (character.CharacterType == AllaganToolsIPC.CharacterType.Character) - { - values.Add(PointData.Measurement("currency") - .Tag("id", character.CharacterId.ToString()) - .Tag("player_name", character.Name) - .Tag("type", character.CharacterType.ToString()) - .Field("gil", currencies.Gil) - .Field("ventures", currencies.Ventures) - .Field("ceruleum_tanks", currencies.CeruleumTanks) - .Field("repair_kits", currencies.RepairKits) - .Timestamp(date, WritePrecision.S)); - } - else if (character.CharacterType == AllaganToolsIPC.CharacterType.Retainer) - { - var owner = stats.Keys.First(x => x.CharacterId == character.OwnerId); - values.Add(PointData.Measurement("currency") - .Tag("id", character.CharacterId.ToString()) - .Tag("player_name", owner.Name) - .Tag("type", character.CharacterType.ToString()) - .Tag("retainer_name", character.Name) - .Field("gil", currencies.Gil) - .Field("ceruleum_tanks", currencies.CeruleumTanks) - .Field("repair_kits", currencies.RepairKits) - .Timestamp(date, WritePrecision.S)); - } - else if (character.CharacterType == AllaganToolsIPC.CharacterType.FreeCompanyChest && validFcIds.Contains(character.CharacterId)) - { - values.Add(PointData.Measurement("currency") - .Tag("id", character.CharacterId.ToString()) - .Tag("fc_name", character.Name) - .Tag("type", character.CharacterType.ToString()) - .Field("gil", currencies.Gil) - .Field("fccredit", currencies.FcCredits) - .Field("ceruleum_tanks", currencies.CeruleumTanks) - .Field("repair_kits", currencies.RepairKits) - .Timestamp(date, WritePrecision.S)); - } - } - - var writeApi = _influxClient.GetWriteApiAsync(); - await writeApi.WritePointsAsync( - values, - _configuration.Server.Bucket, _configuration.Server.Organization); - - if (printDebug) - _chatGui.Print($"Influx: {values.Count} points"); - } - catch (Exception e) - { - _chatGui.PrintError(e.ToString()); - } - }); } public void Dispose() { + _pluginInterface.UiBuilder.Draw -= _windowSystem.Draw; _timer.Dispose(); + _windowSystem.RemoveAllWindows(); _commandManager.RemoveHandler("/influx"); - _influxClient.Dispose(); + _influxStatisticsClient.Dispose(); _allaganToolsIpc.Dispose(); ECommonsMain.Dispose(); diff --git a/Influx/StatisticsUpdate.cs b/Influx/StatisticsUpdate.cs new file mode 100644 index 0000000..5e730d6 --- /dev/null +++ b/Influx/StatisticsUpdate.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Influx; + +internal sealed class StatisticsUpdate +{ + public IReadOnlyDictionary Currencies { get; init; } +} diff --git a/Influx/Windows/ConfigurationWindow.cs b/Influx/Windows/ConfigurationWindow.cs new file mode 100644 index 0000000..abcf840 --- /dev/null +++ b/Influx/Windows/ConfigurationWindow.cs @@ -0,0 +1,15 @@ +using Dalamud.Interface.Windowing; + +namespace Influx.Windows; + +internal class ConfigurationWindow : Window +{ + public ConfigurationWindow() + : base("Configuration###InfluxConfiguration") + { + } + + public override void Draw() + { + } +} diff --git a/Influx/Windows/StatisticsWindow.cs b/Influx/Windows/StatisticsWindow.cs new file mode 100644 index 0000000..c352a7e --- /dev/null +++ b/Influx/Windows/StatisticsWindow.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using Dalamud.Interface.Windowing; +using ImGuiNET; + +namespace Influx.Windows; + +internal sealed class StatisticsWindow : Window +{ + private List _rows = new(); + + public StatisticsWindow() + : base("Statistics###InfluxStatistics") + { + Position = new Vector2(100, 100); + PositionCondition = ImGuiCond.FirstUseEver; + + Size = new Vector2(400, 400); + SizeCondition = ImGuiCond.Appearing; + } + + public override void Draw() + { + if (ImGui.BeginTable("Currencies###InfluxStatisticsCurrencies", 4)) + { + ImGui.TableSetupColumn("Name"); + ImGui.TableSetupColumn("Gil"); + ImGui.TableHeadersRow(); + + foreach (var row in _rows) + { + ImGui.TableNextRow(); + if (ImGui.TableNextColumn()) + ImGui.Text(row.Name); + + if (ImGui.TableNextColumn()) + ImGui.Text(row.Gil.ToString("N0")); + } + + ImGui.EndTable(); + } + } + + public void OnStatisticsUpdate(StatisticsUpdate update) + { + var retainers = update.Currencies + .Where(x => x.Key.CharacterType == AllaganToolsIPC.CharacterType.Retainer) + .GroupBy(x => update.Currencies.FirstOrDefault(y => y.Key.CharacterId == x.Key.OwnerId).Key) + .ToDictionary(x => x.Key, x => x.Select(y => y.Value).ToList()); + + _rows = update.Currencies.Where(x => x.Key.CharacterType == AllaganToolsIPC.CharacterType.Character) + .Select(x => + { + var currencies = new List { x.Value }; + if (retainers.TryGetValue(x.Key, out var retainerCurrencies)) + currencies.AddRange(retainerCurrencies); + return new StatisticsRow + { + Name = x.Key.Name, + Type = x.Key.CharacterType.ToString(), + Gil = currencies.Sum(y => y.Gil), + FcCredits = currencies.Sum(y => y.FcCredits), + }; + }) + .Where(x => x.Gil > 0 || x.FcCredits > 0) + .OrderByDescending(x => x.Gil) + .ToList(); + } + + public sealed class StatisticsRow + { + public string Name { get; init; } + public string Type { get; init; } + public long Gil { get; init; } + public long FcCredits { get; init; } + } +}