Example #1
0
        public override Expression <Func <IndexedContact, bool> > GetPredicate <T>(Type type, BaseAdaptiveConditionBase <T> adaptiveCondition, T ruleContext)
        {
            var leftFacetName = adaptiveCondition.GetLeftValue(ruleContext).ToString();

            var right = adaptiveCondition.GetRightValue(ruleContext).ToString();

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

            if (adaptiveCondition.Operator == Sitecore.Strategy.Adaptive.Items.ItemIDs.BooleanOperatorTrue)
            {
                adaptiveCondition.Operator = Sitecore.Strategy.Adaptive.Items.ItemIDs.StringOperatorTrue;

                /*return StringConditionOperator.Contains.Compare<IndexedContact>(
                 *      c => (string) c[(ObjectIndexerKey)leftFacetName], right);*/
            }
            else if (adaptiveCondition.Operator == Sitecore.Strategy.Adaptive.Items.ItemIDs.BooleanOperatorFalse)
            {
                adaptiveCondition.Operator = Sitecore.Strategy.Adaptive.Items.ItemIDs.StringOperatorFalse;

                /*return StringConditionOperator.Contains.Compare<IndexedContact>(
                 *      c => (string)c[(ObjectIndexerKey)leftFacetName], right);*/
            }
            var conditionOperator = ConditionUtility.GetStringConditionOperatorById(adaptiveCondition.Operator.ToString());

            return(conditionOperator.Compare <IndexedContact>(c => (string)c[(ObjectIndexerKey)leftFacetName], right));
        }
        public override Expression<Func<IndexedContact, bool>> GetPredicate<T>(Type type, BaseAdaptiveConditionBase<T> adaptiveCondition, T ruleContext)
        {
            var leftFacetName = adaptiveCondition.GetLeftValue(ruleContext).ToString();

            object right = adaptiveCondition.GetRightValue(ruleContext);
            if (right == null)
                return null;
            float rightInt;
            if (!float.TryParse(right.ToString(), out rightInt))
            {
                return null;
            }

            var conditionOperator = ConditionUtility.GetConditionOperatorById(adaptiveCondition.Operator.ToString());
            return GetCompareExpression<float>(conditionOperator, c => (float)c[(ObjectIndexerKey)leftFacetName], rightInt);
        }        
        public override Expression <Func <IndexedContact, bool> > GetPredicate <T>(Type type, BaseAdaptiveConditionBase <T> adaptiveCondition, T ruleContext)
        {
            var leftFacetName = adaptiveCondition.GetLeftValue(ruleContext).ToString();

            object right = adaptiveCondition.GetRightValue(ruleContext);

            if (right == null)
            {
                return(null);
            }
            DateTime rightDateTime;

            rightDateTime = DateUtil.ParseDateTime(right.ToString(), DateTime.MinValue);
            if (rightDateTime == DateTime.MinValue)
            {
                return(null);
            }

            var conditionOperator = ConditionUtility.GetConditionOperatorById(adaptiveCondition.Operator.ToString());

            return(GetCompareExpression <DateTime>(conditionOperator, c => (DateTime)c[(ObjectIndexerKey)leftFacetName], rightDateTime));
        }
Example #4
0
        /// <summary>
        /// ログ1行1テロップに対して判定する
        /// </summary>
        /// <param name="telop">テロップ</param>
        /// <param name="log">ログ</param>
        public void MatchCore(
            Ticker telop,
            string log)
        {
            var matched = false;

            var regex       = telop.Regex;
            var regexToHide = telop.RegexToHide;

            // マッチング計測開始
            telop.StartMatching();

            // 開始条件を確認する
            if (ConditionUtility.CheckConditionsForTelop(telop))
            {
                // 通常マッチ
                if (regex == null)
                {
                    var keyword = telop.KeywordReplaced;
                    if (!string.IsNullOrWhiteSpace(keyword))
                    {
                        if (log.Contains(keyword, StringComparison.OrdinalIgnoreCase))
                        {
                            var messageReplaced = ConditionUtility.GetReplacedMessage(telop);

                            // PC名を置換する
                            messageReplaced = XIVPluginHelper.Instance.ReplacePartyMemberName(
                                messageReplaced,
                                Settings.Default.PCNameInitialOnDisplayStyle);

                            if (!telop.AddMessageEnabled)
                            {
                                telop.MessageReplaced = messageReplaced;
                            }
                            else
                            {
                                telop.MessageReplaced += string.IsNullOrWhiteSpace(telop.MessageReplaced) ?
                                                         messageReplaced :
                                                         Environment.NewLine + messageReplaced;
                            }

                            telop.ForceHide     = false;
                            telop.Delayed       = false;
                            telop.MatchedLog    = log;
                            telop.MatchDateTime = DateTime.Now;

                            // マッチング計測終了
                            telop.EndMatching();

                            telop.Play(telop.MatchSound, telop.MatchAdvancedConfig);
                            telop.Play(telop.MatchTextToSpeak, telop.MatchAdvancedConfig);

                            matched = true;
                        }
                    }
                }

                // 正規表現マッチ
                else
                {
                    var match = regex.Match(log);
                    if (match.Success)
                    {
                        var messageReplaced = ConditionUtility.GetReplacedMessage(telop);
                        messageReplaced = match.Result(messageReplaced);

                        // PC名を置換する
                        messageReplaced = XIVPluginHelper.Instance.ReplacePartyMemberName(
                            messageReplaced,
                            Settings.Default.PCNameInitialOnDisplayStyle);

                        if (!telop.AddMessageEnabled)
                        {
                            telop.MessageReplaced = messageReplaced;
                        }
                        else
                        {
                            telop.MessageReplaced += string.IsNullOrWhiteSpace(telop.MessageReplaced) ?
                                                     messageReplaced :
                                                     Environment.NewLine + messageReplaced;
                        }

                        telop.ForceHide     = false;
                        telop.Delayed       = false;
                        telop.MatchedLog    = log;
                        telop.MatchDateTime = DateTime.Now;

                        // マッチング計測終了
                        telop.EndMatching();

                        telop.Play(telop.MatchSound, telop.MatchAdvancedConfig);
                        if (!string.IsNullOrWhiteSpace(telop.MatchTextToSpeak))
                        {
                            var tts = match.Result(telop.MatchTextToSpeak);
                            telop.Play(tts, telop.MatchAdvancedConfig);
                        }

                        matched = true;
                    }
                }
            }

            if (matched)
            {
                // ディレイサウンドをスタートさせる
                telop.StartDelayedSoundTimer();

                SpellsController.Instance.UpdateNormalSpellTimerForTelop(telop, telop.ForceHide);
                SpellsController.Instance.NotifyNormalSpellTimerForTelop(telop.Title);

                return;
            }

            // 通常マッチ(強制非表示)
            if (regexToHide == null)
            {
                var keyword = telop.KeywordToHideReplaced;
                if (!string.IsNullOrWhiteSpace(keyword))
                {
                    if (log.Contains(keyword, StringComparison.OrdinalIgnoreCase))
                    {
                        telop.ForceHide = true;
                        matched         = true;
                    }
                }
            }

            // 正規表現マッチ(強制非表示)
            else
            {
                if (regexToHide.IsMatch(log))
                {
                    telop.ForceHide = true;
                    matched         = true;
                }
            }

            if (matched)
            {
                SpellsController.Instance.UpdateNormalSpellTimerForTelop(telop, telop.ForceHide);
                SpellsController.Instance.NotifyNormalSpellTimerForTelop(telop.Title);
            }
        }
