public static void CalculateWn7(this AccountInfoHistory account)
        {
            if (!account.Battles.HasValue)
            {
                return;
            }

            double avdFrags  = account.Frags.DoubleValue() / account.Battles.DoubleValue();
            double avgDamage = account.DamageDealt.DoubleValue() / account.Battles.DoubleValue();
            double avgSpot   = account.Spotted.DoubleValue() / account.Battles.DoubleValue();
            double avgDef    = account.DroppedCapturePoints.DoubleValue() / account.Battles.DoubleValue();
            double winRate   = (100 * account.Wins.DoubleValue() / account.Battles.DoubleValue()); // - 48;

            account.Wn7 = CalculateWn7(account.Battles.Value, account.AvgTier, avdFrags, avgDamage, avgSpot, avgDef, winRate);
        }
        private async Task<List<(AccountInfoHistory AccountInfoHistory, int UpdatedAt)>> GetAccountInfoHistory(long accountId, DbConnection connection)
        {
            var resultList = new List<(AccountInfoHistory AccountInfoHistory, int UpdatedAt)>();
            // As far as AccountInfoHistory has properties that can be set only via constructor, we use SQLDataReader here instead of DBSet
            using (var command = connection.CreateCommand())
            {
                command.CommandText = AccountInfoHistoryQuery;
                command.Parameters.Add(new SqlParameter("AccountId", SqlDbType.Int) { Value = accountId });
                if (connection.State.Equals(ConnectionState.Closed)) { await connection.OpenAsync(); }

                using (var reader = await command.ExecuteReaderAsync())
                {
                    while (await reader.ReadAsync())
                    {
                        var history = new AccountInfoHistory(reader.GetInt64(reader.GetOrdinal("AccountId")),
                            reader.GetInt32(reader.GetOrdinal("LastBattleTime")))
                        {
                            Battles = reader.GetInt64(reader.GetOrdinal("Battles")),
                            CapturePoints = reader.GetInt64(reader.GetOrdinal("CapturePoints")),
                            DamageDealt = reader.GetInt64(reader.GetOrdinal("DamageDealt")),
                            DamageReceived = reader.GetInt64(reader.GetOrdinal("DamageReceived")),
                            DroppedCapturePoints = reader.GetInt64(reader.GetOrdinal("DroppedCapturePoints")),
                            Frags = reader.GetInt64(reader.GetOrdinal("Frags")),
                            Frags8P = reader.GetInt64(reader.GetOrdinal("Frags8P")),
                            Hits = reader.GetInt64(reader.GetOrdinal("Hits")),
                            Losses = reader.GetInt64(reader.GetOrdinal("Losses")),
                            MaxFrags = reader.GetInt64(reader.GetOrdinal("MaxFrags")),
                            MaxFragsTankId = reader.GetInt64(reader.GetOrdinal("MaxFragsTankId")),
                            MaxXp = reader.GetInt64(reader.GetOrdinal("MaxXp")),
                            MaxXpTankId = reader.GetInt64(reader.GetOrdinal("MaxXpTankId")),
                            Shots = reader.GetInt64(reader.GetOrdinal("Shots")),
                            Spotted = reader.GetInt64(reader.GetOrdinal("Spotted")),
                            SurvivedBattles = reader.GetInt64(reader.GetOrdinal("SurvivedBattles")),
                            WinAndSurvived = reader.GetInt64(reader.GetOrdinal("WinAndSurvived")),
                            Wins = reader.GetInt64(reader.GetOrdinal("Wins")),
                            Xp = reader.GetInt64(reader.GetOrdinal("Xp")),
                            AvgTier = reader.GetDouble(reader.GetOrdinal("AvgTier")),
                            Wn7 = reader.GetDouble(reader.GetOrdinal("Wn7"))
                        };
                        resultList.Add((history, reader.GetInt32(reader.GetOrdinal("LastBattleTime"))));
                    }
                }
            }

            return resultList;
        }
        public Task Invoke(IOperationContext context, Func <IOperationContext, Task>?next)
        {
            var contextData = context.Get <IStatisticsPipelineData>();

            if (contextData?.History != null && contextData.History.Length > 1)
            {
                var diff = new AccountInfoHistory(context.Request.AccountId, contextData.History[0].LastBattleTime);

                var historyLastIndex = contextData.History.Length - 1;

                diff.Battles     = contextData.History[0].Battles - contextData.History[historyLastIndex].Battles;
                diff.Wins        = contextData.History[0].Wins - contextData.History[historyLastIndex].Wins;
                diff.DamageDealt = contextData.History[0].DamageDealt - contextData.History[historyLastIndex].DamageDealt;
                diff.Xp          = contextData.History[0].Xp - contextData.History[historyLastIndex].Xp;

                contextData.PeriodAccountStatistics = _mapper.Map <IStatistics, ShortStatistics>(diff);
            }

            return(next != null?next.Invoke(context) : Task.CompletedTask);
        }
        public static void CalculateMiddleTier(this AccountInfoHistory account, IList <TankInfoHistory> allTanks, Dictionary <long, int> tankTires)
        {
            double x = 0d;

            if (!account.Battles.HasValue)
            {
                return;
            }
            foreach (var tank in allTanks)
            {
                if (tankTires.ContainsKey(tank.TankId) && tank.Battles > 0)
                {
                    x += tankTires[tank.TankId] * tank.Battles.DoubleValue();
                }
            }
            if (account.Battles > 0)
            {
                x /= account.Battles.Value;
            }
            account.AvgTier = x;
        }