CSC/ECE 517 Fall 2023 - E2376. Reimplement student quizzes controller.rb

From Expertiza_Wiki
Jump to navigation Jump to search

Overview

Our team is tasked with creating the backend reimplementation of the student quizzes controller found in student_quizzes_controller.rb. We are to use SOLID principles and adhere to the Guidelines for Reimplementation.

Introduction To Expertiza System

The Expertiza system, a modular and multifunctional platform, empowers students to seamlessly submit assignments and quizzes while facilitating collaborative learning through features like peer review. Widely embraced by students, assistants, and professors, this advanced system streamlines academic assessments, fostering an efficient and interactive educational experience.

The main goal of student quizzes module is to give an environment for students to create quizzes for other students with same assignments, giving them a chance to learn in a collaborative setting where they can collectively enhance their understanding and support each other's learning journey.

Issues with Previous Functionality

Student quizzes are currently a discontinued function from Expertiza. This module orginally interacted with many other components such as questions and questionnaires. The complex structure along with faulty coding practices has resulted in a vulnerable and error prone system. With reimplementing student quizzes we believe many of those problems can be overcome.

Previous implementations of student quizzes were difficult to understand due to:

  • The controller not following CRUD methodology
  • The controller using vague names for variables.
  • Difficulty in setting up a sample quiz and testing
  • Test Driven Development (TDD) was not followed and tests created after the code. The code being in a unknown state led to tests that passed possibly buggy code.

Design

The student_quizzes_controller is responsible for creating, scoring, and recording responses to quizzes of reviewers. Reviewers are students of other teams with the same assignment.

A student can author a Questionnaire composed of many Questions.

The student_quizzes_controller shall assign a Questionnaire to a reviewing student that is not the author. The reviewing student shall take the quiz by answering the Questions in the chosen Questionnaire. The reviewing student will submit their answers and receive a score upon finishing.

Test Driven Development (TDD)

Our approach to developing Expertiza student quizzes will adhere to a test-driven design methodology. This means that we will be utilizing the test skeletons provided to us and tests for each component of the student quizzes module before implementing the corresponding functionalities. By following this rigorous testing approach, we ensure a reliable and thoroughly validated system, enhancing the overall quality and robustness of the Expertiza platform.

Objectives

  • Create: This operation involves the creation of new student quizzes, allowing instructors to input question numbers, set parameters, and establish quiz details. Currently, student_quizzes_controller does not have a direct create method.
  • Read: Enables users to retrieve and view existing student quizzes, accessing details such as questions, answers, and associated information for review or analysis. Currently, student_quizzes_controller does not have a direct read method.
  • Update: This operation allows users to modify or update student quizzes. It includes functionalities such as adjusting quiz parameters to keep content current and relevant. Currently, student_quizzes_controller does not have a direct update method.
  • Delete: Involves the removal of unwanted or outdated student quizzes, giving instructors the ability to manage and maintain the database of quizzes efficiently. Currently, student_quizzes_controller does not have a direct delete method.
  • Index: Index function is part of a controller action responsible for displaying information related to an assignment participant, their associated assignment, and quiz mappings for review. The code does currently have an index function, but the function will be optimized and made clearer for ease of understanding.
  • Calculate score: Calculate score function calculates the score of the participant by comparing the answers given by the users with the actual correct answers. This method will be optimized and edited to increase robustness. This will be a private method.
  • Other functions: Currently Student quizzes have many functions, while some of them are useful and beneficial, some of them can be edited, moved or reimplemented to follow SOLID and DRY principles. Other methods added to the controller outside of CRUD methods will be private methods.

Test Plan

  • cURL shall be used to simulate HTTP requests
  • Only an Instructor shall create a test
  • Only a Participating Student shall take the quiz
  • The JSON response of a Student taking a quiz shall be the score
  • The Student shall be able to look at score of previous responses

Implementation

student_quizzes_controller.rb

module Api

 module V1
   class StudentQuizzesController < ApplicationController
     before_action :authenticate_request!
     before_action :check_instructor_role, except: [:submit_answers]
     before_action :set_student_quiz, only: [:show, :edit, :update, :destroy]


     # GET /student_quizzes
     def index
       @quizzes = Questionnaire.all
       render json: @quizzes
     end
     # GET /student_quizzes/:id
     def show
       render json: @student_quiz
     end
     # GET /student_quizzes/:id/calculate_score
     def calculate_score
       # Find the ResponseMap by its ID.
       # Make sure this ID is the ID of the ResponseMap, not the Questionnaire or the Participant.
       response_map = ResponseMap.find_by(id: params[:id])
       if response_map
         # Return the score of the ResponseMap
         render json: { score: response_map.score }, status: :ok
       else
         render json: { error: 'Attempt not found or you do not have permission to view this score.' }, status: :not_found
       end
     end
     # POST /student_quizzes/assign
     def assign_quiz_to_student
       participant = Participant.find(params[:participant_id])
       questionnaire = Questionnaire.find(params[:questionnaire_id])
       # Check if the quiz is already assigned
       existing_map = ResponseMap.find_by(
         reviewee_id: participant.user_id,
         reviewed_object_id: questionnaire.id
       )
       if existing_map
         render json: { error: "This student is already assigned to the quiz." }, status: :unprocessable_entity
         return
       end
       student_id = participant.user_id
       instructor_id = Assignment.find(questionnaire.assignment_id).instructor_id
       response_map = ResponseMap.new(
         reviewee_id: student_id,
         reviewer_id: instructor_id,
         reviewed_object_id: questionnaire.id
       )
       if response_map.save
         # Handle success
       else
         render json: { error: response_map.errors.full_messages.to_sentence }, status: :unprocessable_entity
       end
     end
     # POST /student_quizzes/create_questionnaire
     def create_questionnaire
       ActiveRecord::Base.transaction do
         questionnaire = Questionnaire.create!(questionnaire_params.except(:questions_attributes))
         questionnaire_params[:questions_attributes].each do |question_attributes|
           question = questionnaire.questions.create!(question_attributes.except(:answers_attributes))
           question_attributes[:answers_attributes].each do |answer_attributes|
             question.answers.create!(answer_attributes)
           end
         end
       end
     rescue ActiveRecord::RecordInvalid => e
       render json: { error: e.message }, status: :unprocessable_entity
     end
     # POST /student_quizzes/submit_answers
     # Method to submit answers for a quiz
     def submit_answers
       ActiveRecord::Base.transaction do
         # Find the existing ResponseMap for this user and questionnaire
         response_map = ResponseMap.find_by(
           reviewee_id: current_user.id,
           reviewed_object_id: params[:questionnaire_id]
         )
         # If no ResponseMap exists for the current user, do not proceed
         unless response_map
           render json: { error: "You are not assigned to take this quiz." }, status: :forbidden
           return
         end
         # Calculate the total score based on correct answers
         total_score = params[:answers].sum do |answer|
           question = Question.find(answer[:question_id])
           submitted_answer = answer[:answer_value]
           # Find or initialize the response for the question
           response = Response.find_or_initialize_by(
             response_map_id: response_map.id,
             question_id: question.id
           )
           response.submitted_answer = submitted_answer
           response.save!
           # Increment score if the answer is correct
           question.correct_answer == submitted_answer ? question.score_value : 0
         end
         # Update the score of the ResponseMap
         response_map.update!(score: total_score)
         render json: { total_score: total_score }, status: :ok
       end
     rescue ActiveRecord::RecordInvalid => e
       render json: { error: e.message }, status: :unprocessable_entity
     end
     # PATCH/PUT /student_quizzes/:id
     def update
       if @student_quiz.update(questionnaire_params)
         render json: @student_quiz
       else
         render json: @student_quiz.errors, status: :unprocessable_entity
       end
     end
     # DELETE /student_quizzes/:id
     def destroy
       @student_quiz.destroy
       head :no_content
     end
     private
     def set_student_quiz
       @student_quiz = Questionnaire.find(params[:id])
     end
     def questionnaire_params
       params.require(:questionnaire).permit(
         :name, :instructor_id, :min_question_score, :max_question_score, :assignment_id,
         questions_attributes: [:id, :txt, :question_type, :break_before, :correct_answer, :score_value,
                                answers_attributes: [:id, :answer_text, :correct]
         ]
       )
     end


     # New method to permit parameters for submitting answers
     def response_map_params
       params.require(:response_map).permit(:student_id, :questionnaire_id)
     end
     # Check for instructor
     def check_instructor_role
       unless current_user.role_id == 3
         render json: { error: 'Only instructors are allowed to perform this action' }, status: :forbidden
         return
       end
     end
   end
 end

