|
|
|
|
class ExerciseQuestionsController < ApplicationController
|
|
|
|
|
before_action :require_login #用户需登陆
|
|
|
|
|
before_action :get_exercise,only:[:new,:create] #获取试卷
|
|
|
|
|
before_action :get_exercise_question,except: [:new,:create] #获取试卷的问题及试卷
|
|
|
|
|
before_action :is_course_teacher #是否为老师
|
|
|
|
|
before_action :validate_params,only: [:create,:update] #传入参数的验证
|
|
|
|
|
before_action :check_exercise_status,only: [:new,:create,:delete_answer,:destroy] #除未发布状态之外,其余状态不能进行增删操作
|
|
|
|
|
before_action :cannot_change_column,only: [:update] #更新时不能更改的内容
|
|
|
|
|
before_action :check_adjust_score,only: [:adjust_score]
|
|
|
|
|
include ExercisesHelper
|
|
|
|
|
|
|
|
|
|
def new
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
@exercise_question = @exercise.exercise_questions.new
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("页面访问失败失败!")
|
|
|
|
|
raise ActiveRecord::Rollback
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#question_type 0为单选题,1为多选题,2为判断题,3为填空题(单空和多空),4为简答题,5为实训题
|
|
|
|
|
def create
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
question_options = {
|
|
|
|
|
:question_title => params[:question_title],
|
|
|
|
|
:question_type => params[:question_type].present? ? params[:question_type].to_i : 0, #默认为单选题
|
|
|
|
|
:question_number => @exercise.exercise_questions.count + 1,
|
|
|
|
|
:question_score => params[:question_score].present? ? params[:question_score].to_f.round(1) : 5.0,
|
|
|
|
|
:shixun_id => params[:shixun_id].blank? ? "" : params[:shixun_id],
|
|
|
|
|
:is_ordered => params[:is_ordered] # 填空题的答案是否为一一对应关系,默认为true即为一一对应
|
|
|
|
|
}
|
|
|
|
|
@exercise_question = @exercise.exercise_questions.new(question_options)
|
|
|
|
|
#插入问题时,那么从插入的这个id以后的question_num都将要+1
|
|
|
|
|
if params[:insert_id].present?
|
|
|
|
|
insert_exercise = @exercise.exercise_questions.find_by(id: params[:insert_id])
|
|
|
|
|
if insert_exercise.present? #如果该问题存在的话,意思是如果是第一题,那么就不存在插入
|
|
|
|
|
ques_num = insert_exercise.question_number.to_i
|
|
|
|
|
@exercise_question.question_number = ques_num + 1 #更新了问题的位置
|
|
|
|
|
@exercise.exercise_questions.insert_question_ex(ques_num).update_all("question_number = question_number + 1")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if @exercise_question.save
|
|
|
|
|
#为选择题(包括单选和多选)的时候,创建问题选项
|
|
|
|
|
ques_type = @exercise_question.question_type
|
|
|
|
|
if ques_type <= 1
|
|
|
|
|
choices_array = params[:question_choices]
|
|
|
|
|
choices_count= choices_array.count
|
|
|
|
|
standard_answer = params[:standard_answers] #为数组格式,因为可能会有单选和多选,标准答案,已提前判断不能为空,
|
|
|
|
|
standard_answer = standard_answer.uniq.reject(&:blank?)
|
|
|
|
|
(1..choices_count).each do |c|
|
|
|
|
|
choice = choices_array[c-1] #每一个选项的内容
|
|
|
|
|
choice_option = {
|
|
|
|
|
:choice_position => c,
|
|
|
|
|
:choice_text => choice.strip
|
|
|
|
|
}
|
|
|
|
|
question_choices = @exercise_question.exercise_choices.new(choice_option)
|
|
|
|
|
question_choices.save
|
|
|
|
|
end
|
|
|
|
|
#标准答案的存储,如:["1","2","3"..]等,1对应A,2对应B,3对应C。。。
|
|
|
|
|
standard_answer.each do |a|
|
|
|
|
|
choice_id = a.to_i
|
|
|
|
|
standard_option = {
|
|
|
|
|
:exercise_question_id => @exercise_question.id,
|
|
|
|
|
:exercise_choice_id => choice_id #即为选择的位置参数
|
|
|
|
|
}
|
|
|
|
|
question_standard_answer = ExerciseStandardAnswer.new(standard_option)
|
|
|
|
|
question_standard_answer.save
|
|
|
|
|
if standard_answer.count > 1 && ques_type == 0 #当标准答案数大于1,且不为多选时,修改为多选
|
|
|
|
|
@exercise_question.update_attribute("question_type",1)
|
|
|
|
|
elsif standard_answer.count == 1 && ques_type == 1
|
|
|
|
|
@exercise_question.update_attribute("question_type",0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
elsif ques_type == 2 #这个为判断题
|
|
|
|
|
choices_array = params[:question_choices] #判断的选项,对/错等等
|
|
|
|
|
choices_count= choices_array.count
|
|
|
|
|
(1..choices_count).each do |c|
|
|
|
|
|
choice = choices_array[c-1] #每一个选项的内容
|
|
|
|
|
choice_option = {
|
|
|
|
|
:choice_position => c,
|
|
|
|
|
:choice_text => choice.strip
|
|
|
|
|
}
|
|
|
|
|
question_choices = @exercise_question.exercise_choices.create(choice_option)
|
|
|
|
|
question_choices.save
|
|
|
|
|
end
|
|
|
|
|
standard_answer = params[:standard_answers] #对应选项的id
|
|
|
|
|
standard_option = {
|
|
|
|
|
:exercise_question_id => @exercise_question.id,
|
|
|
|
|
:exercise_choice_id => standard_answer.first.to_i
|
|
|
|
|
}
|
|
|
|
|
question_standard_answer = ExerciseStandardAnswer.new(standard_option)
|
|
|
|
|
question_standard_answer.save
|
|
|
|
|
elsif ques_type == 3 #填空题,每空的参考答案有多个,那么以位置对应
|
|
|
|
|
standard_answer = params[:standard_answers]
|
|
|
|
|
standard_answer.each do |a|
|
|
|
|
|
null_choice_id = a[:choice_id]
|
|
|
|
|
null_choice_text = a[:answer_text]
|
|
|
|
|
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
|
|
|
|
|
elsif ques_type == 4 #简答题
|
|
|
|
|
if params[:standard_answers].present? && params[:standard_answers].reject(&:blank?).count > 0
|
|
|
|
|
standard_answer = params[:standard_answers]
|
|
|
|
|
standard_answer.each do |a|
|
|
|
|
|
standard_option = {
|
|
|
|
|
:exercise_question_id => @exercise_question.id,
|
|
|
|
|
:answer_text => a,
|
|
|
|
|
}
|
|
|
|
|
question_standard_answer = ExerciseStandardAnswer.new(standard_option)
|
|
|
|
|
question_standard_answer.save
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
elsif ques_type == 5 #实训题
|
|
|
|
|
shixun = Shixun.find_by(id: params[:shixun_id])
|
|
|
|
|
shixun_scores = params[:question_scores] #试卷有多个的分值有多个分数表,所以为分数的数组
|
|
|
|
|
shixun_name = params[:shixun_name] || shixun.name
|
|
|
|
|
question_score = 0
|
|
|
|
|
shixun.challenges.try(:each_with_index) do |challenge,index|
|
|
|
|
|
shixun_option = {
|
|
|
|
|
:challenge_id => challenge.id,
|
|
|
|
|
:shixun_id => shixun.id,
|
|
|
|
|
:exercise_question_id => @exercise_question.id,
|
|
|
|
|
:position => (index + 1),
|
|
|
|
|
:question_score => shixun_scores[index].present? ? shixun_scores[index].to_f.round(1) : 5
|
|
|
|
|
}
|
|
|
|
|
ex_shixun_challenge = ExerciseShixunChallenge.create(shixun_option)
|
|
|
|
|
question_score += ex_shixun_challenge.question_score # 问题的分数,为各个关卡分数的总和
|
|
|
|
|
end
|
|
|
|
|
@exercise_question.update_attributes(:question_score => question_score,:shixun_name=> shixun_name)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("试卷问题创建失败!")
|
|
|
|
|
raise ActiveRecord::Rollback
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def show
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
@exercise_choices = @exercise_question.exercise_choices
|
|
|
|
|
@exercise_question_shixun = @exercise_question.exercise_shixun_challenges
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("页面调用失败!")
|
|
|
|
|
raise ActiveRecord::Rollback
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def edit
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
@exercise_choices = @exercise_question.exercise_choices
|
|
|
|
|
@exercise_question_shixun = @exercise_question.exercise_shixun_challenges
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("页面调用失败!")
|
|
|
|
|
raise ActiveRecord::Rollback
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def update
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
# 更新试卷题目的内容
|
|
|
|
|
question_options = {
|
|
|
|
|
:question_title => params[:question_title],
|
|
|
|
|
:is_ordered => params[:is_ordered], # 填空题的答案是否为一一对应关系,默认为true即为一一对应
|
|
|
|
|
:question_score => params[:question_score].present? ? params[:question_score].to_f.round(1) : 5.0 #不可修改分数
|
|
|
|
|
}
|
|
|
|
|
choices_array = params[:question_choices]
|
|
|
|
|
stan_answer_params = params[:standard_answers]
|
|
|
|
|
standard_answer = stan_answer_params.present? ? stan_answer_params.uniq.reject(&:blank?) : []
|
|
|
|
|
@exercise_question.update_attributes(question_options)
|
|
|
|
|
#当选项存在时,可修改选项内容,但是不能更改选项的位置(即不能增删选项)
|
|
|
|
|
if choices_array.present?
|
|
|
|
|
ex_choices = @exercise_question.exercise_choices
|
|
|
|
|
ex_choice_count = ex_choices.count
|
|
|
|
|
choice_array_count = choices_array.count
|
|
|
|
|
ex_choice_count_array = (1..ex_choice_count).to_a
|
|
|
|
|
choice_array_count_array = (1..choice_array_count).to_a
|
|
|
|
|
if ex_choice_count > choice_array_count #如果选项有减少的,那么只更新传入的,删除以前的
|
|
|
|
|
choice_array_count_array.each do |c|
|
|
|
|
|
choice = choices_array[c-1] #每一个选项的内容
|
|
|
|
|
exercise_choice = @exercise_question.exercise_choices.find_choice_custom("choice_position",(c))
|
|
|
|
|
exercise_choice.update(choice_text:choice)
|
|
|
|
|
end
|
|
|
|
|
drop_ex_choice = @exercise_question.exercise_choices.left_choice_choose("choice_position",(choice_array_count))
|
|
|
|
|
drop_ex_choice.destroy_all
|
|
|
|
|
else
|
|
|
|
|
ex_choice_count_array.each do |c|
|
|
|
|
|
choice = choices_array[c-1] #每一个选项的内容
|
|
|
|
|
exercise_choice = @exercise_question.exercise_choices.find_choice_custom("choice_position",(c))
|
|
|
|
|
exercise_choice.update(choice_text:choice)
|
|
|
|
|
end
|
|
|
|
|
new_add_choice = choice_array_count_array - ex_choice_count_array #新传入的需新增
|
|
|
|
|
if new_add_choice.count > 0
|
|
|
|
|
new_add_choice.each do |i|
|
|
|
|
|
choice_option = {
|
|
|
|
|
:choice_position => i,
|
|
|
|
|
:choice_text => choices_array[i-1].strip
|
|
|
|
|
}
|
|
|
|
|
question_choices = @exercise_question.exercise_choices.new(choice_option)
|
|
|
|
|
question_choices.save
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
#试卷未发布时,当标准答案存在时,可修改标准答案内容,可增删标准答案,否则只能修改标准答案,不能增删标准答案
|
|
|
|
|
@exercise_answers_array = @exercise_question.exercise_standard_answers #问卷的全部标准答案
|
|
|
|
|
if standard_answer.present?
|
|
|
|
|
if @exercise_question.question_type <= 2 #选择题/判断题,标准答案为一个或多个
|
|
|
|
|
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
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
if standard_answer.count > 1 && @exercise_question.question_type == 0 #当标准答案数大于1,且不为多选时,修改为多选
|
|
|
|
|
@exercise_question.update_attribute("question_type",1)
|
|
|
|
|
elsif standard_answer.count == 1 && @exercise_question.question_type == 1
|
|
|
|
|
@exercise_question.update_attribute("question_type",0)
|
|
|
|
|
end
|
|
|
|
|
elsif @exercise_question.question_type == 3 #填空题
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
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|
|
|
|
|
|
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
|
|
|
|
|
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
|
|
|
|
|
end
|
|
|
|
|
if @exercise_question.question_type == 4 #主观题
|
|
|
|
|
main_standard_answer = standard_answer.present? ? standard_answer.first : nil
|
|
|
|
|
if @exercise_answers_array.present?
|
|
|
|
|
@exercise_answers_array.first.update_attribute("answer_text",main_standard_answer)
|
|
|
|
|
else
|
|
|
|
|
standard_option = {
|
|
|
|
|
:exercise_question_id => @exercise_question.id,
|
|
|
|
|
:answer_text => main_standard_answer,
|
|
|
|
|
}
|
|
|
|
|
question_standard_answer = ExerciseStandardAnswer.new(standard_option)
|
|
|
|
|
question_standard_answer.save
|
|
|
|
|
end
|
|
|
|
|
elsif @exercise_question.question_type == 5
|
|
|
|
|
question_score = 0
|
|
|
|
|
shixun_name = params[:shixun_name] || @exercise_question.shixun_name
|
|
|
|
|
@exercise_question.exercise_shixun_challenges.each_with_index do |challenge, index|
|
|
|
|
|
challenge.question_score = params[:question_scores][index].to_f.round(1)
|
|
|
|
|
challenge.save
|
|
|
|
|
question_score += challenge.question_score
|
|
|
|
|
end
|
|
|
|
|
@exercise_question.question_score = question_score
|
|
|
|
|
@exercise_question.shixun_name = shixun_name
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#当试卷已发布时(试卷的总状态),当标准答案修改时,如有已提交的学生,需重新计算分数.
|
|
|
|
|
|
|
|
|
|
if @exercise.exercise_status == 2
|
|
|
|
|
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)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if @exercise_question.save
|
|
|
|
|
normal_status(0,"试卷更新成功!")
|
|
|
|
|
else
|
|
|
|
|
normal_status(-1,"试卷更新失败!")
|
|
|
|
|
end
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("页面调用失败!")
|
|
|
|
|
raise ActiveRecord::Rollback
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 试卷问题的上下移动
|
|
|
|
|
def up_down
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
opr = params[:opr]
|
|
|
|
|
current_q_p = @exercise_question.question_number.to_i #问题的当前位置
|
|
|
|
|
if @exercise.exercise_status.to_i == 1
|
|
|
|
|
if opr.present?
|
|
|
|
|
if opr.to_s == "up"
|
|
|
|
|
last_q_p = @exercise.exercise_questions.find_by(question_number: (current_q_p - 1)) # 当前问题的前一个问题
|
|
|
|
|
if last_q_p.present?
|
|
|
|
|
@exercise_question.update_attribute('question_number', (current_q_p - 1))
|
|
|
|
|
last_q_p.update_attribute('question_number', current_q_p) # 重新获取当前问题的位置
|
|
|
|
|
normal_status(0, "问题上移成功!")
|
|
|
|
|
else
|
|
|
|
|
normal_status(-1, "移动失败,已经是第一个问题了!")
|
|
|
|
|
end
|
|
|
|
|
elsif opr.to_s == "down"
|
|
|
|
|
next_q_p = @exercise.exercise_questions.find_by(question_number: (current_q_p + 1)) # 当前问题的前一个问题
|
|
|
|
|
if next_q_p.present?
|
|
|
|
|
@exercise_question.update_attribute('question_number', (current_q_p + 1))
|
|
|
|
|
next_q_p.update_attribute('question_number', current_q_p)
|
|
|
|
|
normal_status(0, "问题下移成功!")
|
|
|
|
|
else
|
|
|
|
|
normal_status(-1, "移动失败,已经是最后一个问题了!")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
normal_status(-1, "移动失败,请输入参数")
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
normal_status(-1, "已发布的不能移动问题")
|
|
|
|
|
end
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("问题移动失败!")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#试卷选项的删除
|
|
|
|
|
def delete_answer
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
choice_d_id = params[:choice_no].to_i # 选项的当前位置
|
|
|
|
|
question_choices = @exercise_question.exercise_choices
|
|
|
|
|
delete_answer = question_choices.find_by(choice_position: choice_d_id)
|
|
|
|
|
left_choices = question_choices.where("choice_position > ? ",choice_d_id)
|
|
|
|
|
left_choices.update_all("choice_position = choice_position - 1") if left_choices
|
|
|
|
|
if delete_answer.destroy
|
|
|
|
|
normal_status(0, "答案删除成功!")
|
|
|
|
|
else
|
|
|
|
|
normal_status(-1, "答案删除失败!")
|
|
|
|
|
end
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("答案删除失败!")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#试卷问题的删除
|
|
|
|
|
def destroy
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
question_d_id = @exercise_question.question_number.to_i #问题的当前位置
|
|
|
|
|
exercise_questions = @exercise.exercise_questions
|
|
|
|
|
left_questions = exercise_questions.where("question_number > ?", question_d_id)
|
|
|
|
|
left_questions.update_all("question_number = question_number - 1") if left_questions
|
|
|
|
|
if @exercise_question.destroy
|
|
|
|
|
normal_status(0, "问题删除成功!")
|
|
|
|
|
else
|
|
|
|
|
normal_status(-1, "问题删除失败!")
|
|
|
|
|
end
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("问题删除失败!")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#老师调分窗口
|
|
|
|
|
def adjust_score
|
|
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
|
begin
|
|
|
|
|
ex_obj_score = @exercise_current_user.objective_score #全部客观题得分
|
|
|
|
|
ex_subj_score = @exercise_current_user.subjective_score < 0.0 ? 0.0 : @exercise_current_user.subjective_score #全部主观题得分
|
|
|
|
|
ex_answers = @exercise_question.exercise_answers.search_answer_users("user_id",@user_id) #当前用户答案的得分
|
|
|
|
|
if @exercise_question.question_type == 3 #当为填空题,更新问题的总分,
|
|
|
|
|
ex_answer_old = ex_answers.score_reviewed.pluck(:score).sum #每一关的得分总和
|
|
|
|
|
each_right_score = (@c_score / ex_answers.count.to_f) #调分后,平均每关的分数
|
|
|
|
|
new_obj_score = ex_obj_score - ex_answer_old + @c_score
|
|
|
|
|
total_scores = new_obj_score + ex_subj_score
|
|
|
|
|
ex_scores = {
|
|
|
|
|
:objective_score => new_obj_score,
|
|
|
|
|
:score => total_scores
|
|
|
|
|
}
|
|
|
|
|
@exercise_current_user.update_attributes(ex_scores)
|
|
|
|
|
ex_answers.update_all(:score => each_right_score) #所有的正确选项需重新更新
|
|
|
|
|
elsif @exercise_question.question_type == 4 #当为主观题时
|
|
|
|
|
if ex_answers.present?
|
|
|
|
|
ex_answers_old_score = ex_answers.first.score > 0.0 ? ex_answers.first.score : 0.0 #原分数小于0,取0
|
|
|
|
|
new_sub_score = ex_subj_score - ex_answers_old_score + @c_score #原全部主观题总分减去原该主观题得分再加调分后的分数,即为当前全部主观题得分
|
|
|
|
|
ex_answers.first.update_attribute("score",@c_score)
|
|
|
|
|
else #如果学生未答,则创建新的答题记录
|
|
|
|
|
answer_option = {
|
|
|
|
|
:user_id => @user_id,
|
|
|
|
|
:exercise_question_id => @exercise_question.id,
|
|
|
|
|
:score => @c_score,
|
|
|
|
|
:answer_text => ""
|
|
|
|
|
}
|
|
|
|
|
ExerciseAnswer.create(answer_option)
|
|
|
|
|
new_sub_score = @c_score
|
|
|
|
|
end
|
|
|
|
|
total_scores = ex_obj_score + new_sub_score
|
|
|
|
|
ex_scores = {
|
|
|
|
|
:subjective_score => new_sub_score,
|
|
|
|
|
:score => total_scores
|
|
|
|
|
}
|
|
|
|
|
@exercise_current_user.update_attributes(ex_scores)
|
|
|
|
|
|
|
|
|
|
elsif @exercise_question.question_type == 5
|
|
|
|
|
# ex_answers = @exercise_question.exercise_shixun_answers.search_shixun_answers("user_id",@user_id).search_shixun_answers("exercise_shixun_challenge_id",@shixun_a_id)
|
|
|
|
|
ex_answers = @exercise_question.exercise_shixun_answers.where(user_id:@user_id,exercise_shixun_challenge_id:@shixun_a_id)
|
|
|
|
|
|
|
|
|
|
if ex_answers.present? #当为实训题时
|
|
|
|
|
ex_shixun_old_score = ex_answers.first.score > 0.0 ? ex_answers.first.score : 0.0
|
|
|
|
|
new_obj_score = ex_obj_score - ex_shixun_old_score + @c_score
|
|
|
|
|
ex_answers.first.update_attribute("score",@c_score)
|
|
|
|
|
else
|
|
|
|
|
ex_shixun_option ={
|
|
|
|
|
:exercise_question_id => @exercise_question.id,
|
|
|
|
|
:user_id => @user_id,
|
|
|
|
|
:exercise_shixun_challenge_id => @shixun_a_id,
|
|
|
|
|
:score => @c_score,
|
|
|
|
|
:status => 0
|
|
|
|
|
}
|
|
|
|
|
ExerciseShixunAnswer.create(ex_shixun_option)
|
|
|
|
|
new_obj_score = @c_score
|
|
|
|
|
end
|
|
|
|
|
total_scores = new_obj_score + ex_subj_score
|
|
|
|
|
ex_scores = {
|
|
|
|
|
:objective_score => new_obj_score,
|
|
|
|
|
:score => total_scores
|
|
|
|
|
}
|
|
|
|
|
@exercise_current_user.update_attributes(ex_scores)
|
|
|
|
|
end
|
|
|
|
|
comments = params[:comment]
|
|
|
|
|
question_comment = @exercise_question.exercise_answer_comments.first
|
|
|
|
|
if question_comment.present?
|
|
|
|
|
comment_option = {
|
|
|
|
|
:comment => comments.present? ? comments : question_comment.comment,
|
|
|
|
|
:score => @c_score,
|
|
|
|
|
:exercise_answer_id => ex_answers.present? ? ex_answers.first.id : nil
|
|
|
|
|
}
|
|
|
|
|
question_comment.update_attributes(comment_option)
|
|
|
|
|
@exercise_comments = question_comment
|
|
|
|
|
else
|
|
|
|
|
comment_option = {
|
|
|
|
|
:user_id => current_user.id,
|
|
|
|
|
:comment => comments,
|
|
|
|
|
:score => @c_score,
|
|
|
|
|
:exercise_question_id => @exercise_question.id,
|
|
|
|
|
:exercise_shixun_answer_id => @shixun_a_id.present? ? @shixun_a_id : nil,
|
|
|
|
|
:exercise_answer_id => ex_answers.present? ? ex_answers.first.id : nil
|
|
|
|
|
}
|
|
|
|
|
@exercise_comments = ExerciseAnswerComment.new(comment_option)
|
|
|
|
|
@exercise_comments.save
|
|
|
|
|
end
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception("没有权限")
|
|
|
|
|
raise ActiveRecord::Rollback
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
|
|
def questions_params
|
|
|
|
|
params.require(:exercise_question).permit(:question_title,:question_type,
|
|
|
|
|
:question_number,:exercise_id,
|
|
|
|
|
:question_score,:shixun_id,:is_ordered)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def get_exercise
|
|
|
|
|
@exercise = Exercise.find_by(id:params[:exercise_id])
|
|
|
|
|
if @exercise.blank?
|
|
|
|
|
tip_exception(404,"试卷不存在")
|
|
|
|
|
else
|
|
|
|
|
@course = @exercise.course
|
|
|
|
|
if @course.blank?
|
|
|
|
|
tip_exception(404,"课堂不存在")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def is_course_teacher
|
|
|
|
|
@identity = current_user.course_identity(@course)
|
|
|
|
|
unless @identity < Course::STUDENT #为老师/助教/管理员
|
|
|
|
|
tip_exception("403", "无权限操作")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def get_exercise_question
|
|
|
|
|
@exercise_question = ExerciseQuestion.find_by(id: params[:id])
|
|
|
|
|
if @exercise_question.present?
|
|
|
|
|
@exercise = @exercise_question.exercise
|
|
|
|
|
if @exercise.blank?
|
|
|
|
|
tip_exception(404,"试卷不存在")
|
|
|
|
|
else
|
|
|
|
|
@course = @exercise.course
|
|
|
|
|
if @course.blank?
|
|
|
|
|
tip_exception(404,"课堂不存在")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
tip_exception(404,"试卷问题不存在")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def validate_params
|
|
|
|
|
normal_status(-1,"题目不允许为空!") if (params[:question_title].blank? && params[:question_type].to_i !=5 ) #除了实训题,其余题目必需有题干
|
|
|
|
|
normal_status(-1,"问题类型不允许为空!" ) if params[:question_type].blank?
|
|
|
|
|
normal_status(-1,"分值不允许为空!" ) if params[:question_score].blank? && params[:question_scores].blank? #分值的数组或参数必需存在一个
|
|
|
|
|
if params[:question_score].present? && params[:question_score].to_f <= 0.0 #问题类型存在,则分值不能为空,且必需大于0
|
|
|
|
|
normal_status(-1,"分值必需大于0!")
|
|
|
|
|
elsif (params[:question_score].present? && params[:question_score].to_f.round(1) > 100.0) || (params[:question_scores].present? && (params[:question_scores].map{|a| a.to_f.round(1)}.max > 100.0))
|
|
|
|
|
normal_status(-1,"分值不能超过100分!")
|
|
|
|
|
elsif params[:question_scores].present? && params[:question_scores].include?(0.0) #如果有负数,则自动取绝对值,#多个分数值,针对实训题的
|
|
|
|
|
normal_status(-1,"分值必需大于0!")
|
|
|
|
|
elsif params[:standard_answers].present? && params[:question_choices].present? && (params[:standard_answers].count > params[:question_choices].count)
|
|
|
|
|
normal_status(-1,"标准答案数不能大于选项数!")
|
|
|
|
|
elsif [0,1,2,3].include?(params[:question_type].to_i) && (params[:standard_answers].blank? || params[:standard_answers].include?("")) #选择题/判断题/填空题 问题选项/标准答案不能为空,也不能包含空的内容
|
|
|
|
|
normal_status(-1,"标准答案不能为空!")
|
|
|
|
|
elsif params[:question_type].to_i == 2 && (params[:standard_answers].count > 1 || params[:question_choices].blank? || params[:question_choices].include?("")) #判断题的标准答案不能大于1个,选项不能为空
|
|
|
|
|
normal_status(-1,"判断题选项不能为空/标准答案不能大于1个!")
|
|
|
|
|
elsif params[:question_type].to_i <= 1 && (params[:question_choices].blank? || params[:question_choices].include?("") || params[:question_choices].count < 2) #选择题选项不能为空,且不能小于2
|
|
|
|
|
normal_status(-1,"选择题选项内容不能为空,且不能少于2个!")
|
|
|
|
|
elsif params[:question_type].to_i == 3 && (params[:standard_answers].blank? || params[:standard_answers].count > 5 ) #填空题选项最多为5个,且如果为1个的话,不允许修改is_ordered
|
|
|
|
|
normal_status(-1,"填空题标准答案不能为空/不能超过5个!")
|
|
|
|
|
elsif params[:question_type].to_i == 4 && params[:standard_answers].count > 2 #简单题参考答案最多为1个
|
|
|
|
|
normal_status(-1,"简答题的参考答案不能大于2个!")
|
|
|
|
|
elsif params[:question_type].to_i == 5
|
|
|
|
|
if params[:shixun_id].blank? #实训题的id不能为空
|
|
|
|
|
normal_status(-1,"实训题id不能为空!")
|
|
|
|
|
elsif params[:shixun_name].blank?
|
|
|
|
|
normal_status(-1,"实训题名称不能为空!")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def check_exercise_status
|
|
|
|
|
normal_status(-1,"不能更改试卷问题!") if @exercise.exercise_status != 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#更新时不能修改的内容
|
|
|
|
|
def cannot_change_column
|
|
|
|
|
#已发布的/已截止的/评阅中的状态时,不能修改分数,不能增删问题和答案,不能修改标准答案,可以修改选项内容/题目内容,这里仅指单个问题
|
|
|
|
|
if @exercise.exercise_status != 1
|
|
|
|
|
question_score = @exercise_question.question_score #原来的分数
|
|
|
|
|
update_question_score = params[:question_score].to_f.round(1) #传入的分数
|
|
|
|
|
choices_count = @exercise_question.exercise_choices.size #原来的选项个数
|
|
|
|
|
exercise_choice_ids = @exercise_question.exercise_standard_answers.pluck(:exercise_choice_id).uniq
|
|
|
|
|
standard_answers_text = @exercise_question.exercise_standard_answers.pluck(:answer_text).uniq
|
|
|
|
|
update_choices_count = params[:question_choices].present? ? params[:question_choices].count : choices_count #传入的选项个数
|
|
|
|
|
standard_answer = params[:standard_answers] #传参数是怎么传的?能不能传空值?
|
|
|
|
|
if update_question_score.present? && question_score != update_question_score #分数有更改
|
|
|
|
|
normal_status(-1,"已发布/已截止,分数不允许修改!")
|
|
|
|
|
elsif update_choices_count != choices_count #选项个数有修改
|
|
|
|
|
normal_status(-1,"已发布/已截止,不允许增删答案!")
|
|
|
|
|
elsif standard_answer.present?
|
|
|
|
|
if @exercise_question.question_type == 3
|
|
|
|
|
exercise_answers_text = standard_answer.map{|a| a[:answer_text]}.sum.uniq
|
|
|
|
|
unless (standard_answer.count == exercise_choice_ids.count) && (standard_answers_text.count == exercise_answers_text.count)
|
|
|
|
|
normal_status(-1,"已发布/已截止,不允许增删标准答案!")
|
|
|
|
|
end
|
|
|
|
|
elsif @exercise_question.question_type == 4
|
|
|
|
|
unless standard_answers_text.count == standard_answer.count
|
|
|
|
|
normal_status(-1,"已发布/已截止,不允许增删标准答案!")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def check_adjust_score
|
|
|
|
|
@c_score = params[:score].to_f #调分后的分数
|
|
|
|
|
@user_id = params[:user_id]
|
|
|
|
|
@exercise_current_user = @exercise.exercise_users.exercise_commit_users(@user_id).first #当前试卷用户的答案内容
|
|
|
|
|
if @exercise_current_user.blank?
|
|
|
|
|
normal_status(-1,"用户不存在!")
|
|
|
|
|
elsif @c_score.blank?
|
|
|
|
|
normal_status(-1,"分数不能为空!")
|
|
|
|
|
elsif @exercise_question.question_type <= 1 || @exercise_question.question_type == 2
|
|
|
|
|
normal_status(-1,"选择题/判断题不能调分!")
|
|
|
|
|
elsif params[:comment].present? && params[:comment].length > 100
|
|
|
|
|
normal_status(-1,"评语不能超过100个字符!")
|
|
|
|
|
else
|
|
|
|
|
@shixun_a_id = params[:shixun_challenge_id]
|
|
|
|
|
if @exercise_question.question_type == 5 #当为实训题时,为关卡的分数
|
|
|
|
|
@shixun_challenge = @exercise_question.exercise_shixun_challenges.cha_id_find(@shixun_a_id)
|
|
|
|
|
if @shixun_challenge.present?
|
|
|
|
|
@old_ques_score = @shixun_challenge.first.question_score
|
|
|
|
|
else
|
|
|
|
|
@old_ques_score = nil
|
|
|
|
|
normal_status(-1,"实训答案id不能为空!")
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
@old_ques_score = @exercise_question.question_score #当不为实训题时,为各问题的分数
|
|
|
|
|
end
|
|
|
|
|
if @old_ques_score.present? && (@c_score > @old_ques_score)
|
|
|
|
|
normal_status(-1,"分数不能大于题目分数!")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|