⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kernel.cpp

📁 J-Alice是一个用C++实现的Ailcebot的克隆。它可以做为一个mini-http服务器在控制台或irc聊天。目前
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**
 * 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 + -