private static void UpdateCardBaseDefinitions_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = (BackgroundWorker)sender; Debug.Assert(e.Argument != null); UpdateCardBaseDefinitionsArgument managers = (UpdateCardBaseDefinitionsArgument)e.Argument; worker.ReportProgress(0, "Connecting to server..."); // This process will set the locale to English. Here we take the previous value to restore it at the end. string userLocale = managers.ServerQueriesManager.GetUserLocale(); var existingIds = managers.ServerQueriesManager.GetAllCardBaseIds(); var storedIds = managers.DatabaseManager.GetAllCardBaseIds(); var idsToAnalyze = existingIds.Except(storedIds).ToList(); idsToAnalyze.Sort(); /* There are 3 API calls to get characters details: * - characters.getCharacters (labeled "oldGetCharacters") * - characters.getCharacterLevels * - urc.getCharacters (labeled "newGetCharacters") * Some details can be obtained from various of those calls, some only from one of them. * "newGetCharacters" is the fastest one, so we will get most of the details from that one, and the rest from "oldGetCharacters". * "getCharacterLevels" will not be used, all the details that we can obtain from it we can get it from the "new" one too. */ var request = new ApiRequest(); var setLocaleToEnglishCall = new ApiCallList.Players.SetLanguages(new List <string> { ServerQueriesManager.EnglishLocale }); request.EnqueueApiCall(setLocaleToEnglishCall); var oldGetCharactersCall = new ApiCallList.Characters.GetCharacters { // This call is painfully slow, so we optimize it as much as we can, asking only for the info we need charactersIDs = new List <int>(idsToAnalyze), maxLevels = true, ItemsFilter = new List <string>() { "id", "level_min", "level_max", "ability", "ability_unlock_level", "release_date" } }; request.EnqueueApiCall(oldGetCharactersCall); var newGetCharactersCall = new ApiCallList.Urc.GetCharacters(); request.EnqueueApiCall(newGetCharactersCall); string response; HttpStatusCode statusCode = managers.GlobalManager.ApiManagerInstance.SendRequest(request, out response); if (statusCode != HttpStatusCode.OK) { throw new Exception("GetCardBase SendRequest returned: " + statusCode.ToString()); // TODO: Manage timeouts gracefully (GatewayTimeout) } dynamic decoded = JsonDecoder.Decode(response); int progress = 0; var oldData = SortServerCharacterDataIntoDictionary(oldGetCharactersCall.Call, decoded); var newData = SortServerCharacterDataIntoDictionary(newGetCharactersCall.Call, decoded); foreach (int id in idsToAnalyze) { if (worker.CancellationPending == true) { e.Cancel = true; break; } int minLevel = int.Parse(oldData[id]["level_min"].ToString()); int maxLevel = int.Parse(oldData[id]["level_max"].ToString()); string abilityText = oldData[id]["ability"].ToString(); int abilityUnlockLevel = int.Parse(oldData[id]["ability_unlock_level"].ToString()); int timeSinceRelease = int.Parse(oldData[id]["release_date"].ToString()); string name = newData[id]["name"].ToString(); int clanId = int.Parse(newData[id]["clanID"].ToString()); string rarityText = newData[id]["rarity"].ToString(); var cardLevels = new List <CardLevel>(); foreach (dynamic levelItem in newData[id]["levels"]) { int level = int.Parse(levelItem["level"].ToString()); int power = int.Parse(levelItem["power"].ToString()); int damage = int.Parse(levelItem["damage"].ToString()); cardLevels.Add(new CardLevel(level, power, damage)); } worker.ReportProgress((int)(100 * progress / idsToAnalyze.Count()), $"[{id}] {name}"); progress++; var card = ApiToCardBaseAdapter.ToCardBase(id, name, clanId, minLevel, maxLevel, rarityText, abilityText, abilityUnlockLevel, timeSinceRelease, cardLevels); if (card == null) { continue; // TODO: Remove this line if day/night is implemented, or after 11/2018, whatever happens first } managers.DatabaseManager.StoreCardBase(card); managers.InMemoryManager.LoadToMemoryCardBase(card); managers.ImageDownloader.AddCardBaseToDownloadQueue(card, CharacterImageFormat.Color800x640); } managers.ServerQueriesManager.SetUserLocale(userLocale); worker.ReportProgress(100); }
/// <summary> /// /// </summary> /// <param name="id">Must be a valid ID</param> /// <exception cref="ArgumentException"></exception> /// <returns></returns> public CardBase GetCardBase(int id) { if (id <= 0) { throw new ArgumentOutOfRangeException(nameof(id), id, "Must be greater than 0"); } var setEnglishLocaleCall = new ApiCallList.Players.SetLanguages(new List <string>() { EnglishLocale }); var getCardBaseInfoCall = new ApiCallList.Characters.GetCharacters(); getCardBaseInfoCall.charactersIDs = new List <int>() { id }; getCardBaseInfoCall.maxLevels = true; getCardBaseInfoCall.ItemsFilter = new List <string>() { "name", "clan_id", "level_min", "level_max", "rarity", "ability", "ability_unlock_level", "release_date" }; var getCardLevelsCall = new ApiCallList.Characters.GetCharacterLevels(id); getCardLevelsCall.levelMax = -1; // Get all the levels getCardLevelsCall.ItemsFilter = new List <string>() { "level", "power", "damage" }; var request = new ApiRequest(); request.EnqueueApiCall(setEnglishLocaleCall); request.EnqueueApiCall(getCardBaseInfoCall); request.EnqueueApiCall(getCardLevelsCall); string response; HttpStatusCode statusCode = ApiManagerInstance.SendRequest(request, out response); if (statusCode != HttpStatusCode.OK) { throw new Exception("GetCardBase SendRequest returned: " + statusCode.ToString()); } dynamic decoded = JsonDecoder.Decode(response); dynamic dynBaseCard; try { dynBaseCard = decoded[getCardBaseInfoCall.Call]["items"][0]; } catch { // TODO: Log attempt to download invalid ID throw new ArgumentException("The id doesn't exist", nameof(id)); } string name = dynBaseCard["name"].ToString(); int clan_id = int.Parse(dynBaseCard["clan_id"].ToString()); int level_min = int.Parse(dynBaseCard["level_min"].ToString()); int level_max = int.Parse(dynBaseCard["level_max"].ToString()); string rarity = dynBaseCard["rarity"].ToString(); string ability = dynBaseCard["ability"].ToString(); int ability_unlock_level = int.Parse(dynBaseCard["ability_unlock_level"].ToString()); int release_date = int.Parse(dynBaseCard["release_date"].ToString()); var levels = new List <CardLevel>(); foreach (dynamic item in decoded[getCardLevelsCall.Call]["items"]) { int level = int.Parse(item["level"].ToString()); int power = int.Parse(item["power"].ToString()); int damage = int.Parse(item["damage"].ToString()); levels.Add(new CardLevel(level, power, damage)); } return(ApiToCardBaseAdapter.ToCardBase(id, name, clan_id, level_min, level_max, rarity, ability, ability_unlock_level, release_date, levels)); }