-
Notifications
You must be signed in to change notification settings - Fork 0
/
knowledge.c
236 lines (197 loc) · 5.89 KB
/
knowledge.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
* ICT1002 (C Language) Group Project.
*
* This file implements the chatbot's knowledge base.
*
* knowledge_get() retrieves the response to a question.
* knowledge_put() inserts a new response to a question.
* knowledge_read() reads the knowledge base from a file.
* knowledge_reset() erases all of the knowledge.
* knowledge_write() saves the knowledge base in a file.
*
* You may add helper functions as necessary.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "chat1002.h"
#include <stdbool.h>
hash_table *knowledge_base = NULL;
/*
* Get the response to a question.
*
* Input:
* intent - the question word
* entity - the entity
* response - a buffer to receive the response
* n - the maximum number of characters to write to the response buffer
*
* Returns:
* KB_OK, if a response was found for the intent and entity (the response is copied to the response buffer)
* KB_NOTFOUND, if no response could be found
* KB_INVALID, if 'intent' is not a recognised question word
*/
int knowledge_get(const char *intent, const char *entity, char *response, int n) {
// Check if knowledgebase exists
check_for_knowledge_base();
// Check if intent is valid
if(chatbot_is_question(intent) == 1){
if ( retrieve_chat_entry(knowledge_base, intent, entity) == NULL) {
snprintf(response, n, "I don't recognise %s.", intent);
return KB_NOTFOUND;
}
else {
chat_entry *chatEntry= retrieve_chat_entry(knowledge_base, intent, entity);
snprintf(response, n, "%s", chatEntry->response);
}
}
else{
snprintf(response, n, "I don't recognise %s.", intent);
return KB_INVALID;
}
// Check if response found
// if yes, return KB_OK
if(response != NULL){
return KB_OK;
}
return KB_NOTFOUND;
}
/*
* Insert a new response to a question. If a response already exists for the
* given intent and entity, it will be overwritten. Otherwise, it will be added
* to the knowledge base.
*
* Input:
* intent - the question word
* entity - the entity
* response - the response for this question and entity
*
* Returns:
* KB_FOUND, if successful
* KB_NOMEM, if there was a memory allocation failure
* KB_INVALID, if the intent is not a valid question word
*/
int knowledge_put(const char *intent, const char *entity, const char *response) {
check_for_knowledge_base();
chat_entry *chatEntry = create_chat_entry(intent, entity, response);
if (insert_into_hash_table(knowledge_base, chatEntry) == 0) {
return KB_OK;
}
else {
return KB_NOMEM;
}
}
/*
* Read a knowledge base from a file.
*
* Input:
* f - the file
*
* Returns: the number of entity/response pairs successful read from the file
*/
int knowledge_read(FILE * f){
char *line = NULL;
size_t sz = 0;
int entitycount = 0;
char entity[64];
char intent[32];
char response[256];
char *strsplit;
char *backstr;
while(getline(&line,&sz,f) != -1) {
if (strstr(line,"what")){
strcpy(intent,"WHAT");
}
else if(strstr(line,"where")){
strcpy(intent,"WHERE");
}
else if(strstr(line,"who")){
strcpy(intent,"WHO");
}
if(strstr(line,"=")){
strsplit = strtok(line,"=");
strcpy(entity,strsplit);
backstr = strtok(NULL,"=");
backstr =strtok(backstr,"\n");
strcpy(response,backstr);
knowledge_put(intent,entity,response);
entitycount += 1; // inside here because count is added only when entity is found.
}
}
if (line) {
free(line);
}
return entitycount;
}
/*
* Reset the knowledge base, removing all know entitities from all intents.
*/
void knowledge_reset() {
check_for_knowledge_base(); //check if knowledge base exists
hash_table *clearHT = knowledge_base; //create new pointer to point to current knowledge base
knowledge_base = create_hash_table(); //move the global pointer to a new knowledge base
clearHashTable(clearHT); //clear the current knowledge base
}
/*
* Write the knowledge base to a file.
*
* Input:
* f - the file
*/
void knowledge_write(FILE *f) {
// Checking for knowledge base
check_for_knowledge_base();
chat_entry *whatList[TABLE_SIZE];
chat_entry *whoList[TABLE_SIZE];
chat_entry *whereList[TABLE_SIZE];
int whatC = 0;
int whoC = 0;
int whereC = 0;
// Loop through whole table
for(int i=0; i<TABLE_SIZE; i++){
chat_entry * entry;
entry = malloc(sizeof(chat_entry));
entry = knowledge_base -> chat_entries[i];
if(entry != NULL){
if(strcmp(entry->intent, "WHAT") == 0 || strcmp(entry->intent, "What") == 0 || strcmp(entry->intent, "what") == 0){
whatList[whatC] = entry;
whatC++;
}
else if(strcmp(entry->intent, "WHO") == 0 || strcmp(entry->intent, "Who") == 0 || strcmp(entry->intent, "who") == 0){
whoList[whoC] = entry;
whoC++;
}
else if(strcmp(entry->intent, "WHERE") == 0 || strcmp(entry->intent, "Where") == 0 || strcmp(entry->intent, "where") == 0){
whereList[whereC] = entry;
whereC++;
}
}
}
// Write to file
fprintf(f,"[what]\n");
for(int i=0; i<whatC; i++){
fprintf(f,"%s=%s\n", whatList[i]->entity, whatList[i]->response);
}
fprintf(f,"\n[where]\n");
for(int i=0; i<whereC; i++){
fprintf(f,"%s=%s\n", whereList[i]->entity, whereList[i]->response);
}
fprintf(f,"\n[who]\n");
for(int i=0; i<whoC; i++){
fprintf(f,"%s=%s\n", whoList[i]->entity, whoList[i]->response);
}
}
/*
* This function checks if the knowledge_base is NULL
* If it is, it runs the create_hash_table() function
* which should populate it with chat_entry structs.
* This is a void function.
*/
void check_for_knowledge_base() {
if (knowledge_base == NULL) {
knowledge_base = create_hash_table();
}
}
void knowledgedump(){
ht_dump(knowledge_base);
}