Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task 5 #42

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
754d180
fixed double-delete improper memory management bug
gary-vladimir Jan 25, 2025
39910d0
made _chatLogic an exclusive resource to class ChatbotPanelDialog usi…
gary-vladimir Jan 27, 2025
fc21c32
defined special member functions for the rule of five copy and move s…
gary-vladimir Jan 27, 2025
56340fc
implemented chatbot copy constructor
gary-vladimir Jan 27, 2025
bfb8d42
added build and vscode folders
gary-vladimir Jan 27, 2025
1dc79bb
implemented the chatbot copy assignment operator
gary-vladimir Jan 27, 2025
47d78af
implemented chatbot move assignment operator
gary-vladimir Jan 27, 2025
b072f92
Revert "implemented the chatbot copy assignment operator"
gary-vladimir Jan 27, 2025
75eb1ce
implemented chatbot move contructor
gary-vladimir Jan 27, 2025
6e8abe7
implemented chatbot move assignment operator.
gary-vladimir Jan 27, 2025
09f6c1a
fixed typo 'image' instead of '_image'
gary-vladimir Jan 27, 2025
2bfeb12
fixed typo '_chatLogicPtr' instead of '_chatLogic'
gary-vladimir Jan 27, 2025
0f81936
updated getChatLogic getter handle to return _chatlogic.get instead o…
gary-vladimir Jan 27, 2025
4c356fe
replaced vector of raw pointers to nodes for unique_ptr smart pointer…
gary-vladimir Jan 27, 2025
ac5eb05
ChatLogic has exclusive ownership of GraphNode objects via unique_ptr
gary-vladimir Jan 28, 2025
cf586a0
changed the ownership of all instances of GraphEdge in a way that eac…
gary-vladimir Jan 28, 2025
e13bf39
implemented task 5 in theory, it should work, but right now throws se…
gary-vladimir Jan 31, 2025
ed7c6a7
fixed segfault by adding _chatLogic->SetChatbotHandle(this)
gary-vladimir Jan 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
.github/**
.vscode/**
build/**

56 changes: 55 additions & 1 deletion src/chatbot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,62 @@ ChatBot::~ChatBot()

//// STUDENT CODE
////
ChatBot::ChatBot(const ChatBot &source)
{
std::cout << "ChatBot Copy Constructor" << std::endl;
if(source._image != nullptr) _image = new wxBitmap(*source._image);
else _image = nullptr;

_chatLogic = source._chatLogic;
_rootNode = source._rootNode;
_currentNode = source._currentNode;
}

////
ChatBot &ChatBot::operator=(const ChatBot &source)
{
std::cout << "ChatBot Copy Assignment Operator" << std::endl;

if(this == &source) return *this;
if(_image != nullptr) {delete _image; _image = nullptr;}
if(source._image != nullptr) _image = new wxBitmap(*source._image);
else _image = nullptr;

_chatLogic = source._chatLogic;
_rootNode = source._rootNode;
_currentNode = source._currentNode;
return *this;
}

ChatBot::ChatBot(ChatBot &&source)
{
std::cout << "ChatBot Move Constructor" << std::endl;
_image = source._image;
_chatLogic = source._chatLogic;
_rootNode = source._rootNode;
_currentNode = source._currentNode;
_chatLogic->SetChatbotHandle(this);
source._image = nullptr;
source._chatLogic = nullptr;
source._rootNode = nullptr;
source._currentNode = nullptr;
}

ChatBot &ChatBot::operator=(ChatBot &&source)
{
std::cout << "ChatBot Move Assignment Operator" << std::endl;
if(this == &source) return *this;
if(_image != nullptr) {delete _image; _image = nullptr;}
_image = source._image;
_chatLogic = source._chatLogic;
_rootNode = source._rootNode;
_currentNode = source._currentNode;
_chatLogic->SetChatbotHandle(this);
source._image = nullptr;
source._chatLogic = nullptr;
source._rootNode = nullptr;
source._currentNode = nullptr;
return *this;
}
//// EOF STUDENT CODE

void ChatBot::ReceiveMessageFromUser(std::string message)
Expand Down
5 changes: 4 additions & 1 deletion src/chatbot.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ class ChatBot

//// STUDENT CODE
////

ChatBot(const ChatBot &source);
ChatBot &operator=(const ChatBot &source);
ChatBot(ChatBot &&source);
ChatBot &operator=(ChatBot &&source);
////
//// EOF STUDENT CODE

Expand Down
4 changes: 1 addition & 3 deletions src/chatgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ ChatBotPanelDialog::ChatBotPanelDialog(wxWindow *parent, wxWindowID id)
////

// create chat logic instance
_chatLogic = new ChatLogic();
_chatLogic = std::make_unique<ChatLogic>();

// pass pointer to chatbot dialog so answers can be displayed in GUI
_chatLogic->SetPanelDialogHandle(this);
Expand All @@ -135,8 +135,6 @@ ChatBotPanelDialog::~ChatBotPanelDialog()
//// STUDENT CODE
////

delete _chatLogic;

////
//// EOF STUDENT CODE
}
Expand Down
6 changes: 3 additions & 3 deletions src/chatgui.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#ifndef CHATGUI_H_
#define CHATGUI_H_

#include <memory>
#include <wx/wx.h>

class ChatLogic; // forward declaration
Expand All @@ -16,7 +16,7 @@ class ChatBotPanelDialog : public wxScrolledWindow
//// STUDENT CODE
////

ChatLogic *_chatLogic;
std::unique_ptr<ChatLogic> _chatLogic;

////
//// EOF STUDENT CODE
Expand All @@ -27,7 +27,7 @@ class ChatBotPanelDialog : public wxScrolledWindow
~ChatBotPanelDialog();

// getter / setter
ChatLogic *GetChatLogicHandle() { return _chatLogic; }
ChatLogic *GetChatLogicHandle() { return _chatLogic.get(); }

// events
void paintEvent(wxPaintEvent &evt);
Expand Down
57 changes: 28 additions & 29 deletions src/chatlogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ ChatLogic::ChatLogic()
////

// create instance of chatbot
_chatBot = new ChatBot("../images/chatbot.png");
//_chatBot = new ChatBot("../images/chatbot.png");

// add pointer to chatlogic so that chatbot answers can be passed on to the GUI
_chatBot->SetChatLogicHandle(this);
//_chatBot->SetChatLogicHandle(this);

////
//// EOF STUDENT CODE
Expand All @@ -33,19 +33,10 @@ ChatLogic::~ChatLogic()
////

// delete chatbot instance
delete _chatBot;
//delete _chatBot;

// delete all nodes
for (auto it = std::begin(_nodes); it != std::end(_nodes); ++it)
{
delete *it;
}

// delete all edges
for (auto it = std::begin(_edges); it != std::end(_edges); ++it)
{
delete *it;
}
// No need to manually delete edges now.
// The child nodes' unique_ptr<GraphEdge> will handle that.

////
//// EOF STUDENT CODE
Expand Down Expand Up @@ -127,12 +118,19 @@ void ChatLogic::LoadAnswerGraphFromFile(std::string filename)
////

// check if node with this ID exists already
auto newNode = std::find_if(_nodes.begin(), _nodes.end(), [&id](GraphNode *node) { return node->GetID() == id; });
auto newNode = std::find_if(
_nodes.begin(),
_nodes.end(),
[&id](std::unique_ptr<GraphNode> &node) {
return node->GetID() == id;
}
);


// create new element if ID does not yet exist
if (newNode == _nodes.end())
{
_nodes.emplace_back(new GraphNode(id));
_nodes.emplace_back(std::make_unique<GraphNode>(id));
newNode = _nodes.end() - 1; // get iterator to last element

// add all answers to current node
Expand All @@ -156,21 +154,20 @@ void ChatLogic::LoadAnswerGraphFromFile(std::string filename)
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); });
auto childNode = std::find_if(_nodes.begin(), _nodes.end(), [&childToken](GraphNode *node) { return node->GetID() == std::stoi(childToken->second); });
auto parentNode = std::find_if(_nodes.begin(), _nodes.end(), [&parentToken](std::unique_ptr<GraphNode> &node) { return node->GetID() == std::stoi(parentToken->second); });
auto childNode = std::find_if(_nodes.begin(), _nodes.end(), [&childToken](std::unique_ptr<GraphNode> &node) { return node->GetID() == std::stoi(childToken->second); });

// create new edge
GraphEdge *edge = new GraphEdge(id);
edge->SetChildNode(*childNode);
edge->SetParentNode(*parentNode);
_edges.push_back(edge);

auto edge = std::make_unique<GraphEdge>(id);
// _edges.push_back(edge);
edge->SetChildNode(childNode->get());
edge->SetParentNode(parentNode->get());
// find all keywords for current node
AddAllTokensToElement("KEYWORD", tokens, *edge);

// store reference in child node and parent node
(*childNode)->AddEdgeToParentNode(edge);
(*parentNode)->AddEdgeToChildNode(edge);
(*childNode)->AddEdgeToParentNode(edge.get());
(*parentNode)->AddEdgeToChildNode(std::move(edge));
}

////
Expand Down Expand Up @@ -206,18 +203,20 @@ void ChatLogic::LoadAnswerGraphFromFile(std::string filename)

if (rootNode == nullptr)
{
rootNode = *it; // assign current node to root
rootNode = (*it).get(); // assign current node to root
}
else
{
std::cout << "ERROR : Multiple root nodes detected" << std::endl;
}
}
}

ChatBot chatbot("../images/chatbot.png");
SetChatbotHandle(&chatbot);
// add chatbot to graph root node
_chatBot->SetRootNode(rootNode);
rootNode->MoveChatbotHere(_chatBot);
chatbot.SetChatLogicHandle(this);
chatbot.SetRootNode(rootNode);
rootNode->MoveChatbotHere(std::move(chatbot));

////
//// EOF STUDENT CODE
Expand Down
5 changes: 3 additions & 2 deletions src/chatlogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <vector>
#include <string>
#include "chatgui.h"
#include <memory>

// forward declarations
class ChatBot;
Expand All @@ -17,8 +18,8 @@ class ChatLogic
////

// data handles (owned)
std::vector<GraphNode *> _nodes;
std::vector<GraphEdge *> _edges;
std::vector<std::unique_ptr<GraphNode>> _nodes;
// std::vector<GraphEdge *> _edges;

////
//// EOF STUDENT CODE
Expand Down
19 changes: 10 additions & 9 deletions src/graphnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ GraphNode::~GraphNode()
//// STUDENT CODE
////

delete _chatBot;
// We do NOT delete _parentEdges here, since they are non‐owning!
// The unique_ptr in _childEdges will automatically free the GraphEdges.

////
//// EOF STUDENT CODE
Expand All @@ -27,23 +28,23 @@ void GraphNode::AddEdgeToParentNode(GraphEdge *edge)
_parentEdges.push_back(edge);
}

void GraphNode::AddEdgeToChildNode(GraphEdge *edge)
void GraphNode::AddEdgeToChildNode(std::unique_ptr<GraphEdge> edge)
{
_childEdges.push_back(edge);
_childEdges.push_back(std::move(edge));
}

//// STUDENT CODE
////
void GraphNode::MoveChatbotHere(ChatBot *chatbot)
void GraphNode::MoveChatbotHere(ChatBot chatbot)
{
_chatBot = chatbot;
_chatBot->SetCurrentNode(this);
_chatBot = std::move(chatbot);
_chatBot.SetCurrentNode(this);
}

void GraphNode::MoveChatbotToNewNode(GraphNode *newNode)
{
newNode->MoveChatbotHere(_chatBot);
_chatBot = nullptr; // invalidate pointer at source
newNode->MoveChatbotHere(std::move(_chatBot));
//_chatBot = nullptr; // invalidate pointer at source
}
////
//// EOF STUDENT CODE
Expand All @@ -53,7 +54,7 @@ GraphEdge *GraphNode::GetChildEdgeAtIndex(int index)
//// STUDENT CODE
////

return _childEdges[index];
return _childEdges[index].get();

////
//// EOF STUDENT CODE
Expand Down
12 changes: 6 additions & 6 deletions src/graphnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <vector>
#include <string>
#include "chatbot.h"

#include <memory>

// forward declarations
class GraphEdge;
Expand All @@ -16,11 +16,11 @@ class GraphNode
////

// data handles (owned)
std::vector<GraphEdge *> _childEdges; // edges to subsequent nodes
std::vector<std::unique_ptr<GraphEdge>> _childEdges; // edges to subsequent nodes

// data handles (not owned)
std::vector<GraphEdge *> _parentEdges; // edges to preceding nodes
ChatBot *_chatBot;
ChatBot _chatBot;

////
//// EOF STUDENT CODE
Expand All @@ -37,19 +37,19 @@ class GraphNode
// getter / setter
int GetID() { return _id; }
int GetNumberOfChildEdges() { return _childEdges.size(); }
int GetNumberOfParents() { return _parentEdges.size(); }
GraphEdge *GetChildEdgeAtIndex(int index);
std::vector<std::string> GetAnswers() { return _answers; }
int GetNumberOfParents() { return _parentEdges.size(); }

// proprietary functions
void AddToken(std::string token); // add answers to list
void AddEdgeToParentNode(GraphEdge *edge);
void AddEdgeToChildNode(GraphEdge *edge);
void AddEdgeToChildNode(std::unique_ptr<GraphEdge> edge);

//// STUDENT CODE
////

void MoveChatbotHere(ChatBot *chatbot);
void MoveChatbotHere(ChatBot chatbot);

////
//// EOF STUDENT CODE
Expand Down