예제 #1
0
        private void ProcessEvent(BehaviourInfo behaviourInfo, object sender, StateUpdateEventArgs args)
        {
            Debug.Assert(Enabled, "Enabled");

            var targetBehaviour = behaviourInfo.Behaviour;

            if (!targetBehaviour.Enabled)
            {
                return;
            }

            // Wait for the cooldown period before running again
            var lastTriggerTime = TriggerCounter.GetCounter(behaviourInfo.Behaviour).LastTriggerTime;

            if (lastTriggerTime.AddSeconds(behaviourInfo.Behaviour.CooldownPeriod) > args.SnapshotTime)
            {
                return;
            }

            var triggerTester = new Func <ITrigger, bool>(tr =>
            {
                try
                {
                    var triggerResult = tr.ProcessTrigger(sender, args);
                    if ((triggerResult && !tr.InvertResult) || (!triggerResult && tr.InvertResult))
                    {
                        TriggerCounter.BumpCounter(tr, args.SnapshotTime);
                        return(true);
                    }
                }
                catch (Exception ex)
                {
                    DebugTools.WriteException(ex);
                }
                return(false);
            });

            var triggerTriggered = targetBehaviour.Triggers.Where(x => x.Enabled).Any(triggerTester);

            if (triggerTriggered)
            {
                triggerTriggered = targetBehaviour.Conditions.Where(x => x.Enabled).All(triggerTester);
            }

            var result = false;

            switch (targetBehaviour.TriggeringKind)
            {
            case TriggeringMode.RisingEdge:
                result = !behaviourInfo.LastTriggerState && triggerTriggered;
                break;

            case TriggeringMode.FallingEdge:
                result = behaviourInfo.LastTriggerState && !triggerTriggered;
                break;

            case TriggeringMode.Always:
                result = triggerTriggered;
                break;

            case TriggeringMode.BothEdges:
                result = (!behaviourInfo.LastTriggerState && triggerTriggered) ||
                         (behaviourInfo.LastTriggerState && !triggerTriggered);
                break;

            case TriggeringMode.Timed:
                if (triggerTriggered)
                {
                    if (behaviourInfo.InitialTriggerTime.Equals(DateTime.MaxValue))
                    {
                        break;
                    }

                    if (behaviourInfo.InitialTriggerTime.AddSeconds(targetBehaviour.MinimalTimedTriggerDelay)
                        <= args.SnapshotTime)
                    {
                        behaviourInfo.InitialTriggerTime = DateTime.MaxValue;

                        result = true;
                    }
                }
                else
                {
                    behaviourInfo.InitialTriggerTime = args.SnapshotTime;
                }
                break;

            default:
                throw new InvalidEnumArgumentException();
            }

            behaviourInfo.LastTriggerState = triggerTriggered;

            if (!result)
            {
                return;
            }

            Action runActions = () =>
            {
                foreach (var action in targetBehaviour.Actions.Where(x => x.Enabled))
                {
                    try
                    {
                        action.ExecuteAction(sender, args);
                        TriggerCounter.BumpCounter(action, args.SnapshotTime);
                    }
                    catch (Exception ex)
                    {
                        DebugTools.WriteException(ex);
                    }
                }
            };

            if (string.IsNullOrEmpty(targetBehaviour.Group))
            {
                //BUG different than running using BehaviourGroup, can queue next run before it ends
                // Task doesnt exist yet or it has been completed
                if (behaviourInfo.UngroupedTask?.IsCompleted != false)
                {
                    behaviourInfo.UngroupedTask = Task.Run(runActions);
                }
            }
            else
            {
                BehaviourGroup behaviourGroup;

                if (!_groupedTasks.TryGetValue(targetBehaviour.Group, out behaviourGroup))
                {
                    behaviourGroup = new BehaviourGroup();
                    _groupedTasks.Add(targetBehaviour.Group, behaviourGroup);
                }

                behaviourGroup.RunBehaviour(runActions, targetBehaviour);
            }

            TriggerCounter.BumpCounter(behaviourInfo.Behaviour, args.SnapshotTime);
        }