end

Database Setup

1. Create an Institution

Open shell on the mysql server and run:

 mysql -u dev -pexpertiza
 use reimplementation_development;

Then run the followinginsert command:

 INSERT INTO institutions (name, created_at, updated_at) VALUES ('North Carolina State University', NOW(), NOW());

2. Obtain an Encrypted Password

Open a new terminal in the container reimplementation-back-end-app and run the following commands

 rails console
 BCrypt::Password.create('password123')

You should obtain a string like the following but it will not match:

 '$2a$12$TWct/jRMKbb1Pm1NtxKmPuAkk8IOIHnJyBaU4eiMQ5MjV41Se0AXG'

This will be placed as the password in the next step.

3. Create an Admin User

Now, in the mysql terminal run the following (replacing the ‘$2a…’ with the one generated in step 2)

 INSERT INTO users (name, email, password_digest, role_id, created_at, updated_at, full_name, institution_id) VALUES ('admin', 'admin2@example.com', '$2a$12$TWct/jRMKbb1Pm1NtxKmPuAkk8IOIHnJyBaU4eiMQ5MjV41Se0AXG', 1, NOW(), NOW(), 'admin admin', 1);

4. Create an Instructor User

Repeat step 2 for an Instructor. You will receive a different key generation even though the password is the same. (replacing the ‘$2a…’ with the one generated in step 2)

 INSERT INTO users (name, email, password_digest, role_id, created_at, updated_at, full_name, institution_id) VALUES ('instructor', 'instructor@example.com', '$2a$12$TWct/jRMKbb1Pm1NtxKmPuAkk8IOIHnJyBaU4eiMQ5MjV41Se0AXG', 3, NOW(), NOW(), 'instructor instructor’, 1);

4. Create an Student User

Repeat step 2 for an Instructor. You will receive a different key generation even though the password is the same. (replacing the ‘$2a…’ with the one generated in step 2)

 INSERT INTO users (name, email, password_digest, role_id, created_at, updated_at, full_name, institution_id) VALUES ('student', 'student@example.com', '$2a$12$TWct/jRMKbb1Pm1NtxKmPuAkk8IOIHnJyBaU4eiMQ5MjV41Se0AXG', 5, NOW(), NOW(), 'student student', 1);

5. Start the Server

At this point we can start the server to issue cURL commands once the server is running. Start rails server on port 3002

 rails s -p 3002

cURL Instructor Required Setup

1. Login as an Instructor and Get Bearer Token

Get bearer token first (for instructor):

 curl -X POST http://localhost:3002/login -H "Content-Type: application/json" -d '{"user_name": "instructor", "password": "password123"}'


Note: You can use curl commands from the Windows command prompt, but you cannot use single quotes. For example the above JSON command must be written for Windows:

 curl -X POST http://localhost:3002/login -H "Content-Type: application/json" -d “{\"user_name\": \"instructor\", \"password\": \"password123\"}”


Also, RubyMine has an option to construct HTTP requests from cURL commands. Tools->HTTP Client->Convert cURL to HTTP Request

Issuing the HTTP requests will return a Bearer Token that must be included while accessing other pages as an Instructor

2. Instructor Creates Course

Execute the following command. Make sure the Bearer Token matches what was obtained in step 1 when logging in as an instructor. Be sure the ids match the database ids for the instructor and the institution.

 curl -X POST http://localhost:3002/api/v1/courses \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwibmFtZSI6Imluc3RydWN0b3IiLCJmdWxsX25hbWUiOiJOZXcsIEluc3RydWN0b3IiLCJyb2xlIjoiSW5zdHJ1Y3RvciIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA2NjU5Mjh9.rr358F0ELeN0ypOu9YnFrZMhEKOiFJm_zZv7kerjgDyJf683uex9zc2ZOfIpUNjIkq6p81lgB8H0t6o22FtnCIroqxjpThx8pyg6bXd6mX6c5NCpXNl8avde2amguMXwgA64csBy0XjkFCXupVlx89YQ7VUtkF69IOUza4r3CfZjgn3cvP2Ync9JSZAPq3EGmMa3_bUEQQ4-B3B9Y9nsPV84tUK6g3d7VLZx-I1-r0g8HcDJzcWcfkDd2BdwcaMild8f0xH-MXZOL0C2-ZnCzglDX8LN3FvetKP05zEJd5El6rxtjvr7-Ozy9qrRvzHWAnryjR9jEF951I4kUKb0jQ" \
 -d '{
   "course": {
     "name": "Introduction to Ruby",
     "instructor_id": 2,
     "institution_id": 1,
     "directory_path": "/path/to/course_files"
   }
 }'


