Spaces:
Running
Running
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| from quiz.models import QuizSession | |
| from quiz.scoring import xp_for_question, streak_label, compute_grade | |
| 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)) | |