Example #5
0
        /// <summary>
        /// 1ログ1スペルに対して判定する
        /// </summary>
        /// <param name="spell">スペル</param>
        /// <param name="logLine">ログ</param>
        public void MatchCore(
            Models.Spell spell,
            string logLine)
        {
            var regex        = spell.Regex;
            var notifyNeeded = false;
            var matched      = false;

            if (!spell.IsInstance)
            {
                // マッチング計測開始
                spell.StartMatching();

                // 開始条件を確認する
                if (ConditionUtility.CheckConditionsForSpell(spell))
                {
                    // 正規表現が無効?
                    if (!spell.RegexEnabled ||
                        regex == null)
                    {
                        var keyword = spell.KeywordReplaced;
                        if (string.IsNullOrWhiteSpace(keyword))
                        {
                            return;
                        }

                        // キーワードが含まれるか?
                        if (logLine.Contains(keyword, StringComparison.OrdinalIgnoreCase))
                        {
                            matched = true;
                            var targetSpell = spell;

                            // ヒットしたログを格納する
                            targetSpell.MatchedLog = logLine;

                            // スペル名(表示テキスト)を置換する
                            var replacedTitle = ConditionUtility.GetReplacedTitle(targetSpell);

                            // PC名を置換する
                            replacedTitle = FFXIVPlugin.Instance.ReplacePartyMemberName(
                                replacedTitle,
                                Settings.Default.PCNameInitialOnDisplayStyle);

                            targetSpell.SpellTitleReplaced = replacedTitle;
                            targetSpell.UpdateDone         = false;
                            targetSpell.OverDone           = false;
                            targetSpell.BeforeDone         = false;
                            targetSpell.TimeupDone         = false;

                            var now = DateTime.Now;

                            // ホットバーからリキャスト時間の読込みを試みる
                            double d = 0d;
                            if (!this.TryGetHotbarRecast(targetSpell, out d))
                            {
                                d = targetSpell.RecastTime;
                            }

                            targetSpell.CompleteScheduledTime = now.AddSeconds(d);

                            targetSpell.MatchDateTime = now;

                            // マッチング計測終了
                            spell.EndMatching();

                            // マッチ時点のサウンドを再生する
                            targetSpell.Play(targetSpell.MatchSound, targetSpell.MatchAdvancedConfig);
                            targetSpell.Play(targetSpell.MatchTextToSpeak, targetSpell.MatchAdvancedConfig);

                            notifyNeeded = true;

                            // 遅延サウンドタイマを開始する
                            targetSpell.StartOverSoundTimer();
                            targetSpell.StartBeforeSoundTimer();
                            targetSpell.StartTimeupSoundTimer();
                        }
                    }
                    else
                    {
                        // 正規表現でマッチングする
                        var match = regex.Match(logLine);
                        if (match.Success)
                        {
                            matched = true;
#if DEBUG
                            if (logLine.Contains("MARK"))
                            {
                                Debug.WriteLine("MARK");
                            }
#endif
                            var targetSpell = default(Spell);

                            void setTitle()
                            {
                                targetSpell = spell;

                                // ヒットしたログを格納する
                                targetSpell.MatchedLog = logLine;

                                // スペル名(表示テキスト)を置換する
                                var replacedTitle = match.Result(ConditionUtility.GetReplacedTitle(targetSpell));

                                // PC名を置換する
                                replacedTitle = FFXIVPlugin.Instance.ReplacePartyMemberName(
                                    replacedTitle,
                                    Settings.Default.PCNameInitialOnDisplayStyle);

                                // インスタンス化する?
                                if (targetSpell.ToInstance)
                                {
                                    // 同じタイトルのインスタンススペルを探す
                                    // 存在すればそれを使用して、なければ新しいインスタンスを生成する
                                    targetSpell = SpellTable.Instance.GetOrAddInstance(
                                        replacedTitle,
                                        targetSpell);
                                }
                                else
                                {
                                    targetSpell.SpellTitleReplaced = replacedTitle;
                                }
                            }

                            // スペルタイトルを編集する
                            setTitle();

                            targetSpell.UpdateDone = false;
                            targetSpell.OverDone   = false;
                            targetSpell.BeforeDone = false;
                            targetSpell.TimeupDone = false;

                            var now = DateTime.Now;

                            // 効果時間を決定する
                            // グループ "duration" をキャプチャーしていた場合は効果時間を置換する
                            // 最大値9999を超えていた場合は無視する
                            var duration = targetSpell.RecastTime;

                            var d = 0d;
                            var durationAsText = match.Groups["duration"].Value;
                            if (double.TryParse(durationAsText, out d) &&
                                d < 9999)
                            {
                                duration = d;
                            }
                            else
                            {
                                // ホットバーからリキャスト時間の読込を試みる
                                if (this.TryGetHotbarRecast(targetSpell, out d))
                                {
                                    duration = d;
                                }
                            }

                            targetSpell.CompleteScheduledTime = now.AddSeconds(duration);

                            // スペル対象を保存する
                            // グループ "target" をキャプチャーしていた場合はその文字列を保存する
                            var targetName = match.Groups["target"].Value;
                            if (!string.IsNullOrWhiteSpace(targetName))
                            {
                                targetSpell.TargetName = targetName;
                            }

                            // マッチ日時を格納する
                            targetSpell.MatchDateTime = now;

                            // マッチング計測終了
                            spell.EndMatching();

                            // マッチ時点のサウンドを再生する
                            targetSpell.Play(targetSpell.MatchSound, targetSpell.MatchAdvancedConfig);

                            if (!string.IsNullOrWhiteSpace(targetSpell.MatchTextToSpeak))
                            {
                                var tts = match.Result(targetSpell.MatchTextToSpeak);
                                targetSpell.Play(tts, targetSpell.MatchAdvancedConfig);
                            }

                            notifyNeeded = true;

                            // 遅延サウンドタイマを開始する
                            targetSpell.StartOverSoundTimer();
                            targetSpell.StartBeforeSoundTimer();
                            targetSpell.StartTimeupSoundTimer();
                        }
                    }
                }
            }

            // 延長をマッチングする
            if (spell.MatchDateTime > DateTime.MinValue)
            {
                var keywords      = new string[] { spell.KeywordForExtendReplaced1, spell.KeywordForExtendReplaced2 };
                var regexes       = new Regex[] { spell.RegexForExtend1, spell.RegexForExtend2 };
                var timeToExtends = new double[] { spell.RecastTimeExtending1, spell.RecastTimeExtending2 };

                for (int i = 0; i < 2; i++)
                {
                    var keywordToExtend = keywords[i];
                    var regexToExtend   = regexes[i];
                    var timeToExtend    = timeToExtends[i];

                    // マッチングする
                    var exntended = false;

                    if (!spell.RegexEnabled ||
                        regexToExtend == null)
                    {
                        if (!string.IsNullOrWhiteSpace(keywordToExtend))
                        {
                            exntended = logLine.Contains(keywordToExtend, StringComparison.OrdinalIgnoreCase);
                        }
                    }
                    else
                    {
                        var match = regexToExtend.Match(logLine);
                        exntended = match.Success;

                        if (exntended)
                        {
                            // targetをキャプチャーしている?
                            if (!string.IsNullOrWhiteSpace(spell.TargetName))
                            {
                                var targetName = match.Groups["target"].Value;
                                if (!string.IsNullOrWhiteSpace(targetName))
                                {
                                    // targetが当初のマッチングと一致するか確認する
                                    if (spell.TargetName != targetName)
                                    {
                                        exntended = false;
                                    }
                                }
                            }
                        }
                    }

                    if (!exntended)
                    {
                        continue;
                    }

                    var now = DateTime.Now;

                    // リキャストタイムを延長する
                    var newSchedule = spell.CompleteScheduledTime.AddSeconds(timeToExtend);
                    spell.BeforeDone = false;
                    spell.UpdateDone = false;

                    if (spell.ExtendBeyondOriginalRecastTime)
                    {
                        if (spell.UpperLimitOfExtension > 0)
                        {
                            var newDuration = (newSchedule - now).TotalSeconds;
                            if (newDuration > (double)spell.UpperLimitOfExtension)
                            {
                                newSchedule = newSchedule.AddSeconds(
                                    (newDuration - (double)spell.UpperLimitOfExtension) * -1);
                            }
                        }
                    }
                    else
                    {
                        var newDuration = (newSchedule - now).TotalSeconds;
                        if (newDuration > (double)spell.RecastTime)
                        {
                            newSchedule = newSchedule.AddSeconds(
                                (newDuration - (double)spell.RecastTime) * -1);
                        }
                    }

                    spell.CompleteScheduledTime = newSchedule;
                    spell.MatchDateTime         = now;

                    notifyNeeded = true;

                    // 遅延サウンドタイマを開始(更新)する
                    spell.StartOverSoundTimer();
                    spell.StartBeforeSoundTimer();
                    spell.StartTimeupSoundTimer();
                }
            }
            // end if 延長マッチング

            // ホットバー情報を更新する
            if (!matched)
            {
                var now = DateTime.Now;

                if (spell.CompleteScheduledTime > now)
                {
                    double d;
                    if (this.TryGetHotbarRecast(spell, out d))
                    {
                        // ホットバー情報と0.6秒以上乖離したら補正する
                        var newSchedule = now.AddSeconds(d);

                        if (Math.Abs((newSchedule - spell.CompleteScheduledTime).TotalSeconds)
                            >= 0.6d)
                        {
                            spell.CompleteScheduledTime = newSchedule;
                            spell.BeforeDone            = false;
                            spell.UpdateDone            = false;

                            notifyNeeded = true;

                            spell.StartOverSoundTimer();
                            spell.StartBeforeSoundTimer();
                            spell.StartTimeupSoundTimer();
                        }
                    }
                }
            }

            // ACT標準のSpellTimerに変更を通知する
            if (notifyNeeded)
            {
                this.UpdateNormalSpellTimer(spell, false);
                this.NotifyNormalSpellTimer(spell);
            }
        }
