Example #1
0
        public void TestTrueFalse()
        {
            var tree = new TriggerTree();

            tree.AddTrigger("exists(blah) && true", 1);
            tree.AddTrigger("exists(blah) && false", 2);
            tree.AddTrigger("exists(blah)", 3);
            tree.AddTrigger("true", 4);
            tree.AddTrigger("false", 5);
            var memory = new Dictionary <string, object>();

            var matches = tree.Matches(memory).ToList();

            Assert.AreEqual(1, matches.Count);
            var triggers = matches[0].Triggers;

            Assert.AreEqual(1, triggers.Count);
            Assert.AreEqual(4, triggers[0].Action);

            memory.Add("blah", 1);
            matches = tree.Matches(memory).ToList();
            Assert.AreEqual(1, matches.Count());
            triggers = matches[0].Triggers;
            Assert.AreEqual(2, triggers.Count);
            Assert.AreEqual(1, triggers[0].Action);
            Assert.AreEqual(3, triggers[1].Action);
        }
Example #2
0
        public void TestRoot()
        {
            var tree = new TriggerTree();

            tree.AddTrigger("true", "root");
            var matches = tree.Matches(new Dictionary <string, object>());

            Assert.AreEqual(1, matches.Count());
            Assert.AreEqual("root", matches.First().Action);
        }
Example #3
0
        public void TestOr()
        {
            var tree = new TriggerTree();

            tree.AddTrigger("exists(woof) || exists(blah)", 1);
            tree.AddTrigger("exists(blah)", 2);
            tree.AddTrigger("exists(blah) && exists(foo)", 3);
            var frame = new Dictionary <string, object> {
                { "blah", 1 }, { "woof", 3 }
            };
            var matches = tree.Matches(frame).ToList();

            Assert.AreEqual(2, matches.Count);
            Assert.AreEqual(1, matches[0].Action);
            Assert.AreEqual(2, matches[1].Action);
        }
Example #4
0
        public void TestIgnore()
        {
            var tree = new TriggerTree();

            tree.AddTrigger("ignore(!exists(foo)) && exists(blah)", 1);
            tree.AddTrigger("exists(blah) && ignore(!exists(foo2)) && woof == 3", 2);
            tree.AddTrigger("exists(blah) && woof == 3", 3);
            tree.AddTrigger("exists(blah) && woof == 3 && ignore(!exists(foo2))", 2);
            var frame = new Dictionary <string, object> {
                { "blah", 1 }, { "woof", 3 }
            };
            var matches = tree.Matches(frame).ToList();

            Assert.Equal(2, matches.Count);
            Assert.Equal(2, matches[0].Action);
            Assert.Equal(3, matches[1].Action);
        }
        /// <summary>
        /// Selects the best rule to execute.
        /// </summary>
        /// <param name="context">The <see cref="DialogContext"/> for the current turn of conversation.</param>
        /// <param name="cancellationToken">Optional, <see cref="CancellationToken"/> of the task.</param>
        /// <returns>Best rule in original list to execute or -1 if none.</returns>
        public override async Task <IReadOnlyList <OnCondition> > SelectAsync(ActionContext context, CancellationToken cancellationToken)
        {
            var triggers = _tree.Matches(context.State);
            var matches  = new List <OnCondition>();

            foreach (var trigger in triggers)
            {
                matches.Add(trigger.Action as OnCondition);
            }

            IReadOnlyList <OnCondition> selections = matches;

            if (matches.Count > 0 && Selector != null)
            {
                Selector.Initialize(matches, false);
                selections = await Selector.SelectAsync(context, cancellationToken).ConfigureAwait(false);
            }

            return(selections);
        }
Example #6
0
        public virtual async Task <IReadOnlyList <OnCondition> > Select(SequenceContext context, CancellationToken cancel)
        {
            var triggers = _tree.Matches(context.GetState());
            var matches  = new List <OnCondition>();

            foreach (var trigger in triggers)
            {
                matches.Add(trigger.Action as OnCondition);
            }

            IReadOnlyList <OnCondition> selections = matches;

            if (Selector != null)
            {
                Selector.Initialize(matches, false);
                selections = await Selector.Select(context, cancel).ConfigureAwait(false);
            }

            return(selections);
        }
        public async Task <IReadOnlyList <int> > Select(SequenceContext context, CancellationToken cancel)
        {
            var nodes = _tree.Matches(context.State);
            IReadOnlyList <int> selections;

            if (Selector == null)
            {
                // Return all matches
                var matches = new List <int>();
                foreach (var node in nodes)
                {
                    foreach (var trigger in node.AllTriggers)
                    {
                        var(pos, rule) = (ValueTuple <int, OnCondition>)trigger.Action;
                        matches.Add(pos);
                    }
                }

                selections = matches;
            }
            else
            {
                var matches = new List <ValueTuple <int, OnCondition> >();
                foreach (var node in nodes)
                {
                    foreach (var trigger in node.AllTriggers)
                    {
                        matches.Add((ValueTuple <int, OnCondition>)trigger.Action);
                    }
                }

                // Sort rules by original order and then pass to child selector
                matches = (from candidate in matches orderby candidate.Item1 ascending select candidate).ToList();
                Selector.Initialize(matches.Select(m => m.Item2), false);
                selections = (from match in await Selector.Select(context, cancel).ConfigureAwait(false) select matches[match].Item1).ToList();
            }

            return(selections);
        }
