Skip to content

Commit 928a53b

Browse files
committed
First commit
0 parents  commit 928a53b

18 files changed

+898
-0
lines changed

CMakeLists.txt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
cmake_minimum_required(VERSION 3.11.3)
2+
3+
set(CMAKE_CXX_STANDARD 17)
4+
5+
project(Membot)
6+
7+
find_package(wxWidgets REQUIRED COMPONENTS core base)
8+
include(${wxWidgets_USE_FILE})
9+
10+
file(GLOB project_SRCS src/*.cpp)
11+
12+
add_executable(membot ${project_SRCS})
13+
target_link_libraries(membot ${wxWidgets_LIBRARIES})
14+
target_include_directories(membot PRIVATE ${wxWidgets_INCLUDE_DIRS})

README.md

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# CPPND: Memory Management Chatbot
2+
3+
<img src="images/chatbot_demo.png"/>
4+
5+
This is the project for the third course in the [Udacity C++ Nanodegree Program](https://www.udacity.com/course/c-plus-plus-nanodegree--nd213): Memory Management.
6+
7+
## Dependencies for Running Locally
8+
* cmake >= 2.8
9+
* All OSes: [click here for installation instructions](https://cmake.org/install/)
10+
* make >= 4.1 (Linux, Mac), 3.81 (Windows)
11+
* Linux: make is installed by default on most Linux distros
12+
* Mac: [install Xcode command line tools to get make](https://developer.apple.com/xcode/features/)
13+
* Windows: [Click here for installation instructions](http://gnuwin32.sourceforge.net/packages/make.htm)
14+
* gcc/g++ >= 5.4
15+
* Linux: gcc / g++ is installed by default on most Linux distros
16+
* Mac: same deal as make - [install Xcode command line tools](https://developer.apple.com/xcode/features/)
17+
* Windows: recommend using [MinGW](http://www.mingw.org/)
18+
* wxWidgets >= 3.0
19+
* Linux: `sudo apt-get install libwxgtk3.0-dev libwxgtk3.0-0v5-dbg`
20+
* Mac: There is a [homebrew installation available](https://formulae.brew.sh/formula/wxmac).
21+
* Installation instructions can be found [here](https://wiki.wxwidgets.org/Install). Some version numbers may need to be changed in instructions to install v3.0 or greater.
22+
23+
## Basic Build Instructions
24+
25+
1. Clone this repo.
26+
2. Make a build directory in the top level directory: `mkdir build && cd build`
27+
3. Compile: `cmake .. && make`
28+
4. Run it: `./membot`.

images/chatbot.png

2.86 KB
Loading

images/chatbot_demo.png

186 KB
Loading

images/sf_bridge.jpg

1.24 MB
Loading

images/sf_bridge_inner.jpg

184 KB
Loading

images/user.png

2.24 KB
Loading

src/answergraph.txt

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
// define all graph nodes
3+
<TYPE:NODE><ID:0><ANSWER:Welcome! My name is MemBot. You can ask me about things related to memory management in C++. Possible topics are 'pointers' and 'the C++ memory model'. What would you like to talk about?>
4+
5+
<TYPE:NODE><ID:1><ANSWER:Great! Let's talk about pointers. In computer science, a pointer is a special value whose meaning is a memory address. This address can contain either data, such as variables or objects, but also program codes (instructions). By dereferencing the pointer it is possible to access the data or the code. Among other things, pointers are used to manage dynamic memory. Other topics around pointers you can ask about are 'smart pointers' and 'nullptr'>
6+
7+
<TYPE:NODE><ID:2><ANSWER:When instantiating variables, programmers can choose wether to do this on the heap, on the stack or in static memory. Do you want to know more about those two concepts? Simply ask me about 'heap', 'stack' or 'static'.>
8+
9+
<TYPE:NODE><ID:3><ANSWER:A smart pointer is an object that behaves like a pointer, i.e. it must support pointer operations such as dereferencing or indirect access. In addition to these properties, the smart pointer handles resources better. In concrete terms, this means that it takes care not to cause a memory leak. A smart pointer exists in various flavors, which are unique_ptr, shared_ptr and weak_ptr. There are no more topics in this section, starting over!>
10+
11+
<TYPE:NODE><ID:4><ANSWER:The value nullptr can be assigned to pointers of any type. This turns the pointer into a null pointer that does not point to a memory location. The nullptr keyword can be used to test if a pointer or handle reference is null before the reference is used. There are no more topics in this section, starting over!>
12+
13+
<TYPE:NODE><ID:5><ANSWER:Local variables declared as part of a function are stored on the stack. Also, the stack is the place where function parameters are stored. Further, the stack is used for storing the return address of the calling functions, and it keeps the register contents and return address when an interrupt service routine is called. -- There are no more topics in this section, starting over!>
14+
15+
<TYPE:NODE><ID:6><ANSWER:Heap memory, also known as dynamic memory, is an alternative to local stack memory. Local memory is allocated automatically on function call and it is deallocated automatically when a function exits. Heap memory is different. The programmer explicitly requests the allocation of a memory block of a particular size, and the block continues to be allocated until the programmer explicitly requests that it be deallocated. -- There are no more topics in this section, starting over!>
16+
17+
<TYPE:NODE><ID:7><ANSWER:Static memory persists throughout the entire life of the program, and is usually used to store things like global variables, or variables created with the static clause. -- There are no more topics in this section, starting over!>
18+
19+
20+
// connect nodes with edges
21+
<TYPE:EDGE><ID:0><PARENT:0><CHILD:1><KEYWORD:pointer><KEYWORD:smart pointer>
22+
<TYPE:EDGE><ID:1><PARENT:0><CHILD:2><KEYWORD:memory model><KEYWORD:heap><KEYWORD:stack>
23+
24+
<TYPE:EDGE><ID:2><PARENT:1><CHILD:3><KEYWORD:unique pointer><KEYWORD:shared pointer><KEYWORD:weak pointer>
25+
<TYPE:EDGE><ID:3><PARENT:1><CHILD:4><KEYWORD:NULL><KEYWORD:null pointer><KEYWORD:nullptr>
26+
27+
<TYPE:EDGE><ID:4><PARENT:2><CHILD:5><KEYWORD:stack><KEYWORD:stack memory><KEYWORD:local variable storage>
28+
<TYPE:EDGE><ID:5><PARENT:2><CHILD:6><KEYWORD:heap><KEYWORD:heap memory><KEYWORD:dynamic storage>
29+
<TYPE:EDGE><ID:6><PARENT:2><CHILD:7><KEYWORD:static><KEYWORD:static memory><KEYWORD:global variable storage>

src/chatbot.cpp

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#include <iostream>
2+
#include <random>
3+
#include <algorithm>
4+
#include <ctime>
5+
6+
#include "chatlogic.h"
7+
#include "graphnode.h"
8+
#include "graphedge.h"
9+
#include "chatbot.h"
10+
11+
void ChatBot::ReceiveUserQuery(std::string query)
12+
{
13+
// loop over all edges and keywords and compute Levenshtein distance to query
14+
typedef std::pair<GraphEdge*, int> EdgeDist;
15+
std::vector<EdgeDist> levDists; // format is <ptr,levDist>
16+
for (auto edge : _currentNode->GetEdgesToChildNodes())
17+
{
18+
for (auto keyword : edge->GetKeywords())
19+
{
20+
EdgeDist ed{edge, ComputeLevenshteinDistance(keyword, query)};
21+
levDists.push_back(ed);
22+
}
23+
}
24+
25+
// select best fitting edge to proceed along
26+
GraphNode *newNode;
27+
if (levDists.size() > 0)
28+
{
29+
// sort in ascending order of Levenshtein distance (best fit is at the top)
30+
std::sort(levDists.begin(), levDists.end(), [](const EdgeDist &a, const EdgeDist &b) { return a.second < b.second; });
31+
newNode = levDists.at(0).first->GetChildNode(); // after sorting the best edge is at first position
32+
}
33+
else
34+
{
35+
// go back to root node
36+
newNode = _rootNode;
37+
}
38+
39+
// tell current node to move chatbot to new node
40+
_currentNode->moveChatbotToNewNode(newNode);
41+
}
42+
43+
void ChatBot::SetCurrentNode(GraphNode *node)
44+
{
45+
// update pointer to current node
46+
_currentNode = node;
47+
48+
// select a random node answer (if several answers should exist)
49+
std::vector<std::string> answers = _currentNode->GetAnswers();
50+
std::mt19937 generator(int(std::time(0)));
51+
std::uniform_int_distribution<int> dis(0, answers.size() - 1);
52+
std::string answer = answers.at(dis(generator));
53+
54+
// send selected node answer to user
55+
_chatLogic->getChatBotPanelDialog()->printChatbotResponse(answer);
56+
}
57+
58+
int ChatBot::ComputeLevenshteinDistance(std::string s1, std::string s2)
59+
{
60+
// convert both strings to upper-case before comparing
61+
std::transform(s1.begin(), s1.end(), s1.begin(), ::toupper);
62+
std::transform(s2.begin(), s2.end(), s2.begin(), ::toupper);
63+
64+
// compute Levenshtein distance measure between both strings
65+
const size_t m(s1.size());
66+
const size_t n(s2.size());
67+
68+
if (m == 0)
69+
return n;
70+
if (n == 0)
71+
return m;
72+
73+
size_t *costs = new size_t[n + 1];
74+
75+
for (size_t k = 0; k <= n; k++)
76+
costs[k] = k;
77+
78+
size_t i = 0;
79+
for (std::string::const_iterator it1 = s1.begin(); it1 != s1.end(); ++it1, ++i)
80+
{
81+
costs[0] = i + 1;
82+
size_t corner = i;
83+
84+
size_t j = 0;
85+
for (std::string::const_iterator it2 = s2.begin(); it2 != s2.end(); ++it2, ++j)
86+
{
87+
size_t upper = costs[j + 1];
88+
if (*it1 == *it2)
89+
{
90+
costs[j + 1] = corner;
91+
}
92+
else
93+
{
94+
size_t t(upper < corner ? upper : corner);
95+
costs[j + 1] = (costs[j] < t ? costs[j] : t) + 1;
96+
}
97+
98+
corner = upper;
99+
}
100+
}
101+
102+
int result = costs[n];
103+
delete[] costs;
104+
105+
return result;
106+
}

src/chatbot.h

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#ifndef CHATBOT_H_
2+
#define CHATBOT_H_
3+
4+
#include <string>
5+
6+
class GraphNode; // forward declaration
7+
class ChatLogic; // forward declaration
8+
9+
class ChatBot
10+
{
11+
private:
12+
13+
// pointers to chatbot elements
14+
GraphNode *_currentNode;
15+
GraphNode *_rootNode;
16+
ChatLogic *_chatLogic;
17+
18+
// proprietary functions
19+
int ComputeLevenshteinDistance(std::string s1, std::string s2);
20+
21+
public:
22+
// constructors / destructors
23+
ChatBot() {}
24+
25+
// getters / setters
26+
void SetCurrentNode(GraphNode *node);
27+
void SetRootNode(GraphNode *rootNode) { _rootNode = rootNode; }
28+
void SetChatLogic(ChatLogic *chatLogic) { _chatLogic = chatLogic; }
29+
30+
// proprietary functions
31+
void ReceiveUserQuery(std::string query);
32+
33+
};
34+
35+
#endif /* CHATBOT_H_ */

0 commit comments

Comments
 (0)