📄 kernel.cpp
字号:
/**
* Kernel - Brains of the operation
*
* @author Jonathan Roewen
*/
#include "Kernel.h"
#include <fstream>
#include <iostream>
//#ifdef __BEOS__
// #include <sstream>
// #define stringstream strstream
//#else
#include <strstream>
//#endif
#include "Match.h"
#include "Utils.h"
#include "Memory.h"
#include "Parser.h"
#include "Handler.h"
#include "Responder.h"
#include "Nodemaster.h"
#include "Substituter.h"
#include "StringTokenizer.h"
#include "TemplateProcessor.h"
#include "PreParser.h"
#include "AimlWriter.h"
int totalCategories = 0;
long totalSize = 0;
long totalNodes = 0;
const int Kernel::INPUT = 0;
const int Kernel::THAT = 1;
const int Kernel::TOPIC = 2;
const string Kernel::constants = " <that> <topic> ";
static bool trimming = true;
string toString(PElement element) {
if (element == NULL) {
return "*";
}
string result;
PElement child = element->getChild();
while (child != NULL) {
if (child->getTagname() == "#text") {
// Then this child only contains text, no markup
result += child->getText();
} else if (child->getTagname() == "#cdata") {
;
} else {
// Since only using on <that> and <pattern>
// The tag can only be <bot_xxx/> or <bot name="xxx"/> or <name/>
if (child->getTagname() == "name") {
result += Kernel::respond("BOT NAME", "unknown");
} else
if (child->getTagname() == "bot") {
// Is a <bot name="xxx"/> predicate
result += Kernel::respond("BOT " + toUpper(child->getAttribute("name")), "unknown");
} else {
// It is old-skool <bot_xxx/>
result += Kernel::respond("BOT " + toUpper(child->getTagname().substr(4)), "unknown");
}
}
child = child->getNextSibling();
}
return trim(toUpper(result));//Substituter::normalize(result);
}
string templateString(PElement element) {
if (element == NULL) {
return "";
}
string result;
PElement child = element->getChild();
while (child != NULL) {
if (child->getTagname() == "#text") {
result += child->getText();
} else if (child->getTagname() == "#cdata") {
result += child->getText(false);
} else {
string tag = "<";
if (child->hasNamespace()) {
tag += child->getNamespace() + ":";
}
tag += child->getTagname();
if (child->hasAttributes()) {
map<string, string> attr = child->getAttributes();
map<string, string>::const_iterator itr = attr.begin();
while (itr != attr.end()) {
tag += " " + (*itr).first + "=\"" + (*itr).second + "\"";
itr++;
}
}
if (child->hasChildren()) {
tag += ">" + templateString(child);
tag += "</";
if (child->hasNamespace()) {
tag += child->getNamespace() + ":";
}
tag += child->getTagname() + ">";
} else {
tag += "/>";
}
result += tag;
}
child = child->getNextSibling();
}
return result;
}
void prettyPrintHeader(const string &filename, int size, int totalSize, long time) {
string fn = filename;
string::size_type f = fn.find_last_of("\\/:");
if (f != string::npos) {
fn = fn.substr(f + 1);
}
cout << "Learnt: " << fn;
if (fn.length() >= 20) {
cout << endl << " ";
} else {
for (int ix = 0; ix < 20 - fn.length(); ++ix) {
cout << " ";
}
}
int len = 0;
for (int iy = size; iy > 0 && len < 6; iy = iy / 10) {
++len;
}
for (int ix = 0; ix < 6 - len; ++ix) {
cout << " ";
}
cout << size << " categories";
len = 0;
for (int iy = totalSize; iy > 0 && len < 6; iy = iy / 10) {
++len;
}
for (int ix = 0; ix < 10 - len; ++ix) {
cout << " ";
}
cout << totalSize << " total";
len = 0;
for (int iy = (int)time; iy > 0 && len < 6; iy = iy / 10) {
++len;
}
for (int ix = 0; ix < 6 - len; ++ix) {
cout << " ";
}
if (len != 0) {
cout << " ";
}
cout << time << "ms" << endl;
}
Nodemaster *Kernel::root = new Nodemaster();
Kernel::Kernel() {
new Substituter();
Handler::init();
Kernel::loadSubstitutions();
Kernel::load("std-startup.aiml");
Kernel::loadTemporaryData();
}
string Kernel::bootstrap() {
trimming = false;
string result = Kernel::respond("bootstrap", "system");
trimming = true;
return result;
}
void Kernel::load(const string &file) {
PreParser *p = new PreParser();
bool loadedOk = true;
int total = totalCategories;
long time = timerMillis();
ifstream fin;
fin.open(file.c_str(), ios::in | ios::binary);
if (fin.is_open()) {
p->parse(fin,file);
} else {
loadedOk = false;
cout << "File " << file << " could not be found" << endl;
}
if (loadedOk) {
prettyPrintHeader(file, (totalCategories - total), totalCategories, (timerMillis() - time));
// cout << "Learnt: " << file << " \t(" << (totalCategories - total) << " categories) \t(" << totalCategories << " total) \t(" << (timerMillis() - time) << "ms)" << endl;
}
delete p;
}
void Kernel::convertTempAiml() {
PElement eAiml(new Element("aiml"));
PElement eCategory,
ePattern,
eThat,
eTopic,
eTemplate,
eText;
ifstream fin("temporary.data", ios::in | ios::binary);
if (!fin.is_open()) {
cerr << "temporary.data does not exist .. cannot oonvert" << endl;
return;
}
while (fin.good()) {
string pattern, that, topic, _template;
getline(fin, pattern, ',');
if (pattern.empty()) {
break;
}
getline(fin, that, ',');
getline(fin, topic, ',');
getline(fin, _template);
eCategory = new Element("category");
ePattern = new Element("pattern");
eText = new Element("#text");
eText->setText(pattern);
ePattern->addChild(eText);
eCategory->addChild(ePattern);
if (that != "*") {
eThat = new Element("that");
eText = new Element("#text");
eText->setText(that);
eThat->addChild(eText);
eCategory->addChild(eThat);
}
eTemplate = new Element("template");
eText = new Element("#text");
eText->setText(_template);
eTemplate->addChild(eText);
eCategory->addChild(eTemplate);
if (topic != "*") {
eTopic = new Element("topic");
eTopic->setAttribute("name", topic);
eTopic->addChild(eCategory);
eAiml->addChild(eTopic);
} else {
eAiml->addChild(eCategory);
}
}
fin.close();
////////////
ofstream fout("temporary.aiml", ios::out | ios::binary | ios::trunc);
if (!fout.is_open()) {
cerr << "could not open temporary.aiml for writing" << endl;
return;
}
string buffer = AimlWriter::prettyAiml(eAiml);
if (buffer.empty()) {
fout.close();
return;
}
fout << buffer << endl;
fout.close();
}
void Kernel::loadTemporaryData() {
// Format: <pattern>,<that>,<topic>,<template><eol>
ifstream fin("temporary.data", ios::in | ios::binary);
if (!fin.is_open()) {
return;
}
while (fin.good()) {
string pattern, that, topic, _template;
getline(fin, pattern, ',');
getline(fin, that, ',');
getline(fin, topic, ',');
int startIndex = fin.tellg();
getline(fin, _template);
int endIndex = fin.tellg();
Nodemaster *node = add(pattern, that, topic);
if (node != NULL) {
node->addTemplate(
new Template("temporary.data", startIndex, endIndex)
);
++totalCategories;
}
}
fin.close();
}
void Kernel::loadSubstitutions() {
ifstream fin;
PElement root;
fin.open("substitutions.xml", ios::in | ios::binary);
if (fin.is_open()) {
Parser *p = new Parser();
root = p->parse(fin, "substitutions.xml");
delete p;
if (root == NULL) {
return;
}
} else {
return;
}
velement array;
velement_it ix;
root->getChildren("substitute", &array);
for (ix = array.begin(); ix != array.end(); ++ix) {
string name = (*ix)->getAttribute("name");
string find = (*ix)->getAttribute("find");
string replace = (*ix)->getAttribute("replace");
Substituter::addSubstitute(name, find, replace);
}
}
/**
* At A & B we have a problem. Need to fix Element to do a
* deep copy, so that we can safely delete the parsed tree.
* Otherwise will crash and burn, or use far more memory
* than is necessary.
*/
void Kernel::load10(const string &, PElement &root) {
velement array;
velement_it ix;
root->getChildren("substitute", &array);
for (ix = array.begin(); ix != array.end(); ++ix) {
string name = (*ix)->getAttribute("name");
string find = (*ix)->getAttribute("find");
string replace = (*ix)->getAttribute("replace");
Substituter::addSubstitute(name, find, replace);
}
array.clear();
root->getChildren("processor", &array);
for (ix = array.begin(); ix != array.end(); ++ix) {
string tag = (*ix)->getAttribute("tag");
string loc = (*ix)->getAttribute("class");
if (Handler::hasProcessor(tag)) {
// TEMPORARY WORKAROUND
// Once have properly handled platform specific dynamic
// linking, will make processors dynamically linked in
// at startup, rather than statically provided in Handler
TemplateProcessor::addProcessor((*Handler::processors.find(tag)).second);
cout << "Adding Processor: " << loc << endl;
} else {
cout << "No " << tag << " processor" << endl;
}
}
array.clear();
// Now to actually load the AIML itself...
root->getChildren("topic", &array);
// All the <topic> nodes
for (ix = array.begin(); ix != array.end(); ++ix) {
velement categories;
(*ix)->getChildren("category", &categories);
// All of the <category> nodes per <topic>
string topic = (*ix)->getAttribute("name");
for (velement_it iy = categories.begin(); iy != categories.end(); ++iy) {
// Load each category
string that = toString((*iy)->getChild("that"));
string pattern = toString((*iy)->getChild("pattern"));
// Nodemaster *node = add(pattern, that, topic);
// if (node != NULL) {
// //node->addTemplate(templateString((*iy)->getChild("template")));
// ++totalCategories;
// }
}
}
array.clear();
root->getChildren("category", &array);
// All the <category> nodes without a <topic>
for (ix = array.begin(); ix != array.end(); ++ix) {
// Load each category
string that = toString((*ix)->getChild("that"));
string pattern = toString((*ix)->getChild("pattern"));
// Nodemaster *node = add(pattern, that, "*");
// if (node != NULL) {
// node->addTemplate(templateString((*ix)->getChild("template")));
// ++totalCategories;
// }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -