Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2358. Refactor student_quizzes_controller.rb #2656

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ec0d595
Update student_quizzes_controller.rb
SteveEaston Oct 14, 2023
504d734
Test Skeletons for E2358. Refactor student_quizzes_controller.rb
mmustafaolmez Oct 15, 2023
7ad3e98
Create student_quizzes_controller_spec.rb
SteveEaston Oct 18, 2023
e9c57ea
Revert "Create student_quizzes_controller_spec.rb"
SteveEaston Oct 18, 2023
19e3016
Merge pull request #9 from mmustafaolmez/E2358.-Refactor-student_quiz…
SteveEaston Oct 18, 2023
16ba311
Update student_quizzes_controller.rb
SteveEaston Oct 18, 2023
ee7da62
Update student_quizzes_controller.rb
SteveEaston Oct 18, 2023
29b2b1a
Create the action_allowed? tests and verify functionality
Oct 19, 2023
34e027b
Merge branch 'main' of github.com:SteveEaston/expertiza into main
Oct 20, 2023
6f5b42a
Comment question added
Oct 21, 2023
015b4d2
First test in finished_quiz section working
Oct 22, 2023
6856747
Clean up. Still only passing first test.
Oct 22, 2023
f34c220
second test passing
Oct 22, 2023
2d2f92b
All finished_quiz skeleton tests passing
Oct 22, 2023
f183575
Add tests for StudentQuizzesController
Oct 24, 2023
bac796d
Edit tests for StudentQuizzesController
Oct 24, 2023
86360ff
Add logic to controller for test for invalid scores
Oct 24, 2023
7025402
take_quiz tests (except one)
Oct 25, 2023
bcda3be
test commit
yagmurbbayraktar Oct 25, 2023
0452381
finishded_quizzes variables changed
yagmurbbayraktar Oct 25, 2023
b84c703
Refactoring for github issues
yagmurbbayraktar Oct 27, 2023
a7fe8ad
All issues closed
yagmurbbayraktar Oct 27, 2023
2737d10
Merge branch 'rain_refactoring'
SteveEaston Oct 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 51 additions & 21 deletions app/controllers/student_quizzes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ def action_allowed?
end
end

# INDEX
# Finds an assignment participants
# Do not show assignment or quizzes if current user not a participant
# List assignments if participant involved as assignment's submitter or reviewer
def index
@participant = AssignmentParticipant.find(params[:id])
return unless current_user_id?(@participant.user_id)
Expand All @@ -21,79 +25,96 @@ def index
@quiz_mappings = QuizResponseMap.mappings_for_reviewer(@participant.id)
end


def finished_quiz
@response = Response.where(map_id: params[:map_id]).first
@participant_response = Response.where(map_id: params[:map_id]).first #What is the purpose of @response? I don't see it used anywhere else in this file.
#@participant_response is used in finished_quiz.html.erb
@response_map = QuizResponseMap.find(params[:map_id])
@questions = Question.where(questionnaire_id: @response_map.reviewed_object_id) # for quiz response map, the reivewed_object_id is questionnaire id
@quiz_questions = Question.where(questionnaire_id: @response_map.reviewed_object_id) # The reviewed_object_id is questionnaire_id for quiz response_map
@map = ResponseMap.find(params[:map_id])
@participant = AssignmentTeam.find(@map.reviewee_id).participants.first

@quiz_score = @response_map.quiz_score
end

# Create an array of candidate quizzes for current reviewer
def self.take_quiz(assignment_id, reviewer_id)
# Initialize an empty array to store quizzes
quizzes = []
# Find the participant with assignment_id and reviewer_id
reviewer = Participant.where(user_id: reviewer_id, parent_id: assignment_id).first
# Find review response maps of the reviewer
reviewed_team_response_maps = ReviewResponseMap.where(reviewer_id: reviewer.id)
# Iterate each review response map
reviewed_team_response_maps.each do |team_response_map_record|
reviewee_id = team_response_map_record.reviewee_id
reviewee_team = Team.find(reviewee_id) # reviewees should always be teams
# Check if the reviewee team is associated with the given assignment_id
next unless reviewee_team.parent_id == assignment_id

# Find the quiz quiz associated with the reviewee team's instructor
quiz_questionnaire = QuizQuestionnaire.where(instructor_id: reviewee_team.id).first

# if the reviewee team has created quiz
if quiz_questionnaire
quizzes << quiz_questionnaire unless quiz_questionnaire.taken_by? reviewer
end
end
# Return the array available of quizzes
quizzes
end

