// // MaaWpfGui - A part of the MaaCoreArknights project // Copyright (C) 2021 MistEO and Contributors // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License v3.0 only as published by // the Free Software Foundation, either version 3 of the License, or // any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY // #nullable enable using System; using System.Collections.Generic; using System.IO; using System.Linq; using MaaWpfGui.Constants; using MaaWpfGui.ViewModels.UI; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace MaaWpfGui.Helper { public static class DataHelper { public static readonly Dictionary ClientDirectoryMapper = new() { { "zh-tw", "txwy" }, { "en-us", "YoStarEN" }, { "ja-jp", "YoStarJP" }, { "ko-kr", "YoStarKR" }, }; public static readonly Dictionary ClientLanguageMapper = new() { { string.Empty, "zh-cn" }, { "Official", "zh-cn" }, { "Bilibili", "zh-cn" }, { "YoStarEN", "en-us" }, { "YoStarJP", "ja-jp" }, { "YoStarKR", "ko-kr" }, { "txwy", "zh-tw" }, }; // 储存角色信息的字典 public static Dictionary Characters { get; } = new(); public static HashSet CharacterNames { get; } = new(); public static Dictionary RecruitTags { get; private set; } = []; static DataHelper() { const string FilePath = "resource/battle_data.json"; if (!File.Exists(FilePath)) { return; } string jsonText = File.ReadAllText(FilePath); var characterData = JsonConvert.DeserializeObject>(JObject.Parse(jsonText)["chars"]?.ToString() ?? string.Empty) ?? new Dictionary(); var characterNamesLangAdd = GetCharacterNamesAddAction(ConfigurationHelper.GetGlobalValue(ConfigurationKeys.Localization, LocalizationHelper.DefaultLanguage)); var characterNamesClientAdd = GetCharacterNamesAddAction(ConfigurationHelper.GetValue(ConfigurationKeys.ClientType, string.Empty)); foreach (var (key, value) in characterData) { Characters.Add(key, value); if (!key.StartsWith("char_")) { continue; } characterNamesLangAdd.Invoke(value); characterNamesClientAdd.Invoke(value); } InitRecruitTag(); } private static void InitRecruitTag() { var clientType = ConfigurationHelper.GetValue(ConfigurationKeys.ClientType, string.Empty); var clientPath = clientType switch { "" or "Official" or "Bilibili" => string.Empty, _ => Path.Combine("global", clientType, "resource"), }; var displayLanguage = ConfigurationHelper.GetGlobalValue(ConfigurationKeys.Localization, LocalizationHelper.DefaultLanguage); var displayPath = displayLanguage switch { "zh-tw" or "en-us" or "ja-jp" or "ko-kr" => Path.Combine("global", ClientDirectoryMapper[displayLanguage], "resource"), _ => string.Empty, }; var clientTags = ParseRecruit(Path.Combine("resource", clientPath, "recruitment.json")); var displayTags = ParseRecruit(Path.Combine("resource", displayPath, "recruitment.json")); RecruitTags = clientTags.Keys .Select(key => new KeyValuePair(key, (displayTags.TryGetValue(key, out var displayTag) ? displayTag : string.Empty, clientTags.TryGetValue(key, out var clientTag) ? clientTag : string.Empty))) .Where(i => !string.IsNullOrEmpty(i.Value.ClientName)) .Select(i => !string.IsNullOrEmpty(i.Value.DisplayName) ? i : new(i.Key, (i.Value.ClientName, i.Value.ClientName))) .ToDictionary(); static Dictionary ParseRecruit(string path) { Dictionary clientTags = []; if (!File.Exists(path)) { return clientTags; } var jObj = (JObject?)JsonConvert.DeserializeObject(File.ReadAllText(path)); if (jObj is null || !jObj.ContainsKey("tags") || jObj["tags"] is not JObject tags) { return clientTags; } foreach (var item in tags) { clientTags.Add(item.Key, item.Value?.ToString() ?? string.Empty); } return clientTags.Where(i => !string.IsNullOrEmpty(i.Value)).ToDictionary(); } } private static Action GetCharacterNamesAddAction(string str) { return str switch { "zh-cn" or "Official" or "Bilibili" => v => CharacterNames.Add(v.Name ?? string.Empty), "zh-tw" or "txwy" => v => CharacterNames.Add(v.NameTw ?? string.Empty), "en-us" or "YoStarEN" => v => CharacterNames.Add(v.NameEn ?? string.Empty), "ja-jp" or "YoStarJP" => v => CharacterNames.Add(v.NameJp ?? string.Empty), "ko-kr" or "YoStarKR" => v => CharacterNames.Add(v.NameKr ?? string.Empty), _ => v => CharacterNames.Add(v.Name ?? string.Empty), }; } public static CharacterInfo? GetCharacterByNameOrAlias(string characterName) { return Characters.Values.FirstOrDefault( character => new[] { character.Name, character.NameEn, character.NameJp, character.NameKr, character.NameTw, }.Any(name => name?.Equals(characterName, StringComparison.OrdinalIgnoreCase) ?? false)); } public static string? GetLocalizedCharacterName(string? characterName, string? language = null) { if (string.IsNullOrEmpty(characterName)) { return null; } var characterInfo = GetCharacterByNameOrAlias(characterName); if (characterInfo?.Name == null) { return null; } language ??= SettingsViewModel.GuiSettings.OperNameLocalization; return language switch { "zh-cn" => characterInfo.Name, "zh-tw" => characterInfo.NameTw ?? characterInfo.Name, "en-us" => characterInfo.NameEn ?? characterInfo.Name, "ja-jp" => characterInfo.NameJp ?? characterInfo.Name, "ko-kr" => characterInfo.NameKr ?? characterInfo.Name, _ => characterInfo.Name, }; } public static bool IsCharacterAvailableInClient(CharacterInfo? character, string clientType) { if (character is null) { return false; } return clientType switch { "zh-tw" or "txwy" => !character.NameTwUnavailable, "en-us" or "YoStarEN" => !character.NameEnUnavailable, "ja-jp" or "YoStarJP" => !character.NameJpUnavailable, "ko-kr" or "YoStarKR" => !character.NameKrUnavailable, _ => true, }; } public static bool IsCharacterAvailableInClient(string characterName, string clientType) { var character = GetCharacterByNameOrAlias(characterName); return character != null && IsCharacterAvailableInClient(character, clientType); } public class CharacterInfo { [JsonProperty("name")] public string? Name { get; set; } [JsonProperty("name_en")] public string? NameEn { get; set; } [JsonProperty("name_en_unavailable")] public bool NameEnUnavailable { get; set; } = false; [JsonProperty("name_jp")] public string? NameJp { get; set; } [JsonProperty("name_jp_unavailable")] public bool NameJpUnavailable { get; set; } = false; [JsonProperty("name_kr")] public string? NameKr { get; set; } [JsonProperty("name_kr_unavailable")] public bool NameKrUnavailable { get; set; } = false; [JsonProperty("name_tw")] public string? NameTw { get; set; } [JsonProperty("name_tw_unavailable")] public bool NameTwUnavailable { get; set; } = false; [JsonProperty("position")] public string? Position { get; set; } [JsonProperty("profession")] public string? Profession { get; set; } [JsonProperty("rangeId")] public List? RangeId { get; set; } [JsonProperty("rarity")] public int Rarity { get; set; } } } }