from aiogram import Router, F
from aiogram.filters import Command
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
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.task_service import TaskService
from services.ai_service import ai_service
router = Router()
class TaskStates(StatesGroup):
"""Состояния для прохождения заданий"""
doing_tasks = State()
waiting_for_answer = State()
@router.message(Command("task"))
async def cmd_task(message: Message, state: FSMContext):
"""Обработчик команды /task"""
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("Сначала запусти бота командой /start")
return
# Генерируем задания
tasks = await TaskService.generate_translation_tasks(session, user.id, count=5)
if not tasks:
await message.answer(
"📚 У тебя пока нет слов для практики!\n\n"
"Добавь несколько слов командой /add, а затем возвращайся."
)
return
# Сохраняем задания в состоянии
await state.update_data(
tasks=tasks,
current_task_index=0,
correct_count=0,
user_id=user.id
)
await state.set_state(TaskStates.doing_tasks)
# Показываем первое задание
await show_current_task(message, state)
async def show_current_task(message: Message, state: FSMContext):
"""Показать текущее задание"""
data = await state.get_data()
tasks = data.get('tasks', [])
current_index = data.get('current_task_index', 0)
if current_index >= len(tasks):
# Все задания выполнены
await finish_tasks(message, state)
return
task = tasks[current_index]
task_text = (
f"📝 Задание {current_index + 1} из {len(tasks)}\n\n"
f"{task['question']}\n"
)
if task.get('transcription'):
task_text += f"🔊 [{task['transcription']}]\n"
task_text += f"\n💡 Напиши свой ответ:"
await state.set_state(TaskStates.waiting_for_answer)
await message.answer(task_text)
@router.message(TaskStates.waiting_for_answer)
async def process_answer(message: Message, state: FSMContext):
"""Обработка ответа пользователя"""
user_answer = message.text.strip()
data = await state.get_data()
tasks = data.get('tasks', [])
current_index = data.get('current_task_index', 0)
correct_count = data.get('correct_count', 0)
user_id = data.get('user_id')
task = tasks[current_index]
# Показываем индикатор проверки
checking_msg = await message.answer("⏳ Проверяю ответ...")
# Проверяем ответ через AI
check_result = await ai_service.check_answer(
question=task['question'],
correct_answer=task['correct_answer'],
user_answer=user_answer
)
await checking_msg.delete()
is_correct = check_result.get('is_correct', False)
feedback = check_result.get('feedback', '')
# Формируем ответ
if is_correct:
result_text = f"✅ Правильно!\n\n"
correct_count += 1
else:
result_text = f"❌ Неправильно\n\n"
result_text += f"Твой ответ: {user_answer}\n"
result_text += f"Правильный ответ: {task['correct_answer']}\n\n"
if feedback:
result_text += f"💬 {feedback}\n\n"
# Сохраняем результат в БД
async with async_session_maker() as session:
await TaskService.save_task_result(
session=session,
user_id=user_id,
task_type=task['type'],
content={
'question': task['question'],
'word': task['word']
},
user_answer=user_answer,
correct_answer=task['correct_answer'],
is_correct=is_correct,
ai_feedback=feedback
)
# Обновляем статистику слова
if 'word_id' in task:
await TaskService.update_word_statistics(
session=session,
word_id=task['word_id'],
is_correct=is_correct
)
# Обновляем счетчик
await state.update_data(
current_task_index=current_index + 1,
correct_count=correct_count
)
# Показываем результат и кнопку "Далее"
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="➡️ Следующее задание", callback_data="next_task")]
])
await message.answer(result_text, reply_markup=keyboard)
@router.callback_query(F.data == "next_task", TaskStates.doing_tasks)
async def next_task(callback: CallbackQuery, state: FSMContext):
"""Переход к следующему заданию"""
await callback.message.delete()
await show_current_task(callback.message, state)
await callback.answer()
async def finish_tasks(message: Message, state: FSMContext):
"""Завершение всех заданий"""
data = await state.get_data()
tasks = data.get('tasks', [])
correct_count = data.get('correct_count', 0)
total_count = len(tasks)
accuracy = int((correct_count / total_count) * 100) if total_count > 0 else 0
# Определяем эмодзи на основе результата
if accuracy >= 90:
emoji = "🏆"
comment = "Отличный результат!"
elif accuracy >= 70:
emoji = "👍"
comment = "Хорошая работа!"
elif accuracy >= 50:
emoji = "📚"
comment = "Неплохо, продолжай практиковаться!"
else:
emoji = "💪"
comment = "Повтори эти слова еще раз!"
result_text = (
f"{emoji} Задание завершено!\n\n"
f"Правильных ответов: {correct_count} из {total_count}\n"
f"Точность: {accuracy}%\n\n"
f"{comment}\n\n"
f"Используй /task для нового задания\n"
f"Используй /stats для просмотра статистики"
)
await state.clear()
await message.answer(result_text)
@router.message(Command("stats"))
async def cmd_stats(message: Message):
"""Обработчик команды /stats"""
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("Сначала запусти бота командой /start")
return
# Получаем статистику
stats = await TaskService.get_user_stats(session, user.id)
stats_text = (
f"📊 Твоя статистика\n\n"
f"📚 Слов в словаре: {stats['total_words']}\n"
f"📖 Слов изучено: {stats['reviewed_words']}\n"
f"✍️ Заданий выполнено: {stats['total_tasks']}\n"
f"✅ Правильных ответов: {stats['correct_tasks']}\n"
f"🎯 Точность: {stats['accuracy']}%\n\n"
)
if stats['total_words'] == 0:
stats_text += "Добавь слова командой /add чтобы начать обучение!"
elif stats['total_tasks'] == 0:
stats_text += "Выполни первое задание командой /task!"
else:
stats_text += "Продолжай практиковаться! 💪"
await message.answer(stats_text)