3. Instructor Creates An Assignment

Execute the following command. Make sure the Bearer Token matches what was obtained in step 1 when logging in as an instructor. Be sure the ids match the database ids for the instructor.

 curl -X POST http://localhost:3002/api/v1/assignments \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwibmFtZSI6Imluc3RydWN0b3IiLCJmdWxsX25hbWUiOiJOZXcsIEluc3RydWN0b3IiLCJyb2xlIjoiSW5zdHJ1Y3RvciIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA2NjU5Mjh9.rr358F0ELeN0ypOu9YnFrZMhEKOiFJm_zZv7kerjgDyJf683uex9zc2ZOfIpUNjIkq6p81lgB8H0t6o22FtnCIroqxjpThx8pyg6bXd6mX6c5NCpXNl8avde2amguMXwgA64csBy0XjkFCXupVlx89YQ7VUtkF69IOUza4r3CfZjgn3cvP2Ync9JSZAPq3EGmMa3_bUEQQ4-B3B9Y9nsPV84tUK6g3d7VLZx-I1-r0g8HcDJzcWcfkDd2BdwcaMild8f0xH-MXZOL0C2-ZnCzglDX8LN3FvetKP05zEJd5El6rxtjvr7-Ozy9qrRvzHWAnryjR9jEF951I4kUKb0jQ" \
 -d '{
   "assignment": {
     "name": "Test",
     "directory_path": "/path/to/assignment_files",
     "course_id": 1,  
     "instructor_id": 2,  
     "require_quiz": 1,  
     "num_quiz_questions": 5
   }
 }'

4. Instructor Adds a Student to the Assignment as a Participant

