Skip to content

Quiz Attempt & Auto Grading 5.4#25

Open
1000jae wants to merge 8 commits intomainfrom
sprint5/quiz-attempt
Open

Quiz Attempt & Auto Grading 5.4#25
1000jae wants to merge 8 commits intomainfrom
sprint5/quiz-attempt

Conversation

@1000jae
Copy link
Collaborator

@1000jae 1000jae commented Mar 15, 2026

Pull Request: Submit Quiz Attempt Endpoint

  • 🎉 New feature (Extends application, non-breaking feature)

PR Summary

Allow users to submit quiz answers to /api/v1/quiz/attempt, automatically grade their attempt, store the score and per-question correctness, and award XP.

Overview

  • What feature/problem does this PR address?
    Users need to submit quiz answers, have them graded automatically, see an accurate score and per-question results, have the attempt and score stored, receive XP, and have the activity recorded for gamification and history.

  • What approach was taken?

    • Created api/v1/quiz/attempt endpoint that takes in the quiz_id and answer per question.
    • Implemented grading logic to:
      • Compare submitted answers against stored quiz questions.
      • Calculate total_correct, total_questions, and a percentage score.
      • Compute XP with a per-correct value and a perfect-score bonus.
    • XP calculation: 25 XP for each correct answer and 15 bonus XP for perfect score.
    • Persisted:
      • A quiz_attempt row with the final score, counts, XP, and full per-question results.
      • A user_activity entry for the "quiz_attempt" event, linked back to the attempt and quiz.
      • An XP increment via a stored procedure for the user, when XP is earned.
    • Added edge-case validation around:
      • Missing or non-list answers.
      • Mismatched answer count vs. number of questions.
      • Duplicate or missing question indices.
      • Answers that are not valid options for their corresponding question.
    • Updated frontend to call the api/v1/quiz endpoint to generate list of quiz questions and api/v1/quiz/attempt to submit a quiz attempt by the user and save it to the database.
  • Any important design decisions or trade-offs?

    • Strict validation is used to prevent corrupt or partial attempts from being stored and to provide clear API errors to clients.
    • XP effects are non-fatal: failures during XP increment or activity logging are logged but do not invalidate a successful quiz submission.
    • Typed models and helpers are used to keep grading, XP calculation, and persistence logic isolated and easier to test.
  • Frontend: quiz is generated and displayed only when the user clicks on the generate quiz button. The quiz is submitted and provides the correct answers and the score only when the user answers all the questions and clicks on the 'submit quiz' button. Users can get a new set of quiz when they click on the 'regenerate quiz' button.

Checklist

  • Added a clear description
  • Included evidence of Unit Testing
  • Updated documentation (if needed)

Unit Test Evidence

tests/test_submit_quiz.py::TestCalcXP::test_correct_out_of_one_includes_bonus PASSED [  2%]
tests/test_submit_quiz.py::TestCalcXP::test_all_wrong_returns_zero PASSED [  5%]
tests/test_submit_quiz.py::TestCalcXP::test_all_correct PASSED [  8%]
tests/test_submit_quiz.py::TestCalcXP::test_partial_correct_no_bonus PASSED [ 11%]
tests/test_submit_quiz.py::TestGradeQuiz::test_correct_result_fields PASSED [ 14%]
tests/test_submit_quiz.py::TestGradeQuiz::test_incorrect_result_fields PASSED [ 17%]
tests/test_submit_quiz.py::TestGradeQuiz::test_result_fields_type PASSED [ 20%]
tests/test_submit_quiz.py::TestScoreCalculation::test_all_correct_answers PASSED [ 23%]
tests/test_submit_quiz.py::TestScoreCalculation::test_all_wrong_answers PASSED [ 26%]
tests/test_submit_quiz.py::TestScoreCalculation::test_partial_correct_answers PASSED [ 29%]
tests/test_submit_quiz.py::TestScoreCalculation::test_score_decimal PASSED [ 32%]
tests/test_submit_quiz.py::TestPerQuestionResults::test_number_of_results PASSED [ 35%]
tests/test_submit_quiz.py::TestPerQuestionResults::test_result_all_correct PASSED [ 38%]
tests/test_submit_quiz.py::TestPerQuestionResults::test_result_all_wrong PASSED [ 41%]
tests/test_submit_quiz.py::TestAwardXP::test_award_xp_all_correct PASSED [ 44%]
tests/test_submit_quiz.py::TestAwardXP::test_award_xp_all_wrong PASSED [ 47%]
tests/test_submit_quiz.py::TestAwardXP::test_award_xp_partial_correct PASSED [ 50%]
tests/test_submit_quiz.py::TestAwardXP::test_rpc_called_when_xp_positive PASSED [ 52%]
tests/test_submit_quiz.py::TestAwardXP::test_rpc_not_called_when_xp_zero PASSED [ 55%]
tests/test_submit_quiz.py::TestAwardXP::test_xp_rpc_failure_is_non_fatal PASSED [ 58%]
tests/test_submit_quiz.py::TestAwardXP::test_activity_failure_is_non_fatal PASSED [ 61%]
tests/test_submit_quiz.py::TestInputValidation::test_less_answers PASSED [ 64%]
tests/test_submit_quiz.py::TestInputValidation::test_more_answers PASSED [ 67%]
tests/test_submit_quiz.py::TestInputValidation::test_duplicate_answers PASSED [ 70%]
tests/test_submit_quiz.py::TestInputValidation::test_answer_not_in_option PASSED [ 73%]
tests/test_submit_quiz.py::TestInputValidation::test_missing_quiz_id_field PASSED [ 76%]
tests/test_submit_quiz.py::TestInputValidation::test_missing_answers_field PASSED [ 79%]
tests/test_submit_quiz.py::TestInputValidation::test_wrong_type_answers_field PASSED [ 82%]
tests/test_submit_quiz.py::TestInputValidation::test_empty_answers_list PASSED [ 85%]
tests/test_submit_quiz.py::TestInputValidation::test_empty_selected_answer_rejected PASSED [ 88%]
tests/test_submit_quiz.py::TestInputValidation::test_selected_answer_not_string PASSED [ 91%]
tests/test_submit_quiz.py::TestInputValidation::test_quiz_index_out_of_range PASSED [ 94%]
tests/test_submit_quiz.py::TestQuizLookupFailures::test_quiz_not_found PASSED [ 97%]
tests/test_submit_quiz.py::TestQuizLookupFailures::test_quiz_db_failure PASSED [100%]

================== 34 passed in 1.17s ==================

Testing Method

cd backend
source venv/bin/activate  # for macOS/Linux

# Install dependencies
pip install -r requirements.txt

# Run unit tests (no API calls)
venv/bin/python -m pytest tests/test_submit_quiz.py -v

Additional Notes

  • Update the quiz genereation endpoint to save the quiz questions to supabase which was not implemented before.

Jira Ticket

Jira Ticket(s) - [SOC-29]

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@1000jae 1000jae requested a review from Arhum2 March 19, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant