"""Обработчики мини-игр""" import asyncio import random from datetime import datetime from typing import Optional from aiogram import Router, F from aiogram.filters import Command from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup from database.db import async_session_maker from services.user_service import UserService from services.vocabulary_service import VocabularyService from services.ai_service import AIService from utils.i18n import t, get_user_lang, get_user_translation_lang router = Router() ai_service = AIService() class SpeedRoundStates(StatesGroup): """Состояния для игры Speed Round""" playing = State() waiting_answer = State() class MatchGameStates(StatesGroup): """Состояния для игры Match (Найди пару)""" waiting_answer = State() # Константы игры Speed Round SPEED_ROUND_COUNT = 10 # Количество слов в раунде SPEED_ROUND_TIME = 10 # Секунд на ответ POINTS_CORRECT = 100 # Базовые очки за правильный ответ POINTS_SPEED_BONUS = 10 # Бонус за каждую оставшуюся секунду # Константы игры Match MATCH_WORDS_COUNT = 5 # Количество пар слов MATCH_TIME_LIMIT = 60 # Секунд на всю игру (0 = без таймера) MATCH_POINTS_PER_PAIR = 50 # Очки за правильную пару def get_minigames_menu_keyboard(lang: str) -> InlineKeyboardMarkup: """Клавиатура выбора мини-игры""" return InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=f"⚡ {t(lang, 'minigames.speed_round.name')}", callback_data="minigame_speed_round" )], [InlineKeyboardButton( text=f"🎯 {t(lang, 'minigames.match_game.name')}", callback_data="minigame_match" )], ]) def get_speed_round_start_keyboard(lang: str, is_premium: bool = False) -> InlineKeyboardMarkup: """Клавиатура начала игры Speed Round""" buttons = [] if is_premium: # Для премиум-пользователей - выбор режима проверки buttons.append([ InlineKeyboardButton( text=f"🤖 {t(lang, 'minigames.speed_round.mode_ai')}", callback_data="speed_round_start_ai" ) ]) buttons.append([ InlineKeyboardButton( text=f"⚡ {t(lang, 'minigames.speed_round.mode_simple')}", callback_data="speed_round_start_simple" ) ]) else: # Для обычных пользователей - только простой режим buttons.append([ InlineKeyboardButton( text=f"▶️ {t(lang, 'minigames.start_btn')}", callback_data="speed_round_start_simple" ) ]) buttons.append([ InlineKeyboardButton( text=f"⬅️ {t(lang, 'minigames.back_btn')}", callback_data="minigames_menu" ) ]) return InlineKeyboardMarkup(inline_keyboard=buttons) def create_progress_bar(remaining: int, total: int = SPEED_ROUND_TIME) -> str: """Создать прогресс-бар для таймера""" filled = int((remaining / total) * 10) empty = 10 - filled return "█" * filled + "░" * empty @router.message(Command("games")) async def cmd_games(message: Message, state: FSMContext): """Команда /games - показать меню мини-игр""" await state.clear() async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, message.from_user.id) if not user: await message.answer(t('ru', 'common.start_first')) return lang = get_user_lang(user) await message.answer( t(lang, 'minigames.menu_title'), reply_markup=get_minigames_menu_keyboard(lang) ) @router.callback_query(F.data == "minigames_menu") async def minigames_menu_callback(callback: CallbackQuery, state: FSMContext): """Показать меню мини-игр""" await callback.answer() await state.clear() async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) lang = get_user_lang(user) if user else 'ru' await callback.message.edit_text( t(lang, 'minigames.menu_title'), reply_markup=get_minigames_menu_keyboard(lang) ) @router.callback_query(F.data == "minigame_speed_round") async def speed_round_info(callback: CallbackQuery, state: FSMContext): """Показать информацию о игре Speed Round""" await callback.answer() async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) if not user: return lang = get_user_lang(user) learning_lang = user.learning_language or 'en' # Проверяем подписку с учётом даты окончания is_premium = getattr(user, 'is_premium', False) premium_until = getattr(user, 'premium_until', None) if is_premium and premium_until and premium_until < datetime.now(): is_premium = False # Подписка истекла # Проверяем, есть ли слова в словаре (для изучаемого языка) word_count = await VocabularyService.get_words_count(session, user.id, learning_lang=learning_lang) if word_count < 5: await callback.message.edit_text( t(lang, 'minigames.speed_round.not_enough_words', min=5, current=word_count), reply_markup=InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=f"⬅️ {t(lang, 'minigames.back_btn')}", callback_data="minigames_menu" )] ]) ) return # Показываем правила игры rules_text = t(lang, 'minigames.speed_round.rules', count=SPEED_ROUND_COUNT, time=SPEED_ROUND_TIME) # Добавляем информацию о режимах для премиум-пользователей if is_premium: rules_text += f"\n\n✨ {t(lang, 'minigames.speed_round.premium_hint')}" await callback.message.edit_text( f"⚡ {t(lang, 'minigames.speed_round.name')}\n\n{rules_text}", reply_markup=get_speed_round_start_keyboard(lang, is_premium) ) @router.callback_query(F.data == "speed_round_start_ai") async def speed_round_ai_warning(callback: CallbackQuery, state: FSMContext): """Показать предупреждение о работе AI режима""" await callback.answer() async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) lang = get_user_lang(user) if user else 'ru' # Показываем предупреждение о режиме AI warning_text = t(lang, 'minigames.speed_round.ai_mode_warning') keyboard = InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=f"✅ {t(lang, 'minigames.start_btn')}", callback_data="speed_round_start_ai_confirm" )], [InlineKeyboardButton( text=f"⬅️ {t(lang, 'minigames.back_btn')}", callback_data="minigame_speed_round" )] ]) await callback.message.edit_text(warning_text, reply_markup=keyboard) @router.callback_query(F.data.in_({"speed_round_start", "speed_round_start_simple", "speed_round_start_ai_confirm"})) async def speed_round_start(callback: CallbackQuery, state: FSMContext): """Начать игру Speed Round""" await callback.answer() # Определяем режим проверки use_ai_check = callback.data == "speed_round_start_ai_confirm" async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) if not user: return lang = get_user_lang(user) learning_lang = user.learning_language or 'en' translation_lang = user.translation_language or user.language_interface or 'ru' # Получаем слова из словаря пользователя со всеми переводами game_words = await VocabularyService.get_random_words_with_translations( session, user.id, count=SPEED_ROUND_COUNT, learning_lang=learning_lang ) if len(game_words) < 5: await callback.message.edit_text( t(lang, 'minigames.speed_round.not_enough_words', min=5, current=len(game_words)) ) return await state.update_data( game_words=game_words, current_round=0, score=0, correct_count=0, results=[], # Список результатов по раундам user_id=user.id, lang=lang, learning_lang=learning_lang, translation_lang=translation_lang, use_ai_check=use_ai_check, # Режим проверки round_start_time=None, message_id=None ) await state.set_state(SpeedRoundStates.playing) # Удаляем старое сообщение и начинаем игру await callback.message.delete() await show_speed_round_word(callback.message, state) async def show_speed_round_word(message: Message, state: FSMContext): """Показать текущее слово в игре""" data = await state.get_data() game_words = data.get('game_words', []) current_round = data.get('current_round', 0) score = data.get('score', 0) lang = data.get('lang', 'ru') if current_round >= len(game_words): # Игра окончена await finish_speed_round(message, state) return word_data = game_words[current_round] word = word_data['word'] transcription = word_data.get('transcription', '') # Формируем текст word_display = f"{word}" if transcription: word_display += f"\n[{transcription}]" text = ( f"⚡ {t(lang, 'minigames.speed_round.round', current=current_round + 1, total=len(game_words))}\n\n" f"{word_display}\n\n" f"⏱ {create_progress_bar(SPEED_ROUND_TIME)} {SPEED_ROUND_TIME} {t(lang, 'minigames.speed_round.seconds')}\n\n" f"🏆 {t(lang, 'minigames.speed_round.score')}: {score}" ) # Сохраняем время начала раунда await state.update_data( round_start_time=datetime.now().timestamp() ) await state.set_state(SpeedRoundStates.waiting_answer) # Отправляем сообщение sent_msg = await message.answer(text) await state.update_data(message_id=sent_msg.message_id, chat_id=message.chat.id) # Запускаем таймер asyncio.create_task(speed_round_timer(message.bot, state, sent_msg.chat.id, sent_msg.message_id)) async def speed_round_timer(bot, state: FSMContext, chat_id: int, message_id: int): """Таймер для раунда с обновлением прогресс-бара""" for remaining in range(SPEED_ROUND_TIME - 1, -1, -1): await asyncio.sleep(1) # Проверяем, всё ещё ли мы в состоянии ожидания ответа current_state = await state.get_state() if current_state != SpeedRoundStates.waiting_answer: return data = await state.get_data() if data.get('message_id') != message_id: return game_words = data.get('game_words', []) current_round = data.get('current_round', 0) score = data.get('score', 0) lang = data.get('lang', 'ru') if current_round >= len(game_words): return word_data = game_words[current_round] word = word_data['word'] transcription = word_data.get('transcription', '') word_display = f"{word}" if transcription: word_display += f"\n[{transcription}]" if remaining > 0: # Обновляем прогресс-бар text = ( f"⚡ {t(lang, 'minigames.speed_round.round', current=current_round + 1, total=len(game_words))}\n\n" f"{word_display}\n\n" f"⏱ {create_progress_bar(remaining)} {remaining} {t(lang, 'minigames.speed_round.seconds')}\n\n" f"🏆 {t(lang, 'minigames.speed_round.score')}: {score}" ) try: await bot.edit_message_text(text, chat_id=chat_id, message_id=message_id) except: pass else: # Время вышло await state.set_state(SpeedRoundStates.playing) # Сохраняем результат раунда (время вышло) results = data.get('results', []) results.append({ 'word': word_data['word'], 'correct_answer': word_data['translation'], 'user_answer': None, 'is_correct': False }) await state.update_data(current_round=current_round + 1, results=results) # Показываем правильный ответ try: await bot.edit_message_text( f"⏰ {t(lang, 'minigames.speed_round.time_up')}\n\n" f"{word_display}\n\n" f"✅ {t(lang, 'minigames.speed_round.correct_was')}: {word_data['translation']}", chat_id=chat_id, message_id=message_id ) except: pass await asyncio.sleep(1.5) # Следующий раунд try: msg = await bot.send_message(chat_id, "...") await msg.delete() # Создаём фиктивный Message для продолжения from aiogram.types import Chat, User as TgUser fake_message = Message( message_id=0, date=datetime.now(), chat=Chat(id=chat_id, type="private"), from_user=None, text="" ) fake_message._bot = bot await show_speed_round_word(fake_message, state) except Exception as e: pass @router.message(SpeedRoundStates.waiting_answer) async def speed_round_answer(message: Message, state: FSMContext): """Обработка ответа в игре Speed Round""" user_answer = message.text.strip() data = await state.get_data() game_words = data.get('game_words', []) current_round = data.get('current_round', 0) score = data.get('score', 0) correct_count = data.get('correct_count', 0) lang = data.get('lang', 'ru') round_start_time = data.get('round_start_time', datetime.now().timestamp()) old_message_id = data.get('message_id') chat_id = data.get('chat_id') use_ai_check = data.get('use_ai_check', False) user_id = data.get('user_id') learning_lang = data.get('learning_lang', 'en') translation_lang = data.get('translation_lang', 'ru') if current_round >= len(game_words): return word_data = game_words[current_round] correct_answer = word_data['translation'] # Вычисляем время ответа time_taken = datetime.now().timestamp() - round_start_time time_remaining = max(0, SPEED_ROUND_TIME - time_taken) # Переключаем состояние чтобы таймер остановился await state.set_state(SpeedRoundStates.playing) # Простая проверка по всем вариантам перевода из word_translations # AI проверка будет в конце игры для всех ответов сразу user_answer_lower = user_answer.lower().strip() all_translations = word_data.get('all_translations', [correct_answer.lower()]) is_correct = False for valid_translation in all_translations: # Проверяем точное совпадение или вхождение if (user_answer_lower == valid_translation or user_answer_lower in valid_translation.split(',') or valid_translation in user_answer_lower): is_correct = True break # Получаем текущие результаты results = data.get('results', []) if is_correct: # Начисляем очки round_points = POINTS_CORRECT + int(time_remaining * POINTS_SPEED_BONUS) score += round_points correct_count += 1 result_text = ( f"✅ {t(lang, 'minigames.speed_round.correct')}\n\n" f"➕ {round_points} {t(lang, 'minigames.speed_round.points')}\n" f"⏱ {time_taken:.1f} {t(lang, 'minigames.speed_round.seconds')}" ) else: result_text = ( f"❌ {t(lang, 'minigames.speed_round.wrong')}\n\n" f"✅ {t(lang, 'minigames.speed_round.correct_was')}: {correct_answer}" ) # Сохраняем результат раунда (AI проверка будет в конце) results.append({ 'word': word_data['word'], 'correct_answer': correct_answer, 'user_answer': user_answer, 'is_correct': is_correct, # Предварительный результат 'time_remaining': time_remaining # Сохраняем для пересчёта очков }) # Обновляем состояние await state.update_data( current_round=current_round + 1, score=score, correct_count=correct_count, results=results ) # Удаляем старое сообщение с вопросом try: await message.bot.delete_message(chat_id, old_message_id) except: pass # Показываем результат await message.answer(result_text) await asyncio.sleep(1) # Следующий раунд await show_speed_round_word(message, state) async def finish_speed_round(message: Message, state: FSMContext): """Завершение игры Speed Round""" data = await state.get_data() score = data.get('score', 0) correct_count = data.get('correct_count', 0) game_words = data.get('game_words', []) results = data.get('results', []) lang = data.get('lang', 'ru') use_ai_check = data.get('use_ai_check', False) user_id = data.get('user_id') learning_lang = data.get('learning_lang', 'en') translation_lang = data.get('translation_lang', 'ru') total = len(game_words) await state.clear() # AI проверка в конце игры (один запрос для всех ответов) if use_ai_check and results: # Отправляем сообщение о проверке checking_msg = await message.answer(f"🤖 {t(lang, 'minigames.speed_round.ai_checking')}...") # Собираем ответы для проверки (только те, где пользователь ответил) answers_to_check = [ { 'word': r['word'], 'correct_translation': r['correct_answer'], 'user_answer': r['user_answer'] } for r in results if r['user_answer'] ] if answers_to_check: # Проверяем все ответы одним запросом ai_results = await ai_service.check_translations_batch( answers=answers_to_check, source_lang=learning_lang, target_lang=translation_lang, user_id=user_id ) # Обновляем результаты и пересчитываем очки ai_idx = 0 score = 0 correct_count = 0 for result in results: if result['user_answer']: # Обновляем результат из AI проверки ai_result = ai_results[ai_idx] result['is_correct'] = ai_result['is_correct'] result['ai_feedback'] = ai_result.get('feedback', '') result['user_answer_meaning'] = ai_result.get('user_answer_meaning', '') ai_idx += 1 if result['is_correct']: # Пересчитываем очки time_remaining = result.get('time_remaining', 0) round_points = POINTS_CORRECT + int(time_remaining * POINTS_SPEED_BONUS) score += round_points correct_count += 1 else: # Время вышло - ответ неверный result['is_correct'] = False result['ai_feedback'] = '' result['user_answer_meaning'] = '' # Удаляем сообщение о проверке try: await checking_msg.delete() except: pass # Определяем результат accuracy = int((correct_count / total) * 100) if total > 0 else 0 if accuracy >= 90: emoji = "🏆" comment = t(lang, 'minigames.speed_round.result.excellent') elif accuracy >= 70: emoji = "🎉" comment = t(lang, 'minigames.speed_round.result.good') elif accuracy >= 50: emoji = "👍" comment = t(lang, 'minigames.speed_round.result.average') else: emoji = "💪" comment = t(lang, 'minigames.speed_round.result.practice') # Формируем список ответов answers_text = "" for result in results: if result['is_correct']: answers_text += f"✅ {result['word']} → {result['correct_answer']}" if use_ai_check and result.get('ai_feedback'): answers_text += f" ({result['ai_feedback']})" answers_text += "\n" else: user_ans = result['user_answer'] or "⏰" answers_text += f"❌ {result['word']} → {user_ans}" # Показываем значение ответа пользователя (что он на самом деле написал) if use_ai_check and result.get('user_answer_meaning'): answers_text += f" = {result['user_answer_meaning']}" answers_text += f" ({result['correct_answer']})" if use_ai_check and result.get('ai_feedback'): answers_text += f" ({result['ai_feedback']})" answers_text += "\n" # Добавляем пометку об AI проверке ai_badge = "🤖 " if use_ai_check else "" text = ( f"{emoji} {t(lang, 'minigames.speed_round.finished')}\n\n" f"🏆 {t(lang, 'minigames.speed_round.final_score')}: {score}\n" f"✅ {t(lang, 'minigames.speed_round.correct_answers')}: {correct_count}/{total}\n" f"🎯 {t(lang, 'minigames.speed_round.accuracy')}: {accuracy}%\n\n" f"📋 {ai_badge}{t(lang, 'minigames.speed_round.answers_list')}:\n" f"{answers_text}\n" f"{comment}" ) keyboard = InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=f"🔄 {t(lang, 'minigames.play_again')}", callback_data="speed_round_start" )], [InlineKeyboardButton( text=f"⬅️ {t(lang, 'minigames.back_btn')}", callback_data="minigames_menu" )], ]) await message.answer(text, reply_markup=keyboard) # ==================== MATCH GAME (Найди пару) ==================== def get_match_game_start_keyboard(lang: str) -> InlineKeyboardMarkup: """Клавиатура начала игры Match""" return InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=f"▶️ {t(lang, 'minigames.start_btn')}", callback_data="match_game_start" )], [InlineKeyboardButton( text=f"⬅️ {t(lang, 'minigames.back_btn')}", callback_data="minigames_menu" )] ]) @router.callback_query(F.data == "minigame_match") async def match_game_info(callback: CallbackQuery, state: FSMContext): """Показать информацию о игре Match""" await callback.answer() await state.clear() async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) if not user: return lang = get_user_lang(user) learning_lang = user.learning_language or 'en' # Проверяем, есть ли слова в словаре word_count = await VocabularyService.get_words_count(session, user.id, learning_lang=learning_lang) if word_count < MATCH_WORDS_COUNT: await callback.message.edit_text( t(lang, 'minigames.match_game.not_enough_words', min=MATCH_WORDS_COUNT, current=word_count), reply_markup=InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=f"⬅️ {t(lang, 'minigames.back_btn')}", callback_data="minigames_menu" )] ]) ) return # Показываем правила игры rules_text = t(lang, 'minigames.match_game.rules', count=MATCH_WORDS_COUNT) await callback.message.edit_text( f"🎯 {t(lang, 'minigames.match_game.name')}\n\n{rules_text}", reply_markup=get_match_game_start_keyboard(lang) ) @router.callback_query(F.data == "match_game_start") async def match_game_start(callback: CallbackQuery, state: FSMContext): """Начать игру Match""" await callback.answer() async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) if not user: return lang = get_user_lang(user) learning_lang = user.learning_language or 'en' # Получаем случайные слова из словаря game_words = await VocabularyService.get_random_words_with_translations( session, user.id, count=MATCH_WORDS_COUNT, learning_lang=learning_lang ) if len(game_words) < MATCH_WORDS_COUNT: await callback.message.edit_text( t(lang, 'minigames.match_game.not_enough_words', min=MATCH_WORDS_COUNT, current=len(game_words)) ) return # Создаём перемешанные списки words_list = [(i + 1, w['word']) for i, w in enumerate(game_words)] # (номер, слово) translations_list = [(chr(65 + i), w['translation']) for i, w in enumerate(game_words)] # (буква, перевод) # Перемешиваем переводы random.shuffle(translations_list) # Создаём правильные ответы (номер -> буква) correct_pairs = {} for i, word_data in enumerate(game_words): word_num = i + 1 translation = word_data['translation'] # Находим букву перевода в перемешанном списке for letter, trans in translations_list: if trans == translation: correct_pairs[word_num] = letter break await state.update_data( game_words=game_words, words_list=words_list, translations_list=translations_list, correct_pairs=correct_pairs, user_id=user.id, lang=lang, start_time=datetime.now().timestamp() ) await state.set_state(MatchGameStates.waiting_answer) # Формируем текст игры game_text = format_match_game_text(lang, words_list, translations_list) keyboard = InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=f"❌ {t(lang, 'minigames.match_game.cancel')}", callback_data="match_game_cancel" )] ]) await callback.message.edit_text(game_text, reply_markup=keyboard) def format_match_game_text(lang: str, words_list: list, translations_list: list) -> str: """Форматировать текст игры Match""" text = f"🎯 {t(lang, 'minigames.match_game.title')}\n\n" # Формируем две колонки text += f"{t(lang, 'minigames.match_game.words_col')}:\n" for num, word in words_list: text += f" {num}. {word}\n" text += f"\n{t(lang, 'minigames.match_game.translations_col')}:\n" for letter, translation in translations_list: text += f" {letter}. {translation}\n" text += f"\n💡 {t(lang, 'minigames.match_game.hint')}" return text @router.callback_query(F.data == "match_game_cancel") async def match_game_cancel(callback: CallbackQuery, state: FSMContext): """Отменить игру Match""" await callback.answer() await state.clear() async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) lang = get_user_lang(user) if user else 'ru' await callback.message.edit_text( t(lang, 'minigames.match_game.cancelled'), reply_markup=InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=f"⬅️ {t(lang, 'minigames.back_btn')}", callback_data="minigames_menu" )] ]) ) @router.message(MatchGameStates.waiting_answer) async def match_game_answer(message: Message, state: FSMContext): """Обработка ответа в игре Match""" user_input = message.text.strip().upper() data = await state.get_data() correct_pairs = data.get('correct_pairs', {}) words_list = data.get('words_list', []) translations_list = data.get('translations_list', []) game_words = data.get('game_words', []) lang = data.get('lang', 'ru') start_time = data.get('start_time', datetime.now().timestamp()) # Парсим ответ пользователя # Ожидаемый формат: 1A, 2B, 3C или 1A 2B 3C или 1-A, 2-B import re pairs_pattern = r'(\d+)\s*[-]?\s*([A-Z])' user_pairs_raw = re.findall(pairs_pattern, user_input) # Преобразуем в словарь user_pairs = {} for num_str, letter in user_pairs_raw: num = int(num_str) if 1 <= num <= len(words_list): user_pairs[num] = letter # Проверяем, достаточно ли пар введено if len(user_pairs) < len(correct_pairs): await message.answer( t(lang, 'minigames.match_game.not_all_pairs', entered=len(user_pairs), needed=len(correct_pairs)) ) return # Завершаем игру await state.clear() # Считаем время time_taken = datetime.now().timestamp() - start_time # Проверяем ответы correct_count = 0 results = [] for num, letter in correct_pairs.items(): word_data = game_words[num - 1] user_letter = user_pairs.get(num, '?') is_correct = user_letter == letter if is_correct: correct_count += 1 results.append({ 'num': num, 'word': word_data['word'], 'translation': word_data['translation'], 'correct_letter': letter, 'user_letter': user_letter, 'is_correct': is_correct }) # Вычисляем очки score = correct_count * MATCH_POINTS_PER_PAIR total = len(correct_pairs) accuracy = int((correct_count / total) * 100) if total > 0 else 0 # Определяем результат if accuracy == 100: emoji = "🏆" comment = t(lang, 'minigames.match_game.result.perfect') elif accuracy >= 80: emoji = "🎉" comment = t(lang, 'minigames.match_game.result.excellent') elif accuracy >= 60: emoji = "👍" comment = t(lang, 'minigames.match_game.result.good') else: emoji = "💪" comment = t(lang, 'minigames.match_game.result.practice') # Формируем список результатов results_text = "" for r in results: if r['is_correct']: results_text += f"✅ {r['num']}. {r['word']} → {r['correct_letter']}. {r['translation']}\n" else: results_text += f"❌ {r['num']}. {r['word']} → {r['user_letter']} ({r['correct_letter']}. {r['translation']})\n" text = ( f"{emoji} {t(lang, 'minigames.match_game.finished')}\n\n" f"🏆 {t(lang, 'minigames.match_game.score')}: {score}\n" f"✅ {t(lang, 'minigames.match_game.correct_pairs')}: {correct_count}/{total}\n" f"⏱ {t(lang, 'minigames.match_game.time')}: {time_taken:.1f} {t(lang, 'minigames.speed_round.seconds')}\n\n" f"📋 {t(lang, 'minigames.match_game.results')}:\n" f"{results_text}\n" f"{comment}" ) keyboard = InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=f"🔄 {t(lang, 'minigames.play_again')}", callback_data="match_game_start" )], [InlineKeyboardButton( text=f"⬅️ {t(lang, 'minigames.back_btn')}", callback_data="minigames_menu" )], ]) await message.answer(text, reply_markup=keyboard)