-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUser_Database.h
More file actions
311 lines (280 loc) · 9.85 KB
/
User_Database.h
File metadata and controls
311 lines (280 loc) · 9.85 KB
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
#pragma once
#include "Machine.h"
#include "Users.h"
#include "Timer.h"
#include<string>
#include<map>
#include<fstream>
#include<iostream>
using namespace std;
//Users_Database is a slight misnomer - this class creates a singleton overhead object that manages the entire database
class Users_Database
{
private:
//Users_Database pointer, which stores the location of the database object
static Users_Database *instance;
//Stores the currently logged in user's name
string currentuser;
//Default constructor, called through GetInstance public function
Users_Database()
{
currentuser = "";
//Opens memory files, "usersmemory.txt", "washingmachinesmemory.txt", "dryingmachinesmemory.txt"
//and attempts to take information stored within
//The program currently is UNABLE to handle corrupted data (i.e. incomplete information)
//However it is self-sufficient in that it will handle saving and loading memory safely if there is no corruption
ifstream inFileBuffer("usersmemory.txt");
if (inFileBuffer.fail())
{
cerr << "ERROR OPENING MEMORY. Please check that memory files are not corrupted. (USERSMEMORY)";
}
string newnetID;
string newpassword;
bool newstatus;
while (!inFileBuffer.eof())
{
inFileBuffer >> newnetID >> newpassword >> newstatus;
User* userptr;
userptr = new User(newnetID, newpassword, newstatus);
Table.emplace(newnetID, userptr);
}
inFileBuffer.close();
ifstream inFileBuffer2("washingmachinesmemory.txt");
if (inFileBuffer2.fail())
{
cerr << "ERROR OPENING MEMORY. Please check that memory files are not corrupted. (WASHINGMACHINESMEMORY)";
}
string newname2;
bool newstatus2;
int newfunction2;
int newtime2;
while (!inFileBuffer2.eof())
{
inFileBuffer2 >> newname2 >> newstatus2 >> newfunction2 >> newtime2;
WashingMachine* wmachineptr;
wmachineptr = new WashingMachine(newname2, newstatus2, newfunction2, newtime2);
WashingTable.emplace(newname2, wmachineptr);
}
inFileBuffer2.close();
ifstream inFileBuffer3("dryingmachinesmemory.txt");
if (inFileBuffer3.fail())
{
cerr << "ERROR OPENING MEMORY. Please check that memory files are not corrupted. (DRYINGMACHINESMEMORY)";
}
string newname3;
bool newstatus3;
int newfunction3;
int newtime3;
while (!inFileBuffer3.eof())
{
inFileBuffer3 >> newname3 >> newstatus3 >> newfunction3 >> newtime3;
DryingMachine* dmachineptr;
dmachineptr = new DryingMachine(newname3, newstatus3, newfunction3, newtime3);
DryingTable.emplace(newname3, dmachineptr);
}
inFileBuffer3.close();
}
//FOR REFERENCE
//usersmemory.txt stores username, password (NOT HASHED BUT IN PLAINTEXT, SECURITY ISSUE), and number of machines used
//washingmachinesmemory.txt stores machine name, it's availability, it's current function, and the time left of its operation
//dryingmachinesmemory.txt stores machine name, it's availability, it's current function, and the time left of its operation
//Three maps stores the data from the memory - the keys are the names, and the second elements are pointers to objects
//that has been dynamically assigned to memory spaces
map<string, User*> Table;
map<string, WashingMachine*> WashingTable;
map<string, DryingMachine*> DryingTable;
public:
//Singleton construction call
static Users_Database* GetInstance()
{
if (instance == nullptr)
{
instance = new Users_Database();
}
return instance;
}
//Default destructor, essential for storing the session information properly back into the memory files
~Users_Database()
{
ofstream outFileBuffer("usersmemory.txt");
if (outFileBuffer.fail())
{
cerr << "ERROR SAVING TO MEMORY. Warning! No changes to users were saved!";
}
else
{
map<string, User*>::iterator it;
for (it = Table.begin(); it != Table.end(); it++)
{
outFileBuffer << it->first << " ";
outFileBuffer << it->second->getPass() << " ";
outFileBuffer << it->second->getStatus() << endl;
}
}
outFileBuffer.close();
ofstream outFileBuffer2("washingmachinesmemory.txt");
if (outFileBuffer2.fail())
{
cerr << "ERROR SAVING TO MEMORY. Warning! No changes to machines were saved!";
}
else
{
//write a loop function that scans through all machines and saves all private data onto the txt file
map<string, WashingMachine*>::iterator it;
for (it = WashingTable.begin(); it != WashingTable.end(); it++)
{
outFileBuffer2 << it->first << " ";
outFileBuffer2 << it->second-> getstatus()<< " ";
outFileBuffer2 << it->second-> getcurrentfunction() << " ";
outFileBuffer2 << it->second-> getoperations() << endl;
}
}
outFileBuffer2.close();
ofstream outFileBuffer3("dryingmachinesmemory.txt");
if (outFileBuffer3.fail())
{
cerr << "ERROR SAVING TO MEMORY. Warning! No changes to machines were saved!";
}
else
{
//write a loop function that scans through all machines and saves all private data onto the txt file
map<string, DryingMachine*>::iterator it;
for (it = DryingTable.begin(); it != DryingTable.end(); it++)
{
outFileBuffer3 << it->first << " ";
outFileBuffer3 << it->second->getstatus() << " ";
outFileBuffer3 << it->second->getcurrentfunction() << " ";
outFileBuffer3 << it->second->getoperations() << endl;
}
}
outFileBuffer3.close();
Table.clear();
WashingTable.clear();
DryingTable.clear();
currentuser = "";
instance = nullptr;
}
//Function that takes in user's name and designated password and checks if the credentials are correct
//If so, the program will move on to next functionalities and will set the session to the inputID
bool Login(string inputnetID, string &inputpassword)
{
map<string, User*>::iterator it;
it = Table.find(inputnetID);
if (it == Table.end())
{
cout << "Error! No user exists with the given netID.";
return false;
}
if (it->second->checkPassword(inputpassword) == false)
{
cout << "Error! Incorrect password!";
return false;
}
return true;
currentuser = inputnetID;
}
//Function that is called to create a new user by taking in a new ID and password and creates a new object of a user
//It then stores the pointer to this this newly created user into the Users map
//If the user already exists, it simply throws an error and does not store the new information
bool CreateNewUser(string &newnetID, string &newpassword)
{
map<string, User*>::iterator it;
it = Table.find(newnetID);
if (it != Table.end())
{
cout << "Error! This user already exists, please try to log in.";
return false;
}
else
{
User* userptr;
userptr = new User(newnetID, newpassword);
Table.emplace(newnetID,userptr);
return true;
}
};
//Function which takes in userid and password and first attempts to login, and if successful
//it will delete the user from the map of the users
bool DeleteNewUser(string &newnetID, string &newpassword)
{
if (Login(newnetID, newpassword) != true)
{
cout << "You cannot delete this user without proper credentials.";
return false;
}
else
{
map<string, User*>::iterator it;
it = Table.find(newnetID);
Table.erase(newnetID);
cout << "User removed successfully.";
return true;
}
};
//Logout function that clears the name of the current session user
//THIS FUNCTIONALITY IS UNUSED BUT IS PROGRAMMED IN TO ANTICIPATE THE PROGRAM BEING INITIATED IN MULTIPLE SEPARATE INSTANCES
void logout()
{
currentuser = "";
}
//A function that checks the status of the machine given
//This function is identical to checkdryingmachinestatus
//Whilst it is possible to have a general checkmachinestatus (this is actually done elsewhere)
//The way the main calls on this function allows this function to have a limited scope
bool checkwashingmachinestatus(string machinename)
{
map<string, WashingMachine*>::iterator it;
it = WashingTable.find(machinename);
return (it->second->getstatus());
}
//Identical to checkwashingmachinestatus, but for drying machines
bool checkdryingmachinestatus(string machinename)
{
map<string, DryingMachine*>::iterator it;
it = DryingTable.find(machinename);
return (it->second->getstatus());
}
//Changes washing machine status based on the chosen machine functionality
//Prints out a message to confirm that the machine is now in use
//It also calls the timer function
void changewashingmachinestatus(string machinename, int newsetting)
{
map<string, WashingMachine*>::iterator it;
it = WashingTable.find(machinename);
it->second->changestatus(newsetting);
cout << "You have chosen option " << newsetting << ". The machine is now in use.";
cout << "Time left: " << it->second->getminutes(newsetting) << " minutes.";
it->second->starttimer(it->second->getminutes(newsetting),machinename);
}
//Changes drying machine status based on the chosen machine functionality
//Prints out a message to confirm that the machine is now in use
//It also calls the timer function
void changedryingmachinestatus(string machinename, int newsetting)
{
map<string, DryingMachine*>::iterator it;
it = DryingTable.find(machinename);
it->second->changestatus(newsetting);
cout << "You have chosen option " << newsetting << ". The machine is now in use.";
cout << "Time left: " << it->second->getminutes(newsetting) << " minutes.";
it->second->starttimer(it->second->getminutes(newsetting),machinename);
}
//General function call to turn off the machine (set its functionality to -1 and mark it as available to use
//Shows the simple if-else statement that could have been implemented in the 'check' and 'change' functions
void turnoffmachine(string machinename)
{
map<string, DryingMachine*>::iterator it;
it = DryingTable.find(machinename);
if (it == DryingTable.end())
{
map<string, WashingMachine*>::iterator it2;
it2 = WashingTable.find(machinename);
it2->second->changestatus(-1);
}
else
{
it->second->changestatus(-1);
}
}
};
//Initates the static pointer for the singleton
Users_Database* Users_Database::instance = nullptr;