public Reply GetReply(FURRE Furre, string input, string lastfired, Hashtable vars, string prependOutput)
        {
            List<Match> matches = new List<Match>();
            //do replacements, strip áccents is done in ReplaceOnInput if there are no input replacements
            string inputReplaced = TextToolbox.ReplaceOnInput(input, this.inputReplacements);
            //search the children and virtual children (links) of lastfired rule
            if (this.inputs.ContainsKey(lastfired))
            {
                foreach (InputRecognizer ir in this.inputs[lastfired])
                {
                    //if the input recognizer is a capture, use the original input
                    Match match = ir.Matches((ir.IsCapture ? input : inputReplaced), vars, this.csToolbox);

                    if (match.ConfidenceFactor != 0.0)
                    {
                        //copy shortTermMemory vars to inputVars
                        Hashtable inputVars = new Hashtable();
                        foreach (object key in vars.Keys)
                            inputVars[key] = vars[key];
                        //captures the variables and adds them to the inputVars object
                        ir.CaptureVars(input, inputVars);
                        matches.Add(match);
                    }
                }
            }

            if (matches.Count == 0 && this.inputs.ContainsKey("_root"))
            {
                //search all of the primaries
                foreach (InputRecognizer ir in this.inputs["_root"])
                {
                    //if the input recognizer is a capture, use the original input
                    Match match = ir.Matches((ir.IsCapture ? input : inputReplaced), vars, this.csToolbox);
                    if (match.ConfidenceFactor != 0.0)
                    {
                        //copy shortTermMemory vars to inputVars
                        Hashtable inputVars = new Hashtable();
                        foreach (object key in vars.Keys)
                            inputVars[key] = vars[key];
                        //captures the variables and adds them to the inputVars object
                        ir.CaptureVars(input, inputVars);
                        matches.Add(match);
                    }
                }
            }

            if (matches.Count == 0)
                return null;

            matches.Sort();
            Match matchBest = (Match)matches[0];
            //use the matching vars, but maintain the original object so that it persists
            vars.Clone();
            foreach (object key in matchBest.Vars.Keys)
                vars[key] = matchBest.Vars[key];
            //increment the usage count on the chosed InputRecognizer
            matchBest.InputRecognizer.IncUsageCount();

            string ruleId = matchBest.InputRecognizer.RuleId;

            if (!this.outputs.ContainsKey(ruleId) || this.outputs[ruleId].Count == 0)
            {
                Reply noOutputFoundReply = new Reply(Furre,"Rule contains no outputs.", "", "", ruleId, 0, this.knowledgeBaseItem);

                if (this.csToolbox.StandardNoOutputFoundDefined)
                {
                    string noOutputFoundText = this.csToolbox.ExecuteOnNoOutputFound(vars, noOutputFoundReply);
                    noOutputFoundReply.Text += this.DoTextReplacements( noOutputFoundText);
                    noOutputFoundReply.AgentText += this.DoAgentTextReplacements(noOutputFoundText);
                }

                return noOutputFoundReply;
            }

            List<Output> alOutputs = new List<Output>();
            if (this.outputs.ContainsKey(ruleId))
                alOutputs = new List<Output>(this.outputs[ruleId]);

            bool trueNonEmptyOutputConditionFound = false;

            //filter out outputs with false conditions
            for (int i = 0; i < alOutputs.Count; i++)
            {
                Output o = (Output)alOutputs[i];
                if (!this.csToolbox.ExecuteCondition(o.Id, vars))
                {
                    alOutputs.RemoveAt(i);
                    i--;
                }
                else if (o.Condition != null && o.Condition != "")
                {
                    trueNonEmptyOutputConditionFound = true;
                }
            }
            if (alOutputs.Count == 0)//all outputs were removed
            {
                Reply noOutputFoundReply = new Reply(Furre, "No true output found.", "", "", ruleId, 0, this.knowledgeBaseItem);

                if (this.csToolbox.StandardNoOutputFoundDefined)
                {
                    string noOutputFoundText = this.csToolbox.ExecuteOnNoOutputFound(vars, noOutputFoundReply);
                    noOutputFoundReply.Text += this.DoTextReplacements( noOutputFoundText);
                    noOutputFoundReply.AgentText += this.DoAgentTextReplacements(noOutputFoundText);
                }

                return noOutputFoundReply;
            }

            //filter out outputs with no conditions if there is an output which has a true condition
            if (trueNonEmptyOutputConditionFound)
            {
                for (int i = 0; i < alOutputs.Count; i++)
                {
                    Output o = (Output)alOutputs[i];
                    if (o.Condition == null || o.Condition == "")
                    {
                        alOutputs.RemoveAt(i);
                        i--;
                    }
                }
            }

            //choose an output at random
            Output outputChosen = null;
            for (int i = 0; i < alOutputs.Count; i++)//the try again loop
            {
                outputChosen = ((Output)alOutputs[random.Next(alOutputs.Count)]);
                if (!this.recentOutputsByRule.ContainsKey(ruleId) || !this.recentOutputsByRule[ruleId].Contains(outputChosen.Id))
                    break;
            }

            //update the recent list for this rule
            if (alOutputs.Count > 1)
            {
                if (!this.recentOutputsByRule.ContainsKey(ruleId))
                    this.recentOutputsByRule[ruleId] = new List<string>(alOutputs.Count - 1);
                List<string> recent = this.recentOutputsByRule[ruleId];
                int index = recent.IndexOf(outputChosen.Id);
                if (index != -1)
                    recent.RemoveAt(index);
                else if (recent.Count == alOutputs.Count - 1)
                    recent.RemoveAt(0);
                recent.Add(outputChosen.Id);
            }
            //replace vars and output synonyms
            string outputChosenText = prependOutput + outputChosen.Text;
            if (this.csToolbox.OutputExists(outputChosen.Id))
                outputChosenText = this.csToolbox.ExecuteOutput(outputChosen.Id, vars);
            outputChosenText = TextToolbox.ReplaceVars(outputChosenText, vars);
            outputChosenText = TextToolbox.ReplaceOutputSynonyms(outputChosenText, this.synonyms);
            //execute c# code in the command field
            string outputChosenCmd = outputChosen.Cmd;
            if (this.csToolbox.OutputExists(outputChosen.Id + "_cmd"))
                outputChosenCmd = this.csToolbox.ExecuteOutput(outputChosen.Id + "_cmd", vars);

            string outputText = this.DoTextReplacements( outputChosenText);
            string agentText = this.DoAgentTextReplacements(outputChosenText);
            string outputCmd = TextToolbox.ReplaceVars(outputChosenCmd, vars);

            return new Reply(Furre, outputText, agentText, outputCmd, matchBest.InputRecognizer.RuleId, matchBest.ConfidenceFactor, this.knowledgeBaseItem);
        }
 public string ExecuteOnNoRuleFired(State s, Reply r)
 {
     string ret = "";
     if (this.standardNoRuleFiredDefined)
     {
         object[] args = { s, r };
         ret = this.ExecuteStandardJob(this.STD_EVENT_NAME_NO_RULE_FIRED, args);
     }
     return ret;
 }
        public Reply GetReply(FURRE Furre, string input, State state)
        {
            DateTime FurcTime =  TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,
            TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"));
            state.Vars["_input"] = input;
            state.Vars["_lastinput"] = state.Lastinput;
            state.Vars["_lastfired"] = state.Lastfired;
            state.Vars["_time"] = FurcTime.ToString("h:mm tt");
            state.Vars["_time24"] = FurcTime.ToString("HH:mm");
            state.Vars["_date"] = FurcTime.ToString("MMM. d, yyyy");
            state.Vars["_month"] = FurcTime.ToString("MMMM");
            state.Vars["_dayofmonth"] = FurcTime.ToString("d ").Trim();
            state.Vars["_year"] = FurcTime.ToString("yyyy");
            state.Vars["_dayofweek"] = FurcTime.ToString("dddd");
            state.Vars["furrename"] = Furre.Name;
            state.Vars["furregender"] = Furre.Gender.ToString();
            state.Vars["furrespecies"] = Furre.DSSpecies.ToString();
            if (input.Length == 0)
                input = "_blank";

            state.Lastinput = input;
            bool standardNoRuleFiredDefined = false;
            Reply noRuleFiredReply = new Reply("", "", "", "", 0.0, null);
            foreach (string stPath in state.CurrentKBs)
            {
                if (this.compiledKnowledgeBases.ContainsKey(stPath))
                {
                    CompiledKnowledgeBase ckb = (CompiledKnowledgeBase)this.compiledKnowledgeBases[stPath];
                    string ckbOutput = ckb.CSToolbox.ExecuteOnBeforeRuleFired(state);
                    //update our input var incase the Before Rule Fired changes it
                    input = (string)state.Vars["_input"];
                    state.Lastinput = input;
                    Reply reply = ckb.GetReply(Furre, input, state.Lastfired, state.Vars, ckbOutput);
                    if (reply != null)
                    {
                        ckbOutput = ckb.CSToolbox.ExecuteOnAfterRuleFired(state, reply);
                        string outputText = ckb.DoTextReplacements( ckbOutput);
                        string agentText = ckb.DoAgentTextReplacements(ckbOutput);
                        reply.Text += outputText;
                        reply.AgentText += agentText;
                        state.Lastfired = reply.RuleId;
                        state.Vars["_lastoutput"] = reply.Text;
                        return reply;
                    }
                    if (ckb.CSToolbox.StandardNoRuleFiredDefined)
                    {
                        standardNoRuleFiredDefined = true;
                        //if this ckb has a no rule fired handler, fire it
                        noRuleFiredReply.KBItem = ckb.KnowledgeBaseItem;
                        string noReplyText = ckb.CSToolbox.ExecuteOnNoRuleFired(state, noRuleFiredReply);
                        noRuleFiredReply.Text += ckb.DoTextReplacements( noReplyText);
                        noRuleFiredReply.AgentText += ckb.DoAgentTextReplacements(noReplyText);
                    }
                }
            }
            if (standardNoRuleFiredDefined)
                return noRuleFiredReply;
            return null; //if there's no reply, return null
        }
 public string ExecuteOnNoOutputFound(Hashtable vars, Reply r)
 {
     string ret = "";
     if (this.standardNoOutputFoundDefined)
     {
         object[] args = { vars, r };
         ret = this.ExecuteStandardJob(this.STD_EVENT_NAME_NO_OUTPUT_FOUND, args);
     }
     return ret;
 }