From eef4e9255b7bf3dfb2e6e7257e648d8181424ba0 Mon Sep 17 00:00:00 2001 From: Mikhail Shabanov Date: Tue, 5 Jan 2021 13:04:13 +0100 Subject: [PATCH] Tank info history query --- .../Model/TankInfoHistoryResponse.cs | 92 +++++++++++++++++++ .../Model/Accounts/TankInfoHistory.cs | 48 ++++++---- .../WargamingAccountDataAccessor.cs | 2 +- .../Query/WotBlitzStatisticsQuery.cs | 25 ++++- .../IDatabaseTankPipelineContextData.cs | 11 +++ .../FillTankHistoryResponseOperation.cs | 61 ++++++++++++ .../ReadTankHistoryFromDbOperation.cs | 29 ++++++ .../Operations/ReadTankInfoFromDBOperation.cs | 26 ++++++ .../TankHistoryInformationContextData.cs | 29 ++++++ .../Calculations/TierHelper.cs | 2 +- .../Calculations/Wn7Helper.cs | 17 ++-- .../IWargamingAccounts.cs | 3 + .../WargamingAccounts.cs | 36 ++++++++ .../WotBlitzStatisticsLogicInstaller.cs | 3 + 14 files changed, 352 insertions(+), 32 deletions(-) create mode 100644 WotBlitzStatisticsPro.Common/Model/TankInfoHistoryResponse.cs create mode 100644 WotBlitzStatisticsPro.Logic/AccountInformationPipeline/IDatabaseTankPipelineContextData.cs create mode 100644 WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/FillTankHistoryResponseOperation.cs create mode 100644 WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/ReadTankHistoryFromDbOperation.cs create mode 100644 WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/ReadTankInfoFromDBOperation.cs create mode 100644 WotBlitzStatisticsPro.Logic/AccountInformationPipeline/TankHistoryInformationContextData.cs diff --git a/WotBlitzStatisticsPro.Common/Model/TankInfoHistoryResponse.cs b/WotBlitzStatisticsPro.Common/Model/TankInfoHistoryResponse.cs new file mode 100644 index 0000000..d505dfc --- /dev/null +++ b/WotBlitzStatisticsPro.Common/Model/TankInfoHistoryResponse.cs @@ -0,0 +1,92 @@ +using System; + +namespace WotBlitzStatisticsPro.Common.Model +{ + /// + /// Information about tank statistics history + /// + public class TankInfoHistoryResponse + { + /// + /// 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; } = new DateTime(1970, 1, 1); + + /// + /// Mark of Mastery + /// + public MarkOfMastery MarkOfMastery { get; set; } + + + /// + /// Tank name + /// + public string? Name { get; set; } + + /// + /// Is vehicle premium + /// + public bool IsPremium { get; set; } + + /// + /// Vehicle type id + /// + public string? Type { get; set; } + + /// + /// Vehicle nationId + /// + public string? Nation{ get; set; } + + /// + /// Vehicle tier + /// + public int Tier { get; set; } + + /// + /// Vehicle preview image + /// + public string? PreviewImage { get; set; } + + /// + /// Vehicle normal image + /// + public string? NormalImage { get; set; } + + + /// + /// Overall statistics since tank was bought + /// + public ShortStatistics? OverallTankStatistics { get; set; } + + /// + /// Statistics for period + /// + public ShortStatistics? TankPeriodStatistics { get; set; } + + /// + /// Difference between start and end of the period + /// + public StatisticsDifference? PeriodDifference { get; set; } + + /// + /// The detailed history + /// + public StatisticsDifference[]? StatisticsHistory { get; set; } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.DataAccess/Model/Accounts/TankInfoHistory.cs b/WotBlitzStatisticsPro.DataAccess/Model/Accounts/TankInfoHistory.cs index dd32160..3e0a715 100644 --- a/WotBlitzStatisticsPro.DataAccess/Model/Accounts/TankInfoHistory.cs +++ b/WotBlitzStatisticsPro.DataAccess/Model/Accounts/TankInfoHistory.cs @@ -1,9 +1,10 @@ using MongoDB.Bson.Serialization.Attributes; +using WotBlitzStatisticsPro.Common.Model; namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts { - public class TankInfoHistory - { + public class TankInfoHistory: IStatistics + { public TankInfoHistory() { @@ -41,91 +42,100 @@ namespace WotBlitzStatisticsPro.DataAccess.Model.Accounts /// /// 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 /// public double Wn7 { get; set; } + + #region redudant fields + + public long? MaxFragsTankId { get; set; } + public long? MaxXpTankId { get; set; } + public double AvgTier { get; set; } + + #endregion + } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.DataAccess/WargamingAccountDataAccessor.cs b/WotBlitzStatisticsPro.DataAccess/WargamingAccountDataAccessor.cs index faf5695..28d40bf 100644 --- a/WotBlitzStatisticsPro.DataAccess/WargamingAccountDataAccessor.cs +++ b/WotBlitzStatisticsPro.DataAccess/WargamingAccountDataAccessor.cs @@ -125,7 +125,7 @@ namespace WotBlitzStatisticsPro.DataAccess var history = await _database.GetCollection(TankInfoHistoryCollectionName) .FindAsync( Builders.Filter.Where(t => - t.TankInfoHistoryId.AccountId == accountId && t.TankId == tankId && t.TankInfoHistoryId.LastBattleTime >= lastBattleSince), + t.TankInfoHistoryId.AccountId == accountId && t.TankInfoHistoryId.TankId == tankId && t.TankInfoHistoryId.LastBattleTime >= lastBattleSince), new FindOptions {Sort = Builders.Sort.Descending(h => h.TankInfoHistoryId.LastBattleTime)}); return history.ToList(); diff --git a/WotBlitzStatisticsPro.GraphQl/Query/WotBlitzStatisticsQuery.cs b/WotBlitzStatisticsPro.GraphQl/Query/WotBlitzStatisticsQuery.cs index 9679e42..76a9b2c 100644 --- a/WotBlitzStatisticsPro.GraphQl/Query/WotBlitzStatisticsQuery.cs +++ b/WotBlitzStatisticsPro.GraphQl/Query/WotBlitzStatisticsQuery.cs @@ -20,11 +20,6 @@ namespace WotBlitzStatisticsPro.GraphQl.Query _wargamingAccounts = wargamingAccounts; } - //public Task GetPlayerInfo(long accountId) - //{ - // return _wargamingSearcher.GetPlayerAccountInfo(accountId); - //} - /// /// Finds Wargaming accounts by nick /// @@ -87,5 +82,25 @@ namespace WotBlitzStatisticsPro.GraphQl.Query return _wargamingAccounts.GetAccountInfoHistory(realmType ?? RealmType.Ru, accountId, startDate, requestLanguage ?? RequestLanguage.En); } + + /// + /// Tank statistics history for period since "startDate" + /// + /// AccountId + /// TankId + /// Date from history started + /// Account region + /// Request language + /// + public Task TankInfoHistory( + long accountId, + long tankId, + DateTime startDate, + RealmType? realmType, + RequestLanguage? requestLanguage) + { + return _wargamingAccounts.GetTankInfoHistory(realmType ?? RealmType.Ru, accountId, tankId, startDate, + requestLanguage ?? RequestLanguage.En); + } } } diff --git a/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/IDatabaseTankPipelineContextData.cs b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/IDatabaseTankPipelineContextData.cs new file mode 100644 index 0000000..4b7d87d --- /dev/null +++ b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/IDatabaseTankPipelineContextData.cs @@ -0,0 +1,11 @@ +using WotBlitzStatisticsPro.DataAccess.Model.Accounts; + +namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline +{ + public interface IDatabaseTankPipelineContextData + { + long TankId { get; } + + TankInfo? DbTankInfo { get; set; } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/FillTankHistoryResponseOperation.cs b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/FillTankHistoryResponseOperation.cs new file mode 100644 index 0000000..2dd58e9 --- /dev/null +++ b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/FillTankHistoryResponseOperation.cs @@ -0,0 +1,61 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using WotBlitzStatisticsPro.Common.Model; +using WotBlitzStatisticsPro.DataAccess; +using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext; +using WotBlitzStatisticsPro.Logic.Calculations; +using WotBlitzStatisticsPro.Logic.Pipeline; + +namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations +{ + public class FillTankHistoryResponseOperation : IOperation + { + private readonly IDictionariesDataAccessor _wargamingDictionaries; + + public FillTankHistoryResponseOperation(IDictionariesDataAccessor wargamingDictionaries) + { + _wargamingDictionaries = wargamingDictionaries; + } + + public async Task Invoke(IOperationContext context, Func? next) + { + var contextData = context.Get(); + + if (contextData?.DbTankInfo == null) + { + if (next != null) await next.Invoke(context); + return; + } + + var nations = await _wargamingDictionaries.GetNations(context.Request.RequestLanguage); + var tankTypes = await _wargamingDictionaries.GetTankTypes(context.Request.RequestLanguage); + + var vehicleInfos = await _wargamingDictionaries.GetVehicles(new[] {contextData.TankId}); + var vehicleInfo = vehicleInfos[contextData.TankId]; + + contextData.Response = new TankInfoHistoryResponse + { + TankId = contextData.TankId, + LastBattleTime = contextData.DbTankInfo.LastBattleTime.ToDateTime(), + BattleLifeTimeInSeconds = contextData.DbTankInfo.BattleLifeTimeInSeconds, + MarkOfMastery = contextData.DbTankInfo.MarkOfMastery, + Name = vehicleInfo.Name.FirstOrDefault(n => n.Language == context.Request.RequestLanguage)?.Value, + IsPremium = vehicleInfo.IsPremium, + Tier = vehicleInfo.Tier, + NormalImage = vehicleInfo.NormalImage, + PreviewImage = vehicleInfo.PreviewImage, + Nation = nations[vehicleInfo.NationId], + Type = tankTypes[vehicleInfo.TypeId], + + AccountId = context.Request.AccountId, + PeriodDifference = contextData.PeriodDifference, + StatisticsHistory = contextData.StatisticsHistory, + TankPeriodStatistics = contextData.PeriodAccountStatistics, + OverallTankStatistics = contextData.OverallStatistics + }; + + if (next != null) await next.Invoke(context); + } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/ReadTankHistoryFromDbOperation.cs b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/ReadTankHistoryFromDbOperation.cs new file mode 100644 index 0000000..430e813 --- /dev/null +++ b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/ReadTankHistoryFromDbOperation.cs @@ -0,0 +1,29 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using WotBlitzStatisticsPro.DataAccess; +using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext; +using WotBlitzStatisticsPro.Logic.Calculations; +using WotBlitzStatisticsPro.Logic.Pipeline; + +namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations +{ + public class ReadTankHistoryFromDbOperation : IOperation + { + private readonly IWargamingAccountDataAccessor _accountDataAccessor; + + public ReadTankHistoryFromDbOperation(IWargamingAccountDataAccessor accountDataAccessor) + { + _accountDataAccessor = accountDataAccessor; + } + + public async Task Invoke(IOperationContext context, Func? next) + { + var contextData = context.Get(); + + contextData.History = (await _accountDataAccessor.GetTankHistory(context.Request.AccountId, contextData.TankId, contextData.LastBattleSince.ToUnixTimestamp())).ToArray(); + if (next != null) await next.Invoke(context); + + } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/ReadTankInfoFromDBOperation.cs b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/ReadTankInfoFromDBOperation.cs new file mode 100644 index 0000000..c13fb9f --- /dev/null +++ b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/Operations/ReadTankInfoFromDBOperation.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; +using WotBlitzStatisticsPro.DataAccess; +using WotBlitzStatisticsPro.Logic.AccountInformationPipeline.OperationContext; +using WotBlitzStatisticsPro.Logic.Pipeline; + +namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline.Operations +{ + public class ReadTankInfoFromDbOperation : IOperation + { + private readonly IWargamingAccountDataAccessor _accountDataAccessor; + + public ReadTankInfoFromDbOperation(IWargamingAccountDataAccessor accountDataAccessor) + { + _accountDataAccessor = accountDataAccessor; + } + + public async Task Invoke(IOperationContext context, Func? next) + { + var contextData = context.Get(); + + contextData.DbTankInfo = await _accountDataAccessor.ReadTankInfo(context.Request.AccountId, contextData.TankId); + if (next != null) await next.Invoke(context); + } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/TankHistoryInformationContextData.cs b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/TankHistoryInformationContextData.cs new file mode 100644 index 0000000..f9d0aec --- /dev/null +++ b/WotBlitzStatisticsPro.Logic/AccountInformationPipeline/TankHistoryInformationContextData.cs @@ -0,0 +1,29 @@ +using System; +using WotBlitzStatisticsPro.Common.Model; +using WotBlitzStatisticsPro.DataAccess.Model.Accounts; + +namespace WotBlitzStatisticsPro.Logic.AccountInformationPipeline +{ + public class TankHistoryInformationContextData: IDatabaseTankPipelineContextData, IStatisticsPipelineData + { + public TankHistoryInformationContextData(DateTime lastBattleSince, long tankId) + { + LastBattleSince = lastBattleSince; + TankId = tankId; + } + + public DateTime LastBattleSince { get; } + + public long TankId { get; } + + public TankInfo? DbTankInfo { get; set; } + + public IStatistics[]? History { get; set; } + public ShortStatistics? OverallStatistics { get; set; } + public ShortStatistics? PeriodAccountStatistics { get; set; } + public StatisticsDifference? PeriodDifference { get; set; } + public StatisticsDifference[]? StatisticsHistory { get; set; } + + public TankInfoHistoryResponse? Response { get; set; } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/Calculations/TierHelper.cs b/WotBlitzStatisticsPro.Logic/Calculations/TierHelper.cs index 6e169f4..6c4df1f 100644 --- a/WotBlitzStatisticsPro.Logic/Calculations/TierHelper.cs +++ b/WotBlitzStatisticsPro.Logic/Calculations/TierHelper.cs @@ -16,7 +16,7 @@ namespace WotBlitzStatisticsPro.Logic.Calculations { if (tankTires.ContainsKey(tank.TankId) && tank.Battles > 0) { - x += tankTires[tank.TankId] * tank.Battles; + x += tankTires[tank.TankId] * tank.Battles.DoubleValue(); } } if (account.Battles > 0) diff --git a/WotBlitzStatisticsPro.Logic/Calculations/Wn7Helper.cs b/WotBlitzStatisticsPro.Logic/Calculations/Wn7Helper.cs index 7a69aa2..87a9bf6 100644 --- a/WotBlitzStatisticsPro.Logic/Calculations/Wn7Helper.cs +++ b/WotBlitzStatisticsPro.Logic/Calculations/Wn7Helper.cs @@ -26,13 +26,18 @@ namespace WotBlitzStatisticsPro.Logic.Calculations public static void CalculateWn7(this TankInfoHistory tank, double tier) { - 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; + if (!tank.Battles.HasValue) + { + return; + } - tank.Wn7 = CalculateWn7(tank.Battles, tier, avdFrags, avgDamage, avgSpot, avgDef, winRate); + double avdFrags = (double) tank.Frags.DoubleValue() / tank.Battles.DoubleValue(); + double avgDamage = (double)tank.DamageDealt.DoubleValue() / tank.Battles.DoubleValue(); + double avgSpot = (double)tank.Spotted.DoubleValue() / tank.Battles.DoubleValue(); + double avgDef = (double)tank.DroppedCapturePoints.DoubleValue() / tank.Battles.DoubleValue(); + double winRate = (100d * (double) tank.Wins.DoubleValue() / tank.Battles.DoubleValue()); // - 48; + + tank.Wn7 = CalculateWn7(tank.Battles.Value, 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 34134cf..cbda944 100644 --- a/WotBlitzStatisticsPro.Logic/IWargamingAccounts.cs +++ b/WotBlitzStatisticsPro.Logic/IWargamingAccounts.cs @@ -12,5 +12,8 @@ namespace WotBlitzStatisticsPro.Logic Task GetAccountInfoHistory(RealmType realm, long accountId, DateTime startDate, RequestLanguage requestLanguage); + + Task GetTankInfoHistory(RealmType realm, long accountId, long tankId, DateTime startDate, + RequestLanguage requestLanguage); } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/WargamingAccounts.cs b/WotBlitzStatisticsPro.Logic/WargamingAccounts.cs index 74c1efd..20eca77 100644 --- a/WotBlitzStatisticsPro.Logic/WargamingAccounts.cs +++ b/WotBlitzStatisticsPro.Logic/WargamingAccounts.cs @@ -126,5 +126,41 @@ namespace WotBlitzStatisticsPro.Logic } return contextData?.Response ?? new AccountInfoHistoryResponse(); } + + public async Task GetTankInfoHistory(RealmType realm, long accountId, long tankId, DateTime startDate, + RequestLanguage requestLanguage) + { + var contextData = new TankHistoryInformationContextData(startDate, tankId); + try + { + var context = new OperationContext(new AccountRequest(accountId, realm, requestLanguage)); + context.AddOrReplace(contextData); + var pipeline = new Pipeline(_operationFactory); + + pipeline.AddOperation() + .AddOperation() + .AddOperation() + .AddOperation() + .AddOperation() + .AddOperation() + .AddOperation() + .AddOperation() + ; + + var firstOperation = pipeline.Build(); + if (firstOperation != null) + { + await firstOperation + .Invoke(context, null) + .ConfigureAwait(false); + } + } + catch (Exception e) + { + _logger.LogError(e, "GetAccountInfoHistory error"); + throw; + } + return contextData?.Response ?? new TankInfoHistoryResponse(); + } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs b/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs index db5ac71..86a6331 100644 --- a/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs +++ b/WotBlitzStatisticsPro.Logic/WotBlitzStatisticsLogicInstaller.cs @@ -70,6 +70,9 @@ namespace WotBlitzStatisticsPro.Logic services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(serviceProvider => new ServiceProviderOperationFactory(serviceProvider));