From 336e3480ca26e8aaa4ffd4db9029e1c899264391 Mon Sep 17 00:00:00 2001 From: Carina Straub Date: Wed, 10 Jan 2024 19:53:46 +0100 Subject: [PATCH 1/8] Reworked the database layout --- .../server/databases.py | 70 +++++++++++++++---- teamprojekt_competition_server/server/main.py | 32 ++++++--- 2 files changed, 80 insertions(+), 22 deletions(-) diff --git a/teamprojekt_competition_server/server/databases.py b/teamprojekt_competition_server/server/databases.py index 751bf07d..973b5bae 100644 --- a/teamprojekt_competition_server/server/databases.py +++ b/teamprojekt_competition_server/server/databases.py @@ -1,8 +1,11 @@ """Databases""" import sqlite3 +from enum import Enum +from datetime import datetime GAME_DB_NAME = "game" +GameEndState = Enum("GameEndState", ["WIN", "DRAW", "DISCONNECTED"]) class GameDatabase: @@ -18,24 +21,64 @@ def __init__(self) -> None: WHERE type='table' AND name='{GAME_DB_NAME}'""" ) if self.cursor.fetchone() is None: - self.cursor.execute(f"CREATE TABLE {GAME_DB_NAME}(winnerID, loserID)") - - def insert_game(self, winnerID: int, loserID: int) -> int | None: + self.cursor.execute( + f"""CREATE TABLE {GAME_DB_NAME}( + game_ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + player1, + player2, + score1, + score2, + start_time, + end_state, + winner)""" + ) + + def insert_game( + self, + player1_ID: int, + player2_ID: int, + score_player_1: float, + score_player_2: float, + start_time=None, + is_player1_winner=True, + game_end_state=GameEndState.WIN.value, + ) -> int | None: """insert a new game into the database Args: - winnerID (int): playerID of the winner - loserID (int): playerID of the loser + player1 (int): playerID of the winner + player2 (int): playerID of the loser Returns: int: ID of the game """ # TODO separate record file to store game steps - self.cursor.execute(f"INSERT INTO game VALUES ({winnerID}, {loserID})") + if start_time is None: + start_time = datetime.now() + + winner_ID = None + if game_end_state == GameEndState.WIN.value: + winner_ID = player1_ID if is_player1_winner else player2_ID + + self.cursor.execute( + """INSERT INTO + game(player1, player2, score1, score2, start_time, end_state, winner) + VALUES (?, ?, ?, ?, ?, ?, ?)""", + ( + player1_ID, + player2_ID, + score_player_1, + score_player_2, + start_time, + game_end_state, + winner_ID, + ), + ) self.connection.commit() + return self.cursor.lastrowid - def get_playerIDs(self, gameID: int) -> tuple[int, int]: + def get_playerIDs(self, game_ID: int) -> tuple[int, int]: """get the IDs of the players that participated in a game Args: @@ -45,12 +88,12 @@ def get_playerIDs(self, gameID: int) -> tuple[int, int]: (int, int): IDs of the winner and the loser """ res = self.cursor.execute( - f"SELECT winnerID, loserID FROM {GAME_DB_NAME} WHERE rowid={gameID}" + f"SELECT player1, player2 FROM {GAME_DB_NAME} WHERE game_ID=?", (game_ID,) ) players = res.fetchone() return players - def get_gameIDs(self, playerID: int) -> list[int]: + def get_gameIDs(self, player_ID: int) -> list[int]: """get all games that a player participated in Args: @@ -60,15 +103,15 @@ def get_gameIDs(self, playerID: int) -> list[int]: list[int]: IDs of the games """ res = self.cursor.execute( - f"""SELECT rowid FROM {GAME_DB_NAME} - WHERE winnerID={playerID} OR loserID={playerID}""" + f"SELECT game_ID FROM {GAME_DB_NAME} WHERE player1=? OR player2=?", + (player_ID, player_ID), ) games = [] for (result,) in res.fetchall(): games.append(result) return games - def get_won_gameIDs(self, playerID: int) -> list[int]: + def get_won_gameIDs(self, player_ID: int) -> list[int]: """get all games that a player has won Args: @@ -78,7 +121,8 @@ def get_won_gameIDs(self, playerID: int) -> list[int]: list[int]: IDs of the games """ res = self.cursor.execute( - f"SELECT rowid FROM {GAME_DB_NAME} WHERE winnerID={playerID}" + f"SELECT game_ID FROM {GAME_DB_NAME} WHERE winner=? AND end_state=1", + (player_ID,), ) games = [] for (result,) in res.fetchall(): diff --git a/teamprojekt_competition_server/server/main.py b/teamprojekt_competition_server/server/main.py index 8425474c..1c20847b 100644 --- a/teamprojekt_competition_server/server/main.py +++ b/teamprojekt_competition_server/server/main.py @@ -1,5 +1,4 @@ """run the server""" - from .server import COMPServer from .interfaces import IGame, IPlayer from .game_manager import game_manager @@ -54,14 +53,29 @@ def main(): def test_database(): """function to test database""" game_db = GameDatabase() - gameID = game_db.insert_game(12, 23) - gameID = game_db.insert_game(52, 12) - print(gameID) - print(game_db.get_playerIDs(gameID=gameID)) - print(game_db.get_gameIDs(playerID=12)) - print(game_db.get_won_gameIDs(playerID=12)) + gameID1 = game_db.insert_game( + player1_ID=23, player2_ID=4, score_player_1=3, score_player_2=6 + ) + gameID2 = game_db.insert_game( + player1_ID=43, + player2_ID=23, + score_player_1=6, + score_player_2=7, + is_player1_winner=False, + ) + gameID3 = game_db.insert_game( + player1_ID=23, + player2_ID=26, + score_player_1=6, + score_player_2=7, + game_end_state=3, + ) + print(gameID1, gameID2, gameID3) + print(game_db.get_playerIDs(game_ID=gameID2)) + print(game_db.get_gameIDs(player_ID=23)) + print(game_db.get_won_gameIDs(player_ID=23)) if __name__ == "__main__": - main() - # test_database() + # main() + test_database() From 4f885a4528013f6ddb8061da323a83301a42504d Mon Sep 17 00:00:00 2001 From: Carina Straub Date: Sun, 14 Jan 2024 20:42:24 +0100 Subject: [PATCH 2/8] added methods, refactoring --- .../server/databases.py | 259 +++++++++++++++--- teamprojekt_competition_server/server/main.py | 40 +-- 2 files changed, 241 insertions(+), 58 deletions(-) diff --git a/teamprojekt_competition_server/server/databases.py b/teamprojekt_competition_server/server/databases.py index 973b5bae..6fd50fd1 100644 --- a/teamprojekt_competition_server/server/databases.py +++ b/teamprojekt_competition_server/server/databases.py @@ -23,31 +23,43 @@ def __init__(self) -> None: if self.cursor.fetchone() is None: self.cursor.execute( f"""CREATE TABLE {GAME_DB_NAME}( - game_ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - player1, - player2, + game_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + user1, + user2, score1, score2, start_time, end_state, - winner)""" + winner, + disconnected)""" ) - def insert_game( + def _insert_game( self, - player1_ID: int, - player2_ID: int, - score_player_1: float, - score_player_2: float, - start_time=None, - is_player1_winner=True, - game_end_state=GameEndState.WIN.value, + user1_id: int, + user2_id: int, + score_user_1: float, + score_user_2: float, + start_time: str, + game_end_state: int, + is_user1_winner=True, + is_user1_disconnected=True, ) -> int | None: """insert a new game into the database Args: - player1 (int): playerID of the winner - player2 (int): playerID of the loser + user1_id (int): user ID of user 1 (standard: winner or disconnected) + user2_id (int): user ID of user 2 (standard: loser) + score_user_1 (float): score of user 1 + score_user_2 (float): score of user 2 + start_time (String | None): use datetime.now().isoformat(sep=" ") + to generate JJJJ-MM-DD HH-MM-SS.SSSS + (example: 2024-01-14 19:23:13.736286)) + game_end_state(int): GameEndState enum value + is_user1_winner (bool): if user 1 is the winner + (only relevant for won games) + is_user1_disconnected (bool): if user 1 is disconnected + (only relevant for disconnected games) Returns: int: ID of the game @@ -55,76 +67,245 @@ def insert_game( # TODO separate record file to store game steps if start_time is None: start_time = datetime.now() + print(start_time) - winner_ID = None + winner_id = None if game_end_state == GameEndState.WIN.value: - winner_ID = player1_ID if is_player1_winner else player2_ID + winner_id = user1_id if is_user1_winner else user2_id + + disconnected_id = None + if game_end_state == GameEndState.DISCONNECTED.value: + disconnected_id = user1_id if is_user1_disconnected else user2_id self.cursor.execute( """INSERT INTO - game(player1, player2, score1, score2, start_time, end_state, winner) - VALUES (?, ?, ?, ?, ?, ?, ?)""", + game(user1, user2, score1, score2, + start_time, end_state, winner, disconnected) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", ( - player1_ID, - player2_ID, - score_player_1, - score_player_2, + user1_id, + user2_id, + score_user_1, + score_user_2, start_time, game_end_state, - winner_ID, + winner_id, + disconnected_id, ), ) self.connection.commit() return self.cursor.lastrowid - def get_playerIDs(self, game_ID: int) -> tuple[int, int]: - """get the IDs of the players that participated in a game + def insert_won_game( + self, + winner_id: int, + loser_id: int, + score_winner: float, + score_loser: float, + start_time=None, + ) -> int | None: + """insert a won game into the database + + Args: + winner_id (int): user ID of the winner + loser_id (int): user ID of the loser + score_winner (float): score of the winner + score_loser (float): score of the loser + start_time (_type_, optional): use datetime module. Defaults to None. + + Returns: + int | None: game ID + """ + return self._insert_game( + user1_id=winner_id, + user2_id=loser_id, + score_user_1=score_winner, + score_user_2=score_loser, + start_time=start_time, + game_end_state=GameEndState.WIN.value, + ) + + def insert_disconnected_game( + self, + disconnected_user_id: int, + other_user_id: int, + score_disconnected_user: float, + score_other_user: float, + start_time=None, + ) -> int | None: + """insert a disconnected game into the database Args: - gameID (int): ID of the game + disconnected_user_id (int): user ID of the disconnected player + other_user_id (int): user ID of the other player + score_disconnected_user (float): score of the disconnected player + score_other_user (float): score of the other player + start_time (_type_, optional): use datetime module. Defaults to None. Returns: - (int, int): IDs of the winner and the loser + int | None: game ID + """ + return self._insert_game( + user1_id=disconnected_user_id, + user2_id=other_user_id, + score_user_1=score_disconnected_user, + score_user_2=score_other_user, + start_time=start_time, + game_end_state=GameEndState.DISCONNECTED.value, + ) + + def insert_drawn_game( + self, + user1_id: int, + user2_id: int, + score_user_1: float, + score_user_2: float, + start_time=None, + ) -> int | None: + """insert a drawn game into the database + + Args: + user1_id (int): user ID of user 1 + user2_id (int): user ID of user 2 + score_user_1 (float): score of user 1 + score_user_2 (float): score of user 2 + start_time (_type_, optional): use datetime module. Defaults to None. + + Returns: + int | None: game ID + """ + return self._insert_game( + user1_id=user1_id, + user2_id=user2_id, + score_user_1=score_user_1, + score_user_2=score_user_2, + start_time=start_time, + game_end_state=GameEndState.DRAW.value, + ) + + def get_user_ids(self, game_id: int) -> tuple[int, int]: + """get the IDs of the users that participated in a game + + Args: + game_id (int): ID of the game + + Returns: + (int, int): IDs of both users """ res = self.cursor.execute( - f"SELECT player1, player2 FROM {GAME_DB_NAME} WHERE game_ID=?", (game_ID,) + f"SELECT user1, user2 FROM {GAME_DB_NAME} WHERE game_ID=?", (game_id,) ) - players = res.fetchone() - return players + users = res.fetchone() + return users - def get_gameIDs(self, player_ID: int) -> list[int]: - """get all games that a player participated in + def get_game_ids(self, user_id: int) -> list[int]: + """get all games that a user participated in Args: - playerID (int): ID of the player + userID (int): ID of the user Returns: list[int]: IDs of the games """ res = self.cursor.execute( - f"SELECT game_ID FROM {GAME_DB_NAME} WHERE player1=? OR player2=?", - (player_ID, player_ID), + f"SELECT game_ID FROM {GAME_DB_NAME} WHERE user1=? OR user2=?", + (user_id, user_id), ) games = [] for (result,) in res.fetchall(): games.append(result) return games - def get_won_gameIDs(self, player_ID: int) -> list[int]: - """get all games that a player has won + def get_won_game_ids(self, user_id: int) -> list[int]: + """get all games that a user has won Args: - playerID (int): ID of the player + user_id (int): ID of the user Returns: list[int]: IDs of the games """ res = self.cursor.execute( f"SELECT game_ID FROM {GAME_DB_NAME} WHERE winner=? AND end_state=1", - (player_ID,), + (user_id,), ) games = [] for (result,) in res.fetchall(): games.append(result) return games + + def count_played_games(self, user_id: int) -> int: + """count all games the user has played (disconnected and drawn games included) + + Args: + user_id (int): ID of the user + + Returns: + int: count of played games + """ + res = self.cursor.execute( + f"SELECT COUNT() FROM {GAME_DB_NAME} WHERE user1=? OR user2=?", + (user_id, user_id), + ) + return res.fetchone()[0] + + def count_won_games(self, user_id: int) -> int: + """count all games where the user has won + + Args: + user_id (int): ID of the user + + Returns: + int: count of won games + """ + res = self.cursor.execute( + f"SELECT COUNT() FROM {GAME_DB_NAME} WHERE winner=?", + (user_id,), + ) + return res.fetchone()[0] + + def count_disconnected_games(self, user_id: int) -> int: + """count all games where the user disconnected + + Args: + user_id (int): ID of the user + + Returns: + int: count of disconnected games + """ + res = self.cursor.execute( + f"SELECT COUNT() FROM {GAME_DB_NAME} WHERE disconnected=?", + (user_id,), + ) + return res.fetchone()[0] + + def count_games_with_disconnect(self, user_id: int) -> int: + """count all games where the user or the opponent disconnected + + Args: + user_id (int): ID of the user + + Returns: + int: count of disconnected games + """ + res = self.cursor.execute( + f"""SELECT COUNT() FROM {GAME_DB_NAME} + WHERE (user1=? OR user2=?) AND end_state=3""", + (user_id, user_id), + ) + return res.fetchone()[0] + + def win_rate(self, user_id: int) -> float: + """calculates the win-rate of the user (ignoring disconnected games) + + Args: + user_id (int): ID of the user + + Returns: + float: win-rate + """ + all_games = self.count_played_games(user_id) + disconnected_games = self.count_games_with_disconnect(user_id) + won_games = self.count_won_games(user_id) + return won_games / (all_games - disconnected_games) diff --git a/teamprojekt_competition_server/server/main.py b/teamprojekt_competition_server/server/main.py index 1c20847b..729c8073 100644 --- a/teamprojekt_competition_server/server/main.py +++ b/teamprojekt_competition_server/server/main.py @@ -53,29 +53,31 @@ def main(): def test_database(): """function to test database""" game_db = GameDatabase() - gameID1 = game_db.insert_game( - player1_ID=23, player2_ID=4, score_player_1=3, score_player_2=6 + gameID1 = game_db.insert_won_game( + winner_id=23, loser_id=4, score_winner=3, score_loser=6 ) - gameID2 = game_db.insert_game( - player1_ID=43, - player2_ID=23, - score_player_1=6, - score_player_2=7, - is_player1_winner=False, + gameID2 = game_db.insert_won_game( + winner_id=43, + loser_id=23, + score_winner=6, + score_loser=7, ) - gameID3 = game_db.insert_game( - player1_ID=23, - player2_ID=26, - score_player_1=6, - score_player_2=7, - game_end_state=3, + gameID3 = game_db.insert_disconnected_game( + disconnected_user_id=1, + other_user_id=23, + score_disconnected_user=6, + score_other_user=7, ) print(gameID1, gameID2, gameID3) - print(game_db.get_playerIDs(game_ID=gameID2)) - print(game_db.get_gameIDs(player_ID=23)) - print(game_db.get_won_gameIDs(player_ID=23)) + print(game_db.get_user_ids(game_id=gameID2)) + print(game_db.get_game_ids(user_id=23)) + print(game_db.get_won_game_ids(user_id=23)) + print(game_db.count_played_games(user_id=23)) + print(game_db.count_won_games(user_id=23)) + print(game_db.count_disconnected_games(user_id=23)) + print(game_db.win_rate(user_id=23)) if __name__ == "__main__": - # main() - test_database() + main() + # test_database() From 962fc6a294fa104f56bf774592584f603c8c638a Mon Sep 17 00:00:00 2001 From: Carina Straub Date: Sun, 14 Jan 2024 20:51:05 +0100 Subject: [PATCH 3/8] formatting --- teamprojekt_competition_server/server/databases.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/teamprojekt_competition_server/server/databases.py b/teamprojekt_competition_server/server/databases.py index 6fd50fd1..350df319 100644 --- a/teamprojekt_competition_server/server/databases.py +++ b/teamprojekt_competition_server/server/databases.py @@ -53,12 +53,12 @@ def _insert_game( score_user_1 (float): score of user 1 score_user_2 (float): score of user 2 start_time (String | None): use datetime.now().isoformat(sep=" ") - to generate JJJJ-MM-DD HH-MM-SS.SSSS - (example: 2024-01-14 19:23:13.736286)) + to generate JJJJ-MM-DD HH-MM-SS.SSSS + (example: 2024-01-14 19:23:13.736286)) game_end_state(int): GameEndState enum value is_user1_winner (bool): if user 1 is the winner (only relevant for won games) - is_user1_disconnected (bool): if user 1 is disconnected + is_user1_disconnected (bool): if user 1 is disconnected (only relevant for disconnected games) Returns: From 40011821dbf9c84d5f12e4e4abf49e3aec1556c7 Mon Sep 17 00:00:00 2001 From: Carina Straub Date: Mon, 15 Jan 2024 16:47:27 +0100 Subject: [PATCH 4/8] Added requested changes --- .../server/databases.py | 311 ----------------- .../server/game_database.py | 323 ++++++++++++++++++ teamprojekt_competition_server/server/main.py | 30 -- tests/game_database_test.py | 38 +++ 4 files changed, 361 insertions(+), 341 deletions(-) delete mode 100644 teamprojekt_competition_server/server/databases.py create mode 100644 teamprojekt_competition_server/server/game_database.py create mode 100644 tests/game_database_test.py diff --git a/teamprojekt_competition_server/server/databases.py b/teamprojekt_competition_server/server/databases.py deleted file mode 100644 index 350df319..00000000 --- a/teamprojekt_competition_server/server/databases.py +++ /dev/null @@ -1,311 +0,0 @@ -"""Databases""" - -import sqlite3 -from enum import Enum -from datetime import datetime - -GAME_DB_NAME = "game" -GameEndState = Enum("GameEndState", ["WIN", "DRAW", "DISCONNECTED"]) - - -class GameDatabase: - """Database to store the games""" - - def __init__(self) -> None: - self.connection = sqlite3.connect( - "teamprojekt_competition_server/server/COMP_database.db" - ) - self.cursor = self.connection.cursor() - self.cursor.execute( - f"""SELECT name FROM sqlite_master - WHERE type='table' AND name='{GAME_DB_NAME}'""" - ) - if self.cursor.fetchone() is None: - self.cursor.execute( - f"""CREATE TABLE {GAME_DB_NAME}( - game_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - user1, - user2, - score1, - score2, - start_time, - end_state, - winner, - disconnected)""" - ) - - def _insert_game( - self, - user1_id: int, - user2_id: int, - score_user_1: float, - score_user_2: float, - start_time: str, - game_end_state: int, - is_user1_winner=True, - is_user1_disconnected=True, - ) -> int | None: - """insert a new game into the database - - Args: - user1_id (int): user ID of user 1 (standard: winner or disconnected) - user2_id (int): user ID of user 2 (standard: loser) - score_user_1 (float): score of user 1 - score_user_2 (float): score of user 2 - start_time (String | None): use datetime.now().isoformat(sep=" ") - to generate JJJJ-MM-DD HH-MM-SS.SSSS - (example: 2024-01-14 19:23:13.736286)) - game_end_state(int): GameEndState enum value - is_user1_winner (bool): if user 1 is the winner - (only relevant for won games) - is_user1_disconnected (bool): if user 1 is disconnected - (only relevant for disconnected games) - - Returns: - int: ID of the game - """ - # TODO separate record file to store game steps - if start_time is None: - start_time = datetime.now() - print(start_time) - - winner_id = None - if game_end_state == GameEndState.WIN.value: - winner_id = user1_id if is_user1_winner else user2_id - - disconnected_id = None - if game_end_state == GameEndState.DISCONNECTED.value: - disconnected_id = user1_id if is_user1_disconnected else user2_id - - self.cursor.execute( - """INSERT INTO - game(user1, user2, score1, score2, - start_time, end_state, winner, disconnected) - VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", - ( - user1_id, - user2_id, - score_user_1, - score_user_2, - start_time, - game_end_state, - winner_id, - disconnected_id, - ), - ) - self.connection.commit() - - return self.cursor.lastrowid - - def insert_won_game( - self, - winner_id: int, - loser_id: int, - score_winner: float, - score_loser: float, - start_time=None, - ) -> int | None: - """insert a won game into the database - - Args: - winner_id (int): user ID of the winner - loser_id (int): user ID of the loser - score_winner (float): score of the winner - score_loser (float): score of the loser - start_time (_type_, optional): use datetime module. Defaults to None. - - Returns: - int | None: game ID - """ - return self._insert_game( - user1_id=winner_id, - user2_id=loser_id, - score_user_1=score_winner, - score_user_2=score_loser, - start_time=start_time, - game_end_state=GameEndState.WIN.value, - ) - - def insert_disconnected_game( - self, - disconnected_user_id: int, - other_user_id: int, - score_disconnected_user: float, - score_other_user: float, - start_time=None, - ) -> int | None: - """insert a disconnected game into the database - - Args: - disconnected_user_id (int): user ID of the disconnected player - other_user_id (int): user ID of the other player - score_disconnected_user (float): score of the disconnected player - score_other_user (float): score of the other player - start_time (_type_, optional): use datetime module. Defaults to None. - - Returns: - int | None: game ID - """ - return self._insert_game( - user1_id=disconnected_user_id, - user2_id=other_user_id, - score_user_1=score_disconnected_user, - score_user_2=score_other_user, - start_time=start_time, - game_end_state=GameEndState.DISCONNECTED.value, - ) - - def insert_drawn_game( - self, - user1_id: int, - user2_id: int, - score_user_1: float, - score_user_2: float, - start_time=None, - ) -> int | None: - """insert a drawn game into the database - - Args: - user1_id (int): user ID of user 1 - user2_id (int): user ID of user 2 - score_user_1 (float): score of user 1 - score_user_2 (float): score of user 2 - start_time (_type_, optional): use datetime module. Defaults to None. - - Returns: - int | None: game ID - """ - return self._insert_game( - user1_id=user1_id, - user2_id=user2_id, - score_user_1=score_user_1, - score_user_2=score_user_2, - start_time=start_time, - game_end_state=GameEndState.DRAW.value, - ) - - def get_user_ids(self, game_id: int) -> tuple[int, int]: - """get the IDs of the users that participated in a game - - Args: - game_id (int): ID of the game - - Returns: - (int, int): IDs of both users - """ - res = self.cursor.execute( - f"SELECT user1, user2 FROM {GAME_DB_NAME} WHERE game_ID=?", (game_id,) - ) - users = res.fetchone() - return users - - def get_game_ids(self, user_id: int) -> list[int]: - """get all games that a user participated in - - Args: - userID (int): ID of the user - - Returns: - list[int]: IDs of the games - """ - res = self.cursor.execute( - f"SELECT game_ID FROM {GAME_DB_NAME} WHERE user1=? OR user2=?", - (user_id, user_id), - ) - games = [] - for (result,) in res.fetchall(): - games.append(result) - return games - - def get_won_game_ids(self, user_id: int) -> list[int]: - """get all games that a user has won - - Args: - user_id (int): ID of the user - - Returns: - list[int]: IDs of the games - """ - res = self.cursor.execute( - f"SELECT game_ID FROM {GAME_DB_NAME} WHERE winner=? AND end_state=1", - (user_id,), - ) - games = [] - for (result,) in res.fetchall(): - games.append(result) - return games - - def count_played_games(self, user_id: int) -> int: - """count all games the user has played (disconnected and drawn games included) - - Args: - user_id (int): ID of the user - - Returns: - int: count of played games - """ - res = self.cursor.execute( - f"SELECT COUNT() FROM {GAME_DB_NAME} WHERE user1=? OR user2=?", - (user_id, user_id), - ) - return res.fetchone()[0] - - def count_won_games(self, user_id: int) -> int: - """count all games where the user has won - - Args: - user_id (int): ID of the user - - Returns: - int: count of won games - """ - res = self.cursor.execute( - f"SELECT COUNT() FROM {GAME_DB_NAME} WHERE winner=?", - (user_id,), - ) - return res.fetchone()[0] - - def count_disconnected_games(self, user_id: int) -> int: - """count all games where the user disconnected - - Args: - user_id (int): ID of the user - - Returns: - int: count of disconnected games - """ - res = self.cursor.execute( - f"SELECT COUNT() FROM {GAME_DB_NAME} WHERE disconnected=?", - (user_id,), - ) - return res.fetchone()[0] - - def count_games_with_disconnect(self, user_id: int) -> int: - """count all games where the user or the opponent disconnected - - Args: - user_id (int): ID of the user - - Returns: - int: count of disconnected games - """ - res = self.cursor.execute( - f"""SELECT COUNT() FROM {GAME_DB_NAME} - WHERE (user1=? OR user2=?) AND end_state=3""", - (user_id, user_id), - ) - return res.fetchone()[0] - - def win_rate(self, user_id: int) -> float: - """calculates the win-rate of the user (ignoring disconnected games) - - Args: - user_id (int): ID of the user - - Returns: - float: win-rate - """ - all_games = self.count_played_games(user_id) - disconnected_games = self.count_games_with_disconnect(user_id) - won_games = self.count_won_games(user_id) - return won_games / (all_games - disconnected_games) diff --git a/teamprojekt_competition_server/server/game_database.py b/teamprojekt_competition_server/server/game_database.py new file mode 100644 index 00000000..b43c9931 --- /dev/null +++ b/teamprojekt_competition_server/server/game_database.py @@ -0,0 +1,323 @@ +"""Database to store the games""" + +import sqlite3 +import logging as log +from enum import Enum +from datetime import datetime + +GAME_DB_NAME = "game" +GameEndState = Enum("GameEndState", ["WIN", "DRAW", "DISCONNECTED"]) + + +# Connect to the database: +connection = sqlite3.connect("teamprojekt_competition_server/server/COMP_database.db") +cursor = connection.cursor() +cursor.execute( + f"""SELECT name FROM sqlite_master + WHERE type='table' AND name='{GAME_DB_NAME}'""" +) +if cursor.fetchone() is None: + cursor.execute( + f"""CREATE TABLE {GAME_DB_NAME}( + game_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + user1, + user2, + score1, + score2, + start_time, + end_state, + winner, + disconnected)""" + ) + + +def _insert_game( + user1_id: int, + user2_id: int, + score_user_1: float, + score_user_2: float, + start_time: str, + game_end_state: int, + is_user1_winner=True, + is_user1_disconnected=True, +) -> int | None: + """insert a new game into the database + + Args: + user1_id (int): user ID of user 1 (standard: winner or disconnected) + user2_id (int): user ID of user 2 (standard: loser) + score_user_1 (float): score of user 1 + score_user_2 (float): score of user 2 + start_time (String | None): use datetime.now().isoformat(sep=" ") + to generate JJJJ-MM-DD HH-MM-SS.SSSS + (example: 2024-01-14 19:23:13.736286)) + game_end_state(int): GameEndState enum value + is_user1_winner (bool): if user 1 is the winner + (only relevant for won games) + is_user1_disconnected (bool): if user 1 is disconnected + (only relevant for disconnected games) + + Returns: + int: ID of the game + """ + # TODO separate record file to store game steps + if start_time is None: + start_time = datetime.now() + + winner_id = None + if game_end_state == GameEndState.WIN.value: + winner_id = user1_id if is_user1_winner else user2_id + + disconnected_id = None + if game_end_state == GameEndState.DISCONNECTED.value: + disconnected_id = user1_id if is_user1_disconnected else user2_id + + cursor.execute( + """INSERT INTO + game(user1, user2, score1, score2, + start_time, end_state, winner, disconnected) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", + ( + user1_id, + user2_id, + score_user_1, + score_user_2, + start_time, + game_end_state, + winner_id, + disconnected_id, + ), + ) + connection.commit() + log.debug( + ( + "inserted game(" + f"game_id={cursor.lastrowid}, user1={user1_id}, user2={user2_id}, " + f"score1={score_user_1}, score2={score_user_2}, " + f"start_time={start_time}, end_state={game_end_state}, " + f"winner={winner_id}, disconnected={disconnected_id})" + ) + ) + + return cursor.lastrowid + + +def insert_won_game( + winner_id: int, + loser_id: int, + score_winner: float, + score_loser: float, + start_time=None, +) -> int | None: + """insert a won game into the database + + Args: + winner_id (int): user ID of the winner + loser_id (int): user ID of the loser + score_winner (float): score of the winner + score_loser (float): score of the loser + start_time (_type_, optional): use datetime module. Defaults to None. + + Returns: + int | None: game ID + """ + return _insert_game( + user1_id=winner_id, + user2_id=loser_id, + score_user_1=score_winner, + score_user_2=score_loser, + start_time=start_time, + game_end_state=GameEndState.WIN.value, + ) + + +def insert_disconnected_game( + disconnected_user_id: int, + other_user_id: int, + score_disconnected_user: float, + score_other_user: float, + start_time=None, +) -> int | None: + """insert a disconnected game into the database + + Args: + disconnected_user_id (int): user ID of the disconnected player + other_user_id (int): user ID of the other player + score_disconnected_user (float): score of the disconnected player + score_other_user (float): score of the other player + start_time (_type_, optional): use datetime module. Defaults to None. + + Returns: + int | None: game ID + """ + return _insert_game( + user1_id=disconnected_user_id, + user2_id=other_user_id, + score_user_1=score_disconnected_user, + score_user_2=score_other_user, + start_time=start_time, + game_end_state=GameEndState.DISCONNECTED.value, + ) + + +def insert_drawn_game( + user1_id: int, + user2_id: int, + score_user_1: float, + score_user_2: float, + start_time=None, +) -> int | None: + """insert a drawn game into the database + + Args: + user1_id (int): user ID of user 1 + user2_id (int): user ID of user 2 + score_user_1 (float): score of user 1 + score_user_2 (float): score of user 2 + start_time (_type_, optional): use datetime module. Defaults to None. + + Returns: + int | None: game ID + """ + return _insert_game( + user1_id=user1_id, + user2_id=user2_id, + score_user_1=score_user_1, + score_user_2=score_user_2, + start_time=start_time, + game_end_state=GameEndState.DRAW.value, + ) + + +def get_user_ids(game_id: int) -> tuple[int, int]: + """get the IDs of the users that participated in a game + + Args: + game_id (int): ID of the game + + Returns: + (int, int): IDs of both users + """ + res = cursor.execute( + f"SELECT user1, user2 FROM {GAME_DB_NAME} WHERE game_ID=?", (game_id,) + ) + users = res.fetchone() + return users + + +def get_game_ids(user_id: int) -> list[int]: + """get all games that a user participated in + + Args: + userID (int): ID of the user + + Returns: + list[int]: IDs of the games + """ + res = cursor.execute( + f"SELECT game_ID FROM {GAME_DB_NAME} WHERE user1=? OR user2=?", + (user_id, user_id), + ) + games = [] + for (result,) in res.fetchall(): + games.append(result) + return games + + +def get_won_game_ids(user_id: int) -> list[int]: + """get all games that a user has won + + Args: + user_id (int): ID of the user + + Returns: + list[int]: IDs of the games + """ + res = cursor.execute( + f"SELECT game_ID FROM {GAME_DB_NAME} WHERE winner=? AND end_state=1", + (user_id,), + ) + games = [] + for (result,) in res.fetchall(): + games.append(result) + return games + + +def count_played_games(user_id: int) -> int: + """count all games the user has played (disconnected and drawn games included) + + Args: + user_id (int): ID of the user + + Returns: + int: count of played games + """ + res = cursor.execute( + f"SELECT COUNT() FROM {GAME_DB_NAME} WHERE user1=? OR user2=?", + (user_id, user_id), + ) + return res.fetchone()[0] + + +def count_won_games(user_id: int) -> int: + """count all games where the user has won + + Args: + user_id (int): ID of the user + + Returns: + int: count of won games + """ + res = cursor.execute( + f"SELECT COUNT() FROM {GAME_DB_NAME} WHERE winner=?", + (user_id,), + ) + return res.fetchone()[0] + + +def count_disconnected_games(user_id: int) -> int: + """count all games where the user disconnected + + Args: + user_id (int): ID of the user + + Returns: + int: count of disconnected games + """ + res = cursor.execute( + f"SELECT COUNT() FROM {GAME_DB_NAME} WHERE disconnected=?", + (user_id,), + ) + return res.fetchone()[0] + + +def count_games_with_disconnect(user_id: int) -> int: + """count all games where the user or the opponent disconnected + + Args: + user_id (int): ID of the user + + Returns: + int: count of disconnected games + """ + res = cursor.execute( + f"""SELECT COUNT() FROM {GAME_DB_NAME} + WHERE (user1=? OR user2=?) AND end_state=3""", + (user_id, user_id), + ) + return res.fetchone()[0] + + +def win_rate(user_id: int) -> float: + """calculates the win-rate of the user (ignoring disconnected games) + + Args: + user_id (int): ID of the user + + Returns: + float: win-rate + """ + all_games = count_played_games(user_id) + disconnected_games = count_games_with_disconnect(user_id) + won_games = count_won_games(user_id) + return won_games / (all_games - disconnected_games) diff --git a/teamprojekt_competition_server/server/main.py b/teamprojekt_competition_server/server/main.py index 729c8073..d39154c3 100644 --- a/teamprojekt_competition_server/server/main.py +++ b/teamprojekt_competition_server/server/main.py @@ -2,7 +2,6 @@ from .server import COMPServer from .interfaces import IGame, IPlayer from .game_manager import game_manager -from .databases import GameDatabase # from .gymgame import GymGame @@ -50,34 +49,5 @@ def main(): server.start() -def test_database(): - """function to test database""" - game_db = GameDatabase() - gameID1 = game_db.insert_won_game( - winner_id=23, loser_id=4, score_winner=3, score_loser=6 - ) - gameID2 = game_db.insert_won_game( - winner_id=43, - loser_id=23, - score_winner=6, - score_loser=7, - ) - gameID3 = game_db.insert_disconnected_game( - disconnected_user_id=1, - other_user_id=23, - score_disconnected_user=6, - score_other_user=7, - ) - print(gameID1, gameID2, gameID3) - print(game_db.get_user_ids(game_id=gameID2)) - print(game_db.get_game_ids(user_id=23)) - print(game_db.get_won_game_ids(user_id=23)) - print(game_db.count_played_games(user_id=23)) - print(game_db.count_won_games(user_id=23)) - print(game_db.count_disconnected_games(user_id=23)) - print(game_db.win_rate(user_id=23)) - - if __name__ == "__main__": main() - # test_database() diff --git a/tests/game_database_test.py b/tests/game_database_test.py new file mode 100644 index 00000000..599cc98f --- /dev/null +++ b/tests/game_database_test.py @@ -0,0 +1,38 @@ +import teamprojekt_competition_server.server.game_database as game_db +import logging + +logging.basicConfig(level=logging.DEBUG) + +def database_tests(): + gameID1 = game_db.insert_won_game( + winner_id=23, loser_id=4, score_winner=3, score_loser=6 + ) + gameID2 = game_db.insert_won_game( + winner_id=43, + loser_id=23, + score_winner=6, + score_loser=7, + ) + gameID3 = game_db.insert_disconnected_game( + disconnected_user_id=1, + other_user_id=23, + score_disconnected_user=6, + score_other_user=7, + ) + + print(gameID1, gameID2, gameID3) + assert gameID1 % 3 == 1 and gameID2 % 3 == 2 and gameID3 % 3 == 0 + assert game_db.get_user_ids(game_id=gameID2) == (43, 23) + assert game_db.win_rate(user_id=23) == 0.5 + assert len(game_db.get_game_ids(user_id=23)) % 3 == 0 + assert len(game_db.get_won_game_ids(user_id=23)) == len(game_db.get_game_ids(user_id=23))/3 + assert game_db.count_played_games(user_id=23) % 3 == 0 + assert game_db.count_won_games(user_id=23) == game_db.count_played_games(user_id=23)/3 + assert game_db.count_disconnected_games(user_id=23) == 0 + assert game_db.count_games_with_disconnect(user_id=23) == game_db.count_played_games(user_id=23)/3 + + +if __name__ == "__main__": + database_tests() # only enable for manual testing + + From fa6e7b0d5ec85ccf99d499e5441683510d95b032 Mon Sep 17 00:00:00 2001 From: Carina Straub Date: Mon, 15 Jan 2024 16:56:16 +0100 Subject: [PATCH 5/8] formatting --- .../server/COMP_database.db | Bin 0 -> 12288 bytes tests/game_database_test.py | 30 +++++++++++------- 2 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 teamprojekt_competition_server/server/COMP_database.db diff --git a/teamprojekt_competition_server/server/COMP_database.db b/teamprojekt_competition_server/server/COMP_database.db new file mode 100644 index 0000000000000000000000000000000000000000..0a601447f1dd7e7c3bced9d90d7fb44763f48062 GIT binary patch literal 12288 zcmeI&L2lYW6b9fKOd+-u+zs+}mbef!_83f9l~h)RN}QCM1uI0st&kF;fTM1ss%OX{ za-ZCxC+ND*sHtn}rkk#+e}n-)e!nMwyODYKcC<=j@!@K7IZuRQ&l%_Jr4WoUgAR?3 z$HnPO`SFB4)APSAgS8j@kW!`E9jkq%H!KK100Izz00bZa0SG_<0uX?}Pl5AN#cDSB zG?~A@h_}}lv_+k5`pY2lL*%H7Di^lhqz-_f*1y00bZa0SG_<0uX=z1Rwwb2>dgFhHfyO zb3Wiqw<=Xvy55m=j+~Bgy8VvVSF-IY+4FmvePGbDX-evxHUAWKeTp{iY8JK1TBWe7 zOI^EGqw@58x6}5ORGzQd&$6b4^V6uSl-F(AJuBV+bMqUc7ZwB{009U<00Izz00bZa0SG_<0{@l3 M0oUq0{cnT*9Yc_&ng9R* literal 0 HcmV?d00001 diff --git a/tests/game_database_test.py b/tests/game_database_test.py index 599cc98f..cd8ee056 100644 --- a/tests/game_database_test.py +++ b/tests/game_database_test.py @@ -1,8 +1,11 @@ import teamprojekt_competition_server.server.game_database as game_db import logging +# run with python -m tests.game_database_test + logging.basicConfig(level=logging.DEBUG) + def database_tests(): gameID1 = game_db.insert_won_game( winner_id=23, loser_id=4, score_winner=3, score_loser=6 @@ -19,20 +22,23 @@ def database_tests(): score_disconnected_user=6, score_other_user=7, ) - + print(gameID1, gameID2, gameID3) - assert gameID1 % 3 == 1 and gameID2 % 3 == 2 and gameID3 % 3 == 0 + assert gameID1 % 3 == 1 and gameID2 % 3 == 2 and gameID3 % 3 == 0 assert game_db.get_user_ids(game_id=gameID2) == (43, 23) - assert game_db.win_rate(user_id=23) == 0.5 - assert len(game_db.get_game_ids(user_id=23)) % 3 == 0 - assert len(game_db.get_won_game_ids(user_id=23)) == len(game_db.get_game_ids(user_id=23))/3 - assert game_db.count_played_games(user_id=23) % 3 == 0 - assert game_db.count_won_games(user_id=23) == game_db.count_played_games(user_id=23)/3 - assert game_db.count_disconnected_games(user_id=23) == 0 - assert game_db.count_games_with_disconnect(user_id=23) == game_db.count_played_games(user_id=23)/3 - -if __name__ == "__main__": - database_tests() # only enable for manual testing + won_games = game_db.get_won_game_ids(user_id=23) + all_games = game_db.get_game_ids(user_id=23) + assert len(all_games) % 3 == 0 + assert len(won_games) == len(all_games) / 3 + assert game_db.count_played_games(user_id=23) == len(all_games) + assert game_db.count_won_games(user_id=23) == len(won_games) + assert game_db.count_disconnected_games(user_id=23) == 0 + assert game_db.count_games_with_disconnect(user_id=23) == len(all_games) / 3 + assert game_db.win_rate(user_id=23) == 0.5 + +if __name__ == "__main__": + # database_tests() # only enable for manual testing + pass From 44cbb2aadc4d941740d286d2829de209f7337b5b Mon Sep 17 00:00:00 2001 From: Carina Straub Date: Mon, 15 Jan 2024 18:28:17 +0100 Subject: [PATCH 6/8] deleted database file --- .../server/COMP_database.db | Bin 12288 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 teamprojekt_competition_server/server/COMP_database.db diff --git a/teamprojekt_competition_server/server/COMP_database.db b/teamprojekt_competition_server/server/COMP_database.db deleted file mode 100644 index 0a601447f1dd7e7c3bced9d90d7fb44763f48062..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI&L2lYW6b9fKOd+-u+zs+}mbef!_83f9l~h)RN}QCM1uI0st&kF;fTM1ss%OX{ za-ZCxC+ND*sHtn}rkk#+e}n-)e!nMwyODYKcC<=j@!@K7IZuRQ&l%_Jr4WoUgAR?3 z$HnPO`SFB4)APSAgS8j@kW!`E9jkq%H!KK100Izz00bZa0SG_<0uX?}Pl5AN#cDSB zG?~A@h_}}lv_+k5`pY2lL*%H7Di^lhqz-_f*1y00bZa0SG_<0uX=z1Rwwb2>dgFhHfyO zb3Wiqw<=Xvy55m=j+~Bgy8VvVSF-IY+4FmvePGbDX-evxHUAWKeTp{iY8JK1TBWe7 zOI^EGqw@58x6}5ORGzQd&$6b4^V6uSl-F(AJuBV+bMqUc7ZwB{009U<00Izz00bZa0SG_<0{@l3 M0oUq0{cnT*9Yc_&ng9R* From aeb919927741987ab978fc90750ba9318296e1d7 Mon Sep 17 00:00:00 2001 From: Carina Straub Date: Fri, 19 Jan 2024 19:12:21 +0100 Subject: [PATCH 7/8] Changed game_id to uuid --- .../server/game_database.py | 47 +++++++++++-------- tests/game_database_test.py | 19 +++++--- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/teamprojekt_competition_server/server/game_database.py b/teamprojekt_competition_server/server/game_database.py index b43c9931..6e7e7004 100644 --- a/teamprojekt_competition_server/server/game_database.py +++ b/teamprojekt_competition_server/server/game_database.py @@ -2,6 +2,7 @@ import sqlite3 import logging as log +import uuid from enum import Enum from datetime import datetime @@ -19,7 +20,7 @@ if cursor.fetchone() is None: cursor.execute( f"""CREATE TABLE {GAME_DB_NAME}( - game_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + game_id TEXT NOT NULL PRIMARY KEY, user1, user2, score1, @@ -32,6 +33,7 @@ def _insert_game( + game_id: uuid, user1_id: int, user2_id: int, score_user_1: float, @@ -40,10 +42,11 @@ def _insert_game( game_end_state: int, is_user1_winner=True, is_user1_disconnected=True, -) -> int | None: +) : """insert a new game into the database Args: + game_id (uuid): ID of the game user1_id (int): user ID of user 1 (standard: winner or disconnected) user2_id (int): user ID of user 2 (standard: loser) score_user_1 (float): score of user 1 @@ -74,10 +77,9 @@ def _insert_game( cursor.execute( """INSERT INTO - game(user1, user2, score1, score2, - start_time, end_state, winner, disconnected) - VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", + game VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""", ( + str(game_id), user1_id, user2_id, score_user_1, @@ -92,26 +94,26 @@ def _insert_game( log.debug( ( "inserted game(" - f"game_id={cursor.lastrowid}, user1={user1_id}, user2={user2_id}, " + f"game_id={game_id}, user1={user1_id}, user2={user2_id}, " f"score1={score_user_1}, score2={score_user_2}, " f"start_time={start_time}, end_state={game_end_state}, " f"winner={winner_id}, disconnected={disconnected_id})" ) ) - return cursor.lastrowid - def insert_won_game( + game_id: uuid, winner_id: int, loser_id: int, score_winner: float, score_loser: float, start_time=None, -) -> int | None: +): """insert a won game into the database Args: + game_id (uuid): ID of the game winner_id (int): user ID of the winner loser_id (int): user ID of the loser score_winner (float): score of the winner @@ -121,7 +123,8 @@ def insert_won_game( Returns: int | None: game ID """ - return _insert_game( + _insert_game( + game_id=game_id, user1_id=winner_id, user2_id=loser_id, score_user_1=score_winner, @@ -132,15 +135,17 @@ def insert_won_game( def insert_disconnected_game( + game_id: uuid, disconnected_user_id: int, other_user_id: int, score_disconnected_user: float, score_other_user: float, start_time=None, -) -> int | None: +): """insert a disconnected game into the database Args: + game_id (uuid): ID of the game disconnected_user_id (int): user ID of the disconnected player other_user_id (int): user ID of the other player score_disconnected_user (float): score of the disconnected player @@ -150,7 +155,8 @@ def insert_disconnected_game( Returns: int | None: game ID """ - return _insert_game( + _insert_game( + game_id=game_id, user1_id=disconnected_user_id, user2_id=other_user_id, score_user_1=score_disconnected_user, @@ -161,15 +167,17 @@ def insert_disconnected_game( def insert_drawn_game( + game_id: uuid, user1_id: int, user2_id: int, score_user_1: float, score_user_2: float, start_time=None, -) -> int | None: +): """insert a drawn game into the database Args: + game_id (uuid): ID of the game user1_id (int): user ID of user 1 user2_id (int): user ID of user 2 score_user_1 (float): score of user 1 @@ -179,7 +187,8 @@ def insert_drawn_game( Returns: int | None: game ID """ - return _insert_game( + _insert_game( + game_id=game_id, user1_id=user1_id, user2_id=user2_id, score_user_1=score_user_1, @@ -189,7 +198,7 @@ def insert_drawn_game( ) -def get_user_ids(game_id: int) -> tuple[int, int]: +def get_user_ids(game_id: uuid) -> tuple[int, int]: """get the IDs of the users that participated in a game Args: @@ -199,7 +208,7 @@ def get_user_ids(game_id: int) -> tuple[int, int]: (int, int): IDs of both users """ res = cursor.execute( - f"SELECT user1, user2 FROM {GAME_DB_NAME} WHERE game_ID=?", (game_id,) + f"SELECT user1, user2 FROM {GAME_DB_NAME} WHERE game_ID=?", (str(game_id),) ) users = res.fetchone() return users @@ -220,7 +229,7 @@ def get_game_ids(user_id: int) -> list[int]: ) games = [] for (result,) in res.fetchall(): - games.append(result) + games.append(uuid.UUID(result)) return games @@ -239,7 +248,7 @@ def get_won_game_ids(user_id: int) -> list[int]: ) games = [] for (result,) in res.fetchall(): - games.append(result) + games.append(uuid.UUID(result)) return games @@ -320,4 +329,4 @@ def win_rate(user_id: int) -> float: all_games = count_played_games(user_id) disconnected_games = count_games_with_disconnect(user_id) won_games = count_won_games(user_id) - return won_games / (all_games - disconnected_games) + return won_games / (all_games - disconnected_games) \ No newline at end of file diff --git a/tests/game_database_test.py b/tests/game_database_test.py index cd8ee056..c801914a 100644 --- a/tests/game_database_test.py +++ b/tests/game_database_test.py @@ -1,5 +1,6 @@ import teamprojekt_competition_server.server.game_database as game_db import logging +import uuid # run with python -m tests.game_database_test @@ -7,30 +8,36 @@ def database_tests(): - gameID1 = game_db.insert_won_game( - winner_id=23, loser_id=4, score_winner=3, score_loser=6 + gameID1, gameID2, gameID3 = uuid.uuid4(), uuid.uuid4(), uuid.uuid4() + game_db.insert_won_game( + game_id=gameID1, winner_id=23, loser_id=4, score_winner=3, score_loser=6 ) - gameID2 = game_db.insert_won_game( + game_db.insert_won_game( + game_id=gameID2, winner_id=43, loser_id=23, score_winner=6, score_loser=7, ) - gameID3 = game_db.insert_disconnected_game( + game_db.insert_disconnected_game( + game_id=gameID3, disconnected_user_id=1, other_user_id=23, score_disconnected_user=6, score_other_user=7, ) - print(gameID1, gameID2, gameID3) - assert gameID1 % 3 == 1 and gameID2 % 3 == 2 and gameID3 % 3 == 0 assert game_db.get_user_ids(game_id=gameID2) == (43, 23) won_games = game_db.get_won_game_ids(user_id=23) all_games = game_db.get_game_ids(user_id=23) assert len(all_games) % 3 == 0 assert len(won_games) == len(all_games) / 3 + assert all_games.count(gameID1) == 1 + for game in all_games: + assert type(game) == uuid.UUID + for game in won_games: + assert type(game) == uuid.UUID assert game_db.count_played_games(user_id=23) == len(all_games) assert game_db.count_won_games(user_id=23) == len(won_games) From 0081872a071648beb138b6b2b9dcedd8a4939a2c Mon Sep 17 00:00:00 2001 From: Carina Straub Date: Fri, 19 Jan 2024 19:21:54 +0100 Subject: [PATCH 8/8] formatting --- .../server/game_database.py | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/teamprojekt_competition_server/server/game_database.py b/teamprojekt_competition_server/server/game_database.py index 6e7e7004..44a7db64 100644 --- a/teamprojekt_competition_server/server/game_database.py +++ b/teamprojekt_competition_server/server/game_database.py @@ -2,7 +2,7 @@ import sqlite3 import logging as log -import uuid +from uuid import UUID from enum import Enum from datetime import datetime @@ -33,7 +33,7 @@ def _insert_game( - game_id: uuid, + game_id: UUID, user1_id: int, user2_id: int, score_user_1: float, @@ -42,11 +42,11 @@ def _insert_game( game_end_state: int, is_user1_winner=True, is_user1_disconnected=True, -) : +): """insert a new game into the database Args: - game_id (uuid): ID of the game + game_id (UUID): ID of the game user1_id (int): user ID of user 1 (standard: winner or disconnected) user2_id (int): user ID of user 2 (standard: loser) score_user_1 (float): score of user 1 @@ -103,7 +103,7 @@ def _insert_game( def insert_won_game( - game_id: uuid, + game_id: UUID, winner_id: int, loser_id: int, score_winner: float, @@ -113,7 +113,7 @@ def insert_won_game( """insert a won game into the database Args: - game_id (uuid): ID of the game + game_id (UUID): ID of the game winner_id (int): user ID of the winner loser_id (int): user ID of the loser score_winner (float): score of the winner @@ -135,7 +135,7 @@ def insert_won_game( def insert_disconnected_game( - game_id: uuid, + game_id: UUID, disconnected_user_id: int, other_user_id: int, score_disconnected_user: float, @@ -145,7 +145,7 @@ def insert_disconnected_game( """insert a disconnected game into the database Args: - game_id (uuid): ID of the game + game_id (UUID): ID of the game disconnected_user_id (int): user ID of the disconnected player other_user_id (int): user ID of the other player score_disconnected_user (float): score of the disconnected player @@ -167,7 +167,7 @@ def insert_disconnected_game( def insert_drawn_game( - game_id: uuid, + game_id: UUID, user1_id: int, user2_id: int, score_user_1: float, @@ -177,7 +177,7 @@ def insert_drawn_game( """insert a drawn game into the database Args: - game_id (uuid): ID of the game + game_id (UUID): ID of the game user1_id (int): user ID of user 1 user2_id (int): user ID of user 2 score_user_1 (float): score of user 1 @@ -198,7 +198,7 @@ def insert_drawn_game( ) -def get_user_ids(game_id: uuid) -> tuple[int, int]: +def get_user_ids(game_id: UUID) -> tuple[int, int]: """get the IDs of the users that participated in a game Args: @@ -214,7 +214,7 @@ def get_user_ids(game_id: uuid) -> tuple[int, int]: return users -def get_game_ids(user_id: int) -> list[int]: +def get_game_ids(user_id: int) -> list[UUID]: """get all games that a user participated in Args: @@ -229,11 +229,11 @@ def get_game_ids(user_id: int) -> list[int]: ) games = [] for (result,) in res.fetchall(): - games.append(uuid.UUID(result)) + games.append(UUID(result)) return games -def get_won_game_ids(user_id: int) -> list[int]: +def get_won_game_ids(user_id: int) -> list[UUID]: """get all games that a user has won Args: @@ -248,7 +248,7 @@ def get_won_game_ids(user_id: int) -> list[int]: ) games = [] for (result,) in res.fetchall(): - games.append(uuid.UUID(result)) + games.append(UUID(result)) return games @@ -329,4 +329,4 @@ def win_rate(user_id: int) -> float: all_games = count_played_games(user_id) disconnected_games = count_games_with_disconnect(user_id) won_games = count_won_games(user_id) - return won_games / (all_games - disconnected_games) \ No newline at end of file + return won_games / (all_games - disconnected_games)