}//replaceSynonyms(string input, Dictionary<string, Synonym> synonymGroups) public static string ReplaceVars(string text, Hashtable vars) { int start = text.IndexOf("["); int end; while (start != -1) { if (!TextToolbox.IsEscaped(text, start)) { end = TextToolbox.FindNextMatchingChar(text, start); if (end != -1) { string varName = TextToolbox.ReplaceVars(text.Substring(start + 1, end - start - 1), vars); string varDefaultValue = ""; if (varName.IndexOf(':') != -1) { varDefaultValue = varName.Substring(varName.IndexOf(':') + 1).Trim(); varName = varName.Substring(0, varName.IndexOf(':')).Trim(); } varName = varName.Replace(" ", "_"); string varValue = (string)vars[varName.ToLower()]; if (varValue == null) { varValue = varDefaultValue; } if (end == text.Length - 1) //var runs to the end { text = text.Substring(0, start) + varValue; start = -1; } else { text = text.Substring(0, start) + varValue + text.Substring(end + 1); start = text.IndexOf("[", start + varValue.Length); } } else //there's an error with this input, it won't compile { //TODO: log an error somewhere? return(""); } } else // [ is escaped { //remove the '\' text = text.Remove(start - 1, 1); //find the next start if (start >= text.Length - 1) //the old start is now at the end { start = -1; } else { start = text.IndexOf("[", start); } } } //while we have more [vars] string embCmd = "<mem.get "; start = text.IndexOf(embCmd); while (start != -1) { if (!TextToolbox.IsEscaped(text, start)) { end = TextToolbox.FindNextMatchingChar(text, start); if (end != -1) { string name = text.Substring(start + embCmd.Length, end - start - embCmd.Length); string left = ""; if (start > 0) { left = text.Substring(0, start); } string right = ""; if (end + 1 != text.Length) { right = text.Substring(end + 1); } text = left + vars[name.ToLower()] + right; } start = text.IndexOf(embCmd); } else // < is escaped { //remove the '\' text = text.Remove(start - 1, 1); //find the next start if (start >= text.Length - 1) //the old start is now at the end { start = -1; } else { start = text.IndexOf(embCmd, start); } } } //while we have more <mem.get name>s embCmd = "<mem.set "; start = text.IndexOf(embCmd); while (start != -1) { if (!TextToolbox.IsEscaped(text, start)) { end = TextToolbox.FindNextMatchingChar(text, start); if (end != -1) { string nameValue = text.Substring(start + embCmd.Length, end - start - embCmd.Length); string left = ""; string right = ""; string[] cmdArgs = TextToolbox.splitOnFirstUnquotedSpace(nameValue); if (cmdArgs.Length > 1) { string name = cmdArgs[0]; //remove quotes if they are there if (name.Length > 1 && name[0] == '"') { name = name.Substring(1); } if (name.Length > 2 && name[name.Length - 1] == '"') { name = name.Substring(0, name.Length - 1); } string val = cmdArgs[1]; vars[name.ToLower()] = val; } if (start > 0) { left = text.Substring(0, start); } if (end + 1 != text.Length) { right = text.Substring(end + 1); } text = left + right; } start = text.IndexOf(embCmd); } else // < is escaped { //remove the '\' text = text.Remove(start - 1, 1); //find the next start if (start >= text.Length - 1) //the old start is now at the end { start = -1; } else { start = text.IndexOf(embCmd, start); } } } //while we have more <mem.set name>s embCmd = "<mem.del "; start = text.IndexOf(embCmd); while (start != -1) { if (!TextToolbox.IsEscaped(text, start)) { end = TextToolbox.FindNextMatchingChar(text, start); if (end != -1) { string name = text.Substring(start + embCmd.Length, end - start - embCmd.Length); vars.Remove(name.Trim().ToLower()); string left = ""; string right = ""; if (start > 0) { left = text.Substring(0, start); } if (end + 1 != text.Length) { right = text.Substring(end + 1); } text = left + right; } start = text.IndexOf(embCmd); } else // < is escaped { //remove the '\' text = text.Remove(start - 1, 1); //find the next start if (start >= text.Length - 1) //the old start is now at the end { start = -1; } else { start = text.IndexOf(embCmd, start); } } } //while we have more <mem.set name>s return(text); } //ReplaceVars(string text, Hashtable vars)
}//compileRules(string parentId, List<Rule> rules) public Reply GetReply(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("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("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(outputText, agentText, outputCmd, matchBest.InputRecognizer.RuleId, matchBest.ConfidenceFactor, this.knowledgeBaseItem)); } //GetReply(string input, string lastfired)