From 61eee880780893f08eda0512650a401953504ff8 Mon Sep 17 00:00:00 2001 From: SacredFloof Date: Wed, 29 Apr 2026 01:21:18 +0200 Subject: [PATCH] ARAM balance data from aramonly.com --- ARAMUtility/ViewModel/ChampionViewModel.cs | 41 +--- ARAMUtility/ViewModel/MainViewModel.cs | 4 +- LeagueAPI/ARAM/ARAMBalanceService.cs | 212 +++++++++++------- .../Models/DDragon/Champions/ChampionData.cs | 3 +- 4 files changed, 141 insertions(+), 119 deletions(-) diff --git a/ARAMUtility/ViewModel/ChampionViewModel.cs b/ARAMUtility/ViewModel/ChampionViewModel.cs index e34fd36..0ddeb0d 100644 --- a/ARAMUtility/ViewModel/ChampionViewModel.cs +++ b/ARAMUtility/ViewModel/ChampionViewModel.cs @@ -24,46 +24,9 @@ public partial class ChampionViewModel(ChampionData data) : ObservableObject { StringBuilder sb = new(); sb.AppendLine(data.Name); - foreach (KeyValuePair kv in data.AramBalance) + if (data.AramBalance.HasValue) { - switch (kv.Key) - { - case "dmg_dealt": - if (kv.Value == 1) { continue; } - sb.AppendFormat("Dmg Dealt: {0:+#0%;-#0%}", kv.Value - 1); - break; - case "dmg_taken": - if (kv.Value == 1) { continue; } - sb.AppendFormat("Dmg Taken: {0:+#0%;-#0%}", kv.Value - 1); - break; - case "healing": - if (kv.Value == 1) { continue; } - sb.AppendFormat("Healing: {0:+#0%;-#0%}", kv.Value - 1); - break; - case "energyregen_mod": - if (kv.Value == 1) { continue; } - sb.AppendFormat("Energy Regen: {0:+#0%;-#0%}", kv.Value - 1); - break; - case "tenacity": - if (kv.Value == 1) { continue; } - sb.AppendFormat("Tenacity: {0:+#0%;-#0%}", kv.Value - 1); - break; - case "shielding": - if (kv.Value == 1) { continue; } - sb.AppendFormat("Shielding: {0:+#0%;-#0%}", kv.Value - 1); - break; - case "ability_haste": - sb.AppendFormat("Ability Haste: {0}", kv.Value); - break; - case "total_as": - if (kv.Value == 1) { continue; } - sb.AppendFormat("Total AS: {0}", kv.Value); - break; - default: - sb.AppendFormat("{0}: {1}", kv.Key, kv.Value); - break; - } - sb.AppendLine(); + data.AramBalance.Value.ToDisplayString(sb); } return sb.ToString(); } diff --git a/ARAMUtility/ViewModel/MainViewModel.cs b/ARAMUtility/ViewModel/MainViewModel.cs index de7c27d..314593e 100644 --- a/ARAMUtility/ViewModel/MainViewModel.cs +++ b/ARAMUtility/ViewModel/MainViewModel.cs @@ -175,13 +175,13 @@ public partial class MainViewModel : ObservableObject, IDisposable foreach (int championId in championIds) { ChampionData? championData = await _client.GetChampionByIdAsync(championId); - if (championData is null) + if (championData is null || championData.Name is null) { continue; } string imagePath = await ResourceService.GetChampionIconPathAsync(championId); - ChampionViewModel vm = new(championData with { AramBalance = _aramBalanceService.GetAramStats(championData.Id) }) + ChampionViewModel vm = new(championData with { AramBalance = _aramBalanceService.GetAramChampion(championData.Name) }) { IsNeededForChallenge = _needChampionIds.Contains(championData.Id), ImagePath = imagePath, diff --git a/LeagueAPI/ARAM/ARAMBalanceService.cs b/LeagueAPI/ARAM/ARAMBalanceService.cs index 25f3f64..747937c 100644 --- a/LeagueAPI/ARAM/ARAMBalanceService.cs +++ b/LeagueAPI/ARAM/ARAMBalanceService.cs @@ -1,27 +1,17 @@ -using System.Text.Json; -using CliWrap; -using CliWrap.Buffered; -using MoonSharp.Interpreter; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; namespace LeagueAPI.ARAM; -public record class WikiChampion(int Id, WikiChampionStats Stats); -public record class WikiChampionStats(Dictionary Aram); - -public class ARAMBalanceLookup : Dictionary> { } +public class ARAMBalanceLookup : Dictionary { } public class ARAMBalanceService { - private static readonly string URL = "https://wiki.leagueoflegends.com/en-us/rest.php/v1/page/Module:ChampionData%2Fdata"; + private static readonly string ARAMONLY_URL = "https://www.aramonly.com/page-data/aram-changes/page-data.json"; private ARAMBalanceLookup _champions = []; - static ARAMBalanceService() - { - UserData.RegisterType(); - UserData.RegisterType(); - } - public async Task EnsureIsLoadedAsync() { if (_champions is not { Count: > 0 }) @@ -39,71 +29,139 @@ public class ARAMBalanceService return; } - Command curl = Cli.Wrap("curl") - .WithArguments(URL); - BufferedCommandResult result = await curl.ExecuteBufferedAsync(); - - string json = result.StandardOutput; - JsonDocument jsonDocument = JsonDocument.Parse(json); - string lua = jsonDocument.RootElement.GetProperty("source").GetString() ?? string.Empty; - - DynValue champs = Script.RunString(lua); - if (champs.Type == DataType.Table) - { - Dictionary nameDictionary = []; - foreach (TablePair kv in champs.Table.Pairs) - { - if (kv.Key.Type is not DataType.String || kv.Value.Type is not DataType.Table) - { - continue; - } - string key = kv.Key.String; - Table championTable = kv.Value.Table; - DynValue idValue = championTable.Get("id"); - DynValue statsValue = championTable.Get("stats"); - - Dictionary aramStats = []; - - if (statsValue.Type is DataType.Table) - { - DynValue aramValue = statsValue.Table.Get("aram"); - - if (aramValue.Type is DataType.Table) - { - foreach (TablePair aramKv in aramValue.Table.Pairs) - { - if (aramKv.Key.Type is DataType.String && aramKv.Value.Type is DataType.Number) - { - aramStats[aramKv.Key.String] = aramKv.Value.Number; - } - } - } - } - - WikiChampion champ = new(idValue.Type is DataType.Number ? (int)idValue.Number : -1, new(aramStats)); - nameDictionary.Add(key, champ); - } - - _champions = []; - - foreach (KeyValuePair kv in nameDictionary) - { - if (!_champions.TryGetValue(kv.Value.Id, out Dictionary? value)) - { - _champions[kv.Value.Id] = new(kv.Value.Stats.Aram); - } - else - { - kv.Value.Stats.Aram.ToList().ForEach(kv => value.Add(kv.Key, kv.Value)); - } - } - ResourceService.SetARAMBalanceLookup(_champions); - } + await FetchFromAramonly(); } - public Dictionary GetAramStats(int championId) + private async Task FetchFromAramonly() + { + using HttpClient _client = new(); + using HttpResponseMessage response = await _client.GetAsync(ARAMONLY_URL); + if (!response.IsSuccessStatusCode) + { + return false; + } + + string json = await response.Content.ReadAsStringAsync(); + AramonlyComResponse? result = JsonSerializer.Deserialize(json); + AramChampion?[] nodes = result?.Result?.Data?.AllAramModifiersJson?.Nodes ?? []; + if (nodes is not { Length: > 0 }) + { + return false; + } + _champions = []; + foreach (AramChampion? node in nodes) + { + if (node is null || !node.HasValue || !node.Value.Champion.HasValue) + { + continue; + } + string name = node.Value.Champion.Value.Name ?? string.Empty; + if (name == string.Empty) + { + continue; + } + _champions.Add(name, node.Value); + } + + ResourceService.SetARAMBalanceLookup(_champions); + return true; + } + + public AramChampion? GetAramChampion(string championName) { EnsureIsLoadedAsync().Wait(); - return _champions.TryGetValue(championId, out Dictionary? stats) ? stats : []; + return _champions.TryGetValue(championName, out AramChampion aramChampion) ? aramChampion : null; } } + +public record struct AramonlyComResponse([property: JsonPropertyName("result")] AramonlyComResult? Result); +public record struct AramonlyComResult([property: JsonPropertyName("data")] AramonlyComData? Data); + +public record struct AramonlyComData( + [property: JsonPropertyName("allAramModifiersJson")] AramonlyComModifiersJson? AllAramModifiersJson, + [property: JsonPropertyName("patchVersionJson")] PatchVersionJson? PatchVersionJson +); + +public record struct AramonlyComModifiersJson([property: JsonPropertyName("nodes")] AramChampion?[]? Nodes); + +public record struct AramChampion( + [property: JsonPropertyName("timestamp")] DateTime? Timestamp, + [property: JsonPropertyName("champion")] Champion? Champion, + [property: JsonPropertyName("aramDamageDealt")] double? AramDamageDealt, + [property: JsonPropertyName("aramDamageTaken")] double? AramDamageTaken, + [property: JsonPropertyName("aramHealing")] double? AramHealing, + [property: JsonPropertyName("aramShielding")] double? AramShielding, + [property: JsonPropertyName("aramTenacity")] double? AramTenacity, + [property: JsonPropertyName("aramAbilityHaste")] int? AramAbilityHaste, + [property: JsonPropertyName("aramAttackSpeed")] double? AramAttackSpeed, + [property: JsonPropertyName("aramEnergyRegen")] double? AramEnergyRegen +) +{ + public readonly void ToDisplayString(StringBuilder sb) + { + // Damage Dealt + if (AramDamageDealt is not null and not 0 and not 1) + { + double value = (double)AramDamageDealt; + sb.AppendLine($"Dmg Dealt: {value - 1:+#0%;-#0%}"); + } + + // Damage Taken + if (AramDamageTaken is not null and not 0 and not 1) + { + double value = (double)AramDamageTaken; + sb.AppendLine($"Dmg Taken: {value - 1:+#0%;-#0%}"); + } + + // Healing + if (AramHealing is not null and not 0 and not 1) + { + double value = (double)AramHealing; + sb.AppendLine($"Healing: {value - 1:+#0%;-#0%}"); + } + + // Shielding + if (AramShielding is not null and not 0 and not 1) + { + double value = (double)AramShielding; + sb.AppendLine($"Shielding: {value - 1:+#0%;-#0%}"); + } + + // Tenacity + if (AramTenacity is not null and not 0 and not 1) + { + double value = (double)AramTenacity; + sb.AppendLine($"Tenacity: {value - 1:+#0%;-#0%}"); + } + + // Ability Haste (Raw value) + if (AramAbilityHaste is not null and not 0 and not 1) + { + double value = (double)AramAbilityHaste; + sb.AppendLine($"Ability Haste: {value}"); + } + + // Total AS (Raw value) + if (AramAttackSpeed is not null and not 0 and not 1) + { + double value = (double)AramAttackSpeed; + sb.AppendLine($"Total AS: {value}"); + } + + // Energy Regen (Percentage) + if (AramEnergyRegen is not null and not 0 and not 1) + { + double value = (double)AramEnergyRegen; + sb.AppendLine($"Energy Regen: {value - 1:+#0%;-#0%}"); + } + } +} + +public record struct Champion( + [property: JsonPropertyName("name")] string? Name, + [property: JsonPropertyName("sanitizedName")] string? SanitizedName +); + +public record struct PatchVersionJson( + [property: JsonPropertyName("patchVersion")] string? PatchVersion +); diff --git a/LeagueAPI/Models/DDragon/Champions/ChampionData.cs b/LeagueAPI/Models/DDragon/Champions/ChampionData.cs index 7d767be..6b44f8d 100644 --- a/LeagueAPI/Models/DDragon/Champions/ChampionData.cs +++ b/LeagueAPI/Models/DDragon/Champions/ChampionData.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using LeagueAPI.ARAM; namespace LeagueAPI.Models.DDragon.Champions; @@ -41,5 +42,5 @@ public record ChampionData public ChampionDataStats? Stats { get; init; } [JsonIgnore] - public Dictionary AramBalance { get; set; } = []; + public AramChampion? AramBalance { get; set; } }