Execute the following command. Make sure the Bearer Token matches what was obtained in step 1 when logging in as an instructor. Be sure the ids match the database ids for the user and the assignment.

 curl -X POST http://localhost:3002/api/v1/participants \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MywibmFtZSI6InN0dWRlbnQiLCJmdWxsX25hbWUiOiJvbmUsIHN0dWRlbnQiLCJyb2xlIjoiU3R1ZGVudCIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA4NTI5NTV9.bSztjjVs28E90E0cuMNPQj6cBqcE6XIGPKILrFzgz5gtXgb5HoW9RtUza6oITpiDN_vEhSQvSvjfOgpnekaeEcimR3Ov1537fC7i-RsN6ExjjwO25E8v50I1ZkvYOYAnj_19LyYLs48tdap2bntR3Gfw0DpUG5lt4H-yyC94eVEOsIxi59KmRJPYzO53lFHTyjfIjlqp7DapWGc9gQ2H1D9QGrHB2hLdk0Yl46PAYDZPYN76N5FRVyslcCNwjbHXcFu88hOnphDxo26W6_2zrsyNaQrVtgk0NyxaSHQ0pZfQPHke7g94HMw5EzDH3lccB5hx1YStkdxYFxCYo_BapQ" \
 -d '{
   "participant": {
     "user_id": 4,
     "assignment_id": 2
   }
 }'

5. Instructor Makes a Sample Questionnaire

Execute the following command. Make sure the Bearer Token matches what was obtained in step 1 when logging in as an instructor. Be sure the ids match the database ids for the instructor and the assignment.

 curl -X POST http://localhost:3002/api/v1/student_quizzes/create_questionnaire \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwibmFtZSI6Imluc3RydWN0b3IiLCJmdWxsX25hbWUiOiJOZXcsIEluc3RydWN0b3IiLCJyb2xlIjoiSW5zdHJ1Y3RvciIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA4MDQxMTl9.oiaRp3AgE_9Fg_gtHO7-bK75zRw1RdU30bSzDojvB0VFNG_KgdxHPnCRRCHsKkupytpPKEU1w-u5-3UfiJtp2BQ7fWEgt3FKgBR0i2SdQKkG6_Qe99PHJEkVThcne6vqxsPN75voxh1cf2PADKUz3AG0lMzSB2NnIFdIDP98EPncIUVBpLKaZXukYjN6YDgKOer42YQgJpwlXnS9lUr85wvWKo0ouPdR0VHXwrxafTD5e_qyYUYTV3r5P8Bvh5za0Bds-HwHckFpAu0yB0kgS5a9ioFPSxHTCVzm_zCWLr9TDEbwlvJgmp4uaj2E_CkDS3hBFAiPHoEqtAuKuoVXqA" \
 -d '
 {
   "questionnaire": {
     "name": "General Knowledge Quiz",
     "instructor_id": 2,
     "min_question_score": 0,
     "max_question_score": 5,
     "assignment_id": 1,
     "questions_attributes": [
     {
       "txt": "What is the capital of France?",
       "question_type": "multiple_choice",
       "break_before": true,
       "correct_answer": "Paris",
       "score_value": 1,
       "answers_attributes": [
         { "answer_text": "Paris", "correct": true },
         { "answer_text": "Madrid", "correct": false },
         { "answer_text": "Berlin", "correct": false },
         { "answer_text": "Rome", "correct": false }
       ]
     },
     {
       "txt": "What is the largest planet in our solar system?",
       "question_type": "multiple_choice",
       "break_before": true,
       "correct_answer": "Jupiter",
       "score_value": 1,
       "answers_attributes": [
         { "answer_text": "Earth", "correct": false },
         { "answer_text": "Jupiter", "correct": true },
         { "answer_text": "Mars", "correct": false },
         { "answer_text": "Saturn", "correct": false }
       ]
     }
     // Add more questions as needed
     ]
   }
 }
 '

5. Instructor Assigns Participant to Questionnaire

