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
+
+
+
+
+
+
+
+
+
+
+
+
+ Hmmm, i can't learn without topic context
+
+ *
+
+
+
+ OK. You said "" and I replied "".
+
+ BotTrainingProgramThatQuestionAnswer
+
+ SAY
+
+
+
+
+
+
+
+
+ SAY ^
+
+
+
+
+
+
+
+ \r\nWhat should I say instead? Reply starting with "Say "
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Got it, when am asked “”, i will now respond “” under topic:
+
+
+
+
+
+
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 @@
+
+
+
+ *
+ Hmmm i have no answer for that
+
+
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 ^
- Hello world!
+
+
+ greetings
+
+ Hello world!
+
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);
+ }
+ }
+ }
+ }
+ }
}