internal override void AttachToCombatData(CombatData combatData, ParserController operation, ulong gw2Build)
        {
            var addongRunning = new HashSet <AgentItem>();

            operation.UpdateProgressWithCancellationCheck("Attaching healing extension revision " + Revision + " combat events");
            var healData = _healingEvents.GroupBy(x => x.From).ToDictionary(x => x.Key, x => x.ToList());

            foreach (KeyValuePair <AgentItem, List <EXTAbstractHealingEvent> > pair in healData)
            {
                if (SanitizeForSrc(pair.Value) && pair.Key.IsPlayer)
                {
                    addongRunning.Add(pair.Key);
                }
            }
            var healReceivedData = _healingEvents.GroupBy(x => x.To).ToDictionary(x => x.Key, x => x.ToList());

            foreach (KeyValuePair <AgentItem, List <EXTAbstractHealingEvent> > pair in healReceivedData)
            {
                if (SanitizeForDst(pair.Value) && pair.Key.IsPlayer)
                {
                    addongRunning.Add(pair.Key);
                }
            }
            var healDataById = _healingEvents.GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList());
            var running      = addongRunning.Count;

            operation.UpdateProgressWithCancellationCheck(running != 1 ? running + " players have the addon running" : running + " player has the addon running");
            operation.UpdateProgressWithCancellationCheck("Attached " + _healingEvents.Count + " heal events to CombatData");
            combatData.EXTHealingCombatData = new EXTHealingCombatData(healData, healReceivedData, healDataById, GetHybridIDs(gw2Build));
            operation.UpdateProgressWithCancellationCheck("Attached healing extension combat events");
        }
        public static void AdjustBuffs(CombatData combatData, Dictionary <long, Buff> buffsByID, ParserController operation)
        {
            var solved = new Dictionary <byte, ArcDPSEnums.BuffAttribute>();

            foreach (KeyValuePair <BuffFormulaDescriptor, long> pair in _recognizer)
            {
                if (buffsByID.TryGetValue(pair.Value, out Buff buff))
                {
                    BuffInfoEvent buffInfoEvent = combatData.GetBuffInfoEvent(buff.ID);
                    if (buffInfoEvent != null)
                    {
                        foreach (BuffFormula formula in buffInfoEvent.Formulas)
                        {
                            pair.Key.Match(formula, solved);
                        }
                    }
                }
            }
            if (solved.Values.Distinct().Count() != solved.Values.Count)
            {
                operation.UpdateProgressWithCancellationCheck("Incoherent Data in Buff Info Solver, no formula attribute adjustement will be done");
                solved.Clear();
            }
            foreach (KeyValuePair <long, Buff> pair in buffsByID)
            {
                BuffInfoEvent buffInfoEvent = combatData.GetBuffInfoEvent(pair.Key);
                if (buffInfoEvent != null)
                {
                    pair.Value.VerifyBuffInfoEvent(buffInfoEvent, operation);
                    buffInfoEvent.AdjustBuffInfo(solved);
                }
            }
        }
        internal CombatData(List <CombatItem> allCombatItems, FightData fightData, AgentData agentData, SkillData skillData, List <Player> players, ParserController operation)
        {
            _skillIds = new HashSet <long>(allCombatItems.Select(x => (long)x.SkillID));
            IEnumerable <CombatItem> noStateActiBuffRem = allCombatItems.Where(x => x.IsStateChange == ArcDPSEnums.StateChange.None && x.IsActivation == ArcDPSEnums.Activation.None && x.IsBuffRemove == ArcDPSEnums.BuffRemove.None);

            // movement events
            _movementData = CombatEventFactory.CreateMovementEvents(allCombatItems.Where(x =>
                                                                                         x.IsStateChange == ArcDPSEnums.StateChange.Position ||
                                                                                         x.IsStateChange == ArcDPSEnums.StateChange.Velocity ||
                                                                                         x.IsStateChange == ArcDPSEnums.StateChange.Rotation).ToList(), agentData);
            HasMovementData = _movementData.Count > 1;
            // state change events
            operation.UpdateProgressWithCancellationCheck("Creatint status and metadata events");
            CombatEventFactory.CreateStateChangeEvents(allCombatItems, _metaDataEvents, _statusEvents, _rewardEvents, agentData);
            operation.UpdateProgressWithCancellationCheck("Combining SkillInfo with SkillData");
            skillData.CombineWithSkillInfo(_metaDataEvents.SkillInfoEvents);
            // activation events
            operation.UpdateProgressWithCancellationCheck("Creating Cast Events");
            List <AnimatedCastEvent> animatedCastData = CombatEventFactory.CreateCastEvents(allCombatItems.Where(x => x.IsActivation != ArcDPSEnums.Activation.None).ToList(), agentData, skillData);

            operation.UpdateProgressWithCancellationCheck("Creating Weapon Swap Events");
            List <WeaponSwapEvent> wepSwaps = CombatEventFactory.CreateWeaponSwapEvents(allCombatItems.Where(x => x.IsStateChange == ArcDPSEnums.StateChange.WeaponSwap).ToList(), agentData, skillData);

            _weaponSwapData   = wepSwaps.GroupBy(x => x.Caster).ToDictionary(x => x.Key, x => x.ToList());
            _animatedCastData = animatedCastData.GroupBy(x => x.Caster).ToDictionary(x => x.Key, x => x.ToList());
            _instantCastData  = new Dictionary <AgentItem, List <InstantCastEvent> >();
            var allCastEvents = new List <AbstractCastEvent>(animatedCastData);

            allCastEvents.AddRange(wepSwaps);
            _castDataById = allCastEvents.GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList());
            // buff remove event
            var buffCombatEvents = allCombatItems.Where(x => x.IsBuffRemove != ArcDPSEnums.BuffRemove.None && x.IsBuff != 0).ToList();

            buffCombatEvents.AddRange(noStateActiBuffRem.Where(x => x.IsBuff != 0 && x.BuffDmg == 0 && x.Value > 0));
            buffCombatEvents.AddRange(allCombatItems.Where(x => x.IsStateChange == ArcDPSEnums.StateChange.BuffInitial));
            buffCombatEvents.Sort((x, y) => x.Time.CompareTo(y.Time));
            operation.UpdateProgressWithCancellationCheck("Creating Buff Events");
            List <AbstractBuffEvent> buffEvents = CombatEventFactory.CreateBuffEvents(buffCombatEvents, agentData, skillData);

            _buffDataByDst = buffEvents.GroupBy(x => x.To).ToDictionary(x => x.Key, x => x.ToList());
            _buffData      = buffEvents.GroupBy(x => x.BuffID).ToDictionary(x => x.Key, x => x.ToList());
            // damage events
            operation.UpdateProgressWithCancellationCheck("Creating Damage Events");
            List <AbstractDamageEvent> damageData = CombatEventFactory.CreateDamageEvents(noStateActiBuffRem.Where(x => (x.IsBuff != 0 && x.Value == 0) || (x.IsBuff == 0)).ToList(), agentData, skillData);

            _damageData      = damageData.GroupBy(x => x.From).ToDictionary(x => x.Key, x => x.ToList());
            _damageTakenData = damageData.GroupBy(x => x.To).ToDictionary(x => x.Key, x => x.ToList());
            _damageDataById  = damageData.GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList());

            /*healing_data = allCombatItems.Where(x => x.getDstInstid() != 0 && x.isStateChange() == ParseEnum.StateChange.Normal && x.getIFF() == ParseEnum.IFF.Friend && x.isBuffremove() == ParseEnum.BuffRemove.None &&
             *                           ((x.isBuff() == 1 && x.getBuffDmg() > 0 && x.getValue() == 0) ||
             *                           (x.isBuff() == 0 && x.getValue() > 0))).ToList();
             *
             * healing_received_data = allCombatItems.Where(x => x.isStateChange() == ParseEnum.StateChange.Normal && x.getIFF() == ParseEnum.IFF.Friend && x.isBuffremove() == ParseEnum.BuffRemove.None &&
             *                              ((x.isBuff() == 1 && x.getBuffDmg() > 0 && x.getValue() == 0) ||
             *                                  (x.isBuff() == 0 && x.getValue() >= 0))).ToList();*/
            EIExtraEventProcess(players, skillData, agentData, fightData, operation);
            _buffRemoveAllData = _buffData.ToDictionary(x => x.Key, x => x.Value.OfType <BuffRemoveAllEvent>().ToList());
        }
 private void EIExtraEventProcess(List <Player> players, SkillData skillData, AgentData agentData, FightData fightData, ParserController operation)
 {
     operation.UpdateProgressWithCancellationCheck("Creating Custom Buff Events");
     EIBuffParse(players, skillData, fightData);
     operation.UpdateProgressWithCancellationCheck("Creating Custom Damage Events");
     EIDamageParse(skillData, fightData);
     operation.UpdateProgressWithCancellationCheck("Creating Custom Cast Events");
     EICastParse(players, skillData, agentData);
     operation.UpdateProgressWithCancellationCheck("Creating Custom Status Events");
     EIStatusParse();
     // master attachements
     operation.UpdateProgressWithCancellationCheck("Attaching Banners to Warriors");
     WarriorHelper.AttachMasterToWarriorBanners(players, _buffData, _castDataById);
     operation.UpdateProgressWithCancellationCheck("Attaching Turrets to Engineers");
     EngineerHelper.AttachMasterToEngineerTurrets(players, _damageDataById, _castDataById);
     operation.UpdateProgressWithCancellationCheck("Attaching Ranger Gadgets to Rangers");
     RangerHelper.AttachMasterToRangerGadgets(players, _damageDataById, _castDataById);
     operation.UpdateProgressWithCancellationCheck("Attaching Racial Gadgets to Players");
     ProfHelper.AttachMasterToRacialGadgets(players, _damageDataById, _castDataById);
 }
        internal CombatData(List <CombatItem> allCombatItems, FightData fightData, AgentData agentData, SkillData skillData, IReadOnlyList <Player> players, ParserController operation, IReadOnlyDictionary <uint, AbstractExtensionHandler> extensions, int evtcVersion)
        {
            var combatEvents = allCombatItems.OrderBy(x => x.Time).ToList();

            _skillIds = new HashSet <long>();
            var castCombatEvents = new Dictionary <ulong, List <CombatItem> >();
            var buffEvents       = new List <AbstractBuffEvent>();
            var wepSwaps         = new List <WeaponSwapEvent>();
            var brkDamageData    = new List <AbstractBreakbarDamageEvent>();
            var damageData       = new List <AbstractHealthDamageEvent>();

            operation.UpdateProgressWithCancellationCheck("Creating EI Combat Data");
            foreach (CombatItem combatItem in combatEvents)
            {
                _skillIds.Add(combatItem.SkillID);
                if (combatItem.IsStateChange != ArcDPSEnums.StateChange.None)
                {
                    if (combatItem.IsExtension)
                    {
                        if (extensions.TryGetValue(combatItem.Pad, out AbstractExtensionHandler handler))
                        {
                            handler.InsertEIExtensionEvent(combatItem, agentData, skillData);
                        }
                    }
                    else
                    {
                        CombatEventFactory.AddStateChangeEvent(combatItem, agentData, skillData, _metaDataEvents, _statusEvents, _rewardEvents, wepSwaps, buffEvents, evtcVersion);
                    }
                }
                else if (combatItem.IsActivation != ArcDPSEnums.Activation.None)
                {
                    if (castCombatEvents.TryGetValue(combatItem.SrcAgent, out List <CombatItem> list))
                    {
                        list.Add(combatItem);
                    }
                    else
                    {
                        castCombatEvents[combatItem.SrcAgent] = new List <CombatItem>()
                        {
                            combatItem
                        };
                    }
                }
                else if (combatItem.IsBuffRemove != ArcDPSEnums.BuffRemove.None)
                {
                    CombatEventFactory.AddBuffRemoveEvent(combatItem, buffEvents, agentData, skillData);
                }
                else
                {
                    if (combatItem.IsBuff != 0 && combatItem.BuffDmg == 0 && combatItem.Value > 0)
                    {
                        CombatEventFactory.AddBuffApplyEvent(combatItem, buffEvents, agentData, skillData);
                    }
                    else if (combatItem.IsBuff == 0)
                    {
                        CombatEventFactory.AddDirectDamageEvent(combatItem, damageData, brkDamageData, agentData, skillData);
                    }
                    else if (combatItem.IsBuff != 0 && combatItem.Value == 0)
                    {
                        CombatEventFactory.AddIndirectDamageEvent(combatItem, damageData, brkDamageData, agentData, skillData);
                    }
                }
            }
            HasStackIDs           = false;// arcdpsVersion > 20210529 && buffEvents.Any(x => x is BuffStackActiveEvent || x is BuffStackResetEvent) && (fightData.Logic.Mode == EncounterLogic.FightLogic.ParseMode.Instanced10 || fightData.Logic.Mode == EncounterLogic.FightLogic.ParseMode.Instanced5 || fightData.Logic.Mode == EncounterLogic.FightLogic.ParseMode.Benchmark);
            HasMovementData       = _statusEvents.MovementEvents.Count > 1;
            HasBreakbarDamageData = brkDamageData.Any();
            //
            operation.UpdateProgressWithCancellationCheck("Combining SkillInfo with SkillData");
            skillData.CombineWithSkillInfo(_metaDataEvents.SkillInfoEvents);
            //
            operation.UpdateProgressWithCancellationCheck("Creating Cast Events");
            List <AnimatedCastEvent> animatedCastData = CombatEventFactory.CreateCastEvents(castCombatEvents, agentData, skillData, fightData);

            _weaponSwapData       = wepSwaps.GroupBy(x => x.Caster).ToDictionary(x => x.Key, x => x.ToList());
            _animatedCastData     = animatedCastData.GroupBy(x => x.Caster).ToDictionary(x => x.Key, x => x.ToList());
            _instantCastData      = new Dictionary <AgentItem, List <InstantCastEvent> >();
            _animatedCastDataById = animatedCastData.GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList());
            //
            operation.UpdateProgressWithCancellationCheck("Creating Buff Events");
            _buffDataByDst = buffEvents.GroupBy(x => x.To).ToDictionary(x => x.Key, x => x.ToList());
            _buffData      = buffEvents.GroupBy(x => x.BuffID).ToDictionary(x => x.Key, x => x.ToList());
            // damage events
            operation.UpdateProgressWithCancellationCheck("Creating Damage Events");
            _damageData              = damageData.GroupBy(x => x.From).ToDictionary(x => x.Key, x => x.ToList());
            _damageTakenData         = damageData.GroupBy(x => x.To).ToDictionary(x => x.Key, x => x.ToList());
            _damageDataById          = damageData.GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList());
            _breakbarDamageData      = brkDamageData.GroupBy(x => x.From).ToDictionary(x => x.Key, x => x.ToList());
            _breakbarDamageDataById  = brkDamageData.GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList());
            _breakbarDamageTakenData = brkDamageData.GroupBy(x => x.To).ToDictionary(x => x.Key, x => x.ToList());
            _buffRemoveAllData       = _buffData.ToDictionary(x => x.Key, x => x.Value.OfType <BuffRemoveAllEvent>().ToList());
            //

            /*healing_data = allCombatItems.Where(x => x.getDstInstid() != 0 && x.isStateChange() == ParseEnum.StateChange.Normal && x.getIFF() == ParseEnum.IFF.Friend && x.isBuffremove() == ParseEnum.BuffRemove.None &&
             *                           ((x.isBuff() == 1 && x.getBuffDmg() > 0 && x.getValue() == 0) ||
             *                           (x.isBuff() == 0 && x.getValue() > 0))).ToList();
             *
             * healing_received_data = allCombatItems.Where(x => x.isStateChange() == ParseEnum.StateChange.Normal && x.getIFF() == ParseEnum.IFF.Friend && x.isBuffremove() == ParseEnum.BuffRemove.None &&
             *                              ((x.isBuff() == 1 && x.getBuffDmg() > 0 && x.getValue() == 0) ||
             *                                  (x.isBuff() == 0 && x.getValue() >= 0))).ToList();*/
            foreach (AbstractExtensionHandler handler in extensions.Values)
            {
                handler.AttachToCombatData(this, operation, GetBuildEvent().Build);
            }
            EIExtraEventProcess(players, skillData, agentData, fightData, operation, evtcVersion);
        }
        internal BuffsContainer(ulong build, CombatData combatData, ParserController operation)
        {
            var AllBuffs = new List <List <Buff> >()
            {
                Boons,
                Conditions,
                Commons,
                Gear,
                NormalFoods,
                AscendedFood,
                FoodProcs,
                Utilities,
                Potions,
                Writs,
                FightSpecific,
                FractalInstabilities,
                //
                RevenantHelper.Buffs,
                HeraldHelper.Buffs,
                RenegadeHelper.Buffs,
                VindicatorHelper.Buffs,
                //
                WarriorHelper.Buffs,
                BerserkerHelper.Buffs,
                SpellbreakerHelper.Buffs,
                BladeswornHelper.Buffs,
                //
                GuardianHelper.Buffs,
                DragonhunterHelper.Buffs,
                FirebrandHelper.Buffs,
                WillbenderHelper.Buffs,
                //
                RangerHelper.Buffs,
                DruidHelper.Buffs,
                SoulbeastHelper.Buffs,
                UntamedHelper.Buffs,
                //
                ThiefHelper.Buffs,
                DaredevilHelper.Buffs,
                DeadeyeHelper.Buffs,
                SpecterHelper.Buffs,
                //
                EngineerHelper.Buffs,
                ScrapperHelper.Buffs,
                HolosmithHelper.Buffs,
                MechanistHelper.Buffs,
                //
                MesmerHelper.Buffs,
                ChronomancerHelper.Buffs,
                MirageHelper.Buffs,
                VirtuosoHelper.Buffs,
                //
                NecromancerHelper.Buffs,
                ReaperHelper.Buffs,
                ScourgeHelper.Buffs,
                HarbingerHelper.Buffs,
                //
                ElementalistHelper.Buffs,
                TempestHelper.Buffs,
                WeaverHelper.Buffs,
                CatalystHelper.Buffs,
            };
            var currentBuffs = new List <Buff>();

            foreach (List <Buff> buffs in AllBuffs)
            {
                currentBuffs.AddRange(buffs.Where(x => x.Available(build)));
            }
            _buffsByName = currentBuffs.GroupBy(x => x.Name).ToDictionary(x => x.Key, x =>
            {
                var list = x.ToList();
                if (list.Count > 1)
                {
                    throw new InvalidDataException("Same name present multiple times in buffs - " + x.First().Name);
                }
                return(x.First());
            });
            // Unknown consumables
            var buffIDs        = new HashSet <long>(currentBuffs.Select(x => x.ID));
            var foodAndUtility = new List <BuffInfoEvent>(combatData.GetBuffInfoEvent(BuffCategory.Enhancement));

            foodAndUtility.AddRange(combatData.GetBuffInfoEvent(BuffCategory.Food));
            foreach (BuffInfoEvent buffInfoEvent in foodAndUtility)
            {
                if (!buffIDs.Contains(buffInfoEvent.BuffID))
                {
                    string name = buffInfoEvent.Category == BuffCategory.Enhancement ? "Utility" : "Food";
                    string link = buffInfoEvent.Category == BuffCategory.Enhancement ? "https://wiki.guildwars2.com/images/2/23/Nourishment_utility.png" : "https://wiki.guildwars2.com/images/c/ca/Nourishment_food.png";
                    operation.UpdateProgressWithCancellationCheck("Creating consumable " + name + " " + buffInfoEvent.BuffID);
                    currentBuffs.Add(CreateCustomConsumable(name, buffInfoEvent.BuffID, link, buffInfoEvent.MaxStacks));
                }
            }
            //
            BuffsByIds = currentBuffs.GroupBy(x => x.ID).ToDictionary(x => x.Key, x =>
            {
                var list = x.ToList();
                if (list.Count > 1 && x.Key != Buff.NoBuff && x.Key != Buff.Unknown)
                {
                    throw new InvalidDataException("Same id present multiple times in buffs - " + x.First().ID);
                }
                return(x.First());
            });
            operation.UpdateProgressWithCancellationCheck("Adjusting Buffs");
            BuffInfoSolver.AdjustBuffs(combatData, BuffsByIds, operation, build);
            foreach (Buff buff in currentBuffs)
            {
                BuffInfoEvent buffInfoEvt = combatData.GetBuffInfoEvent(buff.ID);
                if (buffInfoEvt != null)
                {
                    foreach (BuffFormula formula in buffInfoEvt.Formulas)
                    {
                        if (formula.Attr1 == BuffAttribute.Unknown)
                        {
                            operation.UpdateProgressWithCancellationCheck("Unknown Formula for " + buff.Name + ": " + formula.GetDescription(true, BuffsByIds));
                        }
                    }
                }
            }
            BuffsByClassification = currentBuffs.GroupBy(x => x.Classification).ToDictionary(x => x.Key, x => (IReadOnlyList <Buff>)x.ToList());
            BuffsBySource         = currentBuffs.GroupBy(x => x.Source).ToDictionary(x => x.Key, x => (IReadOnlyList <Buff>)x.ToList());
            //
            _buffSourceFinder = GetBuffSourceFinder(build, new HashSet <long>(BuffsByClassification[BuffClassification.Boon].Select(x => x.ID)));
        }
        // Constructors
        internal LogData(string buildVersion, CombatData combatData, long evtcLogDuration, List <Player> playerList, ParserController operation)
        {
            ArcVersion = buildVersion;
            double unixStart = 0;
            double unixEnd   = 0;
            //
            PointOfViewEvent povEvt = combatData.GetPointOfViewEvent();

            if (povEvt != null)
            {
                SetPOV(povEvt.PoV, playerList);
            }
            operation.UpdateProgressWithCancellationCheck("PoV " + PoVName);
            //
            BuildEvent buildEvt = combatData.GetBuildEvent();

            if (buildEvt != null)
            {
                GW2Build = buildEvt.Build;
            }
            operation.UpdateProgressWithCancellationCheck("GW2 Build " + GW2Build);
            //
            LanguageEvent langEvt = combatData.GetLanguageEvent();

            if (langEvt != null)
            {
                Language   = langEvt.ToString();
                LanguageID = langEvt.Language;
            }
            operation.UpdateProgressWithCancellationCheck("Language " + Language);
            //
            LogStartEvent logStr = combatData.GetLogStartEvent();

            if (logStr != null)
            {
                SetLogStart(logStr.ServerUnixTimeStamp);
                SetLogStartStd(logStr.ServerUnixTimeStamp);
                unixStart = logStr.ServerUnixTimeStamp;
            }
            //
            LogEndEvent logEnd = combatData.GetLogEndEvent();

            if (logEnd != null)
            {
                SetLogEnd(logEnd.ServerUnixTimeStamp);
                SetLogEndStd(logEnd.ServerUnixTimeStamp);
                unixEnd = logEnd.ServerUnixTimeStamp;
            }
            // log end event is missing, log start is present
            if (LogEnd == DefaultTimeValue && LogStart != DefaultTimeValue)
            {
                operation.UpdateProgressWithCancellationCheck("Missing Log End Event");
                double dur = Math.Round(evtcLogDuration / 1000.0, 3);
                SetLogEnd(dur + unixStart);
                SetLogEndStd(dur + unixStart);
            }
            // log start event is missing, log end is present
            if (LogEnd != DefaultTimeValue && LogStart == DefaultTimeValue)
            {
                operation.UpdateProgressWithCancellationCheck("Missing Log Start Event");
                double dur = Math.Round(evtcLogDuration / 1000.0, 3);
                SetLogStart(unixEnd - dur);
                SetLogStartStd(unixEnd - dur);
            }
            operation.UpdateProgressWithCancellationCheck("Log Start " + LogStartStd);
            operation.UpdateProgressWithCancellationCheck("Log End " + LogEndStd);
            //
            foreach (ErrorEvent evt in combatData.GetErrorEvents())
            {
                operation.UpdateProgressWithCancellationCheck("Error " + evt.Message);
                LogErrors.Add(evt.Message);
            }
        }
        internal CombatData(List <CombatItem> allCombatItems, FightData fightData, AgentData agentData, SkillData skillData, List <Player> players, ParserController operation)
        {
            _skillIds = new HashSet <long>();
            var castCombatEvents = new Dictionary <ulong, List <CombatItem> >();
            var buffEvents       = new List <AbstractBuffEvent>();
            var wepSwaps         = new List <WeaponSwapEvent>();
            var brkDamageData    = new List <AbstractBreakbarDamageEvent>();
            var damageData       = new List <AbstractHealthDamageEvent>();

            operation.UpdateProgressWithCancellationCheck("Creating EI Combat Data");
            foreach (CombatItem combatItem in allCombatItems)
            {
                _skillIds.Add(combatItem.SkillID);
                if (combatItem.IsStateChange != ArcDPSEnums.StateChange.None)
                {
                    CombatEventFactory.AddStateChangeEvent(combatItem, agentData, skillData, _metaDataEvents, _statusEvents, _rewardEvents, wepSwaps, buffEvents);
                }
                else if (combatItem.IsActivation != ArcDPSEnums.Activation.None)
                {
                    if (castCombatEvents.TryGetValue(combatItem.SrcAgent, out List <CombatItem> list))
                    {
                        list.Add(combatItem);
                    }
                    else
                    {
                        castCombatEvents[combatItem.SrcAgent] = new List <CombatItem>()
                        {
                            combatItem
                        };
                    }
                }
                else if (combatItem.IsBuffRemove != ArcDPSEnums.BuffRemove.None)
                {
                    CombatEventFactory.AddBuffRemoveEvent(combatItem, buffEvents, agentData, skillData);
                }
                else
                {
                    if (combatItem.IsBuff != 0 && combatItem.BuffDmg == 0 && combatItem.Value > 0)
                    {
                        CombatEventFactory.AddBuffApplyEvent(combatItem, buffEvents, agentData, skillData);
                        //HasStackIDs = HasStackIDs || combatItem.Pad > 0;
                    }
                    else if (combatItem.IsBuff == 0)
                    {
                        CombatEventFactory.AddDirectDamageEvent(combatItem, damageData, brkDamageData, agentData, skillData);
                    }
                    else if (combatItem.IsBuff != 0 && combatItem.Value == 0)
                    {
                        CombatEventFactory.AddIndirectDamageEvent(combatItem, damageData, brkDamageData, agentData, skillData);
                    }
                }
            }
            HasMovementData       = _statusEvents.MovementEvents.Count > 1;
            HasBreakbarDamageData = brkDamageData.Any();
            //
            operation.UpdateProgressWithCancellationCheck("Combining SkillInfo with SkillData");
            skillData.CombineWithSkillInfo(_metaDataEvents.SkillInfoEvents);
            //
            operation.UpdateProgressWithCancellationCheck("Creating Cast Events");
            List <AnimatedCastEvent> animatedCastData = CombatEventFactory.CreateCastEvents(castCombatEvents, agentData, skillData);

            _weaponSwapData       = wepSwaps.GroupBy(x => x.Caster).ToDictionary(x => x.Key, x => x.ToList());
            _animatedCastData     = animatedCastData.GroupBy(x => x.Caster).ToDictionary(x => x.Key, x => x.ToList());
            _instantCastData      = new Dictionary <AgentItem, List <InstantCastEvent> >();
            _animatedCastDataById = animatedCastData.GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList());
            //
            operation.UpdateProgressWithCancellationCheck("Creating Buff Events");
            _buffDataByDst = buffEvents.GroupBy(x => x.To).ToDictionary(x => x.Key, x => x.ToList());
            _buffData      = buffEvents.GroupBy(x => x.BuffID).ToDictionary(x => x.Key, x => x.ToList());
            // damage events
            operation.UpdateProgressWithCancellationCheck("Creating Damage Events");
            _damageData              = damageData.GroupBy(x => x.From).ToDictionary(x => x.Key, x => x.ToList());
            _damageTakenData         = damageData.GroupBy(x => x.To).ToDictionary(x => x.Key, x => x.ToList());
            _damageDataById          = damageData.GroupBy(x => x.SkillId).ToDictionary(x => x.Key, x => x.ToList());
            _breakbarDamageData      = brkDamageData.GroupBy(x => x.From).ToDictionary(x => x.Key, x => x.ToList());
            _breakbarDamageTakenData = brkDamageData.GroupBy(x => x.To).ToDictionary(x => x.Key, x => x.ToList());
            //

            /*healing_data = allCombatItems.Where(x => x.getDstInstid() != 0 && x.isStateChange() == ParseEnum.StateChange.Normal && x.getIFF() == ParseEnum.IFF.Friend && x.isBuffremove() == ParseEnum.BuffRemove.None &&
             *                           ((x.isBuff() == 1 && x.getBuffDmg() > 0 && x.getValue() == 0) ||
             *                           (x.isBuff() == 0 && x.getValue() > 0))).ToList();
             *
             * healing_received_data = allCombatItems.Where(x => x.isStateChange() == ParseEnum.StateChange.Normal && x.getIFF() == ParseEnum.IFF.Friend && x.isBuffremove() == ParseEnum.BuffRemove.None &&
             *                              ((x.isBuff() == 1 && x.getBuffDmg() > 0 && x.getValue() == 0) ||
             *                                  (x.isBuff() == 0 && x.getValue() >= 0))).ToList();*/
            EIExtraEventProcess(players, skillData, agentData, fightData, operation);
            _buffRemoveAllData = _buffData.ToDictionary(x => x.Key, x => x.Value.OfType <BuffRemoveAllEvent>().ToList());
        }