-
Notifications
You must be signed in to change notification settings - Fork 0
/
Network.cpp
364 lines (289 loc) · 11.5 KB
/
Network.cpp
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/****************************************************************************************************************************
Title : Network.hpp
Author : modified by Kasaf Shah
Description : Implementation files for Network class
Date modified : 11/20/2022
****************************************************************************************************************************/
#include "Network.hpp"
template <typename ItemType>
Network<ItemType>::Network() : account_count_(0), feed_({}){}
template <typename ItemType>
int Network<ItemType>::getSizeOfNetwork() const { return account_count_; }
template <typename ItemType>
bool Network<ItemType>::isEmpty() const { return account_count_ == 0; }
/**
@param : a POINTER to the item that will be added to the Network
@return : bool- true if the item was successfully added, false otherwise
@post : stores a pointer to the item, if there is room. This is a network specific function,
it has an additional constraint: the item will be added only if no other item in the network
has the same username (usernames are considered unique)
Finally, the Account being added to the network will update it's private member to point to this network
*/
template <typename ItemType>
bool Network<ItemType>::addAccount(ItemType* new_entry) {
bool has_room = ( account_count_ < DEFAULT_CAPACITY );
if(has_room && getIndexOf(new_entry->getUsername()) < 0){
network_[account_count_] = new_entry;
new_entry->setNetwork(this);
account_count_++;
return true;
}
return false;
}
/**
Mutator function
@param : a POINTER to the item that will be removed from Network
@return : true if if the item was successfully removed, false otherwise
@post : updates the bag/network to remove the pointer, if a pointer to that item was found.
*/
template <typename ItemType>
bool Network<ItemType>::removeAccount(ItemType* an_entry) {
int found_account = getIndexOf(an_entry->getUsername());
bool can_remove = !isEmpty() && ( found_account > -1 );
if(can_remove){
account_count_--;
if(!(account_count_ == found_account))
network_[found_account] = network_[account_count_];
}
return can_remove;
}
/**
@post :removes all accounts from the network
**/
template <typename ItemType>
void Network<ItemType>::clear(){
// account_count_ = 0;
while (account_count_ > 0) {
removeAccount(*(network_[account_count_-1]));
}
}
/**
@return : true if an_etry is found in network_, false otherwise
**/
template <typename ItemType>
bool Network<ItemType>::containsAccount(const ItemType &an_entry) const {
return getIndexOf(an_entry.getUsername()) > -1;
}
/**
Mutator function
@param : the name of an input file
@pre : The format of the text file is as follows:
username password
username password
;
where ';' signals the end of the file. Check the provided example (accounts.txt).
@post : Reads every line in the input file, creates an Account from that information and
adds the Account to the network. If a line of input is missing some required information,
it prints out "Improper Format" and terminates.
Keep in mind that, although the input will always be an Account, the Network class is
a template, thus it will store a pointer to a generic type. It will do so by creating a new
dynamic object of type ItemType but passing the account information (username and password)
as to the Account constructor. This is a bit hacky, but it will work for our Network.
*/
template <typename ItemType>
void Network<ItemType>::populateNetwork(const std::string input){
std::fstream fin;
fin.open(input, std::ios::in);
std::string usr = "";
std::string pswd = "";
std::string line;
std::string word;
while (std::getline(fin, line)){
if(line == ";") {
break;
}
std::stringstream s(line);
s >> usr;
s >> pswd;
if(usr == "" || pswd == "") {
std::cout << "Improper format" << std::endl;
break;
}
// ItemType new_entry(usr,pswd);
// addAccount(new_entry);
ItemType* new_entry = new ItemType(usr,pswd);
bool is_added = addAccount(*new_entry);
if(!is_added) {
std::cout << "Error when adding account" << std::endl;
break;
}
usr = "";
pswd = "";
}
fin.close();
}
/**
Accessor function
@param : a reference to the item whose feed will be displayed
@post : prints the feed of the given account by checking who they are following
and displaying all the posts from the feed that were made by those accounts.
Keep in mind that the Network parameters are general template types
in this project rather than accounts, although this functionality is
specific to accounts.
*/
template <typename ItemType>
void Network<ItemType>::printFeedForAccount(ItemType &an_entry) {
int location = getIndexOf(an_entry.getUsername());
if(location > -1) {
std::vector<std::string> following_list = network_[location]->viewFollowing();
Node<Post*>* itt = feed_.getHeadPtr();
while(itt != nullptr) {
Post* curr_item = itt->getItem();
std::string curr_user = curr_item->getUsername();
for(std::string acc_username : following_list) {
if(acc_username == curr_user) {
curr_item->displayPost();
break;
}
}
itt = itt->getNext();
}
}
}
template <typename ItemType>
int Network<ItemType>::getIndexOf(const std::string username) const {
bool found = false;
int result = -1;
int index = 0;
while(!found && (index < account_count_)){
if (network_[index]->getUsername() == username) {
found = true;
result = index;
}
else { index++; }
}
return result;
}
/**
@param : a reference to an item (account) and the username of the account
it wants to follow
@return : true if the item was authorized to follow, false otherwise
@post : the referenced Account follows another account with the username
specified by the second argument if they both exist in the network
*/
template <typename ItemType>
bool Network<ItemType>::authenticateFollow(ItemType &an_entry, const std::string username) const {
int index_user = getIndexOf(an_entry.getUsername());
if(index_user > -1){
int index = getIndexOf(username);
if(index > -1) {
an_entry.followAccount(username);
return true;
}
}
return false;
}
/**
@param : a pointer to Post
@post : the post is added to the feed if the account username is in the network
*/
template <typename ItemType>
void Network<ItemType>::addToFeed(Post* p) {
if(getIndexOf(p->getUsername()) > -1)
feed_.insert(p, 0);
}
/**
The (set) difference between two sets A and B is the set that
consists of the elements of A which are not elements of B
@param : a_network to be subtracted from the Network Bag calling the function
@post : removes all the data from network_ that is also found in a_network
**/
template <typename ItemType>
void Network<ItemType>::operator-=(Network<ItemType> &a_network){
int index = 0;
int this_index = 0;
int accounts_left = a_network.account_count_;
while (accounts_left > 0){
if(this->account_count_ == 0){
break;
}
this_index = this->getIndexOf(a_network.network_[index]->getUsername());
if(this_index > -1){
this->removeAccount(*(this->network_[this_index]));
}
index++;
accounts_left--;
}
}
/**
@param : a pointer to Post
@return : true if post was removed from feed, false otherwise
@post : the post is removed from to the feed if there
*/
template <typename ItemType>
bool Network<ItemType>::removePostFromFeed(Post* post){
int postPosition = feed_.getIndexOf(post);
if (postPosition > -1) {
feed_.remove(postPosition);
return true;
}
return false;
}
/*
@param : A string (word or phrase, case-sensitive) passed by reference
@return : The number of items removed from the list
@post : Any Post that contains the provided word or phrase in it's title,
body or both is removed from the Network's `feed_` as well as
the Account's `posts_`.
You are encouraged to create your own helper functions for this endeavour.
*/
template <typename ItemType>
int Network<ItemType>::removeIfContains(const std::string &postBody){
int occurrences{0};
if(feed_.getSize() == 0) { return occurrences; }
else {
Node<Post*>* curr = feed_.getHeadPtr();
while(curr != nullptr){
Post* curr_post = curr->getItem();
curr = curr->getNext();
if (curr_post->getTitle().find(postBody) != std::string::npos ||
curr_post->getBody().find(postBody) != std::string::npos
){
int acc_index = getIndexOf(curr_post->getUsername());
if(acc_index > -1) {
network_[acc_index]->removePost(curr_post);
}
occurrences++;
}
}
}
return occurrences;
}
/**
@param : a pointer to Post
@return : true if post was found and moved to the front of the feed,
false otherwise
@post : The post is moved to the front of the feed
*/
template <typename ItemType>
bool Network<ItemType>::updateFeed(Post* post) {
return feed_.moveItemToTop(post);
}
/**
Accessor function
@post : prints the feed by displaying all the posts from the feed
*/
template <typename ItemType>
void Network<ItemType>::printFeed(){
Node<Post*> *header = feed_.getHeadPtr();
while(header != nullptr) {
std::cout << header->getItem() << '\n';
header = header->getNext();
}
}
/*@comp : The Comparator to sort with
@i : A POINTER to an integer counter that gets incremented every time a swap between two Nodes occurs
(this is for testing purposes).
IT IS IMPORTANT TO PASS OUR GRADESCOPE TESTS TAHT EACH
TIME BUBBLE SORT MAKES A SWAP YOU INCREMENT THIS COUNTER.
@return : A COPY of the feed_ sorted by username using bubble sort
based on Comparator ( std::less or std::greater ),
from least to greatest or greatest to least.
*/
template<typename ItemType>
template<typename Comparator>
LinkedList<Post*> Network<ItemType>::bSortByUsername(Comparator comp, int* i){
LinkedList<Post*>copy(feed_);
copy.bSort(comp, i);
return copy;
}