Example #6
0
        /// <summary>
        /// Spellをマッチングする
        /// </summary>
        /// <param name="spells">Spell</param>
        /// <param name="logLines">ログ</param>
        private void MatchSpells(
            IReadOnlyList <Models.SpellTimer> spells,
            IReadOnlyList <string> logLines)
        {
            foreach (var logLine in logLines)
            {
                // マッチする?
                spells.AsParallel().ForAll(spell =>
                {
                    var regex        = spell.Regex;
                    var notifyNeeded = false;

                    if (!spell.IsInstance)
                    {
                        // 開始条件を確認する
                        if (ConditionUtility.CheckConditionsForSpell(spell))
                        {
                            // 正規表現が無効?
                            if (!spell.RegexEnabled ||
                                regex == null)
                            {
                                var keyword = spell.KeywordReplaced;
                                if (string.IsNullOrWhiteSpace(keyword))
                                {
                                    return;
                                }

                                // キーワードが含まれるか?
                                if (logLine.ToUpper().Contains(
                                        keyword.ToUpper()))
                                {
                                    var targetSpell = spell;

                                    // ヒットしたログを格納する
                                    targetSpell.MatchedLog = logLine;

                                    // スペル名(表示テキスト)を置換する
                                    var replacedTitle = ConditionUtility.GetReplacedTitle(targetSpell);

                                    targetSpell.SpellTitleReplaced    = replacedTitle;
                                    targetSpell.MatchDateTime         = DateTime.Now;
                                    targetSpell.UpdateDone            = false;
                                    targetSpell.OverDone              = false;
                                    targetSpell.BeforeDone            = false;
                                    targetSpell.TimeupDone            = false;
                                    targetSpell.CompleteScheduledTime = targetSpell.MatchDateTime.AddSeconds(targetSpell.RecastTime);

                                    // マッチ時点のサウンドを再生する
                                    this.Play(targetSpell.MatchSound);
                                    this.Play(targetSpell.MatchTextToSpeak);

                                    notifyNeeded = true;

                                    // 遅延サウンドタイマを開始する
                                    targetSpell.StartOverSoundTimer();
                                    targetSpell.StartBeforeSoundTimer();
                                    targetSpell.StartTimeupSoundTimer();
                                }
                            }
                            else
                            {
                                // 正規表現でマッチングする
                                var match = regex.Match(logLine);
                                if (match.Success)
                                {
                                    var targetSpell = spell;

                                    // ヒットしたログを格納する
                                    targetSpell.MatchedLog = logLine;

                                    // スペル名(表示テキスト)を置換する
                                    var replacedTitle = match.Result(ConditionUtility.GetReplacedTitle(targetSpell));

                                    // インスタンス化する?
                                    if (spell.ToInstance)
                                    {
                                        // 同じタイトルのインスタンススペルを探す
                                        // 存在すればそれを使用して、なければ新しいインスタンスを生成する
                                        targetSpell = SpellTimerTable.GetOrAddInstance(
                                            replacedTitle,
                                            spell);

                                        // インスタンスのガーベージタイマをスタートする
                                        targetSpell.StartGarbageInstanceTimer();
                                    }

                                    targetSpell.SpellTitleReplaced = replacedTitle;
                                    targetSpell.MatchDateTime      = DateTime.Now;
                                    targetSpell.UpdateDone         = false;
                                    targetSpell.OverDone           = false;
                                    targetSpell.BeforeDone         = false;
                                    targetSpell.TimeupDone         = false;

                                    // 効果時間を決定する
                                    // グループ "duration" をキャプチャーしていた場合は効果時間を置換する
                                    var durationAsText = match.Groups["duration"].Value;
                                    double duration;
                                    if (!double.TryParse(durationAsText, out duration))
                                    {
                                        duration = targetSpell.RecastTime;
                                    }

                                    targetSpell.CompleteScheduledTime = targetSpell.MatchDateTime.AddSeconds(duration);

                                    // スペル対象を保存する
                                    // グループ "target" をキャプチャーしていた場合はその文字列を保存する
                                    var targetName = match.Groups["target"].Value;
                                    if (!string.IsNullOrWhiteSpace(targetName))
                                    {
                                        targetSpell.TargetName = targetName;
                                    }

                                    // マッチ時点のサウンドを再生する
                                    this.Play(targetSpell.MatchSound);

                                    if (!string.IsNullOrWhiteSpace(targetSpell.MatchTextToSpeak))
                                    {
                                        var tts = match.Result(targetSpell.MatchTextToSpeak);
                                        this.Play(tts);
                                    }

                                    notifyNeeded = true;

                                    // 遅延サウンドタイマを開始する
                                    targetSpell.StartOverSoundTimer();
                                    targetSpell.StartBeforeSoundTimer();
                                    targetSpell.StartTimeupSoundTimer();
                                }
                            }
                        }
                    }

                    // 延長をマッチングする
                    if (spell.MatchDateTime > DateTime.MinValue)
                    {
                        var keywords      = new string[] { spell.KeywordForExtendReplaced1, spell.KeywordForExtendReplaced2 };
                        var regexes       = new Regex[] { spell.RegexForExtend1, spell.RegexForExtend2 };
                        var timeToExtends = new double[] { spell.RecastTimeExtending1, spell.RecastTimeExtending2 };

                        for (int i = 0; i < 2; i++)
                        {
                            var keywordToExtend = keywords[i];
                            var regexToExtend   = regexes[i];
                            var timeToExtend    = timeToExtends[i];

                            // マッチングする
                            var matched = false;

                            if (!spell.RegexEnabled ||
                                regexToExtend == null)
                            {
                                if (!string.IsNullOrWhiteSpace(keywordToExtend))
                                {
                                    matched = logLine.ToUpper().Contains(keywordToExtend.ToUpper());
                                }
                            }
                            else
                            {
                                var match = regexToExtend.Match(logLine);
                                matched   = match.Success;

                                if (matched)
                                {
                                    // targetをキャプチャーしている?
                                    if (!string.IsNullOrWhiteSpace(spell.TargetName))
                                    {
                                        var targetName = match.Groups["target"].Value;
                                        if (!string.IsNullOrWhiteSpace(targetName))
                                        {
                                            // targetが当初のマッチングと一致するか確認する
                                            if (spell.TargetName != targetName)
                                            {
                                                matched = false;
                                            }
                                        }
                                    }
                                }
                            }

                            if (!matched)
                            {
                                continue;
                            }

                            var now = DateTime.Now;

                            // リキャストタイムを延長する
                            var newSchedule  = spell.CompleteScheduledTime.AddSeconds(timeToExtend);
                            spell.BeforeDone = false;
                            spell.UpdateDone = false;

                            if (spell.ExtendBeyondOriginalRecastTime)
                            {
                                if (spell.UpperLimitOfExtension > 0)
                                {
                                    var newDuration = (newSchedule - now).TotalSeconds;
                                    if (newDuration > (double)spell.UpperLimitOfExtension)
                                    {
                                        newSchedule = newSchedule.AddSeconds(
                                            (newDuration - (double)spell.UpperLimitOfExtension) * -1);
                                    }
                                }
                            }
                            else
                            {
                                var newDuration = (newSchedule - now).TotalSeconds;
                                if (newDuration > (double)spell.RecastTime)
                                {
                                    newSchedule = newSchedule.AddSeconds(
                                        (newDuration - (double)spell.RecastTime) * -1);
                                }
                            }

                            spell.MatchDateTime         = now;
                            spell.CompleteScheduledTime = newSchedule;

                            notifyNeeded = true;

                            // 遅延サウンドタイマを開始(更新)する
                            spell.StartOverSoundTimer();
                            spell.StartBeforeSoundTimer();
                            spell.StartTimeupSoundTimer();
                        }
                    }
                    // end if 延長マッチング

                    // ACT標準のSpellTimerに変更を通知する
                    if (notifyNeeded)
                    {
                        this.UpdateNormalSpellTimer(spell, false);
                        this.NotifyNormalSpellTimer(spell);
                    }
                });
                // end loop of Spells
            }
            // end loop of LogLines
        }
