private void CalculateStats()
        {
            foreach (Boss target in _log.FightData.Logic.Targets)
            {
                Dictionary <Player, FinalStats[]> phaseBossStats = new Dictionary <Player, FinalStats[]>();
                foreach (Player player in _log.PlayerList)
                {
                    FinalStats[] stats = new FinalStats[_statistics.Phases.Count];
                    for (int phaseIndex = 0; phaseIndex < _statistics.Phases.Count; phaseIndex++)
                    {
                        stats[phaseIndex] = GetFinalBossStats(player, phaseIndex, target);
                    }
                    phaseBossStats[player] = stats;
                }
                _statistics.StatsBoss[target] = phaseBossStats;


                double[] avgBoons  = new double[_statistics.Phases.Count];
                double[] avgCondis = new double[_statistics.Phases.Count];
                for (int phaseIndex = 0; phaseIndex < _statistics.Phases.Count; phaseIndex++)
                {
                    double avgBoon = 0;
                    foreach (long duration in target.GetBoonPresence(_log, phaseIndex).Values)
                    {
                        avgBoon += duration;
                    }
                    avgBoon /= _statistics.Phases[phaseIndex].GetDuration();
                    avgBoons[phaseIndex] = avgBoon;

                    double avgCondi = 0;
                    foreach (long duration in target.GetCondiPresence(_log, phaseIndex).Values)
                    {
                        avgCondi += duration;
                    }
                    avgCondi /= _statistics.Phases[phaseIndex].GetDuration();
                    avgCondis[phaseIndex] = avgCondi;
                }
                _statistics.AvgBossBoons[target]      = avgBoons;
                _statistics.AvgBossConditions[target] = avgCondis;
            }
            foreach (Player player in _log.PlayerList)
            {
                FinalStatsAll[] phaseStats = new FinalStatsAll[_statistics.Phases.Count];
                for (int phaseIndex = 0; phaseIndex < _statistics.Phases.Count; phaseIndex++)
                {
                    phaseStats[phaseIndex] = GetFinalStats(player, phaseIndex);
                }
                _statistics.StatsAll[player] = phaseStats;
            }
        }
        private FinalStatsAll GetFinalStats(Player p, int phaseIndex)
        {
            PhaseData phase = _statistics.Phases[phaseIndex];
            long      start = _log.FightData.ToLogSpace(phase.Start);
            long      end   = _log.FightData.ToLogSpace(phase.End);
            Dictionary <Target, FinalStats> targetDict = new Dictionary <Target, FinalStats>();

            foreach (Target target in _log.FightData.Logic.Targets)
            {
                if (!_statistics.StatsTarget.ContainsKey(target))
                {
                    _statistics.StatsTarget[target] = new Dictionary <Player, FinalStats[]>();
                }
                Dictionary <Player, FinalStats[]> targetStats = _statistics.StatsTarget[target];
                if (!targetStats.ContainsKey(p))
                {
                    targetStats[p] = new FinalStats[_statistics.Phases.Count];
                }
                targetStats[p][phaseIndex] = new FinalStats();
                targetDict[target]         = targetStats[p][phaseIndex];
            }
            FinalStatsAll final = new FinalStatsAll();

            FillFinalStats(p.GetJustPlayerDamageLogs(null, _log, phase.Start, phase.End), final, targetDict);
            if (p.Account == ":Conjured Sword")
            {
                return(final);
            }
            foreach (CastLog cl in p.GetCastLogs(_log, phase.Start, phase.End))
            {
                if (cl.EndActivation == ParseEnum.Activation.CancelCancel)
                {
                    final.Wasted++;
                    final.TimeWasted += cl.ActualDuration;
                }
                if (cl.EndActivation == ParseEnum.Activation.CancelFire)
                {
                    if (cl.ActualDuration < cl.ExpectedDuration)
                    {
                        final.Saved++;
                        final.TimeSaved += cl.ExpectedDuration - cl.ActualDuration;
                    }
                }
            }
            final.TimeSaved  = Math.Round(final.TimeSaved / 1000.0, 3);
            final.TimeWasted = Math.Round(final.TimeWasted / 1000.0, 3);

            double avgBoons = 0;

            foreach (long duration in p.GetBoonPresence(_log, phaseIndex).Values)
            {
                avgBoons += duration;
            }
            final.AvgBoons = avgBoons / phase.GetDuration();

            double avgCondis = 0;

            foreach (long duration in p.GetCondiPresence(_log, phaseIndex).Values)
            {
                avgCondis += duration;
            }
            final.AvgConditions = avgCondis / phase.GetDuration();


            // Counts
            CombatData combatData = _log.CombatData;

            final.SwapCount = p.GetCastLogs(_log, 0, _log.FightData.FightDuration).Count(x => x.SkillId == SkillItem.WeaponSwapId);

            if (_settings.ParseCombatReplay && _log.FightData.Logic.CanCombatReplay)
            {
                if (_statistics.StackCenterPositions == null)
                {
                    _statistics.StackCenterPositions = new List <Point3D>();
                    List <List <Point3D> > GroupsPosList = new List <List <Point3D> >();
                    foreach (Player player in _log.PlayerList)
                    {
                        if (player.Account == ":Conjured Sword")
                        {
                            continue;
                        }
                        GroupsPosList.Add(player.CombatReplay.GetActivePositions());
                    }
                    for (int time = 0; time < GroupsPosList[0].Count; time++)
                    {
                        float x             = 0;
                        float y             = 0;
                        float z             = 0;
                        int   activePlayers = GroupsPosList.Count;
                        foreach (List <Point3D> points in GroupsPosList)
                        {
                            Point3D point = points[time];
                            if (point != null)
                            {
                                x += point.X;
                                y += point.Y;
                                z += point.Z;
                            }
                            else
                            {
                                activePlayers--;
                            }
                        }
                        x = x / activePlayers;
                        y = y / activePlayers;
                        z = z / activePlayers;
                        _statistics.StackCenterPositions.Add(new Point3D(x, y, z, _settings.PollingRate * time));
                    }
                }
                List <Point3D> positions = p.CombatReplay.Positions.Where(x => x.Time >= phase.Start && x.Time <= phase.End).ToList();
                int            offset    = p.CombatReplay.Positions.Count(x => x.Time < phase.Start);
                if (positions.Count > 1)
                {
                    List <float> distances = new List <float>();
                    for (int time = 0; time < positions.Count; time++)
                    {
                        float deltaX = positions[time].X - _statistics.StackCenterPositions[time + offset].X;
                        float deltaY = positions[time].Y - _statistics.StackCenterPositions[time + offset].Y;
                        //float deltaZ = positions[time].Z - StackCenterPositions[time].Z;


                        distances.Add((float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY));
                    }
                    final.StackDist = distances.Sum() / distances.Count;
                }
                else
                {
                    final.StackDist = -1;
                }
            }
            return(final);
        }
