diff --git a/bot/__main__.py b/bot/__main__.py index f85e425..d8b923e 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -13,6 +13,7 @@ from bot.middlewares.db import DbSessionMiddleware from bot.db.utils import make_connection_string from bot.handlers.default_commands import register_default_handlers +from bot.handlers.statistics import register_statistics_handlers from bot.handlers.callbacks import register_callbacks from bot.updatesworker import get_handled_updates_list @@ -24,7 +25,8 @@ async def set_bot_commands(bot: Bot): ( [ BotCommand(command="start", description="New Game"), - BotCommand(command="help", description="How to play Bombsweeper?") + BotCommand(command="help", description="How to play Bombsweeper?"), + BotCommand(command="stats", description="Your personal statistics") ], BotCommandScopeDefault(), None @@ -60,6 +62,7 @@ async def main(): # Register handlers register_default_handlers(dp) + register_statistics_handlers(dp) register_callbacks(dp) # Register middlewares diff --git a/bot/handlers/statistics.py b/bot/handlers/statistics.py new file mode 100644 index 0000000..5fc3f24 --- /dev/null +++ b/bot/handlers/statistics.py @@ -0,0 +1,59 @@ +from aiogram import Dispatcher, types +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + +from bot.db.models import GameHistoryEntry + + +async def show_stats(message: types.Message, session: AsyncSession): + """ + Get player personal statistics + + :param message: Telegram message with /stats command + :param session: SQLAlchemy DB session + """ + game_data_request = await session.execute( + select(GameHistoryEntry).where(GameHistoryEntry.telegram_id == message.from_user.id) + ) + game_data = game_data_request.scalars().all() + if len(game_data) == 0: + await message.answer("You don't have any stats yet! Press /start and play a game of Bombsweeper") + return + user_data = {} + + # Gather wins and loses, grouping them by field size locally + item: GameHistoryEntry + for item in game_data: + user_data.setdefault(item.field_size, {"wins": 0, "loses": 0}) + if item.victory is True: + user_data[item.field_size]["wins"] += 1 + else: + user_data[item.field_size]["loses"] += 1 + + # Calculate total games for each mode along with winrate. + result_text_array = [] + total_games = 0 + for field_size, field_data in user_data.items(): + total_current = field_data["loses"] + field_data["wins"] + total_games += total_current + + if field_data["loses"] == 0: + winrate = 100 + else: + winrate = field_data["wins"] / total_current * 100 + + result_text_array.append( + "💣 {size}×{size} field:\nGames: {total}. " + "Wins: {wins} ({winrate:.0f}%)".format( + size=field_size, + total=total_current, + wins=field_data["wins"], + winrate=winrate + )) + # Add a header to the beginning of result message + result_text_array.insert(0, f"📊 Your personal stats:\nTotal games played: {total_games}") + await message.answer("\n\n".join(result_text_array)) + + +def register_statistics_handlers(dp: Dispatcher): + dp.register_message_handler(show_stats, commands="stats")