Example #7
0
        /// <summary>
        /// Spellをマッチングする
        /// </summary>
        /// <param name="spells">Spell</param>
        /// <param name="logLines">ログ</param>
        private void MatchSpells(
            IReadOnlyList <SpellTimer> spells,
            IReadOnlyList <string> logLines)
        {
            foreach (var logLine in logLines)
            {
                // マッチする?
                spells.AsParallel().ForAll(spell =>
                {
                    var regex        = spell.Regex;
                    var notifyNeeded = false;

                    if (!spell.IsInstance)
                    {
                        // 開始条件を確認する
                        if (ConditionUtility.CheckConditionsForSpell(spell))
                        {
                            // 正規表現が無効?
                            if (!spell.RegexEnabled ||
                                regex == null)
                            {
                                var keyword = spell.KeywordReplaced;
                                if (string.IsNullOrWhiteSpace(keyword))
                                {
                                    return;
                                }

                                // キーワードが含まれるか?
                                if (logLine.ToUpper().Contains(
                                        keyword.ToUpper()))
                                {
                                    var targetSpell = spell;

                                    // ヒットしたログを格納する
                                    targetSpell.MatchedLog = logLine;

                                    // スペル名(表示テキスト)を置換する
                                    var replacedTitle = ConditionUtility.GetReplacedTitle(targetSpell);

                                    targetSpell.SpellTitleReplaced    = replacedTitle;
                                    targetSpell.MatchDateTime         = DateTime.Now;
                                    targetSpell.UpdateDone            = false;
                                    targetSpell.OverDone              = false;
                                    targetSpell.BeforeDone            = false;
                                    targetSpell.TimeupDone            = false;
                                    targetSpell.CompleteScheduledTime = targetSpell.MatchDateTime.AddSeconds(targetSpell.RecastTime);

                                    // マッチ時点のサウンドを再生する
                                    this.Play(targetSpell.MatchSound);
                                    this.Play(targetSpell.MatchTextToSpeak);

                                    notifyNeeded = true;
                                }
                            }
                            else
                            {
                                // 正規表現でマッチングする
                                var match = regex.Match(logLine);
                                if (match.Success)
                                {
                                    var targetSpell = spell;

                                    // ヒットしたログを格納する
                                    targetSpell.MatchedLog = logLine;

                                    // スペル名(表示テキスト)を置換する
                                    var replacedTitle = match.Result(ConditionUtility.GetReplacedTitle(targetSpell));

                                    // インスタンス化する?
                                    if (spell.ToInstance)
                                    {
                                        // 同じタイトルのインスタンススペルを探す
                                        // 存在すればそれを使用して、なければ新しいインスタンスを生成する
                                        targetSpell = SpellTimerTable.GetOrAddInstance(
                                            replacedTitle,
                                            spell);
                                    }

                                    targetSpell.SpellTitleReplaced = replacedTitle;
                                    targetSpell.MatchDateTime      = DateTime.Now;
                                    targetSpell.UpdateDone         = false;
                                    targetSpell.OverDone           = false;
                                    targetSpell.BeforeDone         = false;
                                    targetSpell.TimeupDone         = false;

                                    // 効果時間を決定する
                                    // グループ "duration" をキャプチャーしていた場合は効果時間を置換する
                                    var durationAsText = match.Groups["duration"].Value;
                                    long duration;
                                    if (!long.TryParse(durationAsText, out duration))
                                    {
                                        duration = targetSpell.RecastTime;
                                    }

                                    targetSpell.CompleteScheduledTime = targetSpell.MatchDateTime.AddSeconds(duration);

                                    // マッチ時点のサウンドを再生する
                                    this.Play(targetSpell.MatchSound);

                                    if (!string.IsNullOrWhiteSpace(targetSpell.MatchTextToSpeak))
                                    {
                                        var tts = match.Result(targetSpell.MatchTextToSpeak);
                                        this.Play(tts);
                                    }

                                    notifyNeeded = true;
                                }
                            }
                        }
                    }

                    // 延長をマッチングする
                    if (spell.MatchDateTime > DateTime.MinValue)
                    {
                        var keywords      = new string[] { spell.KeywordForExtendReplaced1, spell.KeywordForExtendReplaced2 };
                        var regexes       = new Regex[] { spell.RegexForExtend1, spell.RegexForExtend2 };
                        var timeToExtends = new long[] { spell.RecastTimeExtending1, spell.RecastTimeExtending2 };

                        for (int i = 0; i < 2; i++)
                        {
                            var keywordToExtend = keywords[i];
                            var regexToExtend   = regexes[i];
                            var timeToExtend    = timeToExtends[i];

                            // マッチングする
                            var match = false;

                            if (!spell.RegexEnabled ||
                                regexToExtend == null)
                            {
                                if (!string.IsNullOrWhiteSpace(keywordToExtend))
                                {
                                    match = logLine.ToUpper().Contains(keywordToExtend.ToUpper());
                                }
                            }
                            else
                            {
                                match = regexToExtend.Match(logLine).Success;
                            }

                            if (!match)
                            {
                                continue;
                            }

                            var now = DateTime.Now;

                            // リキャストタイムを延長する
                            var newSchedule  = spell.CompleteScheduledTime.AddSeconds(timeToExtend);
                            spell.BeforeDone = false;
                            spell.UpdateDone = false;

                            if (spell.ExtendBeyondOriginalRecastTime)
                            {
                                if (spell.UpperLimitOfExtension > 0)
                                {
                                    var newDuration = (newSchedule - now).TotalSeconds;
                                    if (newDuration > (double)spell.UpperLimitOfExtension)
                                    {
                                        newSchedule = newSchedule.AddSeconds(
                                            (newDuration - (double)spell.UpperLimitOfExtension) * -1);
                                    }
                                }
                            }
                            else
                            {
                                var newDuration = (newSchedule - now).TotalSeconds;
                                if (newDuration > (double)spell.RecastTime)
                                {
                                    newSchedule = newSchedule.AddSeconds(
                                        (newDuration - (double)spell.RecastTime) * -1);
                                }
                            }

                            spell.MatchDateTime         = now;
                            spell.CompleteScheduledTime = newSchedule;

                            notifyNeeded = true;
                        }
                    }
                    // end if 延長マッチング

                    // ACT標準のSpellTimerに変更を通知する
                    if (notifyNeeded)
                    {
                        this.updateNormalSpellTimer(spell, false);
                        this.notifyNormalSpellTimer(spell);
                    }
                });
                // end loop spells
            }

            // スペルの更新とサウンド処理を行う
            foreach (var spell in spells)
            {
                var regex = spell.Regex;

                // Repeat対象のSpellを更新する
                if (spell.RepeatEnabled &&
                    spell.MatchDateTime > DateTime.MinValue)
                {
                    if (DateTime.Now >= spell.MatchDateTime.AddSeconds(spell.RecastTime))
                    {
                        spell.MatchDateTime = DateTime.Now;
                        spell.UpdateDone    = false;
                        spell.OverDone      = false;
                        spell.TimeupDone    = false;
                    }
                }

                // n秒後のSoundを再生する
                if (spell.OverTime > 0 &&
                    !spell.OverDone &&
                    spell.MatchDateTime > DateTime.MinValue)
                {
                    var over = spell.MatchDateTime.AddSeconds(spell.OverTime);

                    if (DateTime.Now >= over)
                    {
                        this.Play(spell.OverSound);
                        if (!string.IsNullOrWhiteSpace(spell.OverTextToSpeak))
                        {
                            var tts = spell.RegexEnabled && regex != null?
                                      regex.Replace(spell.MatchedLog, spell.OverTextToSpeak) :
                                          spell.OverTextToSpeak;

                            this.Play(tts);
                        }

                        spell.OverDone = true;
                    }
                }

                // リキャストn秒前のSoundを再生する
                if (spell.BeforeTime > 0 &&
                    !spell.BeforeDone &&
                    spell.MatchDateTime > DateTime.MinValue)
                {
                    if (spell.CompleteScheduledTime > DateTime.MinValue)
                    {
                        var before = spell.CompleteScheduledTime.AddSeconds(spell.BeforeTime * -1);

                        if (DateTime.Now >= before)
                        {
                            this.Play(spell.BeforeSound);
                            if (!string.IsNullOrWhiteSpace(spell.BeforeTextToSpeak))
                            {
                                var tts = spell.RegexEnabled && regex != null?
                                          regex.Replace(spell.MatchedLog, spell.BeforeTextToSpeak) :
                                              spell.BeforeTextToSpeak;

                                this.Play(tts);
                            }

                            spell.BeforeDone = true;
                        }
                    }
                }

                // リキャスト完了のSoundを再生する
                if (spell.RecastTime > 0 &&
                    !spell.TimeupDone &&
                    spell.MatchDateTime > DateTime.MinValue)
                {
                    if (spell.CompleteScheduledTime > DateTime.MinValue &&
                        DateTime.Now >= spell.CompleteScheduledTime)
                    {
                        this.Play(spell.TimeupSound);
                        if (!string.IsNullOrWhiteSpace(spell.TimeupTextToSpeak))
                        {
                            var tts = spell.RegexEnabled && regex != null?
                                      regex.Replace(spell.MatchedLog, spell.TimeupTextToSpeak) :
                                          spell.TimeupTextToSpeak;

                            this.Play(tts);
                        }

                        spell.TimeupDone = true;
                    }
                }

                // インスタンス化したスペルを削除する
                if (spell.IsInstance)
                {
                    SpellTimerTable.TryRemoveInstance(spell);
                }
            }
        }
