Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving game state to the database #133

Merged
merged 26 commits into from
Mar 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b37c8ef
added database_game
kapselccc Mar 1, 2023
8b490e2
added database_user
kapselccc Mar 3, 2023
663c77e
added database_entity
kapselccc Mar 3, 2023
125b0e4
added database_creature
kapselccc Mar 3, 2023
ca411bc
added database_player
kapselccc Mar 3, 2023
008eab4
added database_item
kapselccc Mar 3, 2023
3233718
added database_equipment
kapselccc Mar 3, 2023
a2f72c4
added database_skill
kapselccc Mar 3, 2023
8057f58
added database_event
kapselccc Mar 3, 2023
2e37fb5
added database_dialog
kapselccc Mar 3, 2023
1b68d4c
added dialog to prototype
kapselccc Mar 3, 2023
1f5224f
added id to every prototype class
kapselccc Mar 3, 2023
92a0895
database_connection: added add_to_db method
kapselccc Mar 4, 2023
5bba81b
changed adding game to db
kapselccc Mar 4, 2023
1f8dcf1
database_user: added adding user;lobby: changed handlers
kapselccc Mar 4, 2023
6cb79a9
adding entity to db
kapselccc Mar 6, 2023
9c2f9ae
database: implement adding player to database
pcichowski Mar 9, 2023
28ffa05
database: add get_db_object and get_player
pcichowski Mar 10, 2023
e37e18a
tests: set up a basic test environment
pcichowski Mar 10, 2023
42c619a
prototype: player: handle exceptions when setting sprite path
pcichowski Mar 10, 2023
fe10df3
prototype: multiverse: handle token not being found in dict
pcichowski Mar 10, 2023
e54173d
database: add more tests
pcichowski Mar 10, 2023
530a9fb
changed adding player and creature to db
kapselccc Mar 10, 2023
960d7e6
fixed issues with adding player to db
kapselccc Mar 11, 2023
fbf70a8
Merge pull request #137 from esoviscode/saving_state_to_db_silentsky
kapselccc Mar 11, 2023
32b3b2b
prototype/creature: changed type of sprite
kapselccc Mar 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 21 additions & 104 deletions dnd-bot/dnd_bot/database/database_connection.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import os
from psycopg2 import connect, ProgrammingError
from sqlite3 import ProgrammingError

from psycopg2 import connect


class DatabaseConnection:
Expand Down Expand Up @@ -58,126 +60,41 @@ def execute_query(query: str):
DatabaseConnection.connection.commit()

@staticmethod
def add_game(token: str, id_host: int, game_state: str, campaign_name: str) -> int | None:
"""start game and add game to database
:param token: lobby/game token (5 digit password)
:param id_host: discord id of host
:param game_state: string enum, initial value of added game is 'LOBBY'
:param campaign_name: campaign name
:return:
on success: game id, on failure: None
"""

DatabaseConnection.cursor.execute('INSERT INTO public."Game" (token, id_host, game_state, campaign_name) VALUES '
'(%s, %s, %s, %s)',
(token, id_host, game_state, campaign_name))
def add_to_db(query: str = "", parameters: tuple = None, element_name: str = "element") -> int | None:
DatabaseConnection.cursor.execute(query, parameters)
DatabaseConnection.cursor.execute('SELECT LASTVAL()')

try:
game_id = DatabaseConnection.cursor.fetchone()[0]
id = DatabaseConnection.cursor.fetchone()[0]
except ProgrammingError as err:
print(f"db: error adding game {err}")
print(f"db: error adding {element_name} {err}")
return None

DatabaseConnection.connection.commit()
return game_id

@staticmethod
def start_game(id_game: int) -> None:
"""starts game
:param id_game: database game id
"""
DatabaseConnection.cursor.execute('UPDATE public."Game" SET game_state=(%s) WHERE id_game = (%s)',
('ACTIVE', id_game))

DatabaseConnection.connection.commit()
return id

