diff --git a/Aiml.NET.Tests/defaults/config.json b/Aiml.NET.Tests/defaults/config.json index f05d3e6..94e4bc9 100644 --- a/Aiml.NET.Tests/defaults/config.json +++ b/Aiml.NET.Tests/defaults/config.json @@ -19,6 +19,6 @@ "SetsDirectory": "sets", "MapsDirectory": "maps", //"Locale": "en-AU", - "LearnfFile": "aiml/learnf.aiml", + "LearnfFile": "learnf.aiml", "UnbindPredicatesWithDefaultValue": false } diff --git a/Aiml.NET.XChatBot/Aiml.NET.XChatBot.csproj b/Aiml.NET.XChatBot/Aiml.NET.XChatBot.csproj index 36fec68..98ae2cd 100644 --- a/Aiml.NET.XChatBot/Aiml.NET.XChatBot.csproj +++ b/Aiml.NET.XChatBot/Aiml.NET.XChatBot.csproj @@ -6,6 +6,8 @@ + + @@ -20,6 +22,12 @@ + + Always + + + Always + Always diff --git a/Aiml.NET.XChatBot/Program.cs b/Aiml.NET.XChatBot/Program.cs index 0f5c90a..a0e5c80 100644 --- a/Aiml.NET.XChatBot/Program.cs +++ b/Aiml.NET.XChatBot/Program.cs @@ -6,9 +6,11 @@ namespace Aiml.NET.XChatBot { internal class Program { + private static string _currentTopic = string.Empty; + /* - * THIS IS A SIMPLE CHAT BOT TO PLAY AROUND WITH IT - */ +* THIS IS A SIMPLE CHAT BOT TO PLAY AROUND WITH IT +*/ static void Main(string[] args) { try @@ -35,6 +37,15 @@ static void Main(string[] args) message = message.Substring(7); } Response botResponse = bot.Chat(new Request(message, user, bot), trace); + + //Log Topic Changed + if (!_currentTopic.Equals(user.Topic)) + { + _currentTopic = user.Topic; + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($":: topic changed to: [{_currentTopic}] ::"); + Console.ResetColor(); + } //replace line breaks with Console Line Breaks string[] lines = botResponse.ToString().Split(new[] { "\\r\\n" }, StringSplitOptions.None); string responseString = string.Join(Environment.NewLine, lines); diff --git a/Aiml.NET.XChatBot/aiml/badanswer.aiml b/Aiml.NET.XChatBot/aiml/badanswer.aiml new file mode 100644 index 0000000..bbe049a --- /dev/null +++ b/Aiml.NET.XChatBot/aiml/badanswer.aiml @@ -0,0 +1,77 @@ + + + + + BAD ANSWER + + + + + + SAY ^ + + + + diff --git a/Aiml.NET.XChatBot/aiml/default.aiml b/Aiml.NET.XChatBot/aiml/default.aiml new file mode 100644 index 0000000..7367254 --- /dev/null +++ b/Aiml.NET.XChatBot/aiml/default.aiml @@ -0,0 +1,7 @@ + + + + * + + + diff --git a/Aiml.NET.XChatBot/aiml/helloworld.aiml b/Aiml.NET.XChatBot/aiml/helloworld.aiml index f61e8ec..4ebc82e 100644 --- a/Aiml.NET.XChatBot/aiml/helloworld.aiml +++ b/Aiml.NET.XChatBot/aiml/helloworld.aiml @@ -2,7 +2,12 @@ HELLO ^ - + HI ^ diff --git a/Aiml.NET.XChatBot/config.json b/Aiml.NET.XChatBot/config.json index f05d3e6..94e4bc9 100644 --- a/Aiml.NET.XChatBot/config.json +++ b/Aiml.NET.XChatBot/config.json @@ -19,6 +19,6 @@ "SetsDirectory": "sets", "MapsDirectory": "maps", //"Locale": "en-AU", - "LearnfFile": "aiml/learnf.aiml", + "LearnfFile": "learnf.aiml", "UnbindPredicatesWithDefaultValue": false } diff --git a/Aiml.NET/Aiml.NET.csproj b/Aiml.NET/Aiml.NET.csproj index 088b1e5..904b09b 100644 --- a/Aiml.NET/Aiml.NET.csproj +++ b/Aiml.NET/Aiml.NET.csproj @@ -4,7 +4,7 @@ netstandard2.0 preview enable - 2.0.1 + 2.0.2 Wainaina George © 2023 Crudsoft Technologies diff --git a/Aiml.NET/Tags/Learn.cs b/Aiml.NET/Tags/Learn.cs index 6afe0e7..a273d01 100644 --- a/Aiml.NET/Tags/Learn.cs +++ b/Aiml.NET/Tags/Learn.cs @@ -1,53 +1,72 @@ using System; using System.Xml; -namespace Aiml.NET { - public partial class TemplateNode { - /// - /// Processes the content as AIML and adds it to the bot's brain, temporarily and for the current user only, and thus temporary. - /// - /// - /// Unlike other elements with content, the content of this element is not normally evaluated. - /// However, the special child element eval is replaced with the result of evaluating its own content. - /// This element is defined by the AIML 2.0 specification. - /// - /// - public sealed class Learn : TemplateNode { - public XmlNode Node { get; } +namespace Aiml.NET +{ + public partial class TemplateNode + { + /// + /// Processes the content as AIML and adds it to the bot's brain, temporarily and for the current user only, and thus temporary. + /// + /// + /// Unlike other elements with content, the content of this element is not normally evaluated. + /// However, the special child element eval is replaced with the result of evaluating its own content. + /// This element is defined by the AIML 2.0 specification. + /// + /// + public sealed class Learn : TemplateNode + { + public XmlNode Node { get; } - public Learn(XmlNode node) { - this.Node = node; - } + public Learn(XmlNode node) + { + this.Node = node; + } - public override string Evaluate(RequestProcess process) { - // Evaluate tags. - XmlNode node = this.Node.Clone(); - this.ProcessXml(node, process); + public override string Evaluate(RequestProcess process) + { + // Evaluate tags. + XmlNode node = this.Node.Clone(); + this.ProcessXml(node, process); - // Learn the result. - process.Log(LogLevel.Diagnostic, $"In element : learning new category for {process.User.ID}: {node.OuterXml}"); - AimlLoader loader = new AimlLoader(process.Bot); - loader.ProcessCategory(process.User.Graphmaster, node, null); + // Check if topic exist and check it's Name attribute, Assign if Not specified + XmlNode topicNode = node.SelectSingleNode("/topic"); + if (topicNode != null && topicNode.Attributes["name"] == null) + { + XmlAttribute nameAttribute = topicNode.OwnerDocument.CreateAttribute("name"); + nameAttribute.Value = process?.User?.Topic ?? "*"; + topicNode.Attributes.Append(nameAttribute); + } + // Learn + process.Log(LogLevel.Diagnostic, $"In element : learning new category for {process.User.ID}: {node.OuterXml}"); + AimlLoader loader = new AimlLoader(process.Bot); + loader.LoadAIML(process.User.Graphmaster, node, null); - return string.Empty; - } + return string.Empty; + } - public static Learn FromXml(XmlNode node, AimlLoader loader) { - return new Learn(node); - } + public static Learn FromXml(XmlNode node, AimlLoader loader) + { + return new Learn(node); + } - private void ProcessXml(XmlNode node, RequestProcess process) { - for (int i = 0; i < node.ChildNodes.Count; ++i) { - XmlNode node2 = node.ChildNodes[i]; - if (node2.NodeType == XmlNodeType.Element) { - if (node2.Name.Equals("eval", StringComparison.InvariantCultureIgnoreCase)) { - TemplateElementCollection tags = TemplateElementCollection.FromXml(node2, process.Bot.AimlLoader); - node2.ParentNode.ReplaceChild(node.OwnerDocument.CreateTextNode(tags.Evaluate(process)), node2); - } else - this.ProcessXml(node2, process); - } - } - } - } - } + private void ProcessXml(XmlNode node, RequestProcess process) + { + for (int i = 0; i < node.ChildNodes.Count; ++i) + { + XmlNode node2 = node.ChildNodes[i]; + if (node2.NodeType == XmlNodeType.Element) + { + if (node2.Name.Equals("eval", StringComparison.InvariantCultureIgnoreCase)) + { + TemplateElementCollection tags = TemplateElementCollection.FromXml(node2, process.Bot.AimlLoader); + node2.ParentNode.ReplaceChild(node.OwnerDocument.CreateTextNode(tags.Evaluate(process)), node2); + } + else + this.ProcessXml(node2, process); + } + } + } + } + } } diff --git a/Aiml.NET/Tags/LearnF.cs b/Aiml.NET/Tags/LearnF.cs index 6c3f4b5..b5dd0d7 100644 --- a/Aiml.NET/Tags/LearnF.cs +++ b/Aiml.NET/Tags/LearnF.cs @@ -2,76 +2,99 @@ using System.IO; using System.Xml; -namespace Aiml.NET { - public partial class TemplateNode { - /// - /// Processes the content as AIML and permanently adds it to the bot's brain, globally for all users. - /// - /// - /// Unlike other elements with content, the content of this element is not normally evaluated. - /// However, the special child element eval is replaced with the result of evaluating its own content. - /// This element is defined by the AIML 2.0 specification. - /// - /// - public sealed class LearnF : TemplateNode { - public XmlNode Node { get; private set; } +namespace Aiml.NET +{ + public partial class TemplateNode + { + /// + /// Processes the content as AIML and permanently adds it to the bot's brain, globally for all users. + /// + /// + /// Unlike other elements with content, the content of this element is not normally evaluated. + /// However, the special child element eval is replaced with the result of evaluating its own content. + /// This element is defined by the AIML 2.0 specification. + /// + /// + public sealed class LearnF : TemplateNode + { + public XmlNode Node { get; private set; } - public LearnF(XmlNode node) { - this.Node = node; - } + public LearnF(XmlNode node) + { + this.Node = node; + } - public override string Evaluate(RequestProcess process) { - // Evaluate tags. - XmlNode node = this.Node.Clone(); - this.ProcessXml(node, process); + public override string Evaluate(RequestProcess process) + { + // Evaluate tags. + XmlNode node = this.Node.Clone(); + this.ProcessXml(node, process); - // Learn the result. - process.Log(LogLevel.Diagnostic, "In element : learning new category: " + node.OuterXml); - AimlLoader loader = new AimlLoader(process.Bot); - loader.ProcessCategory(process.Bot.Graphmaster, node, null); + // Check if topic exist and check it's Name attribute, Assign if Not specified + XmlNode topicNode = node.SelectSingleNode("/topic"); + if (topicNode != null && topicNode.Attributes["name"] == null) + { + XmlAttribute nameAttribute = topicNode.OwnerDocument.CreateAttribute("name"); + nameAttribute.Value = process?.User?.Topic ?? "*"; + topicNode.Attributes.Append(nameAttribute); + } + // Learn + process.Log(LogLevel.Diagnostic, "In element : learning new category: " + node.OuterXml); + AimlLoader loader = new AimlLoader(process.Bot); + loader.LoadAIML(process.Bot.Graphmaster, node, null); - // Write it to a file. - bool newFile = !File.Exists(process.Bot.Config.LearnfFile) || new FileInfo(process.Bot.Config.LearnfFile).Length < 7; - StreamWriter writer = new StreamWriter(File.Open("learnf.aiml", FileMode.OpenOrCreate, FileAccess.Write)); - if (newFile) { - writer.WriteLine(""); - writer.WriteLine(); - writer.WriteLine(""); - writer.WriteLine(); - } else { - // Seek to just before the closing tag. - writer.BaseStream.Seek(-7, SeekOrigin.End); - } + // Write it to a file. + string learnFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, process.Bot.Config.AimlDirectory, process.Bot.Config.LearnfFile.Trim()); + using (StreamWriter writer = new StreamWriter(File.Open(learnFilePath, FileMode.OpenOrCreate, FileAccess.Write))) + { + if (!File.Exists(learnFilePath) || new FileInfo(learnFilePath).Length < 7) + { + writer.WriteLine(""); + writer.WriteLine(); + writer.WriteLine(""); + writer.WriteLine(); + } + else + { + // Seek to just before the closing tag. + writer.BaseStream.Seek(-7, SeekOrigin.End); + } - writer.WriteLine(""); - writer.Write(node.InnerXml.Trim('\r', '\n')); - writer.WriteLine(); - writer.WriteLine(); - writer.Write(""); - writer.Close(); + writer.WriteLine($""); + writer.Write(node.InnerXml.Trim('\r', '\n')); + writer.WriteLine(); + writer.WriteLine(); + writer.Write(""); + } - return string.Empty; - } + return string.Empty; + } - public static LearnF FromXml(XmlNode node, AimlLoader loader) { - XmlDocument document = new XmlDocument(); - document.PreserveWhitespace = true; - document.LoadXml(node.OuterXml); - return new LearnF(document.DocumentElement); - } + public static LearnF FromXml(XmlNode node, AimlLoader loader) + { + XmlDocument document = new XmlDocument(); + document.PreserveWhitespace = true; + document.LoadXml(node.OuterXml); + return new LearnF(document.DocumentElement); + } - private void ProcessXml(XmlNode node, RequestProcess process) { - for (int i = 0; i < node.ChildNodes.Count; ++i) { - XmlNode node2 = node.ChildNodes[i]; - if (node2.NodeType == XmlNodeType.Element) { - if (node2.Name.Equals("eval", StringComparison.InvariantCultureIgnoreCase)) { - TemplateElementCollection tags = TemplateElementCollection.FromXml(node2, process.Bot.AimlLoader); - node2.ParentNode.ReplaceChild(node.OwnerDocument.CreateTextNode(tags.Evaluate(process)), node2); - } else - this.ProcessXml(node2, process); - } - } - } - } - } + private void ProcessXml(XmlNode node, RequestProcess process) + { + for (int i = 0; i < node.ChildNodes.Count; ++i) + { + XmlNode node2 = node.ChildNodes[i]; + if (node2.NodeType == XmlNodeType.Element) + { + if (node2.Name.Equals("eval", StringComparison.InvariantCultureIgnoreCase)) + { + TemplateElementCollection tags = TemplateElementCollection.FromXml(node2, process.Bot.AimlLoader); + node2.ParentNode.ReplaceChild(node.OwnerDocument.CreateTextNode(tags.Evaluate(process)), node2); + } + else + this.ProcessXml(node2, process); + } + } + } + } + } }