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); }
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); }