from __future__ import annotations from dataclasses import dataclass from quiz.models import QuizSession from quiz.scoring import xp_for_question, streak_label, compute_grade @dataclass class AnswerResult: is_correct: bool correct_idx: int xp_delta: int streak_label: str grade: str was_boss: bool class QuizEngine: def submit_next(self, session: QuizSession, selected_idx: int) -> AnswerResult: """Submit answer for the current question (regular or boss — auto-detected via is_boss).""" if session.is_finished: raise RuntimeError("Cannot submit answer: session is finished.") question = session.current_question is_correct = (selected_idx == question.correct_idx) xp_delta = 0 if is_correct: session.score += 1 xp_delta = xp_for_question(question.difficulty, is_boss=question.is_boss) session.xp_earned += xp_delta if not question.is_boss: session.consecutive_correct += 1 else: session.consecutive_correct = 0 if question.topic not in session.wrong_topics: session.wrong_topics.append(question.topic) session.current_idx += 1 label = streak_label(session.consecutive_correct) grade = compute_grade(session.score, session.current_idx) return AnswerResult(is_correct=is_correct, correct_idx=question.correct_idx, xp_delta=xp_delta, streak_label=label, grade=grade, was_boss=question.is_boss) def final_grade(self, session: QuizSession) -> str: return compute_grade(session.score, len(session.questions))