From 03cfa68bf369f992e46b64625af2eba253ece7c2 Mon Sep 17 00:00:00 2001 From: SylorHuang Date: Thu, 22 Aug 2019 10:16:26 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E7=9A=84=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=AD=94=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exercise_questions_controller.rb | 169 ++++++++++-------- app/helpers/exercises_helper.rb | 78 +++++++- 2 files changed, 169 insertions(+), 78 deletions(-) diff --git a/app/controllers/exercise_questions_controller.rb b/app/controllers/exercise_questions_controller.rb index 75ada699d..2257250c9 100644 --- a/app/controllers/exercise_questions_controller.rb +++ b/app/controllers/exercise_questions_controller.rb @@ -178,6 +178,7 @@ class ExerciseQuestionsController < ApplicationController def update ActiveRecord::Base.transaction do begin + standard_answer_change = false # 更新试卷题目的内容 question_options = { :question_title => params[:question_title], @@ -227,96 +228,103 @@ class ExerciseQuestionsController < ApplicationController if standard_answer.present? if @exercise_question.question_type <= Exercise::JUDGMENT #选择题/判断题,标准答案为一个或多个 exercise_standard_choices = @exercise_answers_array.pluck(:exercise_choice_id) #问题以前的全部标准答案选项位置 - common_standard_choices = standard_answer & exercise_standard_choices # 传入的标准答案的选项位置和以前的并集,即表示不用做更改的 - old_left_standard_choices = exercise_standard_choices - common_standard_choices # 以前的差集共同的,剩余的表示需要删掉 - new_left_standard_choices = standard_answer - common_standard_choices # 传入的标准答案差集共同的,剩余的表示需要新建 - if old_left_standard_choices.count > 0 - @exercise_answers_array.standard_by_ids(old_left_standard_choices).destroy_all - end - if new_left_standard_choices.count > 0 #新建标准答案 - new_left_standard_choices.each do |s| - standard_option = { - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => s.to_i #即为选择的位置参数 - } - question_standard_answer = ExerciseStandardAnswer.new(standard_option) - question_standard_answer.save + if exercise_standard_choices.sort != standard_answer.sort #表示答案有更改的 + standard_answer_change = true + common_standard_choices = standard_answer & exercise_standard_choices # 传入的标准答案的选项位置和以前的并集,即表示不用做更改的 + old_left_standard_choices = exercise_standard_choices - common_standard_choices # 以前的差集共同的,剩余的表示需要删掉 + new_left_standard_choices = standard_answer - common_standard_choices # 传入的标准答案差集共同的,剩余的表示需要新建 + if old_left_standard_choices.count > 0 + @exercise_answers_array.standard_by_ids(old_left_standard_choices).destroy_all end + if new_left_standard_choices.count > 0 #新建标准答案 + new_left_standard_choices.each do |s| + standard_option = { + :exercise_question_id => @exercise_question.id, + :exercise_choice_id => s.to_i #即为选择的位置参数 + } + question_standard_answer = ExerciseStandardAnswer.new(standard_option) + question_standard_answer.save + end - end - if standard_answer.count > 1 && @exercise_question.question_type == Exercise::SINGLE #当标准答案数大于1,且不为多选时,修改为多选 - @exercise_question.update_attribute("question_type",Exercise::MULTIPLE) - elsif standard_answer.count == 1 && @exercise_question.question_type == Exercise::MULTIPLE - @exercise_question.update_attribute("question_type",Exercise::SINGLE) + end + if standard_answer.count > 1 && @exercise_question.question_type == Exercise::SINGLE #当标准答案数大于1,且不为多选时,修改为多选 + @exercise_question.update_attribute("question_type",Exercise::MULTIPLE) + elsif standard_answer.count == 1 && @exercise_question.question_type == Exercise::MULTIPLE + @exercise_question.update_attribute("question_type",Exercise::SINGLE) + end end elsif @exercise_question.question_type == Exercise::COMPLETION #填空题 old_ex_answer = @exercise_question.exercise_standard_answers #当前问题的全部标准答案 - old_ex_answer_choice_ids = old_ex_answer.pluck(:exercise_choice_id).uniq #全部的答案数组序号 - new_ex_answer_choice_ids = standard_answer.map {|a| a[:choice_id]}.uniq #新传入的答案数组序号 - - #删除多余的选项 - if old_ex_answer_choice_ids.count > new_ex_answer_choice_ids.count #有减少的填空 - delete_ex_answer_choice_ids = old_ex_answer_choice_ids - new_ex_answer_choice_ids - old_ex_answer.standard_by_ids(delete_ex_answer_choice_ids).destroy_all - end - standard_answer.each do |aa| - null_choice_id = aa[:choice_id] - null_choice_text = aa[:answer_text] - null_choice_text_count = null_choice_text.count #当前传入的答案数量 - null_choice_text_count_array = (1..null_choice_text_count).to_a + old_ex_answer_choice_texts = old_ex_answer.pluck(:answer_text).uniq.sort + new_ex_answer_choice_texts = standard_answer.pluck(:answer_text).sum.uniq.sort + if old_ex_answer_choice_texts != new_ex_answer_choice_texts #填空题标准答案有更改时,才会更新标准答案 + new_ex_answer_choice_ids = standard_answer.map {|a| a[:choice_id]}.uniq #新传入的答案数组序号 + old_ex_answer_choice_ids = old_ex_answer.pluck(:exercise_choice_id).uniq #全部的答案数组序号 + standard_answer_change = true + #删除多余的选项 + if old_ex_answer_choice_ids.count > new_ex_answer_choice_ids.count #有减少的填空 + delete_ex_answer_choice_ids = old_ex_answer_choice_ids - new_ex_answer_choice_ids + old_ex_answer.standard_by_ids(delete_ex_answer_choice_ids).destroy_all + end + standard_answer.each do |aa| + null_choice_id = aa[:choice_id] + null_choice_text = aa[:answer_text] + null_choice_text_count = null_choice_text.count #当前传入的答案数量 + null_choice_text_count_array = (1..null_choice_text_count).to_a - ex_answer_pre = old_ex_answer.standard_by_ids(null_choice_id) #当前问题的全部答案 - ex_answer_pre_count = ex_answer_pre.count - ex_answer_pre_count_array = (1..ex_answer_pre_count).to_a + ex_answer_pre = old_ex_answer.standard_by_ids(null_choice_id) #当前问题的全部答案 + ex_answer_pre_count = ex_answer_pre.count + ex_answer_pre_count_array = (1..ex_answer_pre_count).to_a - if old_ex_answer_choice_ids.include?(null_choice_id) #以前的填空题答案包含有现在的填空序号 - if null_choice_text_count >= ex_answer_pre_count - new_add_choice = null_choice_text_count_array - ex_answer_pre_count_array - ex_answer_pre_count_array.each do |n| - standard_option = { - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => null_choice_id, - :answer_text => null_choice_text[n-1] - } - ex_answer_pre[n-1].update(standard_option) - end - if new_add_choice.count > 0 #表示有新增的 - new_add_choice.each do |i| + if old_ex_answer_choice_ids.include?(null_choice_id) #以前的填空题答案包含有现在的填空序号 + if null_choice_text_count >= ex_answer_pre_count + new_add_choice = null_choice_text_count_array - ex_answer_pre_count_array + ex_answer_pre_count_array.each do |n| standard_option = { :exercise_question_id => @exercise_question.id, :exercise_choice_id => null_choice_id, - :answer_text => null_choice_text[i-1] + :answer_text => null_choice_text[n-1] } - question_standard_answer = ExerciseStandardAnswer.new(standard_option) - question_standard_answer.save + ex_answer_pre[n-1].update(standard_option) + end + if new_add_choice.count > 0 #表示有新增的 + new_add_choice.each do |i| + standard_option = { + :exercise_question_id => @exercise_question.id, + :exercise_choice_id => null_choice_id, + :answer_text => null_choice_text[i-1] + } + question_standard_answer = ExerciseStandardAnswer.new(standard_option) + question_standard_answer.save + end + end + else + new_delete_choice = ex_answer_pre_count_array - null_choice_text_count_array + null_choice_text.each_with_index do |n,index| + standard_option = { + :exercise_question_id => @exercise_question.id, + :exercise_choice_id => null_choice_id, + :answer_text => n + } + ex_answer_pre[index].update(standard_option) + end + if new_delete_choice.count > 0 #表示填空题的答案有删减的 + new_delete_choice.each do |d| + ex_answer_pre[d-1].destroy + end end end else - new_delete_choice = ex_answer_pre_count_array - null_choice_text_count_array - null_choice_text.each_with_index do |n,index| + null_choice_text.each do |n| standard_option = { :exercise_question_id => @exercise_question.id, :exercise_choice_id => null_choice_id, :answer_text => n } - ex_answer_pre[index].update(standard_option) - end - if new_delete_choice.count > 0 #表示填空题的答案有删减的 - new_delete_choice.each do |d| - ex_answer_pre[d-1].destroy - end + question_standard_answer = ExerciseStandardAnswer.new(standard_option) + question_standard_answer.save end end - else - null_choice_text.each do |n| - standard_option = { - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => null_choice_id, - :answer_text => n - } - question_standard_answer = ExerciseStandardAnswer.new(standard_option) - question_standard_answer.save - end end end end @@ -348,20 +356,27 @@ class ExerciseQuestionsController < ApplicationController #当试卷已发布时(试卷的总状态),当标准答案修改时,如有已提交的学生,需重新计算分数. - if @exercise.exercise_status >= Exercise::PUBLISHED + if standard_answer_change && @exercise.exercise_status >= Exercise::PUBLISHED ex_users_committed = @exercise.exercise_users.exercise_user_committed if ex_users_committed.size > 0 ex_users_committed.each do |ex_user| - user = ex_user.user - objective_score = calculate_student_score(@exercise,user)[:total_score] - subjective_score = ex_user.subjective_score - total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score - total_score = objective_score + total_score_subjective_score - ex_user.update_attributes(objective_score:objective_score,score:total_score) + update_objective_score = update_single_score(@exercise_question,ex_user.user_id,standard_answer) + if update_objective_score != 0 + objective_score = ex_user.objective_score + subjective_score = ex_user.subjective_score + total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score + total_score = objective_score + update_objective_score + total_score_subjective_score + ex_user.update_attributes(objective_score:objective_score,score:total_score) + end + # user = ex_user.user + # objective_score = calculate_student_score(@exercise,user)[:total_score] end end + normal_status(0,"试卷更新成功,因标准答案修改,需重新计算学生成绩!") + else + normal_status(0,"试卷更新成功!") end - normal_status(0,"试卷更新成功!") + rescue Exception => e uid_logger_error(e.message) tip_exception("页面调用失败!") diff --git a/app/helpers/exercises_helper.rb b/app/helpers/exercises_helper.rb index baf594a42..d8a91f571 100644 --- a/app/helpers/exercises_helper.rb +++ b/app/helpers/exercises_helper.rb @@ -509,7 +509,7 @@ module ExercisesHelper end end user_scores = answers_content.blank? ? 0.0 : answers_content.score_reviewed.pluck(:score).sum - if user_scores > 0.0 + if user_scores > 0.0 stand_answer = 1 else stand_answer = 0 @@ -535,6 +535,82 @@ module ExercisesHelper } end + #当单个问题的分数更新时,更新用户的总分 + def update_single_score(q,user_id,standard_answer) + score1 = 0.0 #用户的新得分 + origin_score = 0.0 #用户的原来该问题的得分 + answers_content = q&.exercise_answers&.where(user_id: user_id) #学生的答案 + if answers_content.present? #用户回答了该题,才会改分数 + if q.question_type <= 2 #为选择题或判断题时 + origin_score = answers_content.first.score + answer_choice_array = [] + answers_content.each do |a| + answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置 + end + user_answer_content = answer_choice_array.sort + + #TODO: 旧版多选题的标准答案是放在一个里面的,新版又做成了一个题有多个标准答案(exercise_choice_id存放的是标准答案的位置..) + if q.question_type == 1 && standard_answer.size == 1 + standard_answer = standard_answer.first.to_s.split("").map(&:to_i) + end + + if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分 + if standard_answer.size > 0 + q_score_1 = q.question_score + else + q_score_1 = 0.0 + end + answers_content.update_all(:score => q_score_1) + score1 = q_score_1 + else + answers_content.update_all(:score => -1.0) + end + elsif q.question_type == 3 #填空题 + origin_score = answers_content.score_reviewed.pluck(:score).sum + + standard_answer_count = standard_answer.count + if standard_answer_count > 0 #存在标准答案时才有分数 + q_score_2 = (q.question_score.to_f / standard_answer_count) #每一空的得分 + else + q_score_2 = 0.0 + end + if q.is_ordered + answers_content.each do |u| + i_standard_answer = [] + standard_answer.each do |a| + if a[:choice_id] == u.exercise_choice_id + i_standard_answer += a[:answer_text] + end + end + i_standard_answer = i_standard_answer.map(&:downcase) + if i_standard_answer.include?(u.answer_text.downcase) #该空的标准答案包含用户的答案才有分数 + u.update_column('score',q_score_2) + score1 = score1 + q_score_2 + else + u.update_column('score',-1.0) + score1 += 0.0 + end + end + else + st_answer_text = standard_answer.pluck(:answer_text).sum.map(&:downcase) + answers_content.each do |u| + u_answer_text = u.answer_text.downcase + if st_answer_text.include?(u_answer_text) #只要标准答案包含用户的答案,就有分数。同时,下一次循环时,就会删除该标准答案。防止用户的相同答案获分 + u.update_column("score",q_score_2) + score1 = score1 + q_score_2 + st_answer_text.delete(u_answer_text) + else + u.update_column('score',-1.0) + score1 += 0.0 + end + end + end + end + end + origin_score = origin_score < 0.0 ? 0.0 : origin_score + score1 - origin_score + end + #获取用户的相关信息 def exercise_use_info(ex_user,user_status,exercise) course = exercise.course