Execute the following command. Make sure the Bearer Token matches what was obtained in step 1 when logging in as an instructor. Be sure the ids match the database ids for the participant and the questionnaire.

 curl -X POST http://localhost:3002/api/v1/student_quizzes/assign \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwibmFtZSI6Imluc3RydWN0b3IiLCJmdWxsX25hbWUiOiJOZXcsIEluc3RydWN0b3IiLCJyb2xlIjoiSW5zdHJ1Y3RvciIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA4MDQxMTl9.oiaRp3AgE_9Fg_gtHO7-bK75zRw1RdU30bSzDojvB0VFNG_KgdxHPnCRRCHsKkupytpPKEU1w-u5-3UfiJtp2BQ7fWEgt3FKgBR0i2SdQKkG6_Qe99PHJEkVThcne6vqxsPN75voxh1cf2PADKUz3AG0lMzSB2NnIFdIDP98EPncIUVBpLKaZXukYjN6YDgKOer42YQgJpwlXnS9lUr85wvWKo0ouPdR0VHXwrxafTD5e_qyYUYTV3r5P8Bvh5za0Bds-HwHckFpAu0yB0kgS5a9ioFPSxHTCVzm_zCWLr9TDEbwlvJgmp4uaj2E_CkDS3hBFAiPHoEqtAuKuoVXqA" \
 -d '
 {
   "participant_id": "3",
   "questionnaire_id": "8"
 }
 '

cURL Student Takes Questionnaire Quiz

1. Login as an Student and Get Bearer Token

 curl -X POST http://localhost:3002/login \
 -H "Content-Type: application/json" \
 -d '{"user_name": "student", "password": "password123"}'

Issuing the HTTP requests will return a Bearer Token that must be included while accessing other pages as a Student.

2. Student Takes Questionnaire Quiz

Execute the following command. Make sure the Bearer Token matches what was obtained in step 1 when logging in as a student. Be sure the ids match the database ids for the questionnaire and the questions.

 curl -X POST http://localhost:3002/api/v1/student_quizzes/submit_answers \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6NCwibmFtZSI6InN0dWRlbnQyIiwiZnVsbF9uYW1lIjoidHdvLCBzdHVkZW50Iiwicm9sZSI6Ikluc3RydWN0b3IiLCJpbnN0aXR1dGlvbl9pZCI6MSwiZXhwIjoxNzAwODYxMTQ5fQ.sILbToiWD_RxYts_LoIBV3x9nVsziZXE8yvlntEF8YBEyn3cIos87cdQAPYQeR5to0aNpnfTKZP7SEIQJVkFS8ucfjwqHHGRn_mMAwhsW9_muebEY-vVGlXLYlTbHJKcMcpjBeqDk620fcCfNFsOUsSaAw6Z_GA7KtxQtQU10C_XilfTSbzw-MNv7R_h2FmNs8qLqddsrDaGKsRJl_hG85incsRGoFOxT_qWGW68fjqVKkyypXesoXP_7eM8mCjsEwDUY_NBuy5oijy7S1KKvPnaYu9tWbhEh8mZF-AC3_yd9dFKWkHv-UxP-i_i1phyKVIhFbjzX-wMXg_SwtoQPw" \
 -d' 
 {
   "questionnaire_id": 7,
   "answers": [
     { "question_id": 15, "answer_value": "Madrid" },
     { "question_id": 16, "answer_value": "Jupiter" }

   ]
 }
 '

Submitting this POST will return a scored value in the JSON response. For example, the score_value for each answer is 1, but only one of the answers is correct (Madrid is incorrect). The JSON response will return a value of 1.

If we were to submit:

 curl -X POST http://localhost:3002/api/v1/student_quizzes/submit_answers \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6NCwibmFtZSI6InN0dWRlbnQyIiwiZnVsbF9uYW1lIjoidHdvLCBzdHVkZW50Iiwicm9sZSI6Ikluc3RydWN0b3IiLCJpbnN0aXR1dGlvbl9pZCI6MSwiZXhwIjoxNzAwODYxMTQ5fQ.sILbToiWD_RxYts_LoIBV3x9nVsziZXE8yvlntEF8YBEyn3cIos87cdQAPYQeR5to0aNpnfTKZP7SEIQJVkFS8ucfjwqHHGRn_mMAwhsW9_muebEY-vVGlXLYlTbHJKcMcpjBeqDk620fcCfNFsOUsSaAw6Z_GA7KtxQtQU10C_XilfTSbzw-MNv7R_h2FmNs8qLqddsrDaGKsRJl_hG85incsRGoFOxT_qWGW68fjqVKkyypXesoXP_7eM8mCjsEwDUY_NBuy5oijy7S1KKvPnaYu9tWbhEh8mZF-AC3_yd9dFKWkHv-UxP-i_i1phyKVIhFbjzX-wMXg_SwtoQPw" \
 -d' 
 {
   "questionnaire_id": 7,
   "answers": [
     { "question_id": 15, "answer_value": "Paris" },
     { "question_id": 16, "answer_value": "Jupiter" }

   ]
 }
 '

