diff --git a/WotBlitzStatisticsPro.Common/Model/AccountInfoResponse.cs b/WotBlitzStatisticsPro.Common/Model/AccountInfoResponse.cs new file mode 100644 index 0000000..0fb7b63 --- /dev/null +++ b/WotBlitzStatisticsPro.Common/Model/AccountInfoResponse.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; + +namespace WotBlitzStatisticsPro.Common.Model +{ + /// + /// Information about player + /// + public class AccountInfoResponse + { + /// + /// Player account identifier + /// + public long AccountId { get; set; } + + /// + /// Account creation date + /// + public DateTime CreatedAt { get; set; } + + /// + /// Last battle time + /// + public DateTime LastBattleTime { get; set; } + + /// + /// Player's nick + /// + public string Nickname { get; set; } + + /// + /// Battles count + /// + public long Battles { get; set; } + + /// + /// Capture points + /// + public long CapturePoints { get; set; } + + /// + /// Total damage amount + /// + public long DamageDealt { get; set; } + + /// + /// Total amount of received damage + /// + public long DamageReceived { get; set; } + + /// + /// Dropped capture points + /// + public long DroppedCapturePoints { get; set; } + + /// + /// Total amount of frags + /// + public long Frags { get; set; } + + /// + /// Total amount of fras grater ten 8 lvl + /// + public long Frags8P { get; set; } + + /// + /// Total amount of hits + /// + public long Hits { get; set; } + + /// + /// Total amount of losses + /// + public long Losses { get; set; } + + /// + /// Max frags per battle + /// + public long MaxFrags { get; set; } + + /// + /// Tank id, which kills max frags per battle + /// + public long MaxFragsTankId { get; set; } + + /// + /// Max experience per battle + /// + public long MaxXp { get; set; } + + /// + /// Tank Id which created max experience per battle + /// + public long MaxXpTankId { get; set; } + + /// + /// Total shots count + /// + public long Shots { get; set; } + + /// + /// Total count of spotted vehicles + /// + public long Spotted { get; set; } + + /// + /// Total count of survived battles + /// + public long SurvivedBattles { get; set; } + + /// + /// Total count of survived and winned battles + /// + public long WinAndSurvived { get; set; } + + /// + /// Total wins count + /// + public long Wins { get; set; } + + /// + /// Total amount of experience + /// + public long Xp { get; set; } + + /// + /// Average tier + /// + public double AvgTier { get; set; } + + /// + /// Wn7 coefficient + /// + public double Wn7 { get; set; } + + /// + /// Player's win rate + /// + public decimal WinRate => Battles == 0 ? 0m : (decimal) 100 * Wins / Battles; + + /// + /// Player's average damage + /// + public decimal AvgDamage => Battles == 0 ? 0m : (decimal)DamageDealt / Battles; + + /// + /// Player's average XP + /// + public decimal AvgXp => Battles == 0 ? 0m : (decimal)Xp / Battles; + + /// + /// All player's tanks + /// + public List Tanks { get; set; } + + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Common/Model/TankInfoResponse.cs b/WotBlitzStatisticsPro.Common/Model/TankInfoResponse.cs new file mode 100644 index 0000000..c3ba097 --- /dev/null +++ b/WotBlitzStatisticsPro.Common/Model/TankInfoResponse.cs @@ -0,0 +1,186 @@ +using System; + +namespace WotBlitzStatisticsPro.Common.Model +{ + /// + /// Information about player's tank + /// + public class TankInfoResponse + { + /// + /// Player account identifier + /// + public long AccountId { get; set; } + + /// + /// Tank identifier + /// + public long TankId { get; set; } + + /// + /// Total time in battle until tank killed + /// + public int BattleLifeTimeInSeconds { get; set; } + + /// + /// Last battle + /// + public DateTime LastBattleTime { get; set; } + + /// + /// Information is tank in garage or not. Information is not provided without Auth token + /// + public bool? InGarage { get; set; } + + /// + /// Mark of Mastery + /// + public MarkOfMastery MarkOfMastery { get; set; } + + /// + /// Battles count + /// + public long Battles { get; set; } = 1; + + /// + /// Base capture points + /// + public long CapturePoints { get; set; } + + /// + /// Damage dealt + /// + public long DamageDealt { get; set; } + + /// + /// Damage received + /// + public long DamageReceived { get; set; } + + /// + /// Base dropped capture points + /// + public long DroppedCapturePoints { get; set; } + + /// + /// Frags count + /// + public long Frags { get; set; } + + /// + /// Frags count after 8 tier + /// + public long Frags8P { get; set; } + + /// + /// Hits count + /// + public long Hits { get; set; } + + /// + /// Losses count + /// + public long Losses { get; set; } + + /// + /// Max frags per battle + /// + public long MaxFrags { get; set; } + + /// + /// Max XP per battle + /// + public long MaxXp { get; set; } + + /// + /// Shots count + /// + public long Shots { get; set; } + + /// + /// Spotted vehicles count + /// + public long Spotted { get; set; } + + /// + /// Amount of survived battles + /// + public long SurvivedBattles { get; set; } + + /// + /// Amount of survived and wined battles + /// + public long WinAndSurvived { get; set; } + + /// + /// Wins count + /// + public long Wins { get; set; } + + /// + /// Total experience + /// + public long Xp { get; set; } + + /// + /// Wn7 coefficient + /// + public double Wn7 { get; set; } + + /// + /// Average life time in battle until tank is killed. + /// + public decimal AvgBattleLifeTimeInMinutes => (decimal) BattleLifeTimeInSeconds / (60 * Battles); + + /// + /// Tank's win rate + /// + public decimal WinRate => (decimal) 100 * Wins / Battles; + + /// + /// Average tank's damage + /// + public decimal AvgDamage => (decimal) DamageDealt / Battles; + + /// + /// Average XP + /// + public decimal AvgXp => (decimal) Xp / Battles; + + /// + /// Tank name + /// + public string Name { get; set; } + + /// + /// Tank nation dictionary identifier + /// + public string TankNationId { get; set; } + + /// + /// Localized tank nation name + /// + public string TankNation { get; set; } + + /// + /// Tank tier + /// + public int Tier { get; set; } + + /// + /// Tank type dictionary identifier + /// + public string TankTypeId { get; set; } + + /// + /// Localized tank type name + /// + public string TankType { get; set; } + + /// + /// Is it premium tank or not + /// + public bool IsPremium { get; set; } + + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.DataAccess/DictionariesDataAccessor.cs b/WotBlitzStatisticsPro.DataAccess/DictionariesDataAccessor.cs index a391a5b..3635dc9 100644 --- a/WotBlitzStatisticsPro.DataAccess/DictionariesDataAccessor.cs +++ b/WotBlitzStatisticsPro.DataAccess/DictionariesDataAccessor.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using MongoDB.Driver; using WotBlitzStatisticsPro.Common; using WotBlitzStatisticsPro.Common.Dictionaries; +using WotBlitzStatisticsPro.Common.Model; using WotBlitzStatisticsPro.DataAccess.Model; namespace WotBlitzStatisticsPro.DataAccess @@ -101,5 +102,42 @@ namespace WotBlitzStatisticsPro.DataAccess return collection.ToDictionary(k => k.TankId, v => v.Tier); } + + public async Task> GetVehicles(long[] tankIds) + { + var collection = await _database.GetCollection(VehiclesCollectionName) + .Find(Builders.Filter.In(v => v.TankId, tankIds)) + .ToListAsync(); + + return collection.ToDictionary(k => k.TankId, v => v as IVehiclesDictionary); + } + + public async Task> GetNations(RequestLanguage language) + { + var collection = await _database.GetCollection(NationsCollectionName) + .Find(Builders.Filter.Empty) + .Project(n => new + { + nationId = n.NationId, + nationValue = n.NationNames.First(v => v.Language == language).Value + }) + .ToListAsync(); + + return collection.ToDictionary(n => n.nationId, n => n.nationValue); + } + + public async Task> GetTankTypes(RequestLanguage language) + { + var collection = await _database.GetCollection(VehicleTypesCollectionName) + .Find(Builders.Filter.Empty) + .Project(n => new + { + typeId = n.VehicleTypeId, + typeValue = n.VehicleTypeNames.First(v => v.Language == language).Value + }) + .ToListAsync(); + + return collection.ToDictionary(n => n.typeId, n => n.typeValue); + } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.DataAccess/IDictionariesDataAccessor.cs b/WotBlitzStatisticsPro.DataAccess/IDictionariesDataAccessor.cs index 637373d..f757ccc 100644 --- a/WotBlitzStatisticsPro.DataAccess/IDictionariesDataAccessor.cs +++ b/WotBlitzStatisticsPro.DataAccess/IDictionariesDataAccessor.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using WotBlitzStatisticsPro.Common.Dictionaries; +using WotBlitzStatisticsPro.Common.Model; namespace WotBlitzStatisticsPro.DataAccess { @@ -23,5 +24,11 @@ namespace WotBlitzStatisticsPro.DataAccess Task> ReadLanguages(); Task> GetTankTires(long[] tankIds); + + Task> GetVehicles(long[] tankIds); + + Task> GetNations(RequestLanguage language); + + Task> GetTankTypes(RequestLanguage language); } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.DataAccess/Model/Accounts/TankInfoHistory.cs b/WotBlitzStatisticsPro.DataAccess/Model/Accounts/TankInfoHistory.cs index 91f4791..d9db7d6 100644 --- a/WotBlitzStatisticsPro.DataAccess/Model/Accounts/TankInfoHistory.cs +++ b/WotBlitzStatisticsPro.DataAccess/Model/Accounts/TankInfoHistory.cs @@ -19,91 +19,90 @@ - /// /// Battles count /// - public long? Battles { get; set; } + public long Battles { get; set; } /// /// Base capture points /// - public long? CapturePoints { get; set; } + public long CapturePoints { get; set; } /// /// Damage dealt /// - public long? DamageDealt { get; set; } + public long DamageDealt { get; set; } /// /// Damage received /// - public long? DamageReceived { get; set; } + public long DamageReceived { get; set; } /// /// Base dropped capture points /// - public long? DroppedCapturePoints { get; set; } + public long DroppedCapturePoints { get; set; } /// /// Frags count /// - public long? Frags { get; set; } + public long Frags { get; set; } /// /// Frags count after 8 tier /// - public long? Frags8P { get; set; } + public long Frags8P { get; set; } /// /// Hits count /// - public long? Hits { get; set; } + public long Hits { get; set; } /// /// Losses count /// - public long? Losses { get; set; } + public long Losses { get; set; } /// /// Max frags per battle /// - public long? MaxFrags { get; set; } + public long MaxFrags { get; set; } /// /// Max XP per battle /// - public long? MaxXp { get; set; } + public long MaxXp { get; set; } /// /// Shots count /// - public long? Shots { get; set; } + public long Shots { get; set; } /// /// Spotted vehicles count /// - public long? Spotted { get; set; } + public long Spotted { get; set; } /// /// Amount of survived battles /// - public long? SurvivedBattles { get; set; } + public long SurvivedBattles { get; set; } /// /// Amount of survived and wined battles /// - public long? WinAndSurvived { get; set; } + public long WinAndSurvived { get; set; } /// /// Wins count /// - public long? Wins { get; set; } + public long Wins { get; set; } /// /// Total experience /// - public long? Xp { get; set; } + public long Xp { get; set; } /// /// Wn7 coefficient diff --git a/WotBlitzStatisticsPro.GraphQl/Mutation/WotBlitzStatisticsMutation.cs b/WotBlitzStatisticsPro.GraphQl/Mutation/WotBlitzStatisticsMutation.cs index 5d0f19e..1d46a42 100644 --- a/WotBlitzStatisticsPro.GraphQl/Mutation/WotBlitzStatisticsMutation.cs +++ b/WotBlitzStatisticsPro.GraphQl/Mutation/WotBlitzStatisticsMutation.cs @@ -37,7 +37,7 @@ namespace WotBlitzStatisticsPro.GraphQl.Mutation /// AccountId /// Request language /// - public Task GatherAccountInformation(RealmType realmType, long accountId, RequestLanguage requestLanguage) + public Task GatherAccountInformation(RealmType realmType, long accountId, RequestLanguage requestLanguage) { return _wargamingAccounts.GatherAccountInformation(realmType, accountId, requestLanguage); } diff --git a/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/AccountInformationPipelineContext.cs b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/AccountInformationPipelineContext.cs index afa27e5..dc16274 100644 --- a/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/AccountInformationPipelineContext.cs +++ b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/AccountInformationPipelineContext.cs @@ -29,5 +29,7 @@ namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline public Dictionary TanksHistory { get; set; } + public AccountInfoResponse Response { get; set; } + } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/BuildAccountInfoResponseOperation.cs b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/BuildAccountInfoResponseOperation.cs new file mode 100644 index 0000000..5f1992d --- /dev/null +++ b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/BuildAccountInfoResponseOperation.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using AutoMapper; +using WotBlitzStatisticsPro.Common.Dictionaries; +using WotBlitzStatisticsPro.Common.Model; +using WotBlitzStatisticsPro.DataAccess; +using WotBlitzStatisticsPro.DataAccess.Model; +using WotBlitzStatisticsPro.DataAccess.Model.Accounts; +using WotBlitzStatisticsPro.Logic.Pipeline; + +namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations +{ + public class BuildAccountInfoResponseOperation : IOperation + { + private readonly IMapper _mapper; + private readonly IDictionariesDataAccessor _dictionariesDataAccessor; + + public BuildAccountInfoResponseOperation(IMapper mapper, IDictionariesDataAccessor dictionariesDataAccessor) + { + _mapper = mapper; + _dictionariesDataAccessor = dictionariesDataAccessor; + } + + public async Task Invoke(AccountInformationPipelineContext context, Func next) + { + context.Response = _mapper.Map(context.AccountInfo); + context.Response = _mapper.Map(context.AccountInfoHistory, context.Response); + + var tankIds = context.Tanks.Select(t => t.TankId).ToArray(); + var vehicles = await _dictionariesDataAccessor.GetVehicles(tankIds); + + var nations = await _dictionariesDataAccessor.GetNations(context.RequestLanguage); + var tankTypes = await _dictionariesDataAccessor.GetTankTypes(context.RequestLanguage); + + context.Response.Tanks = _mapper.Map, List>(context.Tanks); + context.Response.Tanks.ForEach(t => + { + t = _mapper.Map(context.TanksHistory[t.TankId], t); + var vehicle = vehicles.ContainsKey(t.TankId) ? vehicles[t.TankId] : CreateStubVehicle(); + t = _mapper.Map(vehicle, t, + opt => + { + opt.Items["language"] = context.RequestLanguage; + opt.AfterMap((src, dest) => + { + dest.TankType = tankTypes.ContainsKey(dest.TankTypeId) ? tankTypes[dest.TankTypeId] : "-"; + dest.TankNation = nations.ContainsKey(dest.TankNationId) ? nations[dest.TankNationId] : "-"; + }); + }); + }); + + await next.Invoke(context); + } + + private static IVehiclesDictionary CreateStubVehicle() + { + return new VehiclesDictionary + { + Name = new List() + { + new LocalizableString + {Language = RequestLanguage.En, Value = "[Vehicle is not provided in the dictionary]"}, + new LocalizableString {Language = RequestLanguage.Ru, Value = "[Танк отсутствует в танкопедии]"}, + new LocalizableString + {Language = RequestLanguage.De, Value = "[Tank ist nicht im Wörterbuch enthalten]"}, + } + }; + } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/Calculations/DateTimeHelper.cs b/WotBlitzStatisticsPro.Logic/Calculations/DateTimeHelper.cs new file mode 100644 index 0000000..8ff23c8 --- /dev/null +++ b/WotBlitzStatisticsPro.Logic/Calculations/DateTimeHelper.cs @@ -0,0 +1,17 @@ +using System; + +namespace WotBlitzStatisticsPro.Logic.Calculations +{ + public static class DateTimeHelper + { + public static DateTime ToDateTime(this int unixTimeStamp) + { + // Unix timestamp is seconds past epoch + var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime(); + return dtDateTime; + } + + + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/Calculations/TierHelper.cs b/WotBlitzStatisticsPro.Logic/Calculations/TierHelper.cs index d9763d1..6e169f4 100644 --- a/WotBlitzStatisticsPro.Logic/Calculations/TierHelper.cs +++ b/WotBlitzStatisticsPro.Logic/Calculations/TierHelper.cs @@ -14,9 +14,9 @@ namespace WotBlitzStatisticsPro.Logic.Calculations } foreach (var tank in allTanks) { - if (tankTires.ContainsKey(tank.TankId) && tank.Battles.HasValue && tank.Battles > 0) + if (tankTires.ContainsKey(tank.TankId) && tank.Battles > 0) { - x += tankTires[tank.TankId] * tank.Battles.Value; + x += tankTires[tank.TankId] * tank.Battles; } } if (account.Battles > 0) diff --git a/WotBlitzStatisticsPro.Logic/Calculations/Wn7Helper.cs b/WotBlitzStatisticsPro.Logic/Calculations/Wn7Helper.cs index 7b0e769..7a69aa2 100644 --- a/WotBlitzStatisticsPro.Logic/Calculations/Wn7Helper.cs +++ b/WotBlitzStatisticsPro.Logic/Calculations/Wn7Helper.cs @@ -26,17 +26,13 @@ namespace WotBlitzStatisticsPro.Logic.Calculations public static void CalculateWn7(this TankInfoHistory tank, double tier) { - if (!tank.Battles.HasValue) - { - return; - } - double avdFrags = tank.Frags.DoubleValue() / tank.Battles.DoubleValue(); - double avgDamage = tank.DamageDealt.DoubleValue() / tank.Battles.DoubleValue(); - double avgSpot = tank.Spotted.DoubleValue() / tank.Battles.DoubleValue(); - double avgDef = tank.DroppedCapturePoints.DoubleValue() / tank.Battles.DoubleValue(); - double winRate = (100d * tank.Wins.DoubleValue() / tank.Battles.DoubleValue()); // - 48; + double avdFrags = (double) tank.Frags / tank.Battles; + double avgDamage = (double)tank.DamageDealt / tank.Battles; + double avgSpot = (double)tank.Spotted / tank.Battles; + double avgDef = (double)tank.DroppedCapturePoints / tank.Battles; + double winRate = (100d * (double) tank.Wins / tank.Battles); // - 48; - tank.Wn7 = CalculateWn7(tank.Battles.Value, tier, avdFrags, avgDamage, avgSpot, avgDef, winRate); + tank.Wn7 = CalculateWn7(tank.Battles, tier, avdFrags, avgDamage, avgSpot, avgDef, winRate); } public static void CalculateWn7(this AccountInfoHistory account) diff --git a/WotBlitzStatisticsPro.Logic/IWargamingAccounts.cs b/WotBlitzStatisticsPro.Logic/IWargamingAccounts.cs index 8c80730..c49fe58 100644 --- a/WotBlitzStatisticsPro.Logic/IWargamingAccounts.cs +++ b/WotBlitzStatisticsPro.Logic/IWargamingAccounts.cs @@ -5,6 +5,6 @@ namespace WotBlitzStatisticsPro.Logic { public interface IWargamingAccounts { - Task GatherAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage); + Task GatherAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage); } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/Mappers/AccountDtoProfile.cs b/WotBlitzStatisticsPro.Logic/Mappers/AccountDtoProfile.cs new file mode 100644 index 0000000..277e7b4 --- /dev/null +++ b/WotBlitzStatisticsPro.Logic/Mappers/AccountDtoProfile.cs @@ -0,0 +1,46 @@ +using System.Linq; +using AutoMapper; +using WotBlitzStatisticsPro.Common.Dictionaries; +using WotBlitzStatisticsPro.Common.Model; +using WotBlitzStatisticsPro.DataAccess.Model; +using WotBlitzStatisticsPro.DataAccess.Model.Accounts; +using WotBlitzStatisticsPro.Logic.Calculations; + +namespace WotBlitzStatisticsPro.Logic.Mappers +{ + public class AccountDtoProfile: Profile + { + public AccountDtoProfile() + { + CreateMap() + .ForMember(dest => dest.CreatedAt, + o => o.MapFrom(s => s.CreatedAt.ToDateTime())) + .ForMember(dest => dest.LastBattleTime, + o => o.MapFrom(s => s.LastBattleTime.ToDateTime())); + + CreateMap() + .ForMember(d => d.LastBattleTime, o => o.Ignore()) + .ForMember(d => d.Battles, + o => o.MapFrom(s => s.Battles ?? 0)); + + CreateMap() + .ForMember(dest => dest.LastBattleTime, + o => o.MapFrom(s => s.LastBattleTime.ToDateTime())); + + CreateMap() + .ForMember(d => d.LastBattleTime, + o => o.Ignore()); + + CreateMap() + .ForMember(d => d.TankId, o => o.Ignore()) + .ForMember(d => d.TankNationId, + o => o.MapFrom(s => string.IsNullOrEmpty(s.NationId) ? "-" : s.NationId)) + .ForMember(d => d.TankTypeId, + o => o.MapFrom(s => string.IsNullOrEmpty(s.TypeId) ? "-" : s.TypeId)) + .ForMember(d => d.Name, + o => o.MapFrom((src, dest, destMember, context) => + src.Name.FirstOrDefault(l => l.Language == (RequestLanguage) context.Items["language"])?.Value)); + + } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/WargamingAccounts.cs b/WotBlitzStatisticsPro.Logic/WargamingAccounts.cs index 0f9baa8..c4332be 100644 --- a/WotBlitzStatisticsPro.Logic/WargamingAccounts.cs +++ b/WotBlitzStatisticsPro.Logic/WargamingAccounts.cs @@ -15,7 +15,7 @@ namespace WotBlitzStatisticsPro.Logic _operationFactory = operationFactory; } - public async Task GatherAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage) + public async Task GatherAccountInformation(RealmType realm, long accountId, RequestLanguage requestLanguage) { var context = new AccountInformationPipelineContext(accountId, realm, requestLanguage); var pipeline = new Pipeline(_operationFactory); @@ -23,6 +23,7 @@ namespace WotBlitzStatisticsPro.Logic pipeline.AddOperation() .AddOperation() .AddOperation() + .AddOperation() ; // ToDo: add other operations @@ -32,7 +33,7 @@ namespace WotBlitzStatisticsPro.Logic // ToDo: return context response - return true; + return context.Response; } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs b/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs index 6a4efde..fc149a1 100644 --- a/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs +++ b/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs @@ -62,6 +62,7 @@ namespace WotBlitzStatisticsPro.Logic services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(serviceProvider => new ServiceProviderOperationFactory(serviceProvider)); diff --git a/WotBlitzStatisticsPro.WgApiClient/WargamingApiClient.cs b/WotBlitzStatisticsPro.WgApiClient/WargamingApiClient.cs index 04470ad..12bd80d 100644 --- a/WotBlitzStatisticsPro.WgApiClient/WargamingApiClient.cs +++ b/WotBlitzStatisticsPro.WgApiClient/WargamingApiClient.cs @@ -154,7 +154,7 @@ namespace WotBlitzStatisticsPro.WgApiClient language, "tanks/stats/", $"account_id={accountId}").ConfigureAwait(false); - return tanks[accountId.ToString()]; + return tanks[accountId.ToString()] ?? new List(); } #endregion