from aiogram import Bot, Dispatcher, types, F from aiogram.filters import Command from aiogram.types import WebAppInfo, KeyboardButton, ReplyKeyboardMarkup from bot.database import Database import json import asyncio from bot.config import BOT_TOKEN, WEBAPP_URL import logging # Настройка логирования logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) # Инициализация бота и диспетчера bot = Bot(token=BOT_TOKEN) dp = Dispatcher() db = Database() # Упрощенная клавиатура def get_main_keyboard(): keyboard = [ [ KeyboardButton( text="Записать броски 🎲", web_app=WebAppInfo(url=WEBAPP_URL) ) ], [KeyboardButton(text="Статистика 📊")] ] return ReplyKeyboardMarkup(keyboard=keyboard, resize_keyboard=True) @dp.message(Command("start")) async def start_command(message: types.Message): logger.info(f"User {message.from_user.id} ({message.from_user.username}) started the bot") await message.answer( "🎲 Добро пожаловать в счётчик кубиков для нард!\n\n" "Нажмите «Записать броски» чтобы начать новую игру.", reply_markup=get_main_keyboard() ) # Обновляем функцию подсчета статистики в handle_webapp_data def calculate_throw_sum(throw): dice1, dice2 = throw['dice'] if dice1 == dice2: return (dice1 + dice2) * 2 return dice1 + dice2 @dp.message(F.web_app_data) async def handle_webapp_data(message: types.Message): try: user = message.from_user logger.info(f"Received webapp data from user {user.id} ({user.username})") data = json.loads(message.web_app_data.data) if data['type'] == 'game_session': # Создаем новую игру game_id = db.create_game(user.id, user.username) logger.info(f"Created new game {game_id} for user {user.id}") # Записываем все броски throws = data['throws'] for throw in throws: db.add_throw( game_id, throw['dice'][0], throw['dice'][1] ) # Завершаем игру db.end_game(game_id) logger.info(f"Game {game_id} completed with {len(throws)} throws") # Обновляем подсчет статистики total_throws = len(throws) total_sum = sum(calculate_throw_sum(t) for t in throws) avg_sum = total_sum / total_throws if total_throws > 0 else 0 doubles = sum(1 for t in throws if t['dice'][0] == t['dice'][1]) # Находим максимальный и минимальный броски с учетом дублей throws_with_sums = [(t, calculate_throw_sum(t)) for t in throws] max_throw = max(throws_with_sums, key=lambda x: x[1]) min_throw = min(throws_with_sums, key=lambda x: x[1]) # Формируем сообщение response = "🎯 Игра завершена!\n\n" response += f"📊 Статистика игры:\n" response += f"• Всего бросков: {total_throws}\n" response += f"• Общая сумма: {total_sum}\n" response += f"• Средняя сумма: {avg_sum:.1f}\n" response += f"• Дублей выпало: {doubles}\n" response += f"• Максимальный бросок: {max_throw[0]['dice'][0]}-{max_throw[0]['dice'][1]} (сумма: {max_throw[1]})\n" response += f"• Минимальный бросок: {min_throw[0]['dice'][0]}-{min_throw[0]['dice'][1]} (сумма: {min_throw[1]})\n\n" # Добавляем последние броски с учетом дублей response += "🎲 Последние броски:\n" for i, throw in enumerate(throws[:5]): sum_value = calculate_throw_sum(throw) is_double = throw['dice'][0] == throw['dice'][1] response += f"{i+1}. {throw['dice'][0]}-{throw['dice'][1]} {'🎯' if is_double else ''} (сумма: {sum_value})\n" if total_throws > 5: response += f"... и ещё {total_throws - 5} бросков" await message.answer(response) logger.info(f"Sent game statistics to user {user.id}") except Exception as e: logger.error(f"Error handling webapp data: {e}", exc_info=True) await message.answer("❌ Произошла ошибка при обработке данных.") @dp.message(Command("statistics")) @dp.message(F.text == "Статистика 📊") async def statistics_command(message: types.Message): user_id = message.from_user.id logger.info(f"User {user_id} requested statistics") stats = db.get_statistics(user_id) response = "📊 Общая статистика:\n\n" if stats['total_throws']: response += ( f"• Всего игр: {stats['total_games']}\n" f"• Всего бросков: {stats['total_throws']}\n" f"• Средняя сумма: {stats['avg_sum']:.1f}\n" ) else: response += "У вас пока нет записанных бросков." await message.answer(response) logger.info(f"Sent statistics to user {user_id}") # Запуск бота async def main(): logger.info("Starting bot") await dp.start_polling(bot) if __name__ == '__main__': asyncio.run(main())