private void HandleBiting(ParserContext context, SnifferSession session, AttackStrike strike)
        {
            var text = session.GetReportText(strike);

            if (text == null)
            {
                return;
            }
            var attackerName = strike.KeyValues[SnifferTags.AttackerName];
            var defenderName = strike.KeyValues[SnifferTags.DefenderName];

            var bitePattern = string.Format("{0} bites {1} ", attackerName, defenderName);

            if (text.Contains(bitePattern))
            {
                context.SetBiting(attackerName, defenderName);
            }
            var latchPattern = string.Format("{0} latches on", attackerName);

            if (text.Contains(latchPattern))
            {
                context.SetLatching(attackerName, defenderName);
                if (!context.IsBiting(attackerName, defenderName))
                {
                    context.SetBiting(attackerName, defenderName);
                }
            }
            // TODO - check releases, those they might not actually be attack strikes
        }
 public string GetReportText(AttackStrike strike)
 {
     if (strike.ReportTextIndex == -1)
     {
         return(null);
     }
     return(ReportTexts[strike.ReportTextIndex]);
 }
        TissueLayer PickLayer(AttackStrike strike)
        {
            var part = strike.Wounds.Last().Parts.LastOrDefault(p =>
            {
                int dent   = p.KeyValues.ContainsKey(SnifferTags.DentFraction) ? int.Parse(p.KeyValues[SnifferTags.DentFraction]) : 0;
                int cut    = p.KeyValues.ContainsKey(SnifferTags.CutFraction) ? int.Parse(p.KeyValues[SnifferTags.CutFraction]) : 0;
                int effect = p.KeyValues.ContainsKey(SnifferTags.EffectFraction) ? int.Parse(p.KeyValues[SnifferTags.EffectFraction]) : 0;
                return(dent > 0 || cut > 0 || effect > 0);
            });

            if (part == null)
            {
                return(null);
            }

            if (part.Layers.Any())
            {
                return(part.Layers.Last());
            }
            else
            {
                return(null);
            }
        }
        private bool IsMatch(ParserContext context, AttackStrike strike, string text)
        {
            if (!IsCombatText(text))
            {
                return(false);
            }

            var attackerName = strike.KeyValues[SnifferTags.AttackerName];
            var defenderName = strike.KeyValues[SnifferTags.DefenderName];

            if (!strike.Wounds.Any())
            {
                return(false);

                /*
                 * return text.StartsWith(attackerName)
                 *  && text.Contains(defenderName)
                 *  && IsWhiteList(text);
                 * */
            }

            var wound        = strike.Wounds.Last();
            var severedWound = wound.KeyValues[SnifferTags.Severed].ToLower() == "true";
            var severedText  = text.Contains("severed");

            if (severedText != severedWound)
            {
                return(false);
            }

            var targetBp       = strike.Wounds.Last().Parts.First().KeyValues[SnifferTags.BodyPartNameSingular];
            var targetBpPlural = strike.Wounds.Last().Parts.First().KeyValues[SnifferTags.BodyPartNamePlural];
            var layerName      = "NERP";
            var material       = "NERP";

            var lastLayer = PickLayer(strike);

            if (lastLayer != null)
            {
                layerName = lastLayer.KeyValues[SnifferTags.TissueLayerName].ToLower();
                material  = lastLayer.KeyValues[SnifferTags.Material].ToLower();
            }

            var lastBpName   = strike.Wounds.Last().Parts.Last().KeyValues[SnifferTags.BodyPartNameSingular];
            var lastBpPlural = strike.Wounds.Last().Parts.Last().KeyValues[SnifferTags.BodyPartNamePlural];


            var  combatantRegex   = string.Format("^{0} .+? {1}['| ]", attackerName, defenderName);
            bool isCombatText     = IsCombatText(text);
            bool isCombatantRegex = Regex.IsMatch(text, combatantRegex);
            bool hasBut           = Regex.IsMatch(text, ", but ");
            var  result           = isCombatText && isCombatantRegex && !hasBut;

            var  layerRegex      = string.Format("(({1}'s )|())(({0})|({1})|({2})|({3}))( collapses)*", layerName, lastBpName, lastBpPlural, material);
            bool singleLayerDent = Regex.IsMatch(text, "((tear)|(bruis)|(shatter)|(dent)|(fractur))ing it!");
            bool lastBpCollapse  = Regex.IsMatch(text, string.Format("{0} collapses", lastBpName));
            bool layerMatch      = Regex.IsMatch(text, layerRegex);

            if (!isCombatText || hasBut)
            {
                return(false);
            }

            if (isCombatantRegex)
            {
                if (lastBpCollapse)
                {
                    return(true);
                }

                var bodyPartRegex = string.Format("( in the (({0})|({1}))[ |,|!])|({2}'s {0})", targetBp, targetBpPlural, defenderName);

                if (Regex.IsMatch(text, bodyPartRegex))
                {
                    if (layerMatch || IsWhiteList(text) || singleLayerDent || text.Contains(" bites "))
                    {
                        return(true);
                    }
                }

                if (targetBp.Contains("eyelid"))
                {
                    targetBp = targetBp.Replace("eyelid", "eye");

                    bodyPartRegex = string.Format("( in the {0}[ |,])|({1}'s {0}) ", targetBp, defenderName);
                    if (Regex.IsMatch(text, bodyPartRegex))
                    {
                        if (layerMatch || IsWhiteList(text) || singleLayerDent)
                        {
                            return(true);
                        }
                    }
                }

                if (text.Contains(string.Format("{0} shakes {1} around by the {2}", attackerName, defenderName, targetBp)))
                {
                    if (layerMatch || IsWhiteList(text) || singleLayerDent)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }