Beispiel #1
0
        private void ComputeDamageStats(GenerateStatsOptions options)
        {
            lock (DamageGroupIds)
            {
                if (RaidTotals != null)
                {
                    CombinedStats combined = null;
                    ConcurrentDictionary <string, Dictionary <string, PlayerStats> > childrenStats = new ConcurrentDictionary <string, Dictionary <string, PlayerStats> >();
                    ConcurrentDictionary <string, PlayerStats> topLevelStats   = new ConcurrentDictionary <string, PlayerStats>();
                    Dictionary <string, PlayerStats>           individualStats = new Dictionary <string, PlayerStats>();

                    // always start over
                    RaidTotals.Total = 0;
                    double stopTime = -1;

                    try
                    {
                        FireChartEvent(options, "UPDATE");

                        if (options.RequestSummaryData)
                        {
                            if (options.MaxSeconds > -1 && options.MaxSeconds <= RaidTotals.MaxTime && options.MaxSeconds != RaidTotals.TotalSeconds)
                            {
                                var filteredGroups = new List <List <ActionBlock> >();
                                AllDamageGroups.ForEach(group =>
                                {
                                    var filteredBlocks = new List <ActionBlock>();
                                    filteredGroups.Add(filteredBlocks);
                                    group.ForEach(block =>
                                    {
                                        stopTime = stopTime == -1 ? block.BeginTime + options.MaxSeconds : stopTime;
                                        if (block.BeginTime <= stopTime)
                                        {
                                            filteredBlocks.Add(block);
                                        }
                                    });
                                });

                                DamageGroups            = filteredGroups;
                                RaidTotals.TotalSeconds = options.MaxSeconds;
                            }
                            else
                            {
                                DamageGroups = AllDamageGroups;
                            }

                            DamageGroups.ForEach(group =>
                            {
                                group.ForEach(block =>
                                {
                                    block.Actions.ForEach(action =>
                                    {
                                        if (action is DamageRecord record)
                                        {
                                            var stats = StatsUtil.CreatePlayerStats(individualStats, record.Attacker);

                                            if (!MainWindow.IsBaneDamageEnabled && record.Type == Labels.BANE)
                                            {
                                                stats.BaneHits++;

                                                if (individualStats.TryGetValue(stats.OrigName + " +Pets", out PlayerStats temp))
                                                {
                                                    temp.BaneHits++;
                                                }
                                            }
                                            else
                                            {
                                                RaidTotals.Total  += record.Total;
                                                bool isAttackerPet = PlayerManager.Instance.IsVerifiedPet(record.Attacker);
                                                StatsUtil.UpdateStats(stats, record, isAttackerPet);

                                                if ((!PetToPlayer.TryGetValue(record.Attacker, out string player) && !PlayerPets.ContainsKey(record.Attacker)) || player == Labels.UNASSIGNED)
                                                {
                                                    topLevelStats[record.Attacker] = stats;
                                                    stats.IsTopLevel = true;
                                                }
                                                else
                                                {
                                                    string origName      = player ?? record.Attacker;
                                                    string aggregateName = origName + " +Pets";

                                                    PlayerStats aggregatePlayerStats = StatsUtil.CreatePlayerStats(individualStats, aggregateName, origName);
                                                    StatsUtil.UpdateStats(aggregatePlayerStats, record, isAttackerPet);
                                                    topLevelStats[aggregateName] = aggregatePlayerStats;

                                                    if (!childrenStats.TryGetValue(aggregateName, out Dictionary <string, PlayerStats> children))
                                                    {
                                                        childrenStats[aggregateName] = new Dictionary <string, PlayerStats>();
                                                    }

                                                    childrenStats[aggregateName][stats.Name] = stats;
                                                    stats.IsTopLevel = false;
                                                }

                                                PlayerSubStats subStats = StatsUtil.CreatePlayerSubStats(stats.SubStats, record.SubType, record.Type);

                                                uint critHits = subStats.CritHits;
                                                StatsUtil.UpdateStats(subStats, record, isAttackerPet);

                                                // dont count misses/dodges or where no damage was done
                                                if (record.Total > 0)
                                                {
                                                    Dictionary <long, int> values = subStats.CritHits > critHits ? subStats.CritFreqValues : subStats.NonCritFreqValues;
                                                    Helpers.LongIntAddHelper.Add(values, record.Total, 1);
                                                }
                                            }
                                        }
                                    });
                                });
                            });
        private void ComputeHealingStats(GenerateStatsOptions options)
        {
            lock (HealingGroups)
            {
                if (RaidTotals != null)
                {
                    CombinedStats combined = null;
                    Dictionary <string, PlayerStats> individualStats = new Dictionary <string, PlayerStats>();

                    // always start over
                    RaidTotals.Total = 0;

                    try
                    {
                        FireChartEvent(options, "UPDATE");

                        if (options.RequestSummaryData)
                        {
                            HealingGroups.ForEach(group =>
                            {
                                group.ForEach(block =>
                                {
                                    block.Actions.ForEach(action =>
                                    {
                                        if (action is HealRecord record)
                                        {
                                            RaidTotals.Total += record.Total;
                                            PlayerStats stats = StatsUtil.CreatePlayerStats(individualStats, record.Healer);
                                            StatsUtil.UpdateStats(stats, record);

                                            var spellStatName         = record.SubType ?? Labels.SELFHEAL;
                                            PlayerSubStats spellStats = StatsUtil.CreatePlayerSubStats(stats.SubStats, spellStatName, record.Type);
                                            StatsUtil.UpdateStats(spellStats, record);

                                            var healedStatName         = record.Healed;
                                            PlayerSubStats healedStats = StatsUtil.CreatePlayerSubStats(stats.SubStats2, healedStatName, record.Type);
                                            StatsUtil.UpdateStats(healedStats, record);
                                        }
                                    });
                                });
                            });

                            RaidTotals.DPS = (long)Math.Round(RaidTotals.Total / RaidTotals.TotalSeconds, 2);
                            Parallel.ForEach(individualStats.Values, stats => UpdateStats(stats, HealerSpellTimeRanges, HealerHealedTimeRanges));

                            combined = new CombinedStats
                            {
                                RaidStats   = RaidTotals,
                                TargetTitle = (Selected.Count > 1 ? "Combined (" + Selected.Count + "): " : "") + Title,
                                TimeTitle   = string.Format(CultureInfo.CurrentCulture, StatsUtil.TIME_FORMAT, RaidTotals.TotalSeconds),
                                TotalTitle  = string.Format(CultureInfo.CurrentCulture, StatsUtil.TOTAL_FORMAT, StatsUtil.FormatTotals(RaidTotals.Total), " Heals ", StatsUtil.FormatTotals(RaidTotals.DPS))
                            };

                            combined.StatsList.AddRange(individualStats.Values.AsParallel().OrderByDescending(item => item.Total));
                            combined.FullTitle  = StatsUtil.FormatTitle(combined.TargetTitle, combined.TimeTitle, combined.TotalTitle);
                            combined.ShortTitle = StatsUtil.FormatTitle(combined.TargetTitle, combined.TimeTitle, "");

                            for (int i = 0; i < combined.StatsList.Count; i++)
                            {
                                combined.StatsList[i].Rank = Convert.ToUInt16(i + 1);
                                combined.UniqueClasses[combined.StatsList[i].ClassName] = 1;
                            }
                        }
                    }
#pragma warning disable CA1031 // Do not catch general exception types
                    catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
                    {
                        if (ex is ArgumentNullException || ex is NullReferenceException || ex is ArgumentOutOfRangeException || ex is ArgumentException || ex is OutOfMemoryException)
                        {
                            LOG.Error(ex);
                        }
                    }

                    if (options.RequestSummaryData)
                    {
                        // generating new stats
                        var genEvent = new StatsGenerationEvent()
                        {
                            Type          = Labels.HEALPARSE,
                            State         = "COMPLETED",
                            CombinedStats = combined
                        };

                        genEvent.Groups.AddRange(HealingGroups);
                        EventsGenerationStatus?.Invoke(this, genEvent);
                    }
                }
            }
        }
Beispiel #3
0
        internal static CombinedStats ComputeOverlayStats(int mode, int maxRows, string selectedClass)
        {
            CombinedStats combined = null;

            var   allDamage    = 0L;
            var   allTime      = new TimeRange();
            var   playerTotals = new Dictionary <string, OverlayPlayerTotal>();
            var   playerHasPet = new Dictionary <string, bool>();
            var   updateTime   = 0d;
            var   oldestTime   = 0d;
            var   fights       = DataManager.Instance.GetOverlayFights();
            Fight oldestFight  = null;
            bool  baneEnabled  = MainWindow.IsBaneDamageEnabled;

            // clear out anything pending in the queue
            DamageLineParser.CheckSlainQueue(DateUtil.ToDouble(DateTime.Now.AddSeconds(-3)));

            if (fights.Count > 0)
            {
                oldestFight = fights[0];
                foreach (var fight in fights.Where(fight => !fight.Dead || mode > 0))
                {
                    foreach (var keypair in fight.PlayerTotals)
                    {
                        var player = keypair.Key;
                        if (!string.IsNullOrEmpty(keypair.Value.PetOwner))
                        {
                            player = keypair.Value.PetOwner;
                            playerHasPet[player] = true;
                        }
                        else if (PlayerManager.Instance.GetPlayerFromPet(player) is string owner && owner != Labels.UNASSIGNED)
                        {
                            player = owner;
                            playerHasPet[player] = true;
                        }

                        allDamage += baneEnabled ? keypair.Value.DamageWithBane : keypair.Value.Damage;
                        allTime.Add(new TimeSegment(keypair.Value.BeginTime, fight.LastDamageTime));

                        if (updateTime == 0)
                        {
                            updateTime  = keypair.Value.UpdateTime;
                            oldestTime  = keypair.Value.UpdateTime;
                            oldestFight = fight;
                        }
                        else
                        {
                            updateTime = Math.Max(updateTime, keypair.Value.UpdateTime);
                            if (oldestTime > keypair.Value.UpdateTime)
                            {
                                oldestTime  = keypair.Value.UpdateTime;
                                oldestFight = fight;
                            }
                        }

                        if (playerTotals.TryGetValue(player, out OverlayPlayerTotal total))
                        {
                            total.Damage += baneEnabled ? keypair.Value.DamageWithBane : keypair.Value.Damage;
                            total.Range.Add(new TimeSegment(keypair.Value.BeginTime, keypair.Value.UpdateTime));
                            total.UpdateTime = Math.Max(total.UpdateTime, keypair.Value.UpdateTime);
                        }
                        else
                        {
                            playerTotals[player] = new OverlayPlayerTotal
                            {
                                Name       = player,
                                Damage     = baneEnabled ? keypair.Value.DamageWithBane : keypair.Value.Damage,
                                Range      = new TimeRange(new TimeSegment(keypair.Value.BeginTime, keypair.Value.UpdateTime)),
                                UpdateTime = keypair.Value.UpdateTime
                            };
                        }
                    }
                }

                var timeout      = mode == 0 ? DataManager.FIGHTTIMEOUT : mode;
                var totalSeconds = allTime.GetTotal();
                if (oldestFight != null && totalSeconds > 0 && allDamage > 0 && (DateTime.Now - DateTime.MinValue.AddSeconds(updateTime)).TotalSeconds <= timeout)
                {
                    int rank     = 1;
                    var list     = new List <PlayerStats>();
                    var totalDps = (long)Math.Round(allDamage / totalSeconds, 2);
                    int myIndex  = -1;

                    foreach (var total in playerTotals.Values.OrderByDescending(total => total.Damage))
                    {
                        var time = total.Range.GetTotal();
                        if (time > 0 && (DateTime.Now - DateTime.MinValue.AddSeconds(total.UpdateTime)).TotalSeconds <= DataManager.MAXTIMEOUT)
                        {
                            PlayerStats playerStats = new PlayerStats()
                            {
                                Name         = playerHasPet.ContainsKey(total.Name) ? total.Name + " +Pets" : total.Name,
                                Total        = total.Damage,
                                DPS          = (long)Math.Round(total.Damage / time, 2),
                                TotalSeconds = time,
                                Rank         = (ushort)rank++,
                                ClassName    = PlayerManager.Instance.GetPlayerClass(total.Name),
                                OrigName     = total.Name
                            };

                            if (playerStats.Name.StartsWith(ConfigUtil.PlayerName, StringComparison.Ordinal))
                            {
                                myIndex = list.Count;
                            }

                            if (myIndex == list.Count || selectedClass == Properties.Resources.ANY_CLASS || selectedClass == playerStats.ClassName)
                            {
                                list.Add(playerStats);
                            }
                        }
                    }

                    if (myIndex > (maxRows - 1))
                    {
                        var me = list[myIndex];
                        list = list.Take(maxRows - 1).ToList();
                        list.Add(me);
                    }
                    else
                    {
                        list = list.Take(maxRows).ToList();
                    }

                    combined = new CombinedStats();
                    combined.StatsList.AddRange(list);
                    combined.RaidStats = new PlayerStats {
                        Total = allDamage, DPS = totalDps, TotalSeconds = totalSeconds
                    };
                    combined.TargetTitle = (fights.Count > 1 ? "C(" + fights.Count + "): " : "") + oldestFight.Name;

                    // these are here to support copy/paste of the parse
                    combined.TimeTitle  = string.Format(CultureInfo.CurrentCulture, StatsUtil.TIME_FORMAT, combined.RaidStats.TotalSeconds);
                    combined.TotalTitle = string.Format(CultureInfo.CurrentCulture, StatsUtil.TOTAL_FORMAT, StatsUtil.FormatTotals(combined.RaidStats.Total),
                                                        " Damage ", StatsUtil.FormatTotals(combined.RaidStats.DPS));
                }
            }

            return(combined);
        }
Beispiel #4
0
        internal static Dictionary <string, List <HitFreqChartData> > GetHitFreqValues(PlayerStats selected, CombinedStats damageStats)
        {
            Dictionary <string, List <HitFreqChartData> > results = new Dictionary <string, List <HitFreqChartData> >();

            // get chart data for player and pets if available
            if (damageStats?.Children.ContainsKey(selected.Name) == true)
            {
                damageStats?.Children[selected.Name].ForEach(stats => AddStats(stats));
            }
            else
            {
                AddStats(selected);
            }

            return(results);

            void AddStats(PlayerStats stats)
            {
                results[stats.Name] = new List <HitFreqChartData>();
                foreach (string type in stats.SubStats.Keys)
                {
                    HitFreqChartData chartData = new HitFreqChartData()
                    {
                        HitType = stats.SubStats[type].Name
                    };

                    // add crits
                    chartData.CritXValues.AddRange(stats.SubStats[type].CritFreqValues.Keys.OrderBy(key => key));
                    chartData.CritXValues.ForEach(damage => chartData.CritYValues.Add(stats.SubStats[type].CritFreqValues[damage]));

                    // add non crits
                    chartData.NonCritXValues.AddRange(stats.SubStats[type].NonCritFreqValues.Keys.OrderBy(key => key));
                    chartData.NonCritXValues.ForEach(damage => chartData.NonCritYValues.Add(stats.SubStats[type].NonCritFreqValues[damage]));
                    results[stats.Name].Add(chartData);
                }
            }
        }
Beispiel #5
0
 internal TankingBreakdown(CombinedStats currentStats)
 {
     InitializeComponent();
     titleLabel.Content = currentStats?.ShortTitle;
     RaidStats          = currentStats?.RaidStats;
 }
Beispiel #6
0
        private List <PlayerSubStats> GetSubStats(PlayerStats playerStats)
        {
            var name = playerStats.Name;
            List <PlayerSubStats> list = new List <PlayerSubStats>();

            if (OtherDamage.ContainsKey(name))
            {
                AddToList(playerStats, list, OtherDamage[name]);
            }

            if (GroupedDD.ContainsKey(name))
            {
                PlayerSubStats dds = GroupedDD[name];
                if (dds.Total > 0)
                {
                    if (CurrentGroupDDSetting)
                    {
                        list.Add(dds);
                    }
                    else
                    {
                        AddToList(playerStats, list, UnGroupedDD[name]);
                    }
                }
            }

            if (GroupedDoT.ContainsKey(name))
            {
                PlayerSubStats dots = GroupedDoT[name];
                if (dots.Total > 0)
                {
                    if (CurrentGroupDoTSetting)
                    {
                        list.Add(dots);
                    }
                    else
                    {
                        AddToList(playerStats, list, UnGroupedDoT[name]);
                    }
                }
            }

            if (GroupedProcs.ContainsKey(name))
            {
                PlayerSubStats procs = GroupedProcs[name];
                if (procs.Total > 0)
                {
                    if (CurrentGroupProcsSetting)
                    {
                        list.Add(procs);
                    }
                    else
                    {
                        AddToList(playerStats, list, UnGroupedProcs[name]);
                    }
                }
            }

            if (GroupedResisted.ContainsKey(name))
            {
                if (UnGroupedResisted[name].Count > 0)
                {
                    if (CurrentGroupResistedSetting)
                    {
                        list.Add(GroupedResisted[name]);
                    }
                    else
                    {
                        AddToList(playerStats, list, UnGroupedResisted[name]);
                    }
                }
            }

            return(list);
        }
Beispiel #7
0
        private void BuildGroups(PlayerStats playerStats, List <PlayerSubStats> all)
        {
            List <PlayerSubStats> list = new List <PlayerSubStats>();
            PlayerSubStats        dots = new PlayerSubStats()
            {
                Name = Labels.DOT, Type = Labels.DOT
            };
            PlayerSubStats dds = new PlayerSubStats()
            {
                Name = Labels.DD, Type = Labels.DD
            };
            PlayerSubStats procs = new PlayerSubStats()
            {
                Name = Labels.PROC, Type = Labels.PROC
            };
            PlayerSubStats resisted = new PlayerSubStats()
            {
                Name = Labels.RESIST, Type = Labels.RESIST, ResistRate = 100
            };
            List <PlayerSubStats> allDots     = new List <PlayerSubStats>();
            List <PlayerSubStats> allDds      = new List <PlayerSubStats>();
            List <PlayerSubStats> allProcs    = new List <PlayerSubStats>();
            List <PlayerSubStats> allResisted = new List <PlayerSubStats>();

            all.ForEach(sub =>
            {
                PlayerSubStats stats = null;

                switch (sub.Type)
                {
                case Labels.DOT:
                    stats = dots;
                    allDots.Add(sub);
                    break;

                case Labels.DD:
                case Labels.BANE:
                    stats = dds;
                    allDds.Add(sub);
                    break;

                case Labels.PROC:
                    stats = procs;
                    allProcs.Add(sub);
                    break;

                case Labels.RESIST:
                    stats = resisted;
                    allResisted.Add(sub);
                    break;

                default:
                    list.Add(sub);
                    break;
                }

                StatsUtil.MergeStats(stats, sub);
            });

            foreach (var stats in new PlayerSubStats[] { dots, dds, procs, resisted })
            {
                StatsUtil.CalculateRates(stats, RaidStats, playerStats);
            }

            UnGroupedDD[playerStats.Name]       = allDds;
            UnGroupedDoT[playerStats.Name]      = allDots;
            UnGroupedProcs[playerStats.Name]    = allProcs;
            UnGroupedResisted[playerStats.Name] = allResisted;
            GroupedDD[playerStats.Name]         = dds;
            GroupedDoT[playerStats.Name]        = dots;
            GroupedProcs[playerStats.Name]      = procs;
            GroupedResisted[playerStats.Name]   = resisted;
            OtherDamage[playerStats.Name]       = list;

            Dispatcher.InvokeAsync(() =>
            {
                if (allDds.Count > 0 && !groupDirectDamage.IsEnabled)
                {
                    groupDirectDamage.IsEnabled = true;
                }

                if (allProcs.Count > 0 && !groupProcs.IsEnabled)
                {
                    groupProcs.IsEnabled = true;
                }

                if (allDots.Count > 0 && !groupDoT.IsEnabled)
                {
                    groupDoT.IsEnabled = true;
                }

                if (allResisted.Count > 0 && !groupResisted.IsEnabled)
                {
                    groupResisted.IsEnabled = true;
                }
            });
        }