diff --git a/WotBlitzStatisticsPro.Common/Model/AccountsSearchResponseItem.cs b/WotBlitzStatisticsPro.Common/Model/AccountsSearchResponseItem.cs index 494855a..42996d0 100644 --- a/WotBlitzStatisticsPro.Common/Model/AccountsSearchResponseItem.cs +++ b/WotBlitzStatisticsPro.Common/Model/AccountsSearchResponseItem.cs @@ -1,4 +1,6 @@ -namespace WotBlitzStatisticsPro.Common.Model +using System; + +namespace WotBlitzStatisticsPro.Common.Model { /// /// Account search result item @@ -14,5 +16,26 @@ /// Player nick /// public string? Nickname { get; set; } + + /// + /// Clan tag. Null if player doesn't have clan membership + /// + public string? ClanTag { get; set; } + + /// + /// Win rate from 0 to 100 + /// + public int WinRate { get; set; } + + /// + /// Player's battles count + /// + public long BattlesCount { get; set; } + + /// + /// Last battle time + /// + public DateTime LastBattle { get; set; } = new DateTime(1970, 1, 1); + } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/Mappers/AccountSearchResponseProfile.cs b/WotBlitzStatisticsPro.Logic/Mappers/AccountSearchResponseProfile.cs index 5156a73..35f0d7a 100644 --- a/WotBlitzStatisticsPro.Logic/Mappers/AccountSearchResponseProfile.cs +++ b/WotBlitzStatisticsPro.Logic/Mappers/AccountSearchResponseProfile.cs @@ -1,6 +1,7 @@ using AutoMapper; using WotBlitzStatisticsPro.Common.Model; using WotBlitzStatisticsPro.WgApiClient.Model; +using WotBlitzStatisticsPro.Logic.Calculations; namespace WotBlitzStatisticsPro.Logic.Mappers { @@ -12,6 +13,15 @@ namespace WotBlitzStatisticsPro.Logic.Mappers .ForMember( d => d.AccountId, o => o.MapFrom(s => s.AccountId ?? -1)); + + CreateMap() + .ForMember(dest => dest.LastBattle, + o => o.MapFrom(s => s.LastBattleTime.ToDateTime())) + .ForMember(dest => dest.BattlesCount, + o => o.MapFrom(s => s.Statistics!.All!.Battles)) + .ForMember(dest => dest.WinRate, + o => o.MapFrom(s => s.Statistics!.All!.Battles == 0 ? 0 : 100 * s.Statistics!.All!.Wins / s.Statistics!.All!.Battles)) + ; } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/WargamingSearch.cs b/WotBlitzStatisticsPro.Logic/WargamingSearch.cs index d01c8bf..5a02c7a 100644 --- a/WotBlitzStatisticsPro.Logic/WargamingSearch.cs +++ b/WotBlitzStatisticsPro.Logic/WargamingSearch.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using AutoMapper; using WotBlitzStatisticsPro.Common.Model; @@ -23,18 +24,63 @@ namespace WotBlitzStatisticsPro.Logic RealmType realmType, RequestLanguage language) { - var response = await _wargamingApiClient.FindAccounts(accountNick, realmType, language); + var searchResponse = await _wargamingApiClient.FindAccounts(accountNick, realmType, language); - if (response == null) + if (searchResponse == null) { return new AccountsSearchResponse(); } - return new AccountsSearchResponse + var response = new AccountsSearchResponse { - AccountsCount = response.Count, - Accounts = _mapper.Map, List>(response) + AccountsCount = searchResponse.Count, + Accounts = _mapper.Map, List>(searchResponse) }; + + if (searchResponse.Count > 100) + { + return response; + } + + var accountIds = response.Accounts.Select(a => a.AccountId).ToArray(); + + var shortAccountInfos = + await _wargamingApiClient.GetShortPlayerAccountsInfo(accountIds, realmType, language); + + var accountClans = await _wargamingApiClient.GetBulkPlayerClans(accountIds, realmType, language); + List? clans = null; + if (accountClans != null) + { + clans = await _wargamingApiClient.GetShortClansInfo(accountClans.Where(c => c.ClanId.HasValue).Select(c => c.ClanId!.Value).ToArray(), + realmType, language); + } + + for (int i = 0; i < response.Accounts.Count; i++) + { + var accountResponse = response.Accounts.ToArray()[i]; + var shortAccountInfo = shortAccountInfos?.FirstOrDefault(a => a.AccountId == accountResponse.AccountId); + if (shortAccountInfo != null) + { + _mapper.Map(shortAccountInfo, accountResponse); + } + + // Clan + if (accountClans != null && clans != null) + { + var aClan = accountClans.FirstOrDefault(c => c.AccountId == accountResponse.AccountId); + var clan = clans.FirstOrDefault(c => c.ClanId == aClan?.ClanId); + if (clan != null) + { + accountResponse.ClanTag = clan.Tag; + } + } + } + + // Filter WOT Blitz accounts + response.Accounts = response.Accounts.Where(a => a.BattlesCount > 0).ToList(); + response.AccountsCount = response.Accounts.Count; + + return response; } public async Task FindClans( diff --git a/WotBlitzStatisticsPro.WgApiClient/IWargamingApiClient.cs b/WotBlitzStatisticsPro.WgApiClient/IWargamingApiClient.cs index 969489c..0e8d7b0 100644 --- a/WotBlitzStatisticsPro.WgApiClient/IWargamingApiClient.cs +++ b/WotBlitzStatisticsPro.WgApiClient/IWargamingApiClient.cs @@ -15,15 +15,28 @@ namespace WotBlitzStatisticsPro.WgApiClient RealmType realmType = RealmType.Ru, RequestLanguage language = RequestLanguage.En); + Task?> GetShortPlayerAccountsInfo(long[] accountIds, + RealmType realmType = RealmType.Ru, + RequestLanguage language = RequestLanguage.En, + string? authenticationToken = null); + Task GetPlayerAccountInfo(long accountId, RealmType realmType = RealmType.Ru, RequestLanguage language = RequestLanguage.En, string? authenticationToken = null); + Task?> GetBulkPlayerClans(long[] accountIds, + RealmType realmType = RealmType.Ru, + RequestLanguage language = RequestLanguage.En); + Task GetPlayerClanInfo(long accountId, RealmType realmType = RealmType.Ru, RequestLanguage language = RequestLanguage.En); + Task?> GetShortClansInfo(long[] clanIds, + RealmType realmType = RealmType.Ru, + RequestLanguage language = RequestLanguage.En); + Task GetClanInfo(long clanId, RealmType realmType = RealmType.Ru, RequestLanguage language = RequestLanguage.En); diff --git a/WotBlitzStatisticsPro.WgApiClient/WargamingApiClient.cs b/WotBlitzStatisticsPro.WgApiClient/WargamingApiClient.cs index a51b1a2..b389fb7 100644 --- a/WotBlitzStatisticsPro.WgApiClient/WargamingApiClient.cs +++ b/WotBlitzStatisticsPro.WgApiClient/WargamingApiClient.cs @@ -115,7 +115,19 @@ namespace WotBlitzStatisticsPro.WgApiClient return account?[accountId.ToString()]; } - public async Task GetPlayerClanInfo(long accountId, + public async Task?> GetShortPlayerAccountsInfo(long[] accountIds, RealmType realmType = RealmType.Ru, + RequestLanguage language = RequestLanguage.En, string? authenticationToken = null) + { + var accounts = await GetFromBlitzApi>( + realmType, + language, + "account/info/", + $"account_id={string.Join(',', accountIds)}&fields=account_id,nickname,last_battle_time,statistics.all.battles,statistics.all.wins").ConfigureAwait(false); + + return accounts?.Values.ToList(); + } + + public async Task GetPlayerClanInfo(long accountId, RealmType realmType = RealmType.Ru, RequestLanguage language = RequestLanguage.En) { @@ -148,8 +160,27 @@ namespace WotBlitzStatisticsPro.WgApiClient return null; } - // https://api.wotblitz.ru/wotb/encyclopedia/achievements/?application_id=adc1387489cf9fc8d9a1d85dbd27763d + public async Task?> GetBulkPlayerClans(long[] accountIds, RealmType realmType = RealmType.Ru, + RequestLanguage language = RequestLanguage.En) + { + var clanInfo = await GetFromBlitzApi>( + realmType, + language, + "clans/accountinfo/", + $"account_id={string.Join(',', accountIds)}&fields=account_id,clan_id,account_name").ConfigureAwait(false); + return clanInfo?.Values.Where(c => c != null).ToList(); + } + public async Task?> GetShortClansInfo(long[] clanIds, RealmType realmType = RealmType.Ru, + RequestLanguage language = RequestLanguage.En) + { + var clanInfo = await GetFromBlitzApi>( + realmType, + language, + "clans/info/", + $"clan_id={string.Join(',', clanIds)}&fields=clan_id,tag").ConfigureAwait(false); + return clanInfo?.Values.ToList(); + } #region Tanks methods