Ejemplo n.º 3
0
        private void SetStats(ParsedLog log)
        {
            int phaseIndex = -1;

            _statsAll    = new List <FinalStatsAll>();
            _statsTarget = new Dictionary <Target, List <FinalStats> >();
            foreach (PhaseData phase in log.FightData.GetPhases(log))
            {
                phaseIndex++;
                Dictionary <Target, FinalStats> targetDict = new Dictionary <Target, FinalStats>();
                foreach (Target target in log.FightData.Logic.Targets)
                {
                    if (!_statsTarget.ContainsKey(target))
                    {
                        _statsTarget[target] = new List <FinalStats>();
                    }
                    _statsTarget[target].Add(new FinalStats());
                    targetDict[target] = _statsTarget[target].Last();
                }
                FinalStatsAll final = new FinalStatsAll();
                FillFinalStats(log, GetJustPlayerDamageLogs(null, log, phase), final, targetDict);
                _statsAll.Add(final);
                // If conjured sword, stop
                if (IsFakeActor)
                {
                    continue;
                }
                foreach (CastLog cl in GetCastLogs(log, phase.Start, phase.End))
                {
                    if (cl.EndActivation == ParseEnum.Activation.CancelCancel)
                    {
                        final.Wasted++;
                        final.TimeWasted += cl.ActualDuration;
                    }
                    if (cl.EndActivation == ParseEnum.Activation.CancelFire)
                    {
                        if (cl.ActualDuration < cl.ExpectedDuration)
                        {
                            final.Saved++;
                            final.TimeSaved += cl.ExpectedDuration - cl.ActualDuration;
                        }
                    }
                    if (cl.SkillId == SkillItem.WeaponSwapId)
                    {
                        final.SwapCount++;
                    }
                }
                final.TimeSaved  = Math.Round(final.TimeSaved / 1000.0, GeneralHelper.TimeDigit);
                final.TimeWasted = Math.Round(final.TimeWasted / 1000.0, GeneralHelper.TimeDigit);

                double avgBoons = 0;
                foreach (long duration in GetBuffPresence(log, phaseIndex).Where(x => log.Boons.BoonsByIds[x.Key].Nature == Boon.BoonNature.Boon).Select(x => x.Value))
                {
                    avgBoons += duration;
                }
                final.AvgBoons = Math.Round(avgBoons / phase.DurationInMS, GeneralHelper.BoonDigit);

                double avgCondis = 0;
                foreach (long duration in GetBuffPresence(log, phaseIndex).Where(x => log.Boons.BoonsByIds[x.Key].Nature == Boon.BoonNature.Condition).Select(x => x.Value))
                {
                    avgCondis += duration;
                }
                final.AvgConditions = Math.Round(avgCondis / phase.DurationInMS, GeneralHelper.BoonDigit);

                if (Properties.Settings.Default.ParseCombatReplay && log.CanCombatReplay)
                {
                    if (CombatReplay == null)
                    {
                        InitCombatReplay(log);
                    }
                    List <Point3D> positions            = CombatReplay.Positions.Where(x => x.Time >= phase.Start && x.Time <= phase.End).ToList();
                    List <Point3D> stackCenterPositions = log.Statistics.GetStackCenterPositions(log);
                    int            offset = CombatReplay.Positions.Count(x => x.Time < phase.Start);
                    if (positions.Count > 1)
                    {
                        List <float> distances = new List <float>();
                        for (int time = 0; time < positions.Count; time++)
                        {
                            float deltaX = positions[time].X - stackCenterPositions[time + offset].X;
                            float deltaY = positions[time].Y - stackCenterPositions[time + offset].Y;
                            //float deltaZ = positions[time].Z - StackCenterPositions[time].Z;


                            distances.Add((float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY));
                        }
                        final.StackDist = distances.Sum() / distances.Count;
                    }
                    else
                    {
                        final.StackDist = -1;
                    }
                }
            }
        }
        private FinalStatsAll GetFinalStats(Player p, int phaseIndex)
        {
            PhaseData      phase       = _statistics.Phases[phaseIndex];
            long           start       = phase.Start + _log.FightData.FightStart;
            long           end         = phase.End + _log.FightData.FightStart;
            FinalStatsAll  final       = new FinalStatsAll();
            HashSet <long> nonCritable = new HashSet <long>
            {
                9292,
                52370
            };

            foreach (DamageLog dl in p.GetJustPlayerDamageLogs(null, _log, phase.Start, phase.End))
            {
                if (dl.IsCondi == 0)
                {
                    if (dl.Result == ParseEnum.Result.Crit)
                    {
                        final.CriticalRate++;
                        final.CriticalDmg += dl.Damage;
                    }

                    if (dl.IsNinety > 0)
                    {
                        final.ScholarRate++;
                        final.ScholarDmg += (int)(dl.Damage / 11.0); //regular+10% damage
                    }

                    if (dl.IsMoving > 0)
                    {
                        final.MovingRate++;
                        final.MovingDamage += (int)(dl.Damage / 21.0);
                    }

                    final.FlankingRate += dl.IsFlanking;

                    if (dl.Result == ParseEnum.Result.Glance)
                    {
                        final.GlanceRate++;
                    }

                    if (dl.Result == ParseEnum.Result.Blind)
                    {
                        final.Missed++;
                    }

                    if (dl.Result == ParseEnum.Result.Interrupt)
                    {
                        final.Interrupts++;
                    }

                    if (dl.Result == ParseEnum.Result.Absorb)
                    {
                        final.Invulned++;
                    }
                    final.PowerLoopCount++;
                    if (!nonCritable.Contains(dl.SkillId))
                    {
                        final.CritablePowerLoopCount++;
                    }
                }
            }
            if (p.Account == ":Conjured Sword")
            {
                return(final);
            }
            foreach (CastLog cl in p.GetCastLogs(_log, phase.Start, phase.End))
            {
                if (cl.EndActivation == ParseEnum.Activation.CancelCancel)
                {
                    final.Wasted++;
                    final.TimeWasted += cl.ActualDuration;
                }
                if (cl.EndActivation == ParseEnum.Activation.CancelFire)
                {
                    final.Saved++;
                    if (cl.ActualDuration < cl.ExpectedDuration)
                    {
                        final.TimeSaved += cl.ExpectedDuration - cl.ActualDuration;
                    }
                }
            }
            final.TimeSaved  = final.TimeSaved / 1000f;
            final.TimeWasted = final.TimeWasted / 1000f;

            double avgBoons = 0;

            foreach (long duration in p.GetBoonPresence(_log, phaseIndex).Values)
            {
                avgBoons += duration;
            }
            final.AvgBoons = avgBoons / phase.GetDuration();

            double avgCondis = 0;

            foreach (long duration in p.GetCondiPresence(_log, phaseIndex).Values)
            {
                avgCondis += duration;
            }
            final.AvgConditions = avgCondis / phase.GetDuration();


            // Counts
            CombatData combatData = _log.CombatData;

            final.SwapCount  = combatData.GetStates(p.InstID, ParseEnum.StateChange.WeaponSwap, start, end).Count;
            final.DownCount  = combatData.GetStates(p.InstID, ParseEnum.StateChange.ChangeDown, start, end).Count;
            final.DodgeCount = combatData.GetSkillCount(p.InstID, SkillItem.DodgeId, start, end) + combatData.GetBuffCount(p.InstID, 40408, start, end);//dodge = 65001 mirage cloak =40408

            if (_settings.ParseCombatReplay && _log.FightData.Logic.CanCombatReplay)
            {
                if (_statistics.StackCenterPositions == null)
                {
                    _statistics.StackCenterPositions = new List <Point3D>();
                    List <List <Point3D> > GroupsPosList = new List <List <Point3D> >();
                    foreach (Player player in _log.PlayerList)
                    {
                        if (player.Account == ":Conjured Sword")
                        {
                            continue;
                        }
                        GroupsPosList.Add(player.CombatReplay.GetActivePositions());
                    }
                    for (int time = 0; time < GroupsPosList[0].Count; time++)
                    {
                        float x             = 0;
                        float y             = 0;
                        float z             = 0;
                        int   activePlayers = GroupsPosList.Count;
                        foreach (List <Point3D> points in GroupsPosList)
                        {
                            Point3D point = points[time];
                            if (point != null)
                            {
                                x += point.X;
                                y += point.Y;
                                z += point.Z;
                            }
                            else
                            {
                                activePlayers--;
                            }
                        }
                        x = x / activePlayers;
                        y = y / activePlayers;
                        z = z / activePlayers;
                        _statistics.StackCenterPositions.Add(new Point3D(x, y, z, _settings.PollingRate * time));
                    }
                }
                List <Point3D> positions = p.CombatReplay.Positions.Where(x => x.Time >= phase.Start && x.Time <= phase.End).ToList();
                int            offset    = p.CombatReplay.Positions.Count(x => x.Time < phase.Start);
                if (positions.Count > 1)
                {
                    List <float> distances = new List <float>();
                    for (int time = 0; time < positions.Count; time++)
                    {
                        float deltaX = positions[time].X - _statistics.StackCenterPositions[time + offset].X;
                        float deltaY = positions[time].Y - _statistics.StackCenterPositions[time + offset].Y;
                        //float deltaZ = positions[time].Z - StackCenterPositions[time].Z;


                        distances.Add((float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY));
                    }
                    final.StackDist = distances.Sum() / distances.Count;
                }
                else
                {
                    final.StackDist = -1;
                }
            }

            List <CombatItem> dead = combatData.GetStates(p.InstID, ParseEnum.StateChange.ChangeDead, start, end);
            List <CombatItem> up   = combatData.GetStates(p.InstID, ParseEnum.StateChange.ChangeUp, start, end);

            final.Died = 0.0;
            if (dead.Count > 0)
            {
                final.Died = up.Count > 0 && up.Last().Time > dead.Last().Time ? -dead.Count : dead.Last().Time - start;
            }

            List <CombatItem> disconnect = combatData.GetStates(p.InstID, ParseEnum.StateChange.Despawn, start, end);

            final.Dcd = 0.0;
            if (disconnect.Count > 0)
            {
                final.Dcd = disconnect.Last().Time - start;
            }
            return(final);
        }