/*
         * Testing what KS_ScheduledFilterSelector.OutputPoolNameEmumerator() is returning
         */

        private static void TestOutputPoolNameEnumerator()
        {
            Blackboard blackboard = new Blackboard();

            var fs1 = new KS_ScheduledHighestTierSelector <KC_Order>(blackboard);
            var fs2 = new KS_ScheduledLowestTierSelector <KC_Order>(blackboard);
            var fs3 = new KS_ScheduledFilterSelector(blackboard);
            var fs4 = new KS_ScheduledUniformDistributionSelector(blackboard);

            Console.WriteLine($"fs1.OutputPool = {fs1.OutputPool}");
            Console.WriteLine($"fs1.DefaultOutputPoolName = {fs1.DefaultOutputPoolName}");

            Console.WriteLine($"fs2.OutputPool = {fs2.OutputPool}");
            Console.WriteLine($"fs2.DefaultOutputPoolName = {fs2.DefaultOutputPoolName}");

            Console.WriteLine($"fs3.OutputPool = {fs3.OutputPool}");
            Console.WriteLine($"fs3.DefaultOutputPoolName = {fs3.DefaultOutputPoolName}");

            Console.WriteLine($"fs4.OutputPool = {fs4.OutputPool}");
            Console.WriteLine($"fs4.DefaultOutputPoolName = {fs4.DefaultOutputPoolName}");

            //IEnumerator<string> enumerator = fs.OutputPoolNameEnumerator();
            //for(int i =0; i < 10; i++)
            //{
            //    enumerator.MoveNext();
            //    Console.WriteLine(enumerator.Current);
            //}
        }
        public void TestRemoveKnowledgeSource_ScheduledSequenceController()
        {
            IBlackboard blackboard                 = new Blackboard();
            IScheduledKnowledgeSource   ks1        = new KS_ScheduledFilterSelector(blackboard, inputPool: "pool1");
            IScheduledKnowledgeSource   ks2        = new KS_ScheduledIDSelector(blackboard, inputPool: "pool1", outputPool: "pool2");
            IScheduledKnowledgeSource   ks3        = new KS_ScheduledUniformDistributionSelector(blackboard, inputPool: "pool2", outputPool: "pool3", numberToSelect: 1);
            ScheduledSequenceController controller = new ScheduledSequenceController();

            controller.AddKnowledgeSource(ks1);
            controller.AddKnowledgeSource(ks2);
            controller.AddKnowledgeSource(ks3);

            Assert.True(controller.RegisteredKnowledgeSource(ks1));
            Assert.True(controller.RegisteredKnowledgeSource(ks2));
            Assert.True(controller.RegisteredKnowledgeSource(ks3));

            controller.RemoveKnowledgeSource(ks3);
            Assert.True(controller.RegisteredKnowledgeSource(ks1));
            Assert.True(controller.RegisteredKnowledgeSource(ks2));
            Assert.False(controller.RegisteredKnowledgeSource(ks3));

            controller.RemoveKnowledgeSource(ks2);
            Assert.True(controller.RegisteredKnowledgeSource(ks1));
            Assert.False(controller.RegisteredKnowledgeSource(ks2));
            Assert.False(controller.RegisteredKnowledgeSource(ks3));

            controller.RemoveKnowledgeSource(ks1);
            Assert.False(controller.RegisteredKnowledgeSource(ks1));
            Assert.False(controller.RegisteredKnowledgeSource(ks2));
            Assert.False(controller.RegisteredKnowledgeSource(ks3));
        }
        public Demo2()
        {
            Blackboard = new Blackboard();
            Demo2_DefineUnits(Blackboard);

            m_IDSelector = new KS_ScheduledIDSelector(Blackboard);

            m_prologEval = new KS_ScheduledPrologEval(Blackboard,
                                                      inputPool: m_IDSelector.OutputPool,
                                                      prologExpName: ApplTest_Prolog);

            /*
             * fixme: consider creating a filtered by boolean result KS or a more general filter by KC_EvaluatedExpression (once I have more EvaluatedExpressions than Prolog).
             */
            m_filterByPrologResult = new KS_ScheduledFilterSelector(Blackboard,
                                                                    inputPool: m_prologEval.OutputPool,
                                                                    outputPool: FilteredPrologResultPool,
                                                                    filter: KS_ScheduledPrologEval.FilterByPrologResult(ApplTest_Prolog, true));

            m_uniformRandomSelector = new KS_ScheduledUniformDistributionSelector(Blackboard,
                                                                                  inputPool: FilteredPrologResultPool,
                                                                                  outputPool: UniformlySelectedOutputPool,
                                                                                  numberToSelect: 1);

            m_choicePresenter = new KS_ScheduledChoicePresenter(Blackboard,
                                                                UniformlySelectedOutputPool);

            m_filterPoolCleaner = new KS_ScheduledFilterPoolCleaner(Blackboard,
                                                                    new string[]
            {
                m_IDSelector.OutputPool,           // Output pool for ID selector
                m_prologEval.OutputPool,           // Output pool for prolog eval
                m_filterByPrologResult.OutputPool, // Output pool for filter that filters by prolog result
                m_uniformRandomSelector.OutputPool // Final output pool (written into by UniformDistributionSelector)
            });

            Controller = new ScheduledSequenceController();
            Controller.AddKnowledgeSource(m_IDSelector);
            Controller.AddKnowledgeSource(m_prologEval);
            Controller.AddKnowledgeSource(m_filterByPrologResult);
            Controller.AddKnowledgeSource(m_uniformRandomSelector);
            Controller.AddKnowledgeSource(m_choicePresenter);
            Controller.AddKnowledgeSource(m_filterPoolCleaner);

            // Put request for starting content unit in blackboard
            Unit req = new Unit();

            req.AddComponent(new KC_IDSelectionRequest("start", true));
            req.SetActiveRequest(true);
            Blackboard.AddUnit(req);
        }
        public void TestExecute_ScheduledSequenceController()
        {
            string id    = "id1";
            string pool1 = "pool1";
            string pool2 = "pool2";

            IBlackboard blackboard                 = new Blackboard();
            IScheduledKnowledgeSource   ks1        = new KS_ScheduledFilterSelector(blackboard, inputPool: null, outputPool: pool1, filter: (Unit u) => u.HasComponent <KC_UnitID>());
            IScheduledKnowledgeSource   ks2        = new KS_ScheduledIDSelector(blackboard, inputPool: pool1, outputPool: pool2);
            ScheduledSequenceController controller = new ScheduledSequenceController();

            controller.AddKnowledgeSource(ks1);
            controller.AddKnowledgeSource(ks2);

            Unit unit = new Unit();

            unit.AddComponent(new KC_UnitID(id));
            blackboard.AddUnit(unit);

            Unit req = new Unit();

            req.AddComponent(new KC_IDSelectionRequest(id));
            blackboard.AddUnit(req);
            req.SetActiveRequest(true);

            controller.Execute();

            var pool1Units = from u in blackboard.LookupUnits <Unit>()
                             where u.HasComponent <KC_ContentPool>()
                             where u.ContentPoolEquals(pool1)
                             select u;

            var pool2Units = from u in blackboard.LookupUnits <Unit>()
                             where u.HasComponent <KC_ContentPool>()
                             where u.ContentPoolEquals(pool2)
                             select u;

            int pool1Count = pool1Units.Count();
            int pool2Count = pool2Units.Count();

            Assert.Equal(1, pool1Count);
            Assert.Equal(1, pool2Count);

            Assert.True(pool1Units.First().UnitIDEquals(id));
            Assert.True(pool2Units.First().UnitIDEquals(id));
        }
        public DemoEnsembleLite()
        {
            Blackboard = new Blackboard();
            DemoEnsemble_DefineUnits(Blackboard);

            /*
             * This prolog evaluator evauates the conditions of rules in the rules pool.
             * Construct the prolog evaluator with the following parameters:
             * * The blackboard on which to do the work.
             * * The input pool to look for ContentUnits with prolog expressions to evaluate.
             * * The name of the prolog expression to evaluate (in this case the prolog expression named ApplTest_Prolog, for which a string constant is defined in KCNames).
             */
            var prologEval = new KS_ScheduledPrologEval(Blackboard, inputPool: RulesPool, outputPool: EvalRulesPool, ApplTest_Prolog);

            /*
             * fixme: consider creating a filtered by boolean result KS or a more general filter by KC_EvaluatedExpression (once I have more EvaluatedExpressions than Prolog).
             * This filter selector selects all the rules whose prolog expression evaluated to true.
             */
            var filterByPrologResult = new KS_ScheduledFilterSelector(Blackboard,
                                                                      inputPool: EvalRulesPool,
                                                                      outputPool: SatisfiedRulesPool,
                                                                      filter: KS_ScheduledPrologEval.FilterByPrologResult(ApplTest_Prolog, true));

            /*
             * This KS prints out info about satisified rules (for debugging).
             */
            var printFilteredRules = new KS_ScheduledPrintPool(Blackboard, SatisfiedRulesPool);

            /*
             * This KS takes a pool of things to weight (in this case dialog) and a pool of utility sources (in this case satisfied rules) and sums the utility sources
             * applicable to each unit to weight to compute a new pool of weighted units.
             */
            var weightDialogWithRules = new KS_ScheduledUtilitySum(Blackboard, SatisfiedRulesPool, DialogPool, WeightedDialogPool);

            /*
             * This KS prints out the pool of weighted dialog (for debugging).
             */
            var printWeightedDialog = new KS_ScheduledPrintPool(Blackboard, WeightedDialogPool);

            /*
             * This KS selects the most highly weighted dialog lines into a pool (e.g. if the highest weighting is 10, and their are two dialog lines
             * that share that weight, it will copy both of them into the output pool).
             */
            var selectHighestWeightedDialog = new KS_ScheduledHighestTierSelector <KC_Utility>(Blackboard, WeightedDialogPool, HighestWeightedDialogPool);

            /*
             * This KS prints out the units in the HighestWeightedDialogPool (for debugging).
             */
            var printHighestWeightedDialog = new KS_ScheduledPrintPool(Blackboard, HighestWeightedDialogPool);

            /*
             * This KS selects one line at random from the HighestWeightedDialogPool.
             */
            var selectDialogLine = new KS_ScheduledUniformDistributionSelector(Blackboard,
                                                                               inputPool: HighestWeightedDialogPool, outputPool: SelectedDialogPool, numberToSelect: 1);

            /*
             * This KS prints out the units in the SelectedDialogPool (there will be only one dialog line in this pool). (for debugging)
             */
            var printSelectedDialogLine = new KS_ScheduledPrintPool(Blackboard, SelectedDialogPool);

            /*
             * This KS is updating the prolog KB based on the effects on the selected dialog line.
             * fixme: for now I'm just using KS_ScheduledExecute to call the SelectChoice_PrologKBChanges. Need to refactor SelectChoice_PrologKBChanges because it's not just tied to SelectChoice and possibly move KB updates into
             * a special purpose KS.
             */
            var updatePrologKB = new KS_ScheduledExecute(
                () =>
            {
                var selectedDialodLines = from Unit node in Blackboard.LookupUnits <Unit>()
                                          where ScheduledKnowledgeSource.SelectFromPool(node, SelectedDialogPool)
                                          select node;

                foreach (Unit unit in selectedDialodLines)
                {
                    /*
                     * SelectChoice_PrologKBChanges() is an event handler, so it expects a sender as well as for args to be wrapped in EventArgs.
                     * So I'm using this as the sender (PrologKBChanges doesn't actually use the sender) wrapping in SelectChoiceEventArgs.
                     */
                    var eventArgs = new SelectChoiceEventArgs(unit, Blackboard);
                    EventHandlers_ChoicePresenter.SelectChoice_PrologKBChanges(this, eventArgs);
                }
            }
                );

            /*
             * This KS cleans up all the pools that were created during the selection process.
             */
            var poolCleaner = new KS_ScheduledFilterPoolCleaner(
                Blackboard,
                new string[]
            {
                EvalRulesPool,
                SatisfiedRulesPool,
                WeightedDialogPool,
                HighestWeightedDialogPool,
                SelectedDialogPool
            }
                );

            Controller = new ScheduledSequenceController();
            Controller.AddKnowledgeSource(prologEval);
            Controller.AddKnowledgeSource(filterByPrologResult);
            Controller.AddKnowledgeSource(printFilteredRules);
            Controller.AddKnowledgeSource(weightDialogWithRules);
            Controller.AddKnowledgeSource(printWeightedDialog);
            Controller.AddKnowledgeSource(selectHighestWeightedDialog);
            Controller.AddKnowledgeSource(printHighestWeightedDialog);
            Controller.AddKnowledgeSource(selectDialogLine);
            Controller.AddKnowledgeSource(printSelectedDialogLine);
            Controller.AddKnowledgeSource(updatePrologKB);
            Controller.AddKnowledgeSource(poolCleaner);
        }