The JSON response will return a value of 2 since both values are correct.

Other Tests to Perform

You will need to login and obtain the appropriate Bearer token for the following sections.

Instructor Can Show All Quizzes

 curl -X GET http://localhost:3002/api/v1/student_quizzes \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MywibmFtZSI6InN0dWRlbnQiLCJmdWxsX25hbWUiOiJvbmUsIHN0dWRlbnQiLCJyb2xlIjoiU3R1ZGVudCIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA3OTM1MDZ9.xugyF5xcmTxFAzzQzLuBhK8lKyX1yVdbZEEYZUwBLssYgI7XNI68fCO5gQM7IClh1Y4TNDAZd6-GdunCh6uVkatEPB-PZF8XuQqX_-MfYIJYZCmEaTSCYdpK-OhGRf_pDOCCMI9rGDzy59-AEBI4--fDvW-e5-oeDekS1D7nz5lter5u2UMNb_tUAOSNPkOSm6ZeSFm9uoyLkaZsxzz4jNl8PMPWrh2wNLmVAX5fb9PWMo8Ua8OPiDDohFO6eouSq-WCydciYYuhjTjWvC3eVaNQfQqf6qD8UN2ClK8yZMSwPR14CNZeAr5zcz6z725Jpiim77v2bKK2RmC9n4N1_Q"

Instructor Can Show Details of A Specific Quiz

 curl -X GET http://localhost:3002/api/v1/student_quizzes/1 \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwibmFtZSI6Imluc3RydWN0b3IiLCJmdWxsX25hbWUiOiJOZXcsIEluc3RydWN0b3IiLCJyb2xlIjoiSW5zdHJ1Y3RvciIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA2NjU5Mjh9.rr358F0ELeN0ypOu9YnFrZMhEKOiFJm_zZv7kerjgDyJf683uex9zc2ZOfIpUNjIkq6p81lgB8H0t6o22FtnCIroqxjpThx8pyg6bXd6mX6c5NCpXNl8avde2amguMXwgA64csBy0XjkFCXupVlx89YQ7VUtkF69IOUza4r3CfZjgn3cvP2Ync9JSZAPq3EGmMa3_bUEQQ4-B3B9Y9nsPV84tUK6g3d7VLZx-I1-r0g8HcDJzcWcfkDd2BdwcaMild8f0xH-MXZOL0C2-ZnCzglDX8LN3FvetKP05zEJd5El6rxtjvr7-Ozy9qrRvzHWAnryjR9jEF951I4kUKb0jQ"

Instructor Can Delete a Specific Quiz

But it must not have any questions.

 curl -X DELETE \
 http://localhost:3002/api/v1/student_quizzes/7 \
 -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwibmFtZSI6Imluc3RydWN0b3IiLCJmdWxsX25hbWUiOiJOZXcsIEluc3RydWN0b3IiLCJyb2xlIjoiSW5zdHJ1Y3RvciIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA4MDQxMTl9.oiaRp3AgE_9Fg_gtHO7-bK75zRw1RdU30bSzDojvB0VFNG_KgdxHPnCRRCHsKkupytpPKEU1w-u5-3UfiJtp2BQ7fWEgt3FKgBR0i2SdQKkG6_Qe99PHJEkVThcne6vqxsPN75voxh1cf2PADKUz3AG0lMzSB2NnIFdIDP98EPncIUVBpLKaZXukYjN6YDgKOer42YQgJpwlXnS9lUr85wvWKo0ouPdR0VHXwrxafTD5e_qyYUYTV3r5P8Bvh5za0Bds-HwHckFpAu0yB0kgS5a9ioFPSxHTCVzm_zCWLr9TDEbwlvJgmp4uaj2E_CkDS3hBFAiPHoEqtAuKuoVXqA"