@staticmethod
def add_user(id_game: int, discord_id: int) -> int | None:
"""add user to a game
:param id_game: database game id
:param discord_id: user discord id
"""

DatabaseConnection.cursor.execute('INSERT INTO public."User" (id_game, discord_id) VALUES (%s, %s)',
(id_game, discord_id))
DatabaseConnection.cursor.execute('SELECT LASTVAL()')
def get_object_from_db(query: str = '', parameters: tuple = None, element_name: str = '') -> tuple | None:
DatabaseConnection.cursor.execute(query, parameters)
obj = DatabaseConnection.cursor.fetchone()

try:
user_id = DatabaseConnection.cursor.fetchone()[0]
except ProgrammingError as err:
print(f"db: error adding user {err}")
if not obj:
print(f"db: error getting {element_name}")
return None

DatabaseConnection.connection.commit()
return user_id
return obj

@staticmethod
def find_game_by_token(token: str) -> dict | None:
"""find game by token/password
:param token: game token/password to find the game by
:return: on success: dictionary containing game data - it's keys: 'id game' - database game id, 'token' - game token, 'id_host' -
discord host id, 'id_campaign' - campaign id, 'game_state' - string enum, 'players' - list of players
"""

DatabaseConnection.cursor.execute(f'SELECT * FROM public."Game" WHERE token = %s AND game_state != %s',
(token, 'FINISHED'))
game_tuple = DatabaseConnection.cursor.fetchone()
def get_multiple_objects_from_db(query: str = '', parameters: tuple = None, element_name: str = '') -> list | None:
"""returns list of tuples representing a db object"""
DatabaseConnection.cursor.execute(query, parameters)
objs = DatabaseConnection.cursor.fetchall()

if not game_tuple:
if not objs:
print(f"db: error getting multiple {element_name}")
return None

DatabaseConnection.cursor.execute(f'SELECT * FROM public."User" WHERE id_game = {game_tuple[0]}')
users_tuples = DatabaseConnection.cursor.fetchall()

users = [{'id_user': user_tuple[0], 'id_game': user_tuple[1], 'discord_id': user_tuple[2]}
for user_tuple in users_tuples]

return {'id_game': game_tuple[0], 'token': game_tuple[1], 'id_host': game_tuple[2],
'id_campaign': game_tuple[3],
'game_state': game_tuple[4], 'players': users}

@staticmethod
def update_game_state(id_game: int, game_state: str) -> None:
"""updates game state on the one provided
"""
DatabaseConnection.cursor.execute('UPDATE public."Game" SET game_state = (%s) WHERE id_game = (%s)',
(game_state, id_game))

DatabaseConnection.connection.commit()

@staticmethod
def get_all_game_tokens():
"""returns all tokens currently existing in the database
"""
DatabaseConnection.cursor.execute(f'SELECT token FROM public."Game"')
tokens = DatabaseConnection.cursor.fetchall()
DatabaseConnection.connection.commit()

return [x[0] for x in tokens]

@staticmethod
def get_id_game_from_game_token(token: str) -> int | None:
"""returns database game id based on the token, None if the query fails
"""
DatabaseConnection.cursor.execute(f'SELECT id_game FROM public."Game" WHERE token = (%s)', (token,))
game_id = DatabaseConnection.cursor.fetchone()
DatabaseConnection.connection.commit()
return objs

if not game_id:
return None

return game_id

@staticmethod
def get_game_token_from_id_game(id_game: int) -> str | None:
"""returns game token based on database game id, None if the query fails
"""
DatabaseConnection.cursor.execute(f'SELECT token FROM public."Game" WHERE id_game = (%s)', (id_game,))
game_token = DatabaseConnection.cursor.fetchone()
DatabaseConnection.connection.commit()

if not game_token:
return None

return game_token
37 changes: 37 additions & 0 deletions dnd-bot/dnd_bot/database/database_creature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from dnd_bot.database.database_connection import DatabaseConnection
from dnd_bot.database.database_entity import DatabaseEntity
from dnd_bot.logic.prototype.creature import Creature


class DatabaseCreature:

@staticmethod
def add_creature(x: int = 0, y: int = 0, sprite: str = '', name: str = 'Creature', hp: int = 0, strength: int = 0,
dexterity: int = 0, intelligence: int = 0, charisma: int = 0, perception: int = 0,
initiative: int = 0, action_points: int = 0, level: int = 0, drop_money: int = 0,
id_game: int = 1) -> int | None:
id_entity = DatabaseEntity.add_entity(name=name, x=x, y=y, sprite=sprite, id_game=id_game)
id_creature = DatabaseConnection.add_to_db('INSERT INTO public."Creature" (level, "HP", strength, dexterity, '
'intelligence, charisma, perception, initiative, action_points, '
'money, id_entity) VALUES'
'(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)',
(
level, hp, strength, dexterity, intelligence,
charisma, perception,
initiative, action_points, drop_money, id_entity),
"creature")
return id_creature

@staticmethod
def update_creature(id_creature: int = 0, level: int = 0, hp: int = 0, strength: int = 0, dexterity: int = 0,
intelligence: int = 0, perception: int = 0, initiative: int = 0, action_points: int = 0,
money: int = 0) -> None:
pass

@staticmethod
def get_creature(id_creature: int = 0) -> dict | None:
pass

@staticmethod
def get_creature_items(id_creature) -> list | None:
pass
17 changes: 17 additions & 0 deletions dnd-bot/dnd_bot/database/database_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class DatabaseDialog:

@staticmethod
def add_dialog(id_speaker: int = 0, id_listener: int = 0, content: str = "", status: str = "") -> int | None:
pass

@staticmethod
def update_dialog(id_dialog: int, status: str = "") -> None:
pass

@staticmethod
def get_dialog(id_dialog: int = 0) -> dict | None:
pass

@staticmethod
def get_all_dialogs() -> list | None:
pass
21 changes: 21 additions & 0 deletions dnd-bot/dnd_bot/database/database_entity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from dnd_bot.database.database_connection import DatabaseConnection


class DatabaseEntity:

@staticmethod
def add_entity(name: str = "", x: int = 0, y: int = 0, sprite=None, id_game: int = 1) -> int | None:
return DatabaseConnection.add_to_db('INSERT INTO public."Entity" (name, x, y, sprite, id_game) VALUES'
'(%s, %s, %s, %s, %s)', (name, x, y, sprite, id_game), "entity")

@staticmethod
def update_entity(id_entity: int = 0, x: int = 0, y: int = 0) -> None:
pass

@staticmethod
def get_entity(id_entity: int) -> dict | None:
pass

@staticmethod
def get_entity_skills(id_entity: int = 0) -> list | None:
pass
15 changes: 15 additions & 0 deletions dnd-bot/dnd_bot/database/database_equipment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class DatabaseEquipment:

@staticmethod
def add_equipment(helmet: int = -1, chest: int = -1, leg_armor: int = -1, boots: int = -1, left_hand=-1,
right_hand: int = -1, accessory: int = -1) -> int | None:
pass

@staticmethod
def update_equipment(id_equipment: int = 0, helmet: int = -1, chest: int = -1, leg_armor: int = -1, boots: int = -1,
left_hand: int = -1, right_hand: int = -1, accessory: int = -1) -> None:
pass

@staticmethod
def get_equipment(id_equipment: int = 0) -> dict | None:
pass
14 changes: 14 additions & 0 deletions dnd-bot/dnd_bot/database/database_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class DatabaseEvent:

@staticmethod
def add_event(x: int = 0, y: int = 0, range: int = 0, status: str = "", content: str = "",
id_game: int = 0) -> int | None:
pass

@staticmethod
def get_event(id_event) -> dict | None:
pass

@staticmethod
def get_all_events() -> list | None:
pass
97 changes: 97 additions & 0 deletions dnd-bot/dnd_bot/database/database_game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from sqlite3 import ProgrammingError