# the way 'answers' table store the results of quiz
def calculate_score(map, response)
questionnaire = Questionnaire.find(map.reviewed_object_id)
quiz = Questionnaire.find(map.reviewed_object_id)
scores = []
valid = true
questions = Question.where(questionnaire_id: questionnaire.id)
valid_flag = true # Flag to track if user responses are valid
questions = Question.where(questionnaire_id: quiz.id) # Get all questions of the quiz
questions.each do |question|
score = 0
# Get correct answer(s) for the question
correct_answers = QuizQuestionChoice.where(question_id: question.id, iscorrect: true)
ques_type = question.type
if ques_type.eql? 'MultipleChoiceCheckbox'
#Get the question type to grade (MultipleChoiceCheckbox, MultipleChoiceRadio or True/False)
question_type = question.type
#Grading logic for MultipleChoiceCheckbox
if question_type.eql? 'MultipleChoiceCheckbox'
#Checking if answer is blank
if params[question.id.to_s].nil?
valid = false
valid_flag = false
else
params[question.id.to_s].each do |choice|
# loop the quiz taker's choices and see if 1)all the correct choice are checked and 2) # of quiz taker's choice matches the # of the correct choices
correct_answers.each do |correct|
score += 1 if choice.eql? correct.txt
end
end
# Create Answer objects for each choice selected by the user and validate them
score = score == correct_answers.count && score == params[question.id.to_s].count ? 1 : 0
# for MultipleChoiceCheckbox, score =1 means the quiz taker have done this question correctly, not just make select this choice correctly.
# for MultipleChoiceCheckbox, score =1 means the quiz taker have done this question correctly, each_answer_score is set for each of the multiple answers selected
params[question.id.to_s].each do |choice|
new_score = Answer.new comments: choice, question_id: question.id, response_id: response.id, answer: score
valid = false unless new_score.valid?
scores.push(new_score)
each_answer_score = Answer.new comments: choice, question_id: question.id, response_id: response.id, answer: score
valid_flag = false unless each_answer_score.valid?
# Add the the each_answer_score object to the scores array
scores.push(each_answer_score)
end
end
else # TrueFalse and MultipleChoiceRadio
# TrueFalse and MultipleChoiceRadio logic
else
# Get the correct answer
correct_answer = correct_answers.first
# Check if user's response matches the correct answer, set score to 1 if correct, else 0
score = correct_answer.txt == params[question.id.to_s] ? 1 : 0
new_score = Answer.new comments: params[question.id.to_s], question_id: question.id, response_id: response.id, answer: score
valid = false if new_score.nil? || new_score.comments.nil? || new_score.comments.empty?
scores.push(new_score)
valid_flag = false if new_score.nil? || new_score.comments.nil? || new_score.comments.empty?
scores.push(new_score) # Add the Answer object to the scores array
end
end
if valid
# Check if all user responses are valid_flag
if valid_flag
scores.each(&:save)
redirect_to controller: 'student_quizzes', action: 'finished_quiz', map_id: map.id
#Show error if not all answers are done
else
response.destroy
flash[:error] = 'Please answer every question.'
redirect_to action: :take_quiz, assignment_id: params[:assignment_id], questionnaire_id: questionnaire.id, map_id: map.id
redirect_to action: :take_quiz, assignment_id: params[:assignment_id], questionnaire_id: quiz.id, map_id: map.id
end
end

Expand All @@ -107,7 +128,16 @@ def record_response
response.updated_at = DateTime.current
response.save

calculate_score map, response
score = calculate_score map, response

# Added logic to test for invalid scores to ensure redirect was happening
if score.to_i < 0
response.destroy # Assuming you want to destroy the response if the score is invalid
flash[:error] = 'An error occurred while calculating your score.'

redirect_to controller: 'student_quizzes', action: 'get_quiz_questionnaire' # or wherever we need to redirect for invalid score
end
# end of added logic
else
flash[:error] = 'You have already taken this quiz, below are the records for your responses.'
redirect_to controller: 'student_quizzes', action: 'finished_quiz', map_id: map.id
Expand Down
4 changes: 2 additions & 2 deletions app/views/student_quizzes/finished_quiz.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
<% i = 1 %>


<% @questions.each do |question| %>
<% @quiz_questions.each do |question| %>
<b>Question <%= i %>: </b><%= label_tag "#{question.id}", question.txt %> <br>

<%user_answer=Answer.where(response_id: @response.id, question_id: question.id)%>
<%user_answer=Answer.where(response_id: @participant_response.id, question_id: question.id)%>
<%= question.view_completed_question(user_answer) %><br>
<% i += 1 %>
<%end%>
Expand Down