-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDatabase.py
306 lines (270 loc) · 11.9 KB
/
Database.py
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
import sqlite3
class Database:
__instance = None
def __init__(self):
self.__connection = sqlite3.connect("db/database.db")
self.__cursor = self.__connection.cursor()
self.setupTables()
# self.testPersonData()
# self.testGameData()
def setupTables(self):
sqlCreatePersonTableStatement = """
CREATE TABLE IF NOT EXISTS person (
pid Integer PRIMARY KEY,
userName VARCHAR(30),
password VARCHAR(30),
UNIQUE(userName)
);"""
sqlCreateGameTableStatement = """
CREATE TABLE IF NOT EXISTS game (
gid Integer PRIMARY KEY,
pid Integer,
gameName VARCHAR(30),
difficulty Integer,
outcome VARCHAR(30),
destroyedPawns Integer,
FOREIGN KEY(pid) REFERENCES person(pid)
);"""
self.__cursor.execute(sqlCreatePersonTableStatement)
self.__cursor.execute(sqlCreateGameTableStatement)
self.__connection.commit()
def testGameData(self):
gid = 4
pid = 2
gameName = "Bauernschach"
difficulty = 3
outcome = "won"
destroyedPawns = 6
self.__cursor.execute("INSERT INTO game VALUES(?,?,?,?,?,?)",
(gid, pid, gameName, difficulty, outcome, destroyedPawns))
self.__connection.commit()
def testPersonData(self):
pid = 2
testUserName = "Tester"
self.__cursor.execute("INSERT INTO person VALUES(?,?,?)", (pid, testUserName, None))
self.__connection.commit()
def testSelectRankingData(self):
sqlSelectStatement = """
SELECT
person.userName, game.gameName, game.difficulty,
COUNT() AS 'totalGames',
COUNT(CASE WHEN outcome = 'won' then 1 END) AS 'gamesWon',
COUNT(CASE WHEN outcome = 'lost' then 1 END) AS 'gamesLost',
COUNT(CASE WHEN outcome = 'cancelled' then 1 END) AS 'gamesCancelled',
SUM(game.destroyedPawns) AS 'destroyedPawns'
FROM person
LEFT OUTER JOIN game ON person.pid = game.pid
GROUP By person.pid, game.difficulty, game.gameName
ORDER BY gamesWon DESC
"""
self.__cursor.execute(sqlSelectStatement)
self.__connection.commit()
return self.__cursor.fetchall()
def getTopPlayersForGameAndDifficulty(self, gameName, difficulty, playerCount):
"""get the {playerCount} amount of top Players for the game: {gameName} and the difficulty: {difficulty}
Args:
gameName (str): string representing the game
difficulty (int): int representing the depth of search for the algorithm
playerCount (int): int representing the amount of players to be returned
Returns:
list: Lists filled with:
pid (int)
userName (str),
difficulty (int),
total amount of games (int),
amount of games won (int),
amount of games lost (int),
amount of games cancelled (int),
summ of destroyedPawns (int)
"""
sqlSelectStatement = """
SELECT
person.pid, person.userName, game.difficulty,
COUNT() AS 'totalGames',
COUNT(CASE WHEN game.outcome = 'won' then 1 END) AS 'gamesWon',
COUNT(CASE WHEN game.outcome = 'lost' then 1 END) AS 'gamesLost',
COUNT(CASE WHEN game.outcome = 'cancelled' then 1 END) AS 'gamesCancelled',
SUM(game.destroyedPawns) AS 'destroyedPawns'
FROM person
LEFT OUTER JOIN game ON person.pid = game.pid
WHERE game.gameName = ? AND game.difficulty = ?
GROUP By person.pid, game.difficulty, game.gameName
ORDER BY gamesWon DESC
LIMIT(?)
"""
self.__cursor.execute(sqlSelectStatement, (gameName, difficulty, playerCount))
self.__connection.commit()
return self.__cursor.fetchall()
def getGamesSummaryForGameAndDifficultyAndPlayerID(self, gameName, difficulty, playerID):
"""get the summary of the games for a chosen game, difficulty and playerID
Args:
gameName (str): string representing the game
difficulty (int): int representing the depth of search for the algorithm
playerID (int): int representing the primary key of the chosen player
Returns:
list: Lists filled with:
pid (int)
userName (str),
difficulty (int),
total amount of games (int),
amount of games won (int),
amount of games lost (int),
amount of games cancelled (int),
summ of destroyedPawns (int)
"""
sqlSelectStatement = """
SELECT
person.pid, person.userName, game.difficulty,
COUNT() AS 'totalGames',
COUNT(CASE WHEN game.outcome = 'won' then 1 END) AS 'gamesWon',
COUNT(CASE WHEN game.outcome = 'lost' then 1 END) AS 'gamesLost',
COUNT(CASE WHEN game.outcome = 'cancelled' then 1 END) AS 'gamesCancelled',
SUM(game.destroyedPawns) AS 'destroyedPawns'
FROM person
LEFT OUTER JOIN game ON person.pid = game.pid
WHERE game.gameName = ? AND game.difficulty = ? AND person.pid = ?
GROUP By person.pid, game.difficulty, game.gameName
"""
self.__cursor.execute(sqlSelectStatement, (gameName, difficulty, playerID))
self.__connection.commit()
return self.__cursor.fetchall()
def getGameHistoryForChosenPlayer(self, playerID):
"""get the game-history for a chosen Player
Args:
playerID (int): int representing the primary key of the chosen player
Returns:
list: Lists filled with:
gameName (str),
difficulty (int),
outcome (str),
destroyedPawns (int)
"""
sqlSelectStatement = """
SELECT
gameName, difficulty, outcome, destroyedPawns
FROM game
WHERE pid =?
ORDER BY gid DESC
"""
self.__cursor.execute(sqlSelectStatement, (playerID,))
self.__connection.commit()
return self.__cursor.fetchall()
def getGameHistoryForChosenPlayerFiltered(self, playerID, gameName=None, difficulty=None):
"""
get the game-history for a chosen Player, filtered by gameName and difficulty
getGameHistoryForChosenPlayerFiltered(playerID) will return the full list of games for the chosen player.
getGameHistoryForChosenPlayerFiltered(playerID, gameName) will return the list of games for the chosen player with the given gameName.
getGameHistoryForChosenPlayerFiltered(playerID, None, difficulty) will return the list of games for the chosen player with the given difficulty.
getGameHistoryForChosenPlayerFiltered(playerID, gameName, difficulty) will return the list of games for the chosen player with the given gameName and difficulty.
Args:
playerID (int): int representing the primary key of the chosen player
gameName (str): (optional) the game name to filter for
difficulty (int): (optional) the difficulty to filter for
Returns:
list: Lists filled with:
gameName (str),
difficulty (int),
outcome (str),
destroyedPawns (int)
"""
games = self.getGameHistoryForChosenPlayer(playerID)
filteredGames = []
if gameName is not None and difficulty is not None:
for game in games:
if game[0] == gameName and game[1] == difficulty:
filteredGames.append(game)
elif gameName is not None:
for game in games:
if game[0] == gameName:
filteredGames.append(game)
elif difficulty is not None:
for game in games:
if game[1] == difficulty:
filteredGames.append(game)
else:
filteredGames = games
return filteredGames
def registerNewPerson(self, userName, password):
"""Adds a new set of data representing
Args:
userName (str): string representing the name of the User
password (string): string representing the hash version of the password
Returns:
none
"""
sqlInsertStatement = """
INSERT INTO person values(?,?,?)
"""
self.__cursor.execute(sqlInsertStatement, (None, userName, password))
self.__connection.commit()
def getPersonByUserName(self, userName):
"""returns the data of a player via the serach for the userName
Args:
userName (str): string representing the name of the User
Returns:
list: List filled with:
pid (int),
userName (str),
"""
sqlSelectStatement = """
SELECT pid, userName FROM person
WHERE userName = ?
"""
self.__cursor.execute(sqlSelectStatement, (userName,))
self.__connection.commit()
return self.__cursor.fetchall()
def getPersonByUserNameWithPassword(self, userName):
"""returns the data of a player via the serach for the userName
Args:
userName (str): string representing the name of the User
Returns:
list: List filled with:
pid (int),
userName (str),
password (str) in hash format
"""
sqlSelectStatement = """
SELECT * FROM person
WHERE userName = ?
"""
self.__cursor.execute(sqlSelectStatement, (userName,))
self.__connection.commit()
return self.__cursor.fetchall()
def getPersonByPlayerId(self, playerId):
"""returns the data of a player via the serach for the PlayerId
Args:
PlayerId (int): int representing the id of the player
Returns:
list: List filled with:
pid (int),
userName (str),
"""
sqlSelectStatement = """
SELECT pid, userName FROM person
WHERE pid = ?
"""
self.__cursor.execute(sqlSelectStatement, (playerId,))
self.__connection.commit()
return self.__cursor.fetchall()
def registerNewGame(self, pid, gameName, difficulty, outcome, destroyedPawns):
"""Adds a new set of data representing
Args:
pid (int): int representing the id of the player that played this game
gameName (str): string representing the game
difficulty (int): int representing the depth of search for the algorithm
outcome (str): string representing the outcome of the game ('won'/'lost'/'cancelled')
destroyedPawns (int): int representing the number of opponents destroyed in this game
Returns:
none
"""
sqlInsertStatement = """
INSERT INTO game VALUES(?,?,?,?,?,?)
"""
self.__cursor.execute(sqlInsertStatement, (None, pid, gameName, difficulty, outcome, destroyedPawns))
self.__connection.commit()
@staticmethod
def getInstance():
"""returns the sole existing instance of the database. If it doesn't exist yet, it will be created"""
if Database.__instance is None:
Database.__instance = Database()
return Database.__instance