diff --git a/app/models/quizzes/log_auditing/event_aggregator.rb b/app/models/quizzes/log_auditing/event_aggregator.rb index dc610ee5479..eae8a850976 100644 --- a/app/models/quizzes/log_auditing/event_aggregator.rb +++ b/app/models/quizzes/log_auditing/event_aggregator.rb @@ -85,7 +85,7 @@ module Quizzes::LogAuditing def build_submission_data_from_answers(answers) submission_data = {} answers.each do |question_id, answer| - question = quiz.quiz_questions.find { |qq| qq.id == question_id } + question = quiz.quiz_questions.find { |qq| qq.id == question_id.to_i } question = Quizzes::QuizQuestion.where(id: question_id).first unless question if question.question_data["question_type"] != "text_only_question" serializer = Quizzes::QuizQuestion::AnswerSerializers.serializer_for(question) diff --git a/lib/data_fixup/rebuild_quiz_submissions_from_quiz_submission_events.rb b/lib/data_fixup/rebuild_quiz_submissions_from_quiz_submission_events.rb index 322187b709e..d0826a31ead 100644 --- a/lib/data_fixup/rebuild_quiz_submissions_from_quiz_submission_events.rb +++ b/lib/data_fixup/rebuild_quiz_submissions_from_quiz_submission_events.rb @@ -114,6 +114,74 @@ module DataFixup::RebuildQuizSubmissionsFromQuizSubmissionEvents qs end + def self.pick_questions(qs, seen_question_ids) + # Parsing all the deets from events can do it though + quiz_group_picks = Hash.new {|h, k| h[k] = []} + quiz_group_pick_counts = {} + picked_questions = qs.quiz.stored_questions.select do |question| + if question["entry_type"] == "quiz_group" + group_name = question["id"] + quiz_group_pick_counts[group_name] = question["pick_count"] + matching_questions = question["questions"].select {|q| seen_question_ids.include? q["id"].to_s} + matching_questions.each {|q| q["points_possible"] = question["question_points"]} + quiz_group_picks[group_name] += matching_questions + false + else + true + end + end + + quiz_group_picks.each do |k,v| + qs.quiz.stored_questions.select {|q| q["id"] == k }.map do |question| + question["questions"].shuffle.each do |q| + break if v.count == quiz_group_pick_counts[k] + q["points_possible"] = question["question_points"] + v << q unless v.include? q + end + end + end + + picked_questions += quiz_group_picks.values.flatten + if qs.quiz.question_count != picked_questions.size + Rails.logger.error LOG_PREFIX + "#{qs.id} doesn't match it's question count" + end + picked_questions + end + + # Because we can't regenerate quiz data without getting a different set of questions, + # we need to select the quiz_questions from the questions we can know the student has + # seen. + def self.aggregate_quiz_data_from_events(qs, events) + question_events = events.select {|e| ["question_answered", "question_viewed", "question_flagged"].include?(e.event_type)} + seen_question_ids = [] + question_events.each do |event| + if event.event_type == "question_viewed" + seen_question_ids << event.answers + else + seen_question_ids << event.answers.flatten.map {|h| h["quiz_question_id"]} + end + end + seen_question_ids = seen_question_ids.flatten.uniq + + builder = Quizzes::QuizQuestionBuilder.new({ + shuffle_answers: qs.quiz.shuffle_answers + }) + + if seen_question_ids.count > 0 + picked_questions = pick_questions(qs, seen_question_ids) + + raw_data = builder.shuffle_quiz_data!(picked_questions) + raw_data.each_with_index do |question, index| + Quizzes::QuizQuestionBuilder.decorate_question_for_submission(question, index) + end + else + submission.quiz_data = begin + qs.quiz.stored_questions = nil + builder.build_submission_questions(qs.quiz.id, qs.quiz.stored_questions) + end + end + end + def self.build_new_submission_from_quiz_submission_events(submission) if submission.submission_type != "online_quiz" Rails.logger.warn LOG_PREFIX + "Skipping because this isn't a quiz!\tsubmission_id: #{submission.id}" @@ -160,14 +228,13 @@ module DataFixup::RebuildQuizSubmissionsFromQuizSubmissionEvents # This is sad because assumptions qs.quiz_version = qs.versions.map {|v| v.model.quiz_version}.sort.last + qs.quiz_data = aggregate_quiz_data_from_events(qs, events) # Set reasonable timestamps qs.created_at = submission.created_at qs.started_at = times.first qs.finished_at = submission.submitted_at - # Set internal data for grading - qs.quiz_data = submission.assignment.quiz.quiz_data qs.submission_data = submission_data_hash qs.save!