public void TestEvaluateTimeOut() { _chatBot = new ChatBot(); ConfigurationManager.AppSettings["timeoutMax"] = "10"; _node = new Node(); _request = new Request("Test 1", new User("1", _chatBot), _chatBot); var path = "Test 1 <that> that <topic> topic"; var template = "<srai>TEST</srai>"; _node = new Node(); _node.AddCategory(path, template); var pathAlt = "Alt Test <that> that <topic> topic"; var templateAlt = "<srai>TEST ALT</srai>"; _node.AddCategory(pathAlt, templateAlt); _subQuery = new SubQuery(path); Thread.Sleep(20); var result = _node.Evaluate("Test 1 <that> that <topic> topic", _subQuery, _request, MatchState.UserInput, new StringBuilder()); Assert.AreEqual(string.Empty, result); Assert.AreEqual(true, _request.HasTimedOut); }
/// <summary> /// Loads a dump of the graphmaster into memory so avoiding processing the AIML files again /// </summary> /// <param name="path">the path to the dump file</param> public void loadFromBinaryFile(string path) { FileStream loadFile = File.OpenRead(path); BinaryFormatter bf = new BinaryFormatter(); this.Graphmaster = (Node)bf.Deserialize(loadFile); loadFile.Close(); }
public void Setup() { _chatBot = new ChatBot(); ConfigurationManager.AppSettings["timeoutMax"] = Int32.MaxValue.ToString(); _node = new Node(); _request = new Request("Test 1", new User("1", _chatBot), _chatBot); _subQuery = new SubQuery("Test 1 <that> * <topic> *"); }
/// <summary> /// Instantiates the dictionary objects and collections associated with this class /// </summary> private void setup() { this.GlobalSettings = new SettingsDictionary(this); this.GenderSubstitutions = new SettingsDictionary(this); this.Person2Substitutions = new SettingsDictionary(this); this.PersonSubstitutions = new SettingsDictionary(this); this.Substitutions = new SettingsDictionary(this); this.DefaultPredicates = new SettingsDictionary(this); this.CustomTags = new Hashtable(); this.Graphmaster = new AIMLbot.Utils.Node(); }
public void TestAddCategoryWithGoodData() { var path = "Test 1 <that> * <topic> *"; var template = "<srai>Test</srai>"; _node = new Node(); _node.AddCategory(path, template); Assert.AreEqual(1, _node.NumberOfChildNodes); Assert.AreEqual(string.Empty, _node.Template); Assert.AreEqual(string.Empty, _node.Word); }
public void TestAddCategoryAsLeafNode() { var node = new Node(); var path = ""; var template = "<srai>TEST</srai>"; node.AddCategory(path, template); node.Word = "*"; Assert.AreEqual(0, node.NumberOfChildNodes); Assert.AreEqual(template, node.Template); Assert.AreEqual("*", node.Word); }
/// <summary> /// Adds a category to the node /// </summary> /// <param name="node">the node to which the category will be added</param> /// <param name="path">the path for the category</param> /// <param name="template">the template to find at the end of the path</param> public static void AddCategory(this Node node, string path, string template) { while (true) { if (template.Length == 0) { var message = $"Category {path} has an empty template tag."; throw new XmlException(message); } // check we're not at the leaf node if (path.Trim().Length == 0) { node.Template = template; return; } // otherwise, this sentence requires further child nodemappers in order to // be fully mapped within the GraphMaster structure. // split the input into its component words var words = path.Trim().Split(" ".ToCharArray()); // get the first word (to form the key for the child nodemapper) var firstWord = words[0].ToUpper(); // concatenate the rest of the sentence into a suffix (to act as the // path argument in the child nodemapper) // ToDo: should just join array minus first word. var newPath = path.Substring(firstWord.Length, path.Length - firstWord.Length).Trim(); // o.k. check we don't already have a child with the key from this sentence // if we do then pass the handling of this sentence down the branch to the // child nodemapper otherwise the child nodemapper doesn't yet exist, so create a new one if (node.Children.ContainsKey(firstWord)) { var childNode = node.Children[firstWord]; node = childNode; path = newPath; continue; } else { var childNode = new Node {Word = firstWord}; childNode.AddCategory(newPath, template); node.Children.Add(childNode.Word, childNode); } break; } }
public void TestEvaluateWith_WildCardThat() { var path = "Test 1 <that> _ <topic> topic"; var template = "<srai>TEST</srai>"; var node = new Node(); node.AddCategory(path, template); var pathAlt = "Alt Test <that> that <topic> topic"; var templateAlt = "<srai>TEST ALT</srai>"; node.AddCategory(pathAlt, templateAlt); var request = new Request("Test 1", _user); var searcher = new NodeSearcher(); var result = searcher.Evaluate(node, "Test 1 <that> WILDCARD WORDS <topic> topic", MatchState.UserInput, new StringBuilder()); Assert.AreEqual("<srai>TEST</srai>", result); Assert.AreEqual("WILDCARD WORDS", searcher.Query.ThatStar[0]); }
public void testEvaluateWith_WildCardThat() { var path = "Test 1 <that> _ <topic> topic"; var template = "<srai>TEST</srai>"; _node = new Node(); _node.AddCategory(path, template); var pathAlt = "Alt Test <that> that <topic> topic"; var templateAlt = "<srai>TEST ALT</srai>"; _node.AddCategory(pathAlt, templateAlt); _request = new Request("Test 1", new User("1", _chatBot), _chatBot); _subQuery = new SubQuery(path); var result = _node.Evaluate("Test 1 <that> WILDCARD WORDS <topic> topic", _subQuery, _request, MatchState.UserInput, new StringBuilder()); Assert.AreEqual("<srai>TEST</srai>", result); Assert.AreEqual("WILDCARD WORDS", _subQuery.ThatStar[0]); }
public void TestEvaluateWithEmptyNode() { var node = new Node(); var request = new Request("Test 1", _user); var searcher = new NodeSearcher(); var result = searcher.Evaluate(node, "Test 1 <that> that <topic> topic", MatchState.UserInput, new StringBuilder()); Assert.AreEqual(string.Empty, result); }
public void TestEvaluateWithWildcardsInDifferentPartsOfPath() { var path = "Test * 1 <that> Test * 1 <topic> Test * 1"; var template = "<srai>TEST</srai>"; _node = new Node(); _node.AddCategory(path, template); var pathAlt = "Alt Test <that> that <topic> topic"; var templateAlt = "<srai>TEST ALT</srai>"; _node.AddCategory(pathAlt, templateAlt); _request = new Request("Test 1", new User("1", _chatBot), _chatBot); _subQuery = new SubQuery(path); Assert.AreEqual("<srai>TEST</srai>", _node.Evaluate( "Test WILDCARD USER WORDS 1 <that> Test WILDCARD THAT WORDS 1 <topic> Test WILDCARD TOPIC WORDS 1", _subQuery, _request, MatchState.UserInput, new StringBuilder())); Assert.AreEqual("WILDCARD USER WORDS", _subQuery.InputStar[0]); Assert.AreEqual("WILDCARD THAT WORDS", _subQuery.ThatStar[0]); Assert.AreEqual("WILDCARD TOPIC WORDS", _subQuery.TopicStar[0]); }
public void TestEvaluateWithStarWildCardUserInputNotMatched() { var path = "Test * 1 <that> that <topic> topic>"; var template = "<srai>TEST</srai>"; _node = new Node(); _node.AddCategory(path, template); var pathAlt = "Alt Test <that> that <topic> topic"; var templateAlt = "<srai>TEST ALT</srai>"; _node.AddCategory(pathAlt, templateAlt); _request = new Request("Test 1", new User("1", _chatBot), _chatBot); _subQuery = new SubQuery(path); Assert.AreEqual("<srai>TEST ALT</srai>", _node.Evaluate("Alt Test <that> that <topic> topic", _subQuery, _request, MatchState.UserInput, new StringBuilder())); }
public void TestEvaluateWithInternationalCharset() { var node = new Node(); var path = "中 文 <that> * <topic> *"; var template = "中文 (Chinese)"; node.AddCategory(path, template); var path2 = "日 本 語 <that> * <topic> *"; var template2 = "日 本 語 (Japanese)"; node.AddCategory(path2, template2); var path3 = "Русский язык <that> * <topic> *"; var template3 = "Русский язык (Russian)"; node.AddCategory(path3, template3); var request = new Request("中 文", _user); var searcher = new NodeSearcher(); var result = searcher.Evaluate(node, "中 文 <that> * <topic> *", MatchState.UserInput, new StringBuilder()); Assert.AreEqual("中文 (Chinese)", result); request = new Request("日 本 語", _user); searcher = new NodeSearcher(); result = searcher.Evaluate(node, "日 本 語 <that> * <topic> *", MatchState.UserInput, new StringBuilder()); Assert.AreEqual("日 本 語 (Japanese)", result); request = new Request("Русский язык", _user); searcher = new NodeSearcher(); result = searcher.Evaluate(node, "Русский язык <that> * <topic> *", MatchState.UserInput, new StringBuilder()); Assert.AreEqual("Русский язык (Russian)", result); }
/// <summary> /// Navigates this node (and recusively into child nodes) for a match to the path passed as an argument /// whilst processing the referenced request /// </summary> /// <param name="node">The specified graph node to evaluat.</param> /// <param name="path">The normalized path derived from the user's input</param> /// <param name="matchstate">The part of the input path the node represents</param> /// <param name="wildcard">The contents of the user input absorbed by the AIML wildcards "_" and "*"</param> /// <returns>The template to process to generate the output</returns> public string Evaluate(Node node, string path, MatchState matchstate, StringBuilder wildcard) { while (true) { // so we still have time! path = path.Trim(); // check if this is the end of a branch in the GraphMaster // return the category for this node if (node.Children.Count == 0) { if (path.Length > 0) { // if we get here it means that there is a wildcard in the user input part of the // path. StoreWildCard(path, wildcard); } Query.Template = node.Template; return node.Template; } // if we've matched all the words in the input sentence and this is the end // of the line then return the category for this node if (path.Length == 0) { Query.Template = node.Template; return node.Template; } // otherwise split the input into it's component words var splitPath = path.Split(" \r\n\t".ToCharArray()); // get the first word of the sentence var firstWord = splitPath[0].ToUpper(); // and concatenate the rest of the input into a new path for child nodes var newPath = path.Substring(firstWord.Length, path.Length - firstWord.Length); // first option is to see if this node has a child denoted by the "_" // wildcard. "_" comes first in precedence in the AIML alphabet if (node.Children.ContainsKey("_")) { var childNode = node.Children["_"]; // add the next word to the wildcard match var newWildcard = new StringBuilder(); StoreWildCard(splitPath[0], newWildcard); // move down into the identified branch of the GraphMaster structure var result = Evaluate(childNode, newPath, matchstate, newWildcard); // and if we get a result from the branch process the wildcard matches and return // the result if (result.Length > 0) { if (newWildcard.Length > 0) { // capture and push the star content appropriate to the current matchstate switch (matchstate) { case MatchState.UserInput: Query.InputStar.Add(newWildcard.ToString()); // added due to this match being the end of the line newWildcard.Remove(0, newWildcard.Length); break; case MatchState.That: Query.ThatStar.Add(newWildcard.ToString()); break; case MatchState.Topic: Query.TopicStar.Add(newWildcard.ToString()); break; } } Query.Template = result; return result; } } // second option - the nodemapper may have contained a "_" child, but led to no match // or it didn't contain a "_" child at all. So get the child nodemapper from this // nodemapper that matches the first word of the input sentence. if (node.Children.ContainsKey(firstWord)) { // process the matchstate - this might not make sense but the matchstate is working // with a "backwards" path: "topic <topic> that <that> user input" // the "classic" path looks like this: "user input <that> that <topic> topic" // but having it backwards is more efficient for searching purposes var newMatchstate = matchstate; if (firstWord == "<THAT>") { newMatchstate = MatchState.That; } else if (firstWord == "<TOPIC>") { newMatchstate = MatchState.Topic; } var childNode = node.Children[firstWord]; // move down into the identified branch of the GraphMaster structure using the new // matchstate var newWildcard = new StringBuilder(); var result = Evaluate(childNode, newPath, newMatchstate, newWildcard); // and if we get a result from the child return it if (result.Length > 0) { if (newWildcard.Length > 0) { // capture and push the star content appropriate to the matchstate if it exists // and then clear it for subsequent wildcards switch (matchstate) { case MatchState.UserInput: Query.InputStar.Add(newWildcard.ToString()); newWildcard.Remove(0, newWildcard.Length); break; case MatchState.That: Query.ThatStar.Add(newWildcard.ToString()); newWildcard.Remove(0, newWildcard.Length); break; case MatchState.Topic: Query.TopicStar.Add(newWildcard.ToString()); newWildcard.Remove(0, newWildcard.Length); break; } } Query.Template = result; return result; } } // third option - the input part of the path might have been matched so far but hasn't // returned a match, so check to see it contains the "*" wildcard. "*" comes last in // precedence in the AIML alphabet. if (node.Children.ContainsKey("*")) { // o.k. look for the path in the child node denoted by "*" var childNode = node.Children["*"]; // add the next word to the wildcard match var newWildcard = new StringBuilder(); StoreWildCard(splitPath[0], newWildcard); // var result = Evaluate(childNode, newPath, matchstate, newWildcard); // and if we get a result from the branch process and return it if (result.Length > 0) { if (newWildcard.Length > 0) { // capture and push the star content appropriate to the current matchstate switch (matchstate) { case MatchState.UserInput: Query.InputStar.Add(newWildcard.ToString()); // added due to this match being the end of the line newWildcard.Remove(0, newWildcard.Length); break; case MatchState.That: Query.ThatStar.Add(newWildcard.ToString()); break; case MatchState.Topic: Query.TopicStar.Add(newWildcard.ToString()); break; } } Query.Template = result; return result; } } // o.k. if the nodemapper has failed to match at all: the input contains neither // a "_", the firstWord text, or "*" as a means of denoting a child node. However, // if this node is itself representing a wildcard then the search continues to be // valid if we proceed with the tail. if ((node.Word == "_") || (node.Word == "*")) { StoreWildCard(splitPath[0], wildcard); path = newPath; continue; } // If we get here then we're at a dead end so return an empty string. Hopefully, if the // AIML files have been set up to include a "* <that> * <topic> *" catch-all this // state won't be reached. Remember to empty the surplus to requirements wildcard matches wildcard.Clear(); Query.Template = string.Empty; return string.Empty; } }
/// <summary> /// Instantiates the dictionary objects and collections associated with this class /// </summary> private void setup() { this.GlobalSettings = new SettingsDictionary(this); this.GenderSubstitutions = new SettingsDictionary(this); this.Person2Substitutions = new SettingsDictionary(this); this.PersonSubstitutions = new SettingsDictionary(this); this.Substitutions = new SettingsDictionary(this); this.DefaultPredicates = new SettingsDictionary(this); this.CustomTags = new Dictionary<string, TagHandler>(); this.Graphmaster = new AIMLbot.Utils.Node(); }
public void TestEvaluateWithWildcardsInDifferentPartsOfPath() { var node = new Node(); var path = "Test * 1 <that> Test * 1 <topic> Test * 1"; var template = "<srai>TEST</srai>"; node.AddCategory(path, template); var pathAlt = "Alt Test <that> that <topic> topic"; var templateAlt = "<srai>TEST ALT</srai>"; node.AddCategory(pathAlt, templateAlt); var request = new Request("Test 1", _user); var searcher = new NodeSearcher(); var result = searcher.Evaluate(node, "Test WILDCARD USER WORDS 1 <that> Test WILDCARD THAT WORDS 1 <topic> Test WILDCARD TOPIC WORDS 1", MatchState.UserInput, new StringBuilder()); Assert.AreEqual("<srai>TEST</srai>", result); Assert.AreEqual("WILDCARD USER WORDS", searcher.Query.InputStar[0]); Assert.AreEqual("WILDCARD THAT WORDS", searcher.Query.ThatStar[0]); Assert.AreEqual("WILDCARD TOPIC WORDS", searcher.Query.TopicStar[0]); }
public void TestEvaluateWithStarWildCardUserInputNotMatched() { var node = new Node(); var path = "Test * 1 <that> that <topic> topic>"; var template = "<srai>TEST</srai>"; node.AddCategory(path, template); var pathAlt = "Alt Test <that> that <topic> topic"; var templateAlt = "<srai>TEST ALT</srai>"; node.AddCategory(pathAlt, templateAlt); var request = new Request("Test 1", _user); var searcher = new NodeSearcher(); var result = searcher.Evaluate(node, "Alt Test <that> that <topic> topic", MatchState.UserInput, new StringBuilder()); Assert.AreEqual("<srai>TEST ALT</srai>", result); }
public void TestAddCategoryWithEmptyTemplate() { var node = new Node(); var path = "Test 1 <that> * <topic> *"; node.AddCategory(path, string.Empty); }
public void TestEvaluateWithMultipleWildcardsSwitched() { var node = new Node(); var path = "Test * 1 _ <that> Test * 1 _ <topic> Test _ 1 *"; var template = "<srai>TEST</srai>"; node.AddCategory(path, template); var pathAlt = "Alt Test <that> that <topic> topic"; var templateAlt = "<srai>TEST ALT</srai>"; node.AddCategory(pathAlt, templateAlt); var request = new Request("Test 1", _user); var searcher = new NodeSearcher(); var result = searcher.Evaluate(node, "Test FIRST USER 1 SECOND USER <that> Test FIRST THAT 1 SECOND THAT <topic> Test FIRST TOPIC 1 SECOND TOPIC", MatchState.UserInput, new StringBuilder()); Assert.AreEqual("<srai>TEST</srai>", result); Assert.AreEqual(2, searcher.Query.InputStar.Count); Assert.AreEqual("SECOND USER", searcher.Query.InputStar[0]); Assert.AreEqual("FIRST USER", searcher.Query.InputStar[1]); Assert.AreEqual(2, searcher.Query.ThatStar.Count); Assert.AreEqual("SECOND THAT", searcher.Query.ThatStar[0]); Assert.AreEqual("FIRST THAT", searcher.Query.ThatStar[1]); Assert.AreEqual(2, searcher.Query.TopicStar.Count); Assert.AreEqual("SECOND TOPIC", searcher.Query.TopicStar[0]); Assert.AreEqual("FIRST TOPIC", searcher.Query.TopicStar[1]); }
public void TestEvaluateWithEmptyNode() { _chatBot = new ChatBot(); _node = new Node(); _request = new Request("Test 1", new User("1", _chatBot), _chatBot); _subQuery = new SubQuery("Test 1 <that> that <topic> topic"); Assert.AreEqual(string.Empty, _node.Evaluate("Test 1 <that> that <topic> topic", _subQuery, _request, MatchState.UserInput, new StringBuilder())); }
public void TestEvaluateWithInternationalCharset() { var path = "中 文 <that> * <topic> *"; var template = "中文 (Chinese)"; _node = new Node(); _node.AddCategory(path, template); var path2 = "日 本 語 <that> * <topic> *"; var template2 = "日 本 語 (Japanese)"; _node.AddCategory(path2, template2); var path3 = "Русский язык <that> * <topic> *"; var template3 = "Русский язык (Russian)"; _node.AddCategory(path3, template3); _request = new Request("中 文", new User("1", _chatBot), _chatBot); _subQuery = new SubQuery(path); Assert.AreEqual("中文 (Chinese)", _node.Evaluate("中 文 <that> * <topic> *", _subQuery, _request, MatchState.UserInput, new StringBuilder())); _request = new Request("日 本 語", new User("1", _chatBot), _chatBot); _subQuery = new SubQuery(path); Assert.AreEqual("日 本 語 (Japanese)", _node.Evaluate("日 本 語 <that> * <topic> *", _subQuery, _request, MatchState.UserInput, new StringBuilder())); _request = new Request("Русский язык", new User("1", _chatBot), _chatBot); _subQuery = new SubQuery(path); Assert.AreEqual("Русский язык (Russian)", _node.Evaluate("Русский язык <that> * <topic> *", _subQuery, _request, MatchState.UserInput, new StringBuilder())); }
public void TestEvaluateWithMultipleWildcardsSwitched() { var path = "Test * 1 _ <that> Test * 1 _ <topic> Test _ 1 *"; var template = "<srai>TEST</srai>"; _node = new Node(); _node.AddCategory(path, template); var pathAlt = "Alt Test <that> that <topic> topic"; var templateAlt = "<srai>TEST ALT</srai>"; _node.AddCategory(pathAlt, templateAlt); _request = new Request("Test 1", new User("1", _chatBot), _chatBot); _subQuery = new SubQuery(path); Assert.AreEqual("<srai>TEST</srai>", _node.Evaluate( "Test FIRST USER 1 SECOND USER <that> Test FIRST THAT 1 SECOND THAT <topic> Test FIRST TOPIC 1 SECOND TOPIC", _subQuery, _request, MatchState.UserInput, new StringBuilder())); Assert.AreEqual(2, _subQuery.InputStar.Count); Assert.AreEqual("SECOND USER", _subQuery.InputStar[0]); Assert.AreEqual("FIRST USER", _subQuery.InputStar[1]); Assert.AreEqual(2, _subQuery.ThatStar.Count); Assert.AreEqual("SECOND THAT", _subQuery.ThatStar[0]); Assert.AreEqual("FIRST THAT", _subQuery.ThatStar[1]); Assert.AreEqual(2, _subQuery.TopicStar.Count); Assert.AreEqual("SECOND TOPIC", _subQuery.TopicStar[0]); Assert.AreEqual("FIRST TOPIC", _subQuery.TopicStar[1]); }
/// <summary> /// Adds a category to the node /// </summary> /// <param name="path">the path for the category</param> /// <param name="template">the template to find at the end of the path</param> /// <param name="filename">the file that was the source of this category</param> public void addCategory(string path, string template, string filename) { if (template.Length == 0) { throw new XmlException("The category with a pattern: " + path + " found in file: " + filename + " has an empty template tag. ABORTING"); } // check we're not at the leaf node if (path.Trim().Length == 0) { this.template = template; this.filename = filename; return; } // otherwise, this sentence requires further child nodemappers in order to // be fully mapped within the GraphMaster structure. // split the input into its component words string[] words = path.Trim().Split(" ".ToCharArray()); // get the first word (to form the key for the child nodemapper) string firstWord = Normalize.MakeCaseInsensitive.TransformInput(words[0]); // concatenate the rest of the sentence into a suffix (to act as the // path argument in the child nodemapper) string newPath = path.Substring(firstWord.Length, path.Length - firstWord.Length).Trim(); // o.k. check we don't already have a child with the key from this sentence // if we do then pass the handling of this sentence down the branch to the // child nodemapper otherwise the child nodemapper doesn't yet exist, so create a new one if (this.children.ContainsKey(firstWord)) { Node childNode = this.children[firstWord]; childNode.addCategory(newPath, template, filename); } else { Node childNode = new Node(); childNode.word = firstWord; childNode.addCategory(newPath, template, filename); this.children.Add(childNode.word, childNode); } }
public ChatBot() { Graphmaster = new Node(); PathGenerator = new PathGenerator(); }