diff --git a/PartyPlanner/Models/EventType.cs b/PartyPlanner/Models/EventType.cs index 8003a79..87bea36 100644 --- a/PartyPlanner/Models/EventType.cs +++ b/PartyPlanner/Models/EventType.cs @@ -9,6 +9,8 @@ namespace PartyPlanner.Models { public class EventType { + [JsonProperty("id")] + public int Id { get; set; } [JsonProperty("locationId")] public int LocationId { get; set; } [JsonProperty("description")] @@ -27,6 +29,34 @@ public class EventType public int AttendeeCount { get; set; } [JsonProperty("attachments")] public string[] Attachments { get; set; } = Array.Empty(); + [JsonProperty("locationData")] + public EventLocationData LocationData { get; set; } + } + + public class EventLocationData + { + [JsonProperty("server")] + public EventServerData Server { get; set; } + [JsonProperty("dataCenter")] + public EventServerData DataCenter { get; set; } + } + + public class EventServerData + { + [JsonProperty("id")] + public int Id { get; set; } + [JsonProperty("name")] + public string Name { get; set; } + [JsonProperty("dataCenterId")] + public int DataCenterId { get; set; } + } + + public class EventDataCenterData + { + [JsonProperty("id")] + public int Id { get; set; } + [JsonProperty("name")] + public string Name { get; set; } } public class EventsResponseType diff --git a/PartyPlanner/PartyPlanner.csproj b/PartyPlanner/PartyPlanner.csproj index f0a98e4..6419113 100644 --- a/PartyPlanner/PartyPlanner.csproj +++ b/PartyPlanner/PartyPlanner.csproj @@ -31,8 +31,8 @@ - - + + $(DalamudLibPath)FFXIVClientStructs.dll diff --git a/PartyPlanner/PartyVerseApi.cs b/PartyPlanner/PartyVerseApi.cs index 383780e..8d95078 100644 --- a/PartyPlanner/PartyVerseApi.cs +++ b/PartyPlanner/PartyVerseApi.cs @@ -78,18 +78,29 @@ public PartyVerseApi() Query = @" { events(game: ""final-fantasy-xiv"", sortBy: STARTS_AT) { + id, title, locationId, ageRating, attendeeCount, startsAt, endsAt, - launchUrl, location, tags, description(type: PLAIN_TEXT) attendeeCount attachments + locationData { + server { + id + name + dataCenterId + } + dataCenter { + id + name + } + } } }" }; @@ -117,18 +128,29 @@ public PartyVerseApi() Query = @" { activeEvents(game: ""final-fantasy-xiv"", sortBy: STARTS_AT) { + id, title, locationId, ageRating, attendeeCount, startsAt, endsAt, - launchUrl, location, tags, description(type: PLAIN_TEXT) attendeeCount attachments + locationData { + server { + id + name + dataCenterId + } + dataCenter { + id + name + } + } } }" }; diff --git a/PartyPlanner/PluginUI.cs b/PartyPlanner/PluginUI.cs index 6729669..dd4b59e 100644 --- a/PartyPlanner/PluginUI.cs +++ b/PartyPlanner/PluginUI.cs @@ -3,6 +3,7 @@ using ImGuiNET; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Numerics; using System.Reflection; @@ -18,9 +19,12 @@ class PluginUI : IDisposable { private Configuration configuration; private PartyVerseApi partyVerseApi { get; init; } + // All the events private readonly List partyVerseEvents = new(50); private string filterTag; private string windowTitle; + private readonly Dictionary> eventsByDc = new(); + private readonly Dictionary> tagsByDc = new(); // this extra bool exists for ImGui, since you can't ref a property private bool visible = false; @@ -56,12 +60,7 @@ public PluginUI(Configuration configuration) PluginLog.Error(e, "error loading assembly"); } - Task.Run(async () => - { - partyVerseEvents.Clear(); - partyVerseEvents.AddRange(await this.partyVerseApi.GetActiveEvents()); - partyVerseEvents.AddRange(await this.partyVerseApi.GetEvents()); - }); + Task.Run(UpdateEvents); } public void Dispose() @@ -74,25 +73,41 @@ public void Draw() DrawEventWindow(); } + public async void UpdateEvents() + { + partyVerseEvents.Clear(); + eventsByDc.Clear(); + tagsByDc.Clear(); + partyVerseEvents.AddRange(await this.partyVerseApi.GetActiveEvents()); + partyVerseEvents.AddRange(await this.partyVerseApi.GetEvents()); + foreach (var ev in partyVerseEvents) + { + var key = ev.LocationData.DataCenter.Id; + + if (!eventsByDc.ContainsKey(key)) + eventsByDc.Add(key, new()); + eventsByDc[key].Add(ev); + if (!tagsByDc.ContainsKey(key)) + tagsByDc.Add(key, new()); + + foreach(var tag in ev.Tags) + { + if (!tagsByDc[key].ContainsKey(tag)) + tagsByDc[key].Add(tag, false); + } + } + } + public void DrawMainWindow() { if (!Visible) - { return; - } ImGui.SetNextWindowSize(new Vector2(1000, 500), ImGuiCond.FirstUseEver); if (ImGui.Begin(windowTitle, ref this.visible, ImGuiWindowFlags.None)) { if (ImGui.Button("Reload Events")) - { - Task.Run(async () => - { - partyVerseEvents.Clear(); - partyVerseEvents.AddRange(await this.partyVerseApi.GetActiveEvents()); - partyVerseEvents.AddRange(await this.partyVerseApi.GetEvents()); - }); - } + Task.Run(UpdateEvents); ImGui.Spacing(); @@ -109,10 +124,12 @@ public void DrawMainWindow() if (ImGui.BeginTabItem(location.ToUpper())) { ImGui.BeginTabBar("datacenters_tab_bar"); - foreach (var datacenter in this.partyVerseApi.DataCenters) + foreach (var dataCenter in this.partyVerseApi.DataCenters) { - if (datacenter.Value.Location == location) - DrawDataCenter(datacenter.Value); + if (dataCenter.Value.Location == location) + { + DrawDataCenter(dataCenter.Value); + } } ImGui.EndTabBar(); ImGui.EndTabItem(); @@ -127,26 +144,21 @@ public void DrawDataCenter(Models.DataCenterType dataCenter) { if (ImGui.BeginTabItem(dataCenter.Name)) { - var events = partyVerseEvents - .FindAll(ev => ev.LocationId >= 0 && ev.LocationId < partyVerseApi.Servers.Count - && partyVerseApi.GetServerType(ev.LocationId).DataCenter == dataCenter.Id); - - var tags = events.SelectMany(ev => ev.Tags).Distinct().OrderBy(x => x); + var events = eventsByDc.GetValueOrDefault(dataCenter.Id); + events ??= new(); - if (filterTag != "" && !tags.Contains(filterTag)) - filterTag = ""; + var tags = tagsByDc.GetValueOrDefault(dataCenter.Id); + tags ??= new(); - if (ImGui.RadioButton("None", filterTag == "")) - { - filterTag = ""; - } + ImGui.Spacing(); - foreach (var tag in tags) + foreach (var (tag, selected) in tags) { ImGui.SameLine(); - if (ImGui.RadioButton(tag, filterTag == tag)) + var selectedLocal = selected; + if (ImGui.Checkbox(tag, ref selectedLocal)) { - filterTag = tag; + tags[tag] = selectedLocal; } } @@ -156,7 +168,7 @@ public void DrawDataCenter(Models.DataCenterType dataCenter) ImGuiTableFlags.RowBg | ImGuiTableFlags.Borders | ImGuiTableFlags.BordersInner)) { ImGui.TableHeader("Events"); - ImGui.TableSetupColumn("Title", ImGuiTableColumnFlags.WidthFixed); + ImGui.TableSetupColumn("Title (click for more info)", ImGuiTableColumnFlags.WidthFixed); ImGui.TableSetupColumn("Location", ImGuiTableColumnFlags.WidthFixed); ImGui.TableSetupColumn("Description", ImGuiTableColumnFlags.WidthStretch); ImGui.TableSetupColumn("Starts", ImGuiTableColumnFlags.WidthFixed); @@ -164,11 +176,23 @@ public void DrawDataCenter(Models.DataCenterType dataCenter) ImGui.TableHeadersRow(); ImGui.TableNextRow(); - foreach (var ev in events.Where(x => filterTag == "" || x.Tags.Contains(filterTag))) + foreach (var ev in events) { - var serverType = partyVerseApi.GetServerType(ev.LocationId); + bool filtered = false; + foreach(var (tag, selected) in tags) + { + if(selected && !ev.Tags.Contains(tag)) + { + filtered = true; + break; + } + } - DrawEventRow(ev, serverType); + if(!filtered) + { + DrawEventRow(ev); + } + } ImGui.EndTable(); @@ -177,14 +201,13 @@ public void DrawDataCenter(Models.DataCenterType dataCenter) } } - public void DrawEventRow(Models.EventType ev, Models.ServerType serverType) + public void DrawEventRow(Models.EventType ev) { ImGui.TableNextColumn(); ImGui.Spacing(); var greenColor = new Vector4(0.0742f, 0.530f, 0.150f, 1.0f); - ImGui.PushStyleColor(ImGuiCol.Button, greenColor); var title = ev.Title; if (title.Length > 30) @@ -195,7 +218,6 @@ public void DrawEventRow(Models.EventType ev, Models.ServerType serverType) this.eventDetails = ev; EventDetailsOpen = true; } - ImGui.PopStyleColor(); if (ImGui.IsItemHovered()) { @@ -213,7 +235,7 @@ public void DrawEventRow(Models.EventType ev, Models.ServerType serverType) ImGui.TableNextColumn(); - var originalLocation = string.Format("[{0}] {1}", serverType.Name, ev.Location); + var originalLocation = string.Format("[{0}] {1}", ev.LocationData.Server.Name, ev.Location); var location = originalLocation; if (location.Length > 100) location = location[..100] + "..."; diff --git a/PartyPlanner/packages.lock.json b/PartyPlanner/packages.lock.json index 14895c6..5e2369c 100644 --- a/PartyPlanner/packages.lock.json +++ b/PartyPlanner/packages.lock.json @@ -10,23 +10,23 @@ }, "GraphQL.Client": { "type": "Direct", - "requested": "[5.1.0, )", - "resolved": "5.1.0", - "contentHash": "ygsFiS/+DSQBmfP1kjmVk8igODFGNihy81EzTqrq7RmwHgyS34+5Nm9Jkd4mgpFsC8a8UZaWerTilKGqDyePHg==", + "requested": "[5.1.1, )", + "resolved": "5.1.1", + "contentHash": "6bfM9qU4AMcFWm4BHd2M6LE5+rLtK47/+VRtypggwb9appC8sbF58ytVBVOKpqKhKpmZERfPLGJap8O/FH3w5w==", "dependencies": { - "GraphQL.Client.Abstractions": "5.1.0", - "GraphQL.Client.Abstractions.Websocket": "5.1.0", + "GraphQL.Client.Abstractions": "5.1.1", + "GraphQL.Client.Abstractions.Websocket": "5.1.1", "System.Reactive": "5.0.0" } }, "GraphQL.Client.Serializer.Newtonsoft": { "type": "Direct", - "requested": "[5.1.0, )", - "resolved": "5.1.0", - "contentHash": "SM7ijGJqtFbTsHedjMnDNfGCQqz+ha5C+8XsvV5k59fu+7qnWQ333+LqlkHrKO0s77BMGzZ9dHWakRpQAdMcPg==", + "requested": "[5.1.1, )", + "resolved": "5.1.1", + "contentHash": "K0laxF0Jd7x35XTsDfn9DIlqDBT0LrzwM9uXOqczF91WUFgjOrakaMhEkuVd23umS339q098J1Qgdy5gumSiAw==", "dependencies": { - "GraphQL.Client.Abstractions.Websocket": "5.1.0", - "Newtonsoft.Json": "13.0.1" + "GraphQL.Client.Abstractions.Websocket": "5.1.1", + "Newtonsoft.Json": "13.0.2" } }, "Humanizer.Core": { @@ -37,29 +37,29 @@ }, "GraphQL.Client.Abstractions": { "type": "Transitive", - "resolved": "5.1.0", - "contentHash": "IwZUs8WZtSUorZMKaqxykA/PFtn59gVcwbmkPecjnts2mk+sj/x2owlVbv5SnS2f9Za54zFPG2U3YOGZwBk3NQ==", + "resolved": "5.1.1", + "contentHash": "/znG7Lcz3rzG9VSCq+V2ARb63c/uIs8idGOvXyltZ32Wy570GX/I8HNUIZ1yDThmQRJ5KOGSd9Mzk37lFg49rg==", "dependencies": { - "GraphQL.Primitives": "5.1.0" + "GraphQL.Primitives": "5.1.1" } }, "GraphQL.Client.Abstractions.Websocket": { "type": "Transitive", - "resolved": "5.1.0", - "contentHash": "4Pctkq7yrhzDYDrR/BGhsp6HEM4i9JHaBQ2KQIeIzDjHGY55YueIRujGcFziJ8KGFRJvQxnpjrGX2+FPRANNCQ==", + "resolved": "5.1.1", + "contentHash": "n1gU3GlqJ0jQceb/VEEr4c0D2vpQc5AtDwthK89+yX7VpzlhJKqE5B4RJwx//Jb33mKybfJioWwDgVfSOPAwdw==", "dependencies": { - "GraphQL.Client.Abstractions": "5.1.0" + "GraphQL.Client.Abstractions": "5.1.1" } }, "GraphQL.Primitives": { "type": "Transitive", - "resolved": "5.1.0", - "contentHash": "NQmodHoO343gQW9/LbBWteRWlQhLxHV661s3Su8lHl2bPHZ0eauWBkjzWuVY9mLDo54mEDhQv5dTCkFnW21meA==" + "resolved": "5.1.1", + "contentHash": "RlGNsv19gbz6sQwkzif9J6Jd148nuIg1kRQf2AFOLp5K00IA+pKMdJvHF5t5llDR52Rok46ynhJv/wg+ps9ZhQ==" }, "Newtonsoft.Json": { "type": "Transitive", - "resolved": "13.0.1", - "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + "resolved": "13.0.2", + "contentHash": "R2pZ3B0UjeyHShm9vG+Tu0EBb2lC8b0dFzV9gVn50ofHXh9Smjk6kTn7A/FdAsC8B5cKib1OnGYOXxRBz5XQDg==" }, "System.Reactive": { "type": "Transitive",