Example #8
0
        public void TestTree()
        {
            var numPredicates   = 100;
            var numSingletons   = 50;
            var numConjunctions = 100;
            var numDisjunctions = 100;
            var numOptionals    = 100;
            var numQuantifiers  = 100;
            var numNots         = 100;

            var minClause      = 2;
            var maxClause      = 4;
            var maxExpansion   = 3;
            var maxQuantifiers = 3;
            var singletons     = _generator.GeneratePredicates(numPredicates, "mem");
            var tree           = new TriggerTree();
            var predicates     = new List <ExpressionInfo>(singletons);
            var triggers       = new List <Trigger>();

            // Add singletons
            foreach (var predicate in singletons.Take(numSingletons))
            {
                triggers.Add(tree.AddTrigger(predicate.Expression, predicate.Bindings));
            }

            Assert.AreEqual(numSingletons, tree.TotalTriggers);

            // Add conjunctions and test matches
            var conjunctions = _generator.GenerateConjunctions(predicates, numConjunctions, minClause, maxClause);

            foreach (var conjunction in conjunctions)
            {
                var memory = new Dictionary <string, object>();
                foreach (var binding in conjunction.Bindings)
                {
                    memory.Add(binding.Key, binding.Value.Value);
                }

                var trigger = tree.AddTrigger(conjunction.Expression, conjunction.Bindings);
                var matches = tree.Matches(memory);
                triggers.Add(trigger);
                Assert.IsTrue(matches.Count() >= 1);
                var first = matches.First().Clauses.First();
                foreach (var match in matches)
                {
                    Assert.AreEqual(RelationshipType.Equal, first.Relationship(match.Clauses.First(), tree.Comparers));
                }
            }

            Assert.AreEqual(numSingletons + numConjunctions, tree.TotalTriggers);

            // Add disjunctions
            predicates.AddRange(conjunctions);
            var disjunctions = _generator.GenerateDisjunctions(predicates, numDisjunctions, minClause, maxClause);

            foreach (var disjunction in disjunctions)
            {
                triggers.Add(tree.AddTrigger(disjunction.Expression, disjunction.Bindings));
            }

            Assert.AreEqual(numSingletons + numConjunctions + numDisjunctions, tree.TotalTriggers);

            var all = new List <ExpressionInfo>(predicates);

            all.AddRange(disjunctions);

            // Add optionals
            var optionals = _generator.GenerateOptionals(all, numOptionals, minClause, maxClause);

            foreach (var optional in optionals)
            {
                triggers.Add(tree.AddTrigger(optional.Expression, optional.Bindings));
            }

            Assert.AreEqual(numSingletons + numConjunctions + numDisjunctions + numOptionals, tree.TotalTriggers);
            all.AddRange(optionals);

            // Add quantifiers
            var quantified = _generator.GenerateQuantfiers(all, numQuantifiers, maxClause, maxExpansion, maxQuantifiers);

            foreach (var expr in quantified)
            {
                triggers.Add(tree.AddTrigger(expr.Expression, expr.Bindings, expr.Quantifiers.ToArray()));
            }

            Assert.AreEqual(numSingletons + numConjunctions + numDisjunctions + numOptionals + numQuantifiers, tree.TotalTriggers);
            all.AddRange(quantified);

            var nots = _generator.GenerateNots(all, numNots);

            foreach (var expr in nots)
            {
                triggers.Add(tree.AddTrigger(expr.Expression, expr.Bindings, expr.Quantifiers.ToArray()));
            }

            Assert.AreEqual(numSingletons + numConjunctions + numDisjunctions + numOptionals + numQuantifiers + numNots, tree.TotalTriggers);
            all.AddRange(nots);

            VerifyTree(tree);

            // Test matches
            foreach (var predicate in predicates)
            {
                var memory = new Dictionary <string, object>();
                foreach (var binding in predicate.Bindings)
                {
                    memory.Add(binding.Key, binding.Value.Value);
                }

                var matches = tree.Matches(memory).ToList();

                // Clauses in every match must not generalize or specialize other matches
                for (var i = 0; i < matches.Count; ++i)
                {
                    var first = matches[i];
                    for (var j = i + 1; j < matches.Count; ++j)
                    {
                        var second = matches[j];
                        var found  = false;
                        foreach (var firstClause in first.Clauses)
                        {
                            var(match, error) = firstClause.TryEvaluate <bool>(memory);
                            if (error == null && match)
                            {
                                foreach (var secondClause in second.Clauses)
                                {
                                    bool match2;
                                    (match2, error) = firstClause.TryEvaluate <bool>(memory);
                                    if (error == null && match2)
                                    {
                                        var reln = firstClause.Relationship(secondClause, tree.Comparers);
                                        if (reln == RelationshipType.Equal || reln == RelationshipType.Incomparable)
                                        {
                                            found = true;
                                            break;
                                        }
                                    }
                                }

                                if (found)
                                {
                                    break;
                                }
                            }
                        }

                        Assert.IsTrue(found);
                    }
                }
            }

            // NOTE: This is useful to test tree visualization, but not really a test.
            // tree.GenerateGraph("tree.dot");

            // Delete triggers
            Assert.AreEqual(triggers.Count, tree.TotalTriggers);
            foreach (var trigger in triggers)
            {
                tree.RemoveTrigger(trigger);
            }

            Assert.AreEqual(0, tree.TotalTriggers);
            VerifyTree(tree);
        }