from dnd_bot.database.database_connection import DatabaseConnection


class DatabaseGame:

@staticmethod
def add_game(token: str, id_host: int, game_state: str, campaign_name: str) -> int | None:
"""start game and add game to database
:param token: lobby/game token (5 digit password)
:param id_host: discord id of host
:param game_state: string enum, initial value of added game is 'LOBBY'
:param campaign_name: campaign name
:return:
on success: game id, on failure: None
"""
return DatabaseConnection.add_to_db('INSERT INTO public."Game" (token, id_host, game_state, campaign_name)'
'VALUES (%s, %s, %s, %s)', (token, id_host, game_state, campaign_name),
"game")

@staticmethod
def start_game(id_game: int) -> None:
"""starts game
:param id_game: database game id
"""
DatabaseGame.update_game_state(id_game, 'ACTIVE')

@staticmethod
def update_game_state(id_game: int, game_state: str) -> None:
"""updates game state on the one provided
"""
DatabaseConnection.cursor.execute('UPDATE public."Game" SET game_state = (%s) WHERE id_game = (%s)',
(game_state, id_game))

DatabaseConnection.connection.commit()

@staticmethod
def get_all_game_tokens():
"""returns all tokens currently existing in the database
"""
DatabaseConnection.cursor.execute(f'SELECT token FROM public."Game"')
tokens = DatabaseConnection.cursor.fetchall()
DatabaseConnection.connection.commit()

return [x[0] for x in tokens]

@staticmethod
def get_id_game_from_game_token(token: str) -> int | None:
"""returns database game id based on the token, None if the query fails
"""
DatabaseConnection.cursor.execute(f'SELECT id_game FROM public."Game" WHERE token = (%s)', (token,))
game_id = DatabaseConnection.cursor.fetchone()
DatabaseConnection.connection.commit()

if not game_id:
return None

return game_id

@staticmethod
def get_game_token_from_id_game(id_game: int) -> str | None:
"""returns game token based on database game id, None if the query fails
"""
DatabaseConnection.cursor.execute(f'SELECT token FROM public."Game" WHERE id_game = (%s)', (id_game,))
game_token = DatabaseConnection.cursor.fetchone()
DatabaseConnection.connection.commit()

if not game_token:
return None

return game_token

@staticmethod
def find_game_by_token(token: str) -> dict | None:
"""find game by token/password
:param token: game token/password to find the game by
:return: on success: dictionary containing game data - it's keys: 'id game' - database game id, 'token' - game token, 'id_host' -
discord host id, 'id_campaign' - campaign id, 'game_state' - string enum, 'players' - list of players
"""

DatabaseConnection.cursor.execute(f'SELECT * FROM public."Game" WHERE token = %s AND game_state != %s',
(token, 'FINISHED'))
game_tuple = DatabaseConnection.cursor.fetchone()

if not game_tuple:
return None

DatabaseConnection.cursor.execute(f'SELECT * FROM public."User" WHERE id_game = {game_tuple[0]}')
users_tuples = DatabaseConnection.cursor.fetchall()

users = [{'id_user': user_tuple[0], 'id_game': user_tuple[1], 'discord_id': user_tuple[2]}
for user_tuple in users_tuples]

return {'id_game': game_tuple[0], 'token': game_tuple[1], 'id_host': game_tuple[2],
'id_campaign': game_tuple[3],
'game_state': game_tuple[4], 'players': users}
16 changes: 16 additions & 0 deletions dnd-bot/dnd_bot/database/database_item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class DatabaseItem:

@staticmethod
def add_item(name: str = "", hp: int = 0, strength: int = 0, dexterity: int = 0, intelligence: int = 0,
charisma: int = 0, perception: int = 0, action_points: int = 0, effect: str = "",
base_price: int = 0) -> int | None:
pass

@staticmethod
def get_item(id_item) -> dict | None:
pass

@staticmethod
def add_creature_item(id_creature: int = 0, id_item: int = 0, amount: int = 0) -> None:
pass

Loading