Student Can Get a Specific Quiz Attempt Score

(The id here (which is showing 14) is the id from the response_map linking to the students attempt)

 curl -X GET \
 http://localhost:3002/api/v1/student_quizzes/14/calculate_score \
 -H "Content-Type: application/json" -H "Authorization: Bearer yJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwibmFtZSI6Imluc3RydWN0b3IiLCJmdWxsX25hbWUiOiJOZXcsIEluc3RydWN0b3IiLCJyb2xlIjoiSW5zdHJ1Y3RvciIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA4MDQxMTl9.oiaRp3AgE_9Fg_gtHO7-bK75zRw1RdU30bSzDojvB0VFNG_KgdxHPnCRRCHsKkupytpPKEU1w-u5-3UfiJtp2BQ7fWEgt3FKgBR0i2SdQKkG6_Qe99PHJEkVThcne6vqxsPN75voxh1cf2PADKUz3AG0lMzSB2NnIFdIDP98EPncIUVBpLKaZXukYjN6YDgKOer42YQgJpwlXnS9lUr85wvWKo0ouPdR0VHXwrxafTD5e_qyYUYTV3r5P8Bvh5za0Bds-HwHckFpAu0yB0kgS5a9ioFPSxHTCVzm_zCWLr9TDEbwlvJgmp4uaj2E_CkDS3hBFAiPHoEqtAuKuoVXqA"

Student Can Update a Specific Quiz Answer

Also, make sure you pass the id of the question and the id of the answer you want to update.

 curl -X PUT http://localhost:3002/api/v1/student_quizzes/7 \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwibmFtZSI6Imluc3RydWN0b3IiLCJmdWxsX25hbWUiOiJOZXcsIEluc3RydWN0b3IiLCJyb2xlIjoiSW5zdHJ1Y3RvciIsImluc3RpdHV0aW9uX2lkIjoxLCJleHAiOjE3MDA4MDQxMTl9.oiaRp3AgE_9Fg_gtHO7-bK75zRw1RdU30bSzDojvB0VFNG_KgdxHPnCRRCHsKkupytpPKEU1w-u5-3UfiJtp2BQ7fWEgt3FKgBR0i2SdQKkG6_Qe99PHJEkVThcne6vqxsPN75voxh1cf2PADKUz3AG0lMzSB2NnIFdIDP98EPncIUVBpLKaZXukYjN6YDgKOer42YQgJpwlXnS9lUr85wvWKo0ouPdR0VHXwrxafTD5e_qyYUYTV3r5P8Bvh5za0Bds-HwHckFpAu0yB0kgS5a9ioFPSxHTCVzm_zCWLr9TDEbwlvJgmp4uaj2E_CkDS3hBFAiPHoEqtAuKuoVXqA" \
 -d '{
   "questionnaire": {
     "name": "Knowledge Quiz",
     "instructor_id": 2,
     "min_question_score": 0,
     "max_question_score": 5,
     "assignment_id": 1,
     "questions_attributes": [
     {
       "id": 15,
       "txt": "What is the capital of England?",
       "question_type": "multiple_choice",
       "break_before": true,
       "correct_answer": "London",
       "score_value": 1,
       "answers_attributes": [
         {
           "id": 35,
           "answer_text": "London",
           "correct": true
         }
       ]
      }
     ]
   }
 }'