226 lines
7.8 KiB
C++
226 lines
7.8 KiB
C++
#include <fstream>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <iterator>
|
|
#include <tuple>
|
|
#include <algorithm>
|
|
|
|
#include "graphedge.h"
|
|
#include "graphnode.h"
|
|
#include "chatbot.h"
|
|
#include "chatlogic.h"
|
|
|
|
ChatLogic::ChatLogic()
|
|
{
|
|
_chatBot = new ChatBot();
|
|
_chatBot->SetChatLogicHandle(this);
|
|
}
|
|
|
|
ChatLogic::~ChatLogic()
|
|
{
|
|
|
|
delete _chatBot;
|
|
|
|
// delete all nodes
|
|
for (auto it = std::begin(_nodes); it != std::end(_nodes); ++it)
|
|
{
|
|
delete *it;
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void ChatLogic::AddAllTokensToElement(std::string tokenID, tokenlist &tokens, T &element)
|
|
{
|
|
// find all occurences for current node
|
|
auto token = tokens.begin();
|
|
while (true)
|
|
{
|
|
token = std::find_if(token, tokens.end(), [&tokenID](const std::pair<std::string, std::string> &pair) { return pair.first == tokenID;; });
|
|
if (token != tokens.end())
|
|
{
|
|
element.AddToken(token->second); // add new keyword to edge
|
|
token++; // increment iterator to next element
|
|
}
|
|
else
|
|
{
|
|
break; // quit infinite while-loop
|
|
}
|
|
}
|
|
}
|
|
|
|
void ChatLogic::LoadAnswerGraphFromFile(std::string filename)
|
|
{
|
|
// load file with answer graph elements
|
|
std::ifstream file(filename);
|
|
|
|
// check for file availability and process it line by line
|
|
if (file)
|
|
{
|
|
// loop over all lines in the file
|
|
std::string lineStr;
|
|
while (getline(file, lineStr))
|
|
{
|
|
// extract all tokens from current line
|
|
tokenlist tokens;
|
|
while (lineStr.size() > 0)
|
|
{
|
|
// extract next token
|
|
int posTokenFront = lineStr.find("<");
|
|
int posTokenBack = lineStr.find(">");
|
|
if (posTokenFront < 0 || posTokenBack < 0)
|
|
break; // quit loop if no complete token has been found
|
|
std::string tokenStr = lineStr.substr(posTokenFront + 1, posTokenBack - 1);
|
|
|
|
// extract token type and info
|
|
int posTokenInfo = tokenStr.find(":");
|
|
if (posTokenInfo != std::string::npos)
|
|
{
|
|
std::string tokenType = tokenStr.substr(0, posTokenInfo);
|
|
std::string tokenInfo = tokenStr.substr(posTokenInfo + 1, tokenStr.size() - 1);
|
|
|
|
// add token to vector
|
|
tokens.push_back(std::make_pair(tokenType, tokenInfo));
|
|
}
|
|
|
|
// remove token from current line
|
|
lineStr = lineStr.substr(posTokenBack + 1, lineStr.size());
|
|
}
|
|
|
|
// process tokens for current line
|
|
auto type = std::find_if(tokens.begin(), tokens.end(), [](const std::pair<std::string, std::string> &pair) { return pair.first == "TYPE"; });
|
|
if (type != tokens.end())
|
|
{
|
|
// check for id
|
|
auto idToken = std::find_if(tokens.begin(), tokens.end(), [](const std::pair<std::string, std::string> &pair) { return pair.first == "ID"; });
|
|
if (idToken != tokens.end())
|
|
{
|
|
// extract id from token
|
|
int id = std::stoi(idToken->second);
|
|
|
|
// node-based processing
|
|
if (type->second == "NODE")
|
|
{
|
|
// check if node with this ID exists already
|
|
auto newNode = std::find_if(_nodes.begin(), _nodes.end(), [&id](GraphNode *node) { return node->GetID() == id; }); // TODO
|
|
|
|
// create new element if ID does not yet exist
|
|
if (newNode == _nodes.end())
|
|
{
|
|
_nodes.emplace_back(new GraphNode(id)); // TODO
|
|
newNode = _nodes.end() - 1; // get iterator to last element
|
|
|
|
// add all answers to current node
|
|
AddAllTokensToElement("ANSWER", tokens, **newNode);
|
|
}
|
|
|
|
}
|
|
|
|
// edge-based processing
|
|
if (type->second == "EDGE")
|
|
{
|
|
//// STUDENT CODE
|
|
////
|
|
|
|
// find tokens for incoming (parent) and outgoing (child) node
|
|
auto parentToken = std::find_if(tokens.begin(), tokens.end(), [](const std::pair<std::string, std::string> &pair) { return pair.first == "PARENT"; });
|
|
auto childToken = std::find_if(tokens.begin(), tokens.end(), [](const std::pair<std::string, std::string> &pair) { return pair.first == "CHILD"; });
|
|
|
|
if (parentToken != tokens.end() && childToken != tokens.end())
|
|
{
|
|
// get iterator on incoming and outgoing node via ID search
|
|
auto parentNode = std::find_if(_nodes.begin(), _nodes.end(), [&parentToken](GraphNode *node) { return node->GetID() == std::stoi(parentToken->second); }); // TODO
|
|
auto childNode = std::find_if(_nodes.begin(), _nodes.end(), [&childToken](GraphNode *node) { return node->GetID() == std::stoi(childToken->second); }); // TODO
|
|
|
|
// TODO: create new edge
|
|
GraphEdge *edge = new GraphEdge(id);
|
|
edge->SetChildNode(*childNode);
|
|
edge->SetParentNode(*parentNode);
|
|
//_edges.push_back(edge);
|
|
// END OF TODO
|
|
|
|
// find all keywords for current node
|
|
AddAllTokensToElement("KEYWORD", tokens, *edge);
|
|
|
|
// TODO: store reference in child node and parent node
|
|
(*childNode)->AddEdgeToParentNode(edge); // TODO: add non-owning reference
|
|
(*parentNode)->AddEdgeToChildNode(edge); // TODO: transfer ownership to parent node
|
|
// END OF TODO
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Error: ID missing. Line is ignored!" << std::endl;
|
|
}
|
|
}
|
|
} // eof loop over all lines in the file
|
|
|
|
file.close();
|
|
|
|
} // eof check for file availability
|
|
else
|
|
{
|
|
std::cout << "File could not be opened!" << std::endl;
|
|
return;
|
|
}
|
|
|
|
//// STUDENT CODE
|
|
////
|
|
|
|
// identify root node
|
|
GraphNode *rootNode = nullptr;
|
|
for (auto it = std::begin(_nodes); it != std::end(_nodes); ++it)
|
|
{
|
|
// search for nodes which have no incoming edges
|
|
if ((*it)->GetNumberOfParents() == 0)
|
|
{
|
|
|
|
if (rootNode == nullptr)
|
|
{
|
|
// assign current node to root
|
|
rootNode = *it; // TODO: assign current node to root
|
|
}
|
|
else
|
|
{
|
|
std::cout << "ERROR : Multiple root nodes detected" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: add chatbot to graph root node
|
|
_chatBot->SetRootNode(rootNode);
|
|
rootNode->moveChatbotHere(_chatBot);
|
|
// END OF TODO
|
|
|
|
}
|
|
|
|
#ifdef GUI_APP
|
|
void ChatLogic::SetPanelDialogHandle(ChatBotPanelDialog *panelDialog)
|
|
{
|
|
_panelDialog = panelDialog;
|
|
}
|
|
|
|
void ChatLogic::SendMessageToUser(std::string message)
|
|
{
|
|
_panelDialog->PrintChatbotResponse(message);
|
|
}
|
|
#else
|
|
void ChatLogic::SetPanelDialogHandle(ChatBotPanelDialog *panelDialog) {}
|
|
void ChatLogic::SendMessageToUser(std::string message) {}
|
|
|
|
void ChatLogic::SetChatbotHandle(ChatBot *chatbot) {
|
|
_chatBot = chatbot;
|
|
}
|
|
|
|
void ChatLogic::SendMessageToChatbot(std::string message) {
|
|
if (_chatBot) {
|
|
_chatBot->ReceiveMessageFromUser(message);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool ChatLogic::IsGraphLoaded() const {
|
|
return !_nodes.empty();
|
|
}
|