예제 #1
0
        internal static SpellCountData GetSpellCounts(List <string> playerList, PlayerStats raidStats)
        {
            var result = new SpellCountData();
            HashSet <TimedAction> castsDuring    = new HashSet <TimedAction>();
            HashSet <TimedAction> receivedDuring = new HashSet <TimedAction>();

            QuerySpellBlocks(raidStats, castsDuring, receivedDuring);

            foreach (var action in castsDuring.AsParallel().Where(cast => playerList.Contains((cast as SpellCast).Caster)))
            {
                SpellCast cast = action as SpellCast;
                if (cast.SpellData != null)
                {
                    UpdateMaps(cast.SpellData, cast.Caster, result.PlayerCastCounts, result.PlayerInterruptedCounts, result.MaxCastCounts, result.UniqueSpells, cast.Interrupted);
                }
            }

            foreach (var action in receivedDuring.AsParallel().Where(received => playerList.Contains((received as ReceivedSpell).Receiver)))
            {
                ReceivedSpell received = action as ReceivedSpell;

                // dont include detrimental received spells since they're mostly things like being nuked
                if (received.SpellData != null && received.SpellData.IsBeneficial)
                {
                    UpdateMaps(received.SpellData, received.Receiver, result.PlayerReceivedCounts, null, result.MaxReceivedCounts, result.UniqueSpells);
                }
            }

            return(result);
        }
예제 #2
0
        internal static SpellCountData GetSpellCounts(List <string> playerList, PlayerStats raidStats)
        {
            var result = new SpellCountData();

            HashSet <IAction> castsDuring    = new HashSet <IAction>();
            HashSet <IAction> receivedDuring = new HashSet <IAction>();
            double            maxTime        = -1;

            raidStats.Ranges.TimeSegments.ForEach(segment =>
            {
                maxTime    = maxTime == -1 ? segment.BeginTime + raidStats.TotalSeconds : maxTime;
                var blocks = DataManager.Instance.GetCastsDuring(segment.BeginTime - COUNT_OFFSET, segment.EndTime);
                blocks.ForEach(block =>
                {
                    if (raidStats.MaxTime == raidStats.TotalSeconds || block.BeginTime <= maxTime)
                    {
                        block.Actions.ForEach(action => castsDuring.Add(action));
                    }
                });

                blocks = DataManager.Instance.GetReceivedSpellsDuring(segment.BeginTime - COUNT_OFFSET, segment.EndTime);
                blocks.ForEach(block =>
                {
                    if (raidStats.MaxTime == raidStats.TotalSeconds || block.BeginTime <= maxTime)
                    {
                        block.Actions.ForEach(action => receivedDuring.Add(action));
                    }
                });
            });

            foreach (var action in castsDuring.AsParallel().Where(cast => playerList.Contains((cast as SpellCast).Caster)))
            {
                SpellCast cast      = action as SpellCast;
                var       spellData = DataManager.Instance.GetSpellByAbbrv(DataManager.Instance.AbbreviateSpellName(cast.Spell));
                if (spellData != null)
                {
                    UpdateMaps(spellData, cast.Caster, result.PlayerCastCounts, result.MaxCastCounts, result.UniqueSpells);
                }
            }

            foreach (var action in receivedDuring.AsParallel().Where(received => playerList.Contains((received as ReceivedSpell).Receiver)))
            {
                ReceivedSpell received = action as ReceivedSpell;

                var spellData = received.SpellData;
                if (spellData == null && received.Ambiguity.Count > 0 && DataManager.ResolveSpellAmbiguity(received, out SpellData replaced))
                {
                    spellData = replaced;
                }

                // dont include detrimental received spells since they're mostly things like being nuked
                if (spellData != null && spellData.IsBeneficial)
                {
                    UpdateMaps(spellData, received.Receiver, result.PlayerReceivedCounts, result.MaxReceivedCounts, result.UniqueSpells);
                }
            }

            return(result);
        }
예제 #3
0
        internal static bool ResolveSpellAmbiguity(ReceivedSpell spell, out SpellData replaced)
        {
            replaced = null;

            if (spell.Ambiguity.Count < 30)
            {
                int spellClass = (int)PlayerManager.Instance.GetPlayerClassEnum(spell.Receiver);
                var subset     = spell.Ambiguity.FindAll(test => test.Target == (int)SpellTarget.SELF && spellClass != 0 && (test.ClassMask & spellClass) == spellClass);
                var distinct   = subset.Distinct(AbbrvComparer).ToList();
                replaced = distinct.Count == 1 ? distinct.First() : spell.Ambiguity.First();
            }

            return(replaced != null);
        }
예제 #4
0
        private const int SPELL_TIME_OFFSET = 10; // seconds back

        internal static SpellCountData GetSpellCounts(List <string> playerList, PlayerStats raidStats)
        {
            var result  = new SpellCountData();
            var offsets = GetOffsetTimes(raidStats);
            var begins  = offsets.Item1;
            var lasts   = offsets.Item2;

            List <IAction> castsDuring    = new List <IAction>();
            List <IAction> receivedDuring = new List <IAction>();

            for (int i = 0; i < begins.Count; i++)
            {
                var blocks = DataManager.Instance.GetCastsDuring(begins[i], lasts[i]);
                blocks.ForEach(block => castsDuring.AddRange(block.Actions));
                blocks = DataManager.Instance.GetReceivedSpellsDuring(begins[i], lasts[i]);
                blocks.ForEach(block => receivedDuring.AddRange(block.Actions));
            }

            foreach (var action in castsDuring.AsParallel().Where(cast => playerList.Contains((cast as SpellCast).Caster)))
            {
                SpellCast cast      = action as SpellCast;
                var       spellData = DataManager.Instance.GetSpellByAbbrv(Helpers.AbbreviateSpellName(cast.Spell));
                if (spellData != null)
                {
                    UpdateMaps(spellData, cast.Caster, result.PlayerCastCounts, result.MaxCastCounts, result.UniqueSpells);
                }
            }

            foreach (var action in receivedDuring.AsParallel().Where(received => playerList.Contains((received as ReceivedSpell).Receiver)))
            {
                ReceivedSpell received = action as ReceivedSpell;

                var spellData  = received.SpellData;
                var spellClass = PlayerManager.Instance.GetPlayerClassEnum(received.Receiver);

                if (DataManager.Instance.CheckForSpellAmbiguity(spellData, spellClass, out SpellData replaced))
                {
                    spellData = replaced;
                }

                UpdateMaps(spellData, received.Receiver, result.PlayerReceivedCounts, result.MaxReceivedCounts, result.UniqueSpells);
            }

            return(result);
        }
예제 #5
0
        private bool IsValid(ReceivedSpell spell, Dictionary <string, byte> uniqueNames, string player, out SpellData replaced)
        {
            bool valid = false;

            replaced = spell.SpellData;

            if (!string.IsNullOrEmpty(player) && uniqueNames.ContainsKey(player))
            {
                SpellData spellData = spell.SpellData ?? null;

                if (spellData == null && spell.Ambiguity.Count > 0 && DataManager.ResolveSpellAmbiguity(spell, out replaced))
                {
                    spellData = replaced;
                }

                if (spellData != null)
                {
                    valid = !spellData.IsProc && (CurrentShowSelfOnly || (spell is SpellCast || !string.IsNullOrEmpty(spellData.LandsOnOther)));
                    valid = valid && (CurrentSpellType == 0 || CurrentSpellType == 1 && spellData.IsBeneficial || CurrentSpellType == 2 && !spellData.IsBeneficial);
                }
            }

            return(valid);
        }
예제 #6
0
 internal void AddReceivedSpell(ReceivedSpell received, double beginTime) => Helpers.AddAction(AllReceivedSpellBlocks, received, beginTime);
예제 #7
0
        public static void Process(LineData lineData)
        {
            bool handled = false;

            try
            {
                string[] split = lineData.Action.Split(' ');

                if (split != null && split.Length > 1 && !split[0].Contains("."))
                {
                    string player        = null;
                    string spellName     = null;
                    bool   isYou         = false;
                    bool   isSpell       = false;
                    bool   isInterrupted = false;

                    // [Sat Mar 14 19:57:48 2020] You activate Venon's Vindication.
                    // [Mon Mar 02 19:46:09 2020] You begin casting Shield of Destiny Rk. II.
                    // [Sat Mar 14 19:45:40 2020] You begin singing Agilmente's Aria of Eagles.
                    // [Tue Dec 25 11:38:42 2018] You begin casting Focus of Arcanum VI.
                    // [Sun Dec 02 16:33:37 2018] You begin singing Vainglorious Shout VI.
                    // [Mon Mar 02 19:44:27 2020] Stabborz activates Conditioned Reflexes Rk. II.
                    // [Mon Mar 02 19:47:43 2020] Sancus begins casting Burnout XIV Rk. II.
                    // [Mon Mar 02 19:33:49 2020] Iggokk begins singing Shauri's Sonorous Clouding III.
                    // [Tue Dec 25 09:58:20 2018] Sylfvia begins to cast a spell. <Syllable of Mending Rk. II>
                    // [Tue Dec 25 14:19:57 2018] Sonozen begins to sing a song. <Lyre Leap>
                    // [Thu Apr 18 01:38:10 2019] Incogitable's Dizzying Wheel Rk. II spell is interrupted.
                    // [Thu Apr 18 01:38:00 2019] Your Stormjolt Vortex Rk. III spell is interrupted.
                    // [Sun Mar 01 22:34:58 2020] You have entered The Eastern Wastes.
                    if (split[0] == "You")
                    {
                        player = ConfigUtil.PlayerName;
                        isYou  = true;

                        if (split[1] == "activate")
                        {
                            spellName = ParseNewSpellName(split, 2);
                        }

                        // ZONE EVENT - moved here to keep it in the same thread as lands on message parsing
                        if (split[1] == "have" && split[2] == "entered")
                        {
                            string zone = string.Join(" ", split, 3, split.Length - 3).TrimEnd('.');
                            DataManager.Instance.AddMiscRecord(new ZoneRecord {
                                Zone = zone
                            }, DateUtil.ParseLogDate(lineData.Line, out _));
                            handled = true;

                            if (!zone.StartsWith("an area", StringComparison.OrdinalIgnoreCase))
                            {
                                DataManager.Instance.ZoneChanged();
                            }
                        }
                        else if (split[1] == "begin")
                        {
                            if (split[2] == "casting")
                            {
                                spellName = ParseNewSpellName(split, 3);
                                isSpell   = true;
                            }
                            else if (split[2] == "singing")
                            {
                                spellName = ParseNewSpellName(split, 3);
                            }
                        }
                    }
                    else if (split[1] == "activates")
                    {
                        player    = split[0];
                        spellName = ParseNewSpellName(split, 2);
                    }
                    else if (split[1] == "begins")
                    {
                        if (split[2] == "casting")
                        {
                            player    = split[0];
                            spellName = ParseNewSpellName(split, 3);
                            isSpell   = true;
                        }
                        else if (split[2] == "singing")
                        {
                            player    = split[0];
                            spellName = ParseNewSpellName(split, 3);
                        }
                        else if (split.Length > 5 && split[2] == "to" && split[4] == "a")
                        {
                            if (split[3] == "cast" && split[5] == "spell.")
                            {
                                player    = split[0];
                                spellName = ParseOldSpellName(split, 6);
                                isSpell   = true;
                            }
                            else if (split[3] == "sing" && split[5] == "song.")
                            {
                                player    = split[0];
                                spellName = ParseOldSpellName(split, 6);
                            }
                        }
                    }
                    else if (split.Length > 4 && split[split.Length - 1] == "interrupted." && split[split.Length - 2] == "is" && split[split.Length - 3] == "spell")
                    {
                        isInterrupted = true;
                        spellName     = string.Join(" ", split, 1, split.Length - 4);

                        if (split[0] == "Your")
                        {
                            player = ConfigUtil.PlayerName;
                        }
                        else if (split[0].Length > 3 && split[0][split[0].Length - 1] == 's' && split[0][split[0].Length - 2] == '\'')
                        {
                            player = split[0].Substring(0, split[0].Length - 2);
                        }
                    }

                    if (!handled && !string.IsNullOrEmpty(player) && !string.IsNullOrEmpty(spellName))
                    {
                        double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24));

                        if (!isInterrupted)
                        {
                            if (isSpell && isYou)
                            {
                                // For some reason Glyphs don't show up for current player
                                CheckForSpecial(SpecialYouCodes, spellName, player, currentTime);
                            }

                            var spellData = DataManager.Instance.GetSpellByName(spellName);
                            DataManager.Instance.AddSpellCast(new SpellCast {
                                Caster = player, Spell = string.Intern(spellName), SpellData = spellData, BeginTime = currentTime
                            }, currentTime);
                        }
                        else
                        {
                            DataManager.Instance.HandleSpellInterrupt(player, spellName, currentTime);
                        }

                        handled = true;
                    }

                    if (!handled && lineData.Line[lineData.Line.Length - 1] != ')')
                    {
                        if (split[0].Length > 3 && split[0][split[0].Length - 1] == 's' && split[0][split[0].Length - 2] == '\'')
                        {
                            player = string.Intern(split[0].Substring(0, split[0].Length - 2));
                            var landsOnPosessiveMessage = string.Join(" ", split, 1, split.Length - 1);
                            List <SpellData> result     = DataManager.Instance.GetPosessiveLandsOnOther(player, landsOnPosessiveMessage, out _);
                            if (result != null)
                            {
                                double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24));
                                var    newSpell    = new ReceivedSpell {
                                    Receiver = player, BeginTime = currentTime
                                };

                                if (result.Count == 1)
                                {
                                    newSpell.SpellData = result.First();
                                    CheckForSpecial(SpecialLandsOnCodes, newSpell.SpellData.Name, newSpell.Receiver, currentTime);
                                }
                                else
                                {
                                    newSpell.Ambiguity.AddRange(result);
                                }

                                // valid lands on other. check for pet receiving DPS AA
                                if (PetCheck.ContainsKey(landsOnPosessiveMessage))
                                {
                                    PlayerManager.Instance.AddVerifiedPet(player);
                                }

                                DataManager.Instance.AddReceivedSpell(newSpell, currentTime);
                                handled = true;
                            }
                        }
                        else if (split.Length > 0)
                        {
                            string landsOnMessage = string.Join(" ", split, 1, split.Length - 1);
                            int    midPeriod      = -1;

                            // some abilities like staunch show a lands on message followed by a heal. so search based on first sentence
                            if (landsOnMessage.Length >= 2)
                            {
                                if ((midPeriod = landsOnMessage.LastIndexOf('.', landsOnMessage.Length - 2)) > -1)
                                {
                                    landsOnMessage = landsOnMessage.Substring(0, midPeriod + 1);
                                }
                            }

                            player = split[0];
                            List <SpellData> result = DataManager.Instance.GetNonPosessiveLandsOnOther(player, landsOnMessage, out _);

                            if (result == null)
                            {
                                result = DataManager.Instance.GetLandsOnYou(player, player + " " + landsOnMessage, out _);
                                if (result != null)
                                {
                                    player = ConfigUtil.PlayerName;
                                }
                            }
                            else
                            {
                                // valid lands on other. check for pet receiving DPS AA
                                if (PetCheck.ContainsKey(landsOnMessage))
                                {
                                    PlayerManager.Instance.AddVerifiedPet(player);
                                }
                            }

                            if (result != null)
                            {
                                double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24));
                                var    newSpell    = new ReceivedSpell()
                                {
                                    Receiver = string.Intern(player), BeginTime = currentTime
                                };

                                if (result.Count == 1)
                                {
                                    newSpell.SpellData = result.First();
                                    CheckForSpecial(SpecialLandsOnCodes, newSpell.SpellData.Name, newSpell.Receiver, currentTime);
                                }
                                else
                                {
                                    newSpell.Ambiguity.AddRange(result);
                                }

                                DataManager.Instance.AddReceivedSpell(newSpell, currentTime);
                                handled = true;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LOG.Error(e);
            }

            DebugUtil.UnregisterLine(lineData.LineNumber, handled);
        }
예제 #8
0
        public static void Process(LineData lineData)
        {
            try
            {
                string[] split = lineData.Action.Split(' ');

                if (split != null && split.Length > 2 && !split[0].Contains("."))
                {
                    string player        = null;
                    string spellName     = null;
                    bool   isYou         = false;
                    bool   isSpell       = false;
                    bool   isInterrupted = false;
                    bool   handled       = false;

                    // [Sat Mar 14 19:57:48 2020] You activate Venon's Vindication.
                    // [Mon Mar 02 19:46:09 2020] You begin casting Shield of Destiny Rk. II.
                    // [Sat Mar 14 19:45:40 2020] You begin singing Agilmente's Aria of Eagles.
                    // [Tue Dec 25 11:38:42 2018] You begin casting Focus of Arcanum VI.
                    // [Sun Dec 02 16:33:37 2018] You begin singing Vainglorious Shout VI.
                    // [Mon Mar 02 19:44:27 2020] Stabborz activates Conditioned Reflexes Rk. II.
                    // [Mon Mar 02 19:47:43 2020] Sancus begins casting Burnout XIV Rk. II.
                    // [Mon Mar 02 19:33:49 2020] Iggokk begins singing Shauri's Sonorous Clouding III.
                    // [Tue Dec 25 09:58:20 2018] Sylfvia begins to cast a spell. <Syllable of Mending Rk. II>
                    // [Tue Dec 25 14:19:57 2018] Sonozen begins to sing a song. <Lyre Leap>
                    // [Thu Apr 18 01:38:10 2019] Incogitable's Dizzying Wheel Rk. II spell is interrupted.
                    // [Thu Apr 18 01:38:00 2019] Your Stormjolt Vortex Rk. III spell is interrupted.
                    if (split[0] == "You")
                    {
                        player = ConfigUtil.PlayerName;
                        isYou  = true;

                        if (split[1] == "activate")
                        {
                            spellName = ParseNewSpellName(split, 2);
                        }
                        else if (split[1] == "begin")
                        {
                            if (split[2] == "casting")
                            {
                                spellName = ParseNewSpellName(split, 3);
                                isSpell   = true;
                            }
                            else if (split[2] == "singing")
                            {
                                spellName = ParseNewSpellName(split, 3);
                            }
                        }
                    }
                    else if (split[1] == "activates")
                    {
                        player    = split[0];
                        spellName = ParseNewSpellName(split, 2);
                    }
                    else if (split[1] == "begins")
                    {
                        if (split[2] == "casting")
                        {
                            player    = split[0];
                            spellName = ParseNewSpellName(split, 3);
                            isSpell   = true;
                        }
                        else if (split[2] == "singing")
                        {
                            player    = split[0];
                            spellName = ParseNewSpellName(split, 3);
                        }
                        else if (split.Length > 5 && split[2] == "to" && split[4] == "a")
                        {
                            if (split[3] == "cast" && split[5] == "spell.")
                            {
                                player    = split[0];
                                spellName = ParseOldSpellName(split, 6);
                                isSpell   = true;
                            }
                            else if (split[3] == "sing" && split[5] == "song.")
                            {
                                player    = split[0];
                                spellName = ParseOldSpellName(split, 6);
                            }
                        }
                    }
                    else if (split.Length > 4 && split[split.Length - 1] == "interrupted." && split[split.Length - 2] == "is" && split[split.Length - 3] == "spell")
                    {
                        isInterrupted = true;
                        spellName     = string.Join(" ", split, 1, split.Length - 4);

                        if (split[0] == "Your")
                        {
                            player = ConfigUtil.PlayerName;
                        }
                        else if (split[0].Length > 3 && split[0][split[0].Length - 1] == 's' && split[0][split[0].Length - 2] == '\'')
                        {
                            player = split[0].Substring(0, split[0].Length - 2);
                        }
                    }

                    if (!string.IsNullOrEmpty(player) && !string.IsNullOrEmpty(spellName))
                    {
                        double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24));

                        if (!isInterrupted)
                        {
                            if (isSpell && isYou)
                            {
                                // For some reason Glyphs don't show up for current player
                                CheckForSpecial(SpecialYouCodes, spellName, player, currentTime);
                            }
                            else if (isSpell && !isYou)
                            {
                                // Some spells only show up as casting
                                CheckForSpecial(SpecialOtherCodes, spellName, player, currentTime);
                            }

                            DataManager.Instance.AddSpellCast(new SpellCast()
                            {
                                Caster = player, Spell = string.Intern(spellName)
                            }, currentTime);
                        }
                        else
                        {
                            DataManager.Instance.HandleSpellInterrupt(player, spellName, currentTime);
                        }

                        handled = true;
                    }

                    if (!handled && lineData.Line[lineData.Line.Length - 1] != ')')
                    {
                        if (split[0].Length > 3 && split[0][split[0].Length - 1] == 's' && split[0][split[0].Length - 2] == '\'')
                        {
                            SpellData result = DataManager.Instance.GetPosessiveLandsOnOther(string.Join(" ", split, 1, split.Length - 1), out _);
                            if (result != null)
                            {
                                double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24));
                                var    newSpell    = new ReceivedSpell()
                                {
                                    Receiver = string.Intern(split[0].Substring(0, split[0].Length - 2)), SpellData = result
                                };
                                DataManager.Instance.AddReceivedSpell(newSpell, currentTime);
                                CheckForSpecial(SpecialLandsOnCodes, result.Name, newSpell.Receiver, currentTime);
                            }
                        }
                        else
                        {
                            string landsOnMessage = string.Join(" ", split, 1, split.Length - 1);
                            int    midPeriod      = -1;

                            // some abilities like staunch show a lands on message followed by a heal. so search based on first sentence
                            if ((midPeriod = landsOnMessage.LastIndexOf('.', landsOnMessage.Length - 2)) > -1)
                            {
                                landsOnMessage = landsOnMessage.Substring(0, midPeriod + 1);
                            }

                            player = split[0];
                            SpellData result = DataManager.Instance.GetNonPosessiveLandsOnOther(landsOnMessage, out _);

                            if (result == null)
                            {
                                result = DataManager.Instance.GetLandsOnYou(player + " " + landsOnMessage, out _);
                                if (result != null)
                                {
                                    player = ConfigUtil.PlayerName;
                                }
                            }

                            if (result != null)
                            {
                                double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24));
                                var    newSpell    = new ReceivedSpell()
                                {
                                    Receiver = string.Intern(player), SpellData = result
                                };
                                DataManager.Instance.AddReceivedSpell(newSpell, currentTime);
                                CheckForSpecial(SpecialLandsOnCodes, result.Name, newSpell.Receiver, currentTime);
                            }
                        }
                    }
                }
            }
            catch (ArgumentNullException ne)
            {
                LOG.Error(ne);
            }
            catch (NullReferenceException nr)
            {
                LOG.Error(nr);
            }
            catch (ArgumentOutOfRangeException aor)
            {
                LOG.Error(aor);
            }
            catch (ArgumentException ae)
            {
                LOG.Error(ae);
            }
        }