Example #8
0
        /// <summary>
        /// ログとマッチングする
        /// </summary>
        /// <param name="telops">Telops</param>
        /// <param name="logLines">ログ行</param>
        public static void Match(
            IReadOnlyList <OnePointTelop> telops,
            IReadOnlyList <string> logLines)
        {
            foreach (var log in logLines)
            {
                telops.AsParallel().ForAll(telop =>
                {
                    var matched = false;

                    var regex       = telop.Regex;
                    var regexToHide = telop.RegexToHide;

                    // 開始条件を確認する
                    if (ConditionUtility.CheckConditionsForTelop(telop))
                    {
                        // 通常マッチ
                        if (regex == null)
                        {
                            var keyword = telop.KeywordReplaced;
                            if (!string.IsNullOrWhiteSpace(keyword))
                            {
                                if (log.ToUpper().Contains(
                                        keyword.ToUpper()))
                                {
                                    var messageReplaced = ConditionUtility.GetReplacedMessage(telop);
                                    if (!telop.AddMessageEnabled)
                                    {
                                        telop.MessageReplaced = messageReplaced;
                                    }
                                    else
                                    {
                                        telop.MessageReplaced += string.IsNullOrWhiteSpace(telop.MessageReplaced) ?
                                                                 messageReplaced :
                                                                 Environment.NewLine + messageReplaced;
                                    }

                                    telop.MatchDateTime = DateTime.Now;
                                    telop.Delayed       = false;
                                    telop.MatchedLog    = log;
                                    telop.ForceHide     = false;

                                    SoundController.Default.Play(telop.MatchSound);
                                    SoundController.Default.Play(telop.MatchTextToSpeak);

                                    matched = true;
                                }
                            }
                        }

                        // 正規表現マッチ
                        else
                        {
                            var match = regex.Match(log);
                            if (match.Success)
                            {
                                var messageReplaced = ConditionUtility.GetReplacedMessage(telop);
                                if (!telop.AddMessageEnabled)
                                {
                                    telop.MessageReplaced = match.Result(messageReplaced);
                                }
                                else
                                {
                                    telop.MessageReplaced += string.IsNullOrWhiteSpace(telop.MessageReplaced) ?
                                                             match.Result(messageReplaced) :
                                                             Environment.NewLine + match.Result(messageReplaced);
                                }

                                telop.MatchDateTime = DateTime.Now;
                                telop.Delayed       = false;
                                telop.MatchedLog    = log;
                                telop.ForceHide     = false;

                                SoundController.Default.Play(telop.MatchSound);
                                if (!string.IsNullOrWhiteSpace(telop.MatchTextToSpeak))
                                {
                                    var tts = match.Result(telop.MatchTextToSpeak);
                                    SoundController.Default.Play(tts);
                                }

                                matched = true;
                            }
                        }
                    }

                    if (matched)
                    {
                        // ディレイサウンドをスタートさせる
                        telop.StartDelayedSoundTimer();

                        SpellTimerCore.Default.UpdateNormalSpellTimerForTelop(telop, telop.ForceHide);
                        SpellTimerCore.Default.NotifyNormalSpellTimerForTelop(telop.Title);

                        return;
                    }

                    // 通常マッチ(強制非表示)
                    if (regexToHide == null)
                    {
                        var keyword = telop.KeywordToHideReplaced;
                        if (!string.IsNullOrWhiteSpace(keyword))
                        {
                            if (log.ToUpper().Contains(
                                    keyword.ToUpper()))
                            {
                                telop.ForceHide = true;
                                matched         = true;
                            }
                        }
                    }

                    // 正規表現マッチ(強制非表示)
                    else
                    {
                        if (regexToHide.IsMatch(log))
                        {
                            telop.ForceHide = true;
                            matched         = true;
                        }
                    }

                    if (matched)
                    {
                        SpellTimerCore.Default.UpdateNormalSpellTimerForTelop(telop, telop.ForceHide);
                        SpellTimerCore.Default.NotifyNormalSpellTimerForTelop(telop.Title);
                    }
                });   // end loop telops
            }
        }
Example #9
0
        /// <summary>
        /// ログとマッチングする
        /// </summary>
        /// <param name="telops">Telops</param>
        /// <param name="logLines">ログ行</param>
        public static void Match(
            IReadOnlyList <OnePointTelop> telops,
            IReadOnlyList <string> logLines)
        {
            foreach (var log in logLines)
            {
                telops.AsParallel().ForAll(telop =>
                {
                    var matched = false;

                    var regex       = telop.Regex;
                    var regexToHide = telop.RegexToHide;

                    // 開始条件を確認する
                    if (ConditionUtility.CheckConditionsForTelop(telop))
                    {
                        // 通常マッチ
                        if (regex == null)
                        {
                            var keyword = telop.KeywordReplaced;
                            if (!string.IsNullOrWhiteSpace(keyword))
                            {
                                if (log.ToUpper().Contains(
                                        keyword.ToUpper()))
                                {
                                    var messageReplaced = ConditionUtility.GetReplacedMessage(telop);
                                    if (!telop.AddMessageEnabled)
                                    {
                                        telop.MessageReplaced = messageReplaced;
                                    }
                                    else
                                    {
                                        telop.MessageReplaced += string.IsNullOrWhiteSpace(telop.MessageReplaced) ?
                                                                 messageReplaced :
                                                                 Environment.NewLine + messageReplaced;
                                    }

                                    telop.MatchDateTime = DateTime.Now;
                                    telop.Delayed       = false;
                                    telop.MatchedLog    = log;
                                    telop.ForceHide     = false;

                                    SoundController.Default.Play(telop.MatchSound);
                                    SoundController.Default.Play(telop.MatchTextToSpeak);

                                    matched = true;
                                }
                            }
                        }

                        // 正規表現マッチ
                        else
                        {
                            var match = regex.Match(log);
                            if (match.Success)
                            {
                                var messageReplaced = ConditionUtility.GetReplacedMessage(telop);
                                if (!telop.AddMessageEnabled)
                                {
                                    telop.MessageReplaced = match.Result(messageReplaced);
                                }
                                else
                                {
                                    telop.MessageReplaced += string.IsNullOrWhiteSpace(telop.MessageReplaced) ?
                                                             match.Result(messageReplaced) :
                                                             Environment.NewLine + match.Result(messageReplaced);
                                }

                                telop.MatchDateTime = DateTime.Now;
                                telop.Delayed       = false;
                                telop.MatchedLog    = log;
                                telop.ForceHide     = false;

                                SoundController.Default.Play(telop.MatchSound);
                                if (!string.IsNullOrWhiteSpace(telop.MatchTextToSpeak))
                                {
                                    var tts = match.Result(telop.MatchTextToSpeak);
                                    SoundController.Default.Play(tts);
                                }

                                matched = true;
                            }
                        }
                    }

                    if (matched)
                    {
                        SpellTimerCore.Default.updateNormalSpellTimerForTelop(telop, telop.ForceHide);
                        SpellTimerCore.Default.notifyNormalSpellTimerForTelop(telop.Title);
                        return;
                    }

                    // 通常マッチ(強制非表示)
                    if (regexToHide == null)
                    {
                        var keyword = telop.KeywordToHideReplaced;
                        if (!string.IsNullOrWhiteSpace(keyword))
                        {
                            if (log.ToUpper().Contains(
                                    keyword.ToUpper()))
                            {
                                telop.ForceHide = true;
                                matched         = true;
                            }
                        }
                    }

                    // 正規表現マッチ(強制非表示)
                    else
                    {
                        if (regexToHide.IsMatch(log))
                        {
                            telop.ForceHide = true;
                            matched         = true;
                        }
                    }

                    if (matched)
                    {
                        SpellTimerCore.Default.updateNormalSpellTimerForTelop(telop, telop.ForceHide);
                        SpellTimerCore.Default.notifyNormalSpellTimerForTelop(telop.Title);
                    }
                });   // end loop telops
            }

            // スペルの更新とサウンド処理を行う
            foreach (var telop in telops)
            {
                var regex = telop.Regex;

                // ディレイ時間が経過した?
                if (!telop.Delayed &&
                    telop.MatchDateTime > DateTime.MinValue &&
                    telop.Delay > 0)
                {
                    var delayed = telop.MatchDateTime.AddSeconds(telop.Delay);
                    if (DateTime.Now >= delayed)
                    {
                        telop.Delayed = true;
                        SoundController.Default.Play(telop.DelaySound);
                        var tts = regex != null && !string.IsNullOrWhiteSpace(telop.DelayTextToSpeak) ?
                                  regex.Replace(telop.MatchedLog, telop.DelayTextToSpeak) :
                                  telop.DelayTextToSpeak;
                        SoundController.Default.Play(tts);
                    }
                }
            }
#if false
            Parallel.ForEach(telops, (telop) =>
            {
            }); // end loop telops
#endif
        }
        /// <summary>
        /// 1ログ1スペルに対して判定する
        /// </summary>
        /// <param name="spell">スペル</param>
        /// <param name="logLine">ログ</param>
        public void MatchCore(
            Models.SpellTimer spell,
            string logLine)
        {
            var regex        = spell.Regex;
            var notifyNeeded = false;

            if (!spell.IsInstance)
            {
                // マッチング計測開始
                spell.StartMatching();

                // 開始条件を確認する
                if (ConditionUtility.CheckConditionsForSpell(spell))
                {
                    // 正規表現が無効?
                    if (!spell.RegexEnabled ||
                        regex == null)
                    {
                        var keyword = spell.KeywordReplaced;
                        if (string.IsNullOrWhiteSpace(keyword))
                        {
                            return;
                        }

                        // キーワードが含まれるか?
                        if (logLine.Contains(keyword, StringComparison.OrdinalIgnoreCase))
                        {
                            var targetSpell = spell;

                            // ヒットしたログを格納する
                            targetSpell.MatchedLog = logLine;

                            // スペル名(表示テキスト)を置換する
                            var replacedTitle = ConditionUtility.GetReplacedTitle(targetSpell);

                            // PC名を置換する
                            replacedTitle = FFXIVPlugin.Instance.ReplacePartyMemberName(replacedTitle);

                            targetSpell.SpellTitleReplaced = replacedTitle;
                            targetSpell.UpdateDone         = false;
                            targetSpell.OverDone           = false;
                            targetSpell.BeforeDone         = false;
                            targetSpell.TimeupDone         = false;

                            var now = DateTime.Now;
                            targetSpell.CompleteScheduledTime = now.AddSeconds(targetSpell.RecastTime);
                            targetSpell.MatchDateTime         = now;

                            // マッチング計測終了
                            spell.EndMatching();

                            // マッチ時点のサウンドを再生する
                            this.Play(targetSpell.MatchSound);
                            this.Play(targetSpell.MatchTextToSpeak);

                            // DISCORDに通知する?
                            if (targetSpell.NotifyToDiscord)
                            {
                                DiscordBridge.Instance.SendMessageDelegate?.Invoke(
                                    $"{replacedTitle} {targetSpell.RecastTime:N0}");
                            }

                            notifyNeeded = true;

                            // 遅延サウンドタイマを開始する
                            targetSpell.StartOverSoundTimer();
                            targetSpell.StartBeforeSoundTimer();
                            targetSpell.StartTimeupSoundTimer();
                        }
                    }
                    else
                    {
                        // 正規表現でマッチングする
                        var match = regex.Match(logLine);
                        if (match.Success)
                        {
                            var targetSpell = spell;

                            // ヒットしたログを格納する
                            targetSpell.MatchedLog = logLine;

                            // スペル名(表示テキスト)を置換する
                            var replacedTitle = match.Result(ConditionUtility.GetReplacedTitle(targetSpell));

                            // PC名を置換する
                            replacedTitle = FFXIVPlugin.Instance.ReplacePartyMemberName(replacedTitle);

                            // インスタンス化する?
                            if (spell.ToInstance)
                            {
                                // 同じタイトルのインスタンススペルを探す
                                // 存在すればそれを使用して、なければ新しいインスタンスを生成する
                                targetSpell = SpellTimerTable.Instance.GetOrAddInstance(
                                    replacedTitle,
                                    spell);

                                // インスタンスのガーベージタイマをスタートする
                                targetSpell.StartGarbageInstanceTimer();
                            }

                            targetSpell.SpellTitleReplaced = replacedTitle;
                            targetSpell.UpdateDone         = false;
                            targetSpell.OverDone           = false;
                            targetSpell.BeforeDone         = false;
                            targetSpell.TimeupDone         = false;

                            var now = DateTime.Now;

                            // 効果時間を決定する
                            // グループ "duration" をキャプチャーしていた場合は効果時間を置換する
                            var    durationAsText = match.Groups["duration"].Value;
                            double duration;
                            if (!double.TryParse(durationAsText, out duration))
                            {
                                duration = targetSpell.RecastTime;
                            }

                            targetSpell.CompleteScheduledTime = now.AddSeconds(duration);

                            // スペル対象を保存する
                            // グループ "target" をキャプチャーしていた場合はその文字列を保存する
                            var targetName = match.Groups["target"].Value;
                            if (!string.IsNullOrWhiteSpace(targetName))
                            {
                                targetSpell.TargetName = targetName;
                            }

                            // マッチ日時を格納する
                            targetSpell.MatchDateTime = now;

                            // マッチング計測終了
                            spell.EndMatching();

                            // マッチ時点のサウンドを再生する
                            this.Play(targetSpell.MatchSound);

                            if (!string.IsNullOrWhiteSpace(targetSpell.MatchTextToSpeak))
                            {
                                var tts = match.Result(targetSpell.MatchTextToSpeak);
                                this.Play(tts);
                            }

                            // DISCORDに通知する?
                            if (targetSpell.NotifyToDiscord)
                            {
                                DiscordBridge.Instance.SendMessageDelegate?.Invoke(
                                    $"{replacedTitle} {targetSpell.RecastTime:N0}");
                            }

                            notifyNeeded = true;

                            // 遅延サウンドタイマを開始する
                            targetSpell.StartOverSoundTimer();
                            targetSpell.StartBeforeSoundTimer();
                            targetSpell.StartTimeupSoundTimer();
                        }
                    }
                }
            }

            // 延長をマッチングする
            if (spell.MatchDateTime > DateTime.MinValue)
            {
                var keywords      = new string[] { spell.KeywordForExtendReplaced1, spell.KeywordForExtendReplaced2 };
                var regexes       = new Regex[] { spell.RegexForExtend1, spell.RegexForExtend2 };
                var timeToExtends = new double[] { spell.RecastTimeExtending1, spell.RecastTimeExtending2 };

                for (int i = 0; i < 2; i++)
                {
                    var keywordToExtend = keywords[i];
                    var regexToExtend   = regexes[i];
                    var timeToExtend    = timeToExtends[i];

                    // マッチングする
                    var matched = false;

                    if (!spell.RegexEnabled ||
                        regexToExtend == null)
                    {
                        if (!string.IsNullOrWhiteSpace(keywordToExtend))
                        {
                            matched = logLine.Contains(keywordToExtend, StringComparison.OrdinalIgnoreCase);
                        }
                    }
                    else
                    {
                        var match = regexToExtend.Match(logLine);
                        matched = match.Success;

                        if (matched)
                        {
                            // targetをキャプチャーしている?
                            if (!string.IsNullOrWhiteSpace(spell.TargetName))
                            {
                                var targetName = match.Groups["target"].Value;
                                if (!string.IsNullOrWhiteSpace(targetName))
                                {
                                    // targetが当初のマッチングと一致するか確認する
                                    if (spell.TargetName != targetName)
                                    {
                                        matched = false;
                                    }
                                }
                            }
                        }
                    }

                    if (!matched)
                    {
                        continue;
                    }

                    var now = DateTime.Now;

                    // リキャストタイムを延長する
                    var newSchedule = spell.CompleteScheduledTime.AddSeconds(timeToExtend);
                    spell.BeforeDone = false;
                    spell.UpdateDone = false;

                    if (spell.ExtendBeyondOriginalRecastTime)
                    {
                        if (spell.UpperLimitOfExtension > 0)
                        {
                            var newDuration = (newSchedule - now).TotalSeconds;
                            if (newDuration > (double)spell.UpperLimitOfExtension)
                            {
                                newSchedule = newSchedule.AddSeconds(
                                    (newDuration - (double)spell.UpperLimitOfExtension) * -1);
                            }
                        }
                    }
                    else
                    {
                        var newDuration = (newSchedule - now).TotalSeconds;
                        if (newDuration > (double)spell.RecastTime)
                        {
                            newSchedule = newSchedule.AddSeconds(
                                (newDuration - (double)spell.RecastTime) * -1);
                        }
                    }

                    spell.CompleteScheduledTime = newSchedule;
                    spell.MatchDateTime         = now;

                    notifyNeeded = true;

                    // 遅延サウンドタイマを開始(更新)する
                    spell.StartOverSoundTimer();
                    spell.StartBeforeSoundTimer();
                    spell.StartTimeupSoundTimer();
                }
            }
            // end if 延長マッチング

            // ACT標準のSpellTimerに変更を通知する
            if (notifyNeeded)
            {
                this.UpdateNormalSpellTimer(spell, false);
                this.NotifyNormalSpellTimer(spell);
            }
        }