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