source: network-game/server/DataAccess.cpp@ 53643ca

Last change on this file since 53643ca was 53643ca, checked in by Dmitry Portnoy <dmp1488@…>, 10 years ago

Server loads user profile and game history info from the database, saves game history to the db after every game, and uses a lua settings file to load db settings

  • Property mode set to 100644
File size: 8.3 KB
Line 
1#include "DataAccess.h"
2
3#include <iostream>
4#include <sstream>
5#include <cstdlib>
6#include <crypt.h>
7
8#include "LuaLoader.h"
9
10using namespace std;
11
12DataAccess::DataAccess()
13{
14 LuaLoader luaLoader;
15
16 string database, username, password;
17
18 if (luaLoader.runScript("db_settings.lua")) {
19 cout << "Loading settings" << endl;
20
21 database = luaLoader.getValue("database");
22 username = luaLoader.getValue("username");
23 password = luaLoader.getValue("password");
24
25 cout << database << endl;
26 cout << username << endl;
27 cout << password << endl;
28 } else {
29 cout << "Failed to load settings from lua script" << endl;
30 }
31
32 mysql_init(&mysql);
33 connection = mysql_real_connect(&mysql, "localhost", "pythonAdmin", "pyMaster09*", "pythondb", 0, 0, 0);
34
35 if (connection == NULL) {
36 cout << mysql_error(&mysql) << endl;
37 }else
38 cout << "Connection successful" << endl;
39}
40
41DataAccess::~DataAccess()
42{
43 mysql_close(connection);
44 mysql_close(&mysql);
45}
46
47int DataAccess::insertPlayer(string username, string password, Player::PlayerClass playerClass)
48{
49 ostringstream oss;
50
51 string salt = "$1$";
52 int random;
53 char chr;
54 for(int i=0; i<8; i++)
55 {
56 random = rand() % 62;
57 if (random < 26)
58 chr = (char)('a'+random);
59 else if (random < 52)
60 chr = (char)('A'+random-26);
61 else
62 chr = (char)('0'+random-52);
63 salt += chr;
64 }
65 salt += '$';
66
67 string encrypted(crypt(password.c_str(), salt.c_str()));
68
69 oss << "'" << username << "', '" << encrypted << "', " << playerClass;
70
71 return insert("users", "name, password, class", oss.str());
72}
73
74// this is no longer used anywhere
75int DataAccess::updatePlayer(string username, string password)
76{
77 ostringstream values, where;
78
79 values << "password='" << password << "'";
80
81 where << "name='" << username << "'";
82
83 return update("users", values.str(), where.str());
84}
85
86Player *DataAccess::getPlayer(string username)
87{
88 MYSQL_RES *result;
89 MYSQL_ROW row;
90 Player *p;
91 ostringstream oss;
92
93 oss << "name='" << username << "'";
94
95 result = select("users", oss.str().c_str());
96
97 cout << "Got result" << endl;
98
99 if (result == NULL) {
100 cout << "Error occured" << endl;
101 cout << mysql_error(connection) << endl;
102 return NULL;
103 }
104
105 if ( ( row = mysql_fetch_row(result)) != NULL ) {
106 cout << "Creating a new player" << endl;
107 p = new Player(string(row[1]), string(row[2]));
108 p->setId(atoi(row[0]));
109 if (row[3] == NULL) {
110 p->setClass(Player::CLASS_NONE);
111 cout << "Class from db was NULL" << endl;
112 }else {
113 p->setClass((Player::PlayerClass)atoi(row[3]));
114 cout << "Class from db: " << atoi(row[3]) << endl;
115 }
116 cout << "Player class: " << p->playerClass << endl;
117 if (row[7] == NULL)
118 cout << "wins: NULL" << endl;
119 else
120 cout << "wins: " << atoi(row[7]) << endl;
121 if (row[8] == NULL)
122 cout << "losses: NULL" << endl;
123 else
124 cout << "losses: " << atoi(row[8]) << endl;
125 cout << "Loaded player from db" << endl;
126 }else {
127 cout << "Returned no results for some reason" << endl;
128 p = NULL;
129 }
130
131 mysql_free_result(result);
132
133 return p;
134}
135
136// need to make sure this list is freed
137// since we need to create a DataAccess class
138// when calling these functions,
139// we could free this list in the destructor
140list<Player*>* DataAccess::getPlayers()
141{
142 MYSQL_RES *result;
143 MYSQL_ROW row;
144
145 result = select("users", "");
146
147 if (result == NULL) {
148 cout << mysql_error(connection) << endl;
149 return NULL;
150 }
151
152 list<Player*>* lstPlayers = new list<Player*>();
153 while ( ( row = mysql_fetch_row(result)) != NULL ) {
154 cout << row[0] << ", " << row[1] << ", " << row[2] << endl;
155 lstPlayers->push_back(new Player(row[1], row[2]));
156 }
157
158 mysql_free_result(result);
159
160 return lstPlayers;
161}
162
163bool DataAccess::verifyPassword(string password, string encrypted)
164{
165 string test(crypt(password.c_str(), encrypted.c_str()));
166
167 return encrypted.compare(test) == 0;
168}
169
170int* DataAccess::getPlayerRecord(int playerId) {
171 MYSQL_RES *result;
172 MYSQL_ROW row;
173 ostringstream oss;
174 int* record = new int[5];
175
176 oss << "id=" << playerId;
177 result = select("users", oss.str());
178
179 if ( ( row = mysql_fetch_row(result)) != NULL ) {
180 cout << "Retrieved player record successfully" << endl;
181 record[0] = atoi(row[4]); // level
182 record[1] = atoi(row[5]); // experience
183 record[2] = atoi(row[6]); // honor
184 record[3] = atoi(row[7]); // wins
185 record[4] = atoi(row[8]); // losses
186 cout << "record[0]:" << record[0] << endl;
187 cout << "record[1]:" << record[1] << endl;
188 cout << "record[2]:" << record[2] << endl;
189 cout << "record[3]:" << record[3] << endl;
190 cout << "record[4]:" << record[4] << endl;
191 }
192
193 if (result == NULL) {
194 cout << mysql_error(connection) << endl;
195 return NULL;
196 }
197
198 mysql_free_result(result);
199
200 return record;
201}
202
203int** DataAccess::getPlayerGameHistory(int playerId, unsigned int& numGames)
204{
205 // each array is the score for one game
206 // the columns are result, team, blue score, and red score
207 // for result 0 is defeat and 1 is victory
208 // for team, 0 is blue and 1 is red
209
210 MYSQL_RES *result;
211 MYSQL_ROW row;
212 ostringstream oss;
213
214 int** gameHistory;
215
216 oss << "user_id=" << playerId;
217 result = select("gameHistory", oss.str());
218
219 numGames = mysql_num_rows(result);
220 gameHistory = (int**)malloc(sizeof(int*)*numGames);
221 cout << "Result has " << numGames << " rows" << endl;
222
223 int i=0;
224 while ( ( row = mysql_fetch_row(result)) != NULL ) {
225 gameHistory[i] = new int[4];
226
227 int userTeam = atoi(row[2]);
228 int blueScore = atoi(row[4]);
229 int redScore = atoi(row[3]);
230 int gameResult = -1;
231
232 if (blueScore == 3) {
233 if (userTeam == 0)
234 gameResult = 1;
235 else
236 gameResult = 0;
237 }else if (redScore == 3) {
238 if (userTeam == 1)
239 gameResult = 1;
240 else
241 gameResult = 0;
242 }else {
243 cout << "Recorded game has no team with 3 points" << endl;
244 }
245
246 gameHistory[i][0] = gameResult;
247 gameHistory[i][1] = userTeam;
248 gameHistory[i][2] = blueScore;
249 gameHistory[i][3] = redScore;
250
251 i++;
252 }
253
254 if (result == NULL) {
255 cout << mysql_error(connection) << endl;
256 return NULL;
257 }
258
259 mysql_free_result(result);
260
261 return gameHistory;
262}
263
264int DataAccess::saveGameHistory(int playerId, int team, int blueScore, int redScore)
265{
266 ostringstream oss;
267
268 cout << "Saving game to db" << endl;
269 oss << playerId << ", " << team << ", " << blueScore << ", " << redScore;
270
271 return insert("gameHistory", "user_id, user_team, blue_score, red_score", oss.str());
272}
273
274int DataAccess::insert(string table, string columns, string values)
275{
276 int query_state;
277 ostringstream oss;
278
279 if (connection == NULL) {
280 cout << "Error: non database connection exists" << endl;
281 return -1;
282 }
283
284 oss << "INSERT into " << table << " (" << columns << ") VALUES (" << values << ")";
285 cout << "query: " << oss.str() << endl;
286
287 query_state = mysql_query(connection, oss.str().c_str());
288
289 if (query_state != 0) {
290 cout << mysql_error(connection) << endl;
291 return -1;
292 }
293
294 return 0;
295}
296
297int DataAccess::update(string table, string values, string where)
298{
299 int query_state;
300 ostringstream oss;
301
302 if (connection == NULL) {
303 cout << "Error: no database connection exists" << endl;
304 return -1;
305 }
306
307 oss << "UPDATE " << table << " SET " << values << " WHERE " << where;
308 cout << "query: " << oss.str() << endl;
309
310 query_state = mysql_query(connection, oss.str().c_str());
311
312 if (query_state != 0) {
313 cout << mysql_error(connection) << endl;
314 return -1;
315 }
316
317 return 0;
318}
319
320MYSQL_RES *DataAccess::select(string table, string filter)
321{
322 int query_state;
323 ostringstream oss;
324
325 if (connection == NULL) {
326 cout << "Error: non database connection exists" << endl;
327 return NULL;
328 }
329
330 oss << "SELECT * FROM " << table;
331 if (!filter.empty())
332 oss << " WHERE " << filter;
333 cout << "executing select query: " << oss.str() << endl;
334
335 query_state = mysql_query(connection, oss.str().c_str());
336
337 if (query_state != 0) {
338 cout << mysql_error(connection) << endl;
339 return NULL;
340 }
341
342 return mysql_store_result(connection);
343}
Note: See TracBrowser for help on using the repository browser.