You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
educoder/app/controllers/exercises_controller.rb

1711 lines
78 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

class ExercisesController < ApplicationController
before_action :require_login, :check_auth, except: [:index]
before_action :find_course,only: [:index,:new,:create,:my_exercises,:public_exercises,:set_public,:destroys,
:join_exercise_banks,:publish_modal,:publish,:end_modal,:end_exercise] #需要有课堂id参数的
before_action :get_exercise,except: [:index,:new,:create,:my_exercises,:public_exercises,:set_public,:destroys,
:join_exercise_banks,:publish_modal,:publish,:end_modal,:end_exercise]
before_action :user_course_identity
before_action :is_course_teacher,except: [:index,:start_answer,:exercise_setting,:commit_exercise,:exercise_lists,:review_exercise,
:exercise_result,:common_header,:cancel_exercise,:begin_commit]
before_action :get_left_banner_id,only:[:common_header,:start_answer,:review_exercise,:index,:new,:edit]
before_action :validates_exercise_params,only: [:create,:update]
before_action :get_exercise_question_counts,only: [:show,:edit,:start_answer,:review_exercise,:blank_exercise,:export_exercise]
before_action :validate_publish_time,only: [:commit_setting] #提交设置时,需判断时间是否符合
before_action :check_course_public,only: [:set_public]
before_action :check_user_on_answer,only: [:show,:start_answer,:exercise_lists] #判断当前用户在试卷的权限/老师是否属于分班的权限
before_action :only_student_in,only: [:start_answer]
before_action :check_user_id_start_answer,only: [:start_answer,:review_exercise]
# before_action :commit_user_exercise,only: [:start_answer,:exercise_lists,:review_exercise] #已有定时的任务
before_action :check_exercise_time,only: [:commit_exercise] #提交试卷时,判断时间是否超过
before_action :check_exercise_status,only: [:redo_modal,:redo_exercise]
before_action :check_exercise_is_end, only: [:review_exercise]
before_action :check_exercise_public,only: [:exercise_result] #试卷是否为公开
before_action :commit_shixun_present,only: [:commit_shixun]
include ExportHelper
include ExercisesHelper
def index
ActiveRecord::Base.transaction do
begin
# 按发布时间或创建时间排序
@exercises_all = @course.exercises
member_show_exercises = @exercises_all.is_exercise_published #已发布的或已截止的试卷
@current_user_ = current_user
# 课堂的学生人数
@course_all_members = @course.students #当前课堂的全部学生
@current_student = @course_all_members.course_find_by_ids("user_id",current_user.id) #当前用户是否为课堂的学生
# exercises的不同用户群体的显示
if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教
@is_teacher_or = 1
@exercises = @exercises_all #老师能看到全部的试卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同)
elsif @user_course_identity == Course::STUDENT # 2为课堂成员能看到统一设置的和自己班级的
@is_teacher_or = 2
@member_group_id = @current_student.first.try(:course_group_id).to_i # 成员的分班id默认为0
if @member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的)
@exercises = member_show_exercises.exists? ? member_show_exercises.unified_setting : []
else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷
# 已发布 当前用户班级分组的 试卷id
not_exercise_ids = @course.exercise_group_settings.exercise_group_not_published.where("course_group_id = #{@member_group_id}").pluck(:exercise_id)
@exercises = member_show_exercises.where.not(id: not_exercise_ids)
end
else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁
@is_teacher_or = 0
@exercises = member_show_exercises.unified_setting
end
if @exercises.size > 0
if params[:type].present?
choose_type = params[:type].to_i
ex_setting_ids = []
if @is_teacher_or != 2
@exercises = @exercises.where("exercise_status = #{choose_type}")
else
case choose_type
when 1
ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}").exercise_group_not_published.pluck(:exercise_id)
when 2
ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}")
.where("publish_time is not null and publish_time <= ? and end_time > ?",Time.now,Time.now).pluck(:exercise_id)
when 3
ex_setting_ids = @course.exercise_group_settings.where("course_group_id = #{@member_group_id}").exercise_group_ended.pluck(:exercise_id)
end
unified_setting_ids = @exercises.unified_setting.where("exercise_status = #{choose_type}").pluck(:id)
ex_ids = (ex_setting_ids + unified_setting_ids).uniq
@exercises = @exercises.where(id: ex_ids)
end
end
if params[:search].present?
search_type = params[:search].to_s.strip
@exercises = @exercises.exercise_search(search_type)
end
@exercises_select_count = @exercises.size # 全部页面,需返回
@exercises = @exercises.distinct.order( "IF(ISNULL(publish_time),0,1), publish_time DESC,created_at DESC") #出现错误
# 分页
@page = params[:page] || 1
@limit = params[:limit] || 15
@exercises = @exercises.page(@page).per(@limit)
@exercises = @exercises&.includes(:published_settings)
else
@exercises = []
end
@course_all_members_count = @course_all_members.size #当前课堂的学生数
@exercises_count = @exercises_all.size # 全部页面,需返回
@exercises_unpublish_counts = @exercises_all.exercise_by_status(1).size #未发布的试卷数
@exercises_published_counts = @exercises_count - @exercises_unpublish_counts # 已发布的试卷数,包含已截止的
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def new
ActiveRecord::Base.transaction do
begin
@exercise = Exercise.new
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷创建失败!")
raise ActiveRecord::Rollback
end
end
end
def create
ActiveRecord::Base.transaction do
begin
ex_name = params[:exercise_name]
ex_desc = params[:exercise_description]
exercise_options = {
:exercise_name => ex_name,
:exercise_description => ex_desc,
:user_id => current_user.id,
:course_id => @course.id,
:time => -1,
:exercise_status => 1
}
@exercise = Exercise.create(exercise_options)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷创建失败!")
raise ActiveRecord::Rollback
end
end
end
#试卷的内容,及试题/答案的内容编辑
def edit
ActiveRecord::Base.transaction do
begin
@exercise_questions = @exercise.exercise_questions.order("question_number ASC")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷创建失败!")
raise ActiveRecord::Rollback
end
end
end
def update
ActiveRecord::Base.transaction do
begin
ex_name = params[:exercise_name]
ex_desc = params[:exercise_description]
exercise_options = {
:exercise_name => ex_name,
:exercise_description => ex_desc,
}
@exercise.update_attributes(exercise_options)
normal_status(0,"试卷更新成功!")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷创建失败!")
raise ActiveRecord::Rollback
end
end
end
def show
ActiveRecord::Base.transaction do
begin
if @user_course_identity < Course::STUDENT
@is_teacher_or = 1 #为老师/助教/管理员
else
@is_teacher_or = 0 #为学生
end
@exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_shixun_challenges,:exercise_standard_answers).order("question_number ASC")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷创建失败!")
raise ActiveRecord::Rollback
end
end
end
#试卷的公用头部
def common_header
ActiveRecord::Base.transaction do
begin
@user_left_time = nil
if @user_course_identity > Course::ASSISTANT_PROFESSOR
@is_teacher_or = 0
@user_exercise_answer = @exercise.check_user_answer_status(current_user)
@user_commit_counts = 0
@user_left_time = get_exercise_left_time(@exercise,current_user)
else
@is_teacher_or = 1
@user_exercise_answer = 3 #教师页面
@user_commit_counts = @exercise.exercise_users.where(commit_status:1).size #已提交的用户数
end
@ex_status = @exercise.get_exercise_status(current_user)
exercise_id_array = [@exercise.id]
@exercise_publish_count = get_user_permission_course(exercise_id_array,Exercise::PUBLISHED).size #是否存在已发布的
@exercise_unpublish_count = get_user_permission_course(exercise_id_array,Exercise::UNPUBLISHED).size #是否存在未发布的
if (@exercise_publish_count == 0) && (@exercise_unpublish_count == 0) #即表示没有分班
if @ex_status == Exercise::UNPUBLISHED
@exercise_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候
elsif @ex_status == Exercise::PUBLISHED
@exercise_publish_count = 1 #试卷未发布,且课堂没有分班的时候
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
end
end
end
#实训题目的选用
def choose_shixun
ActiveRecord::Base.transaction do
begin
search = params[:search]
if @user_course_identity > Course::ADMIN #当不为管理员的时候
user_school_id = current_user.school_id #当前用户的学校id
if user_school_id.present?
none_shixun_ids = ShixunSchool.where("school_id != #{user_school_id}").pluck(:shixun_id)
@publish_shixuns = Shixun.where.not(id: none_shixun_ids).unhidden
end
else
@publish_shixuns = Shixun.unhidden
end
if search.present?
@publish_shixuns = @publish_shixuns.search_by_name(search)
end
@shixuns = @publish_shixuns.joins(:challenges).where("challenges.st != 0").distinct
# 全部页面,需返回
@shixuns_count = @shixuns.count
# 分页
@page = params[:page] || 1
@limit = params[:limit] || 8
@shixuns = @shixuns.page(@page).per(@limit)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("实训选择失败!")
end
end
end
#确认实训的选择
def commit_shixun
ActiveRecord::Base.transaction do
begin
@shixun_challenges = @shixun.challenges
@shixun_challenges_count = @shixun_challenges.size
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
end
end
end
# 首页批量或单独删除
def destroys
ActiveRecord::Base.transaction do
begin
check_ids = Exercise.where(id: params[:check_ids])
check_ids.destroy_all
normal_status(0, "试卷已删除成功!")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷删除失败!")
raise ActiveRecord::Rollback
end
end
end
# 设为公开
def set_public
ActiveRecord::Base.transaction do
begin
check_ids = Exercise.where(id: params[:check_ids])
check_ids.each do |exercise|
exercise.update_attribute('is_public', true)
end
normal_status(0, "试卷已设为公开!")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷设为公开失败!")
raise ActiveRecord::Rollback
end
end
end
## 加入题库
def join_exercise_banks
ActiveRecord::Base.transaction do
begin
check_ids = Exercise.where(id: params[:check_ids])
check_ids.each do |exercise|
current_ex_bank = current_user.exercise_banks.find_by_container(exercise.id,"Exercise")&.first
if current_ex_bank.present? #当前用户的选择试卷是否已加入习题库,存在则更新习题库和问题库,否则新建习题库和问题库
ex_params = {
:name => exercise.exercise_name,
:description => exercise.exercise_description,
:course_list_id => exercise.course.try(:course_list_id)
}
current_ex_bank.update_attributes(ex_params)
# question_bank = QuestionBank.ques_by_container(current_ex_bank.id,current_ex_bank.container_type).first #该习题库是否存在于问题库里
# ques_params = {
# :name => current_ex_bank.name,
# :course_list_id => current_ex_bank.course_list_id
# }
# question_bank.update_attributes(ques_params) if question_bank.present?
current_ex_bank.exercise_bank_questions.destroy_all # 更新后,习题库的问题全部删除,后续重新再建
else
ex_params = {
:name => exercise.exercise_name,
:description => exercise.exercise_description,
:user_id => current_user.id,
:is_public => 0,
:course_list_id => exercise.course.try(:course_list_id),
:container_id => exercise.id,
:container_type => "Exercise",
:quotes => 1
}
current_ex_bank= ExerciseBank.new ex_params
current_ex_bank.save! #如果习题库保存成功则会创建问题库question_bank
# if current_ex_bank.save
# ques_params = {
# :name => current_ex_bank.name,
# :container_id => current_ex_bank.id,
# :container_type => current_ex_bank.container_type,
# :quotes => current_ex_bank.quotes,
# :user_id => current_ex_bank.user_id,
# :is_public => current_ex_bank.is_public,
# :course_list_id => current_ex_bank.course_list_id
# }
# question_bank = QuestionBank.new ques_params
# question_bank.save
# end
end
# 试卷的问题的输入
exercise.exercise_questions.each do |q|
option = {
:question_title => q.question_title,
:question_type => q.question_type,
:question_number => q.question_number,
:question_score => q.question_score,
:shixun_id => q.shixun_id,
:shixun_name => q.shixun_name
}
exercise_bank_question = current_ex_bank.exercise_bank_questions.new option
exercise_bank_question.save
## 试卷选项的输入
if q.question_type != Exercise::PRACTICAL #不为实训题时,试卷选项加入试题答案库
ex_choices = q.exercise_choices
ex_standard = q.exercise_standard_answers
ex_choices.each do |c|
choice_option = {
:choice_position => c.choice_position,
:choice_text =>c.choice_text
}
ex_bank_choice = exercise_bank_question.exercise_bank_choices.new choice_option
ex_bank_choice.save
end
ex_standard.each do |s|
ex_stand = {
:exercise_bank_choice_id => s.exercise_choice_id,
:answer_text => s.answer_text
}
ex_stand_bank = exercise_bank_question.exercise_bank_standard_answers.new ex_stand
ex_stand_bank.save
end
else #当为实训题时
shixun_challenges = q.exercise_shixun_challenges
shixun_challenges.each do |c|
challenge_option = {
:position => c.position,
:challenge_id => c.challenge_id,
:shixun_id => q.shixun_id,
:question_score => c.question_score
}
shixun_challenge_bank = exercise_bank_question.exercise_bank_shixun_challenges.new challenge_option
shixun_challenge_bank.save
end
end
end
current_ex_bank.save
end
normal_status(0, "题库更新成功!")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("题库更新失败!")
raise ActiveRecord::Rollback
end
end
end
#试卷的设置页面
def exercise_setting
ActiveRecord::Base.transaction do
begin
@user_permission = 2
@user_course_groups = @course.teacher_group(current_user.id) #当前老师的分班
@being_setting_course_ids = @exercise.common_published_ids(current_user.id) #当前用户已发布的班级的id
@user_published_setting = @exercise.exercise_group_settings
.find_in_exercise_group("course_group_id",@being_setting_course_ids) #当前用户已发布班级的试卷设置
exercise_ids = [@exercise.id]
@exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).count #判断当前用户是否有试卷已发布的分班,用于显示立即截止/撤销发布
@exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).count #判断当前用户是否有试卷未发布的分班,用户显示立即发布
@exercise_users_count = @exercise.exercise_users.commit_exercise_by_status(1).count #判断当前试卷是否有已提交的
# ## 需添加发送消息的接口,稍后添加
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
end
end
end
#试卷的提交设置
def commit_setting
ActiveRecord::Base.transaction do
begin
error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。
# course_group_ids = @course.teacher_course_group_ids(current_user.id) #当前老师的班级id数组
course_group_ids = @course.charge_group_ids(current_user) #当前老师的班级id数组
exercise_status = @exercise.get_exercise_status(current_user)
if exercise_status == Exercise::UNPUBLISHED && course_group_ids.size > 0 # 试卷未发布且老师的分班大于1 ,才可以修改统一设置,否则按试卷默认的来处理
unified_setting = params[:unified_setting]
else
unified_setting = @exercise.unified_setting
end
show_statistic = params[:show_statistic] ? true :false
exercise_time = params[:time].blank? ? -1 : params[:time]
question_random = params[:question_random] ? true :false #问题是否随机0为不随机1为随机
choice_random = params[:choice_random] ? true :false
score_open = params[:score_open] ? true : false #分数是否公开
answer_open = params[:answer_open] ? true : false #答案是否公开
# 统一设置或者分班为0则更新试卷并删除试卷分组
if unified_setting || (course_group_ids.size == 0)
params_publish_time = params[:publish_time].blank? ? nil : params[:publish_time].to_time
params_end_time = nil
if params[:end_time].blank?
if params_publish_time.present?
params_end_time = params_publish_time + 30.days
end
else
params_end_time = params[:end_time].to_time
end
if (exercise_status != Exercise::UNPUBLISHED) && (@exercise.publish_time != params_publish_time)
normal_status(-1,"已发布/已截止,不允许修改发布时间")
elsif params_publish_time.present? && params_end_time.present? && params_end_time < params_publish_time
normal_status(-1,"截止时间不能小于发布时间")
else
#发布时间小于当前时间,则试卷显示为未发布,当截止时间大于当前时间,则显示为已截止
exercise_status_n = set_exercise_status(params_publish_time,params_end_time)
exercise_params = {
:unified_setting => unified_setting,
:show_statistic => show_statistic,
:time => exercise_time,
:question_random => question_random,
:choice_random => choice_random,
:score_open => score_open,
:answer_open => answer_open,
:exercise_status => exercise_status_n,
:publish_time => params_publish_time,
:end_time => params_end_time
}
@exercise.update_attributes(exercise_params)
@exercise.exercise_group_settings.destroy_all
normal_status(0, "试卷设置成功!")
end
else
params_times = params[:publish_time_groups] #分班返回的json数组{"publish_time_groups":[{"course_group_id":"1","publish_time":"xx","end_time":"xxx"}]}
exercise_groups = @exercise.exercise_group_settings.find_in_exercise_group("course_id",@course.id) #试卷的全部分班信息
exercise_groups_ids = exercise_groups.pluck(:course_group_id) #问卷的全部分班id
total_common = params_times.map{|k| k[:course_group_id]}.sum.uniq #传入的所有分组的分班id
total_common_group = exercise_groups_ids & total_common #传入的分班与问卷已存在的分班的交集
old_exercise_groups = exercise_groups_ids - total_common_group #后来传入的分班里,没有了的班级,即需要删除
params_times.each do |t|
course_id = t[:course_group_id]
exercise_publish_time = t[:publish_time].present? ? t[:publish_time].to_time : nil
exercise_end_time = nil
if t[:end_time].blank?
if exercise_publish_time.present?
exercise_end_time = exercise_publish_time + 30.days
end
else
exercise_end_time = t[:end_time].to_time
end
exercise_group = exercise_groups.find_in_exercise_group("course_group_id",course_id) #判断该分班是否存在
if exercise_group.present? && (exercise_group.first.publish_time < Time.now) && (exercise_publish_time != exercise_group.first.publish_time)
error_count += 1
end
if error_count == 0
common_group = exercise_groups_ids & course_id #传入的班级与问卷已存在的班级的交集,即表示已有分班的
new_group_ids = course_id - common_group #新传入的班级id
if common_group.count > 0 #判断试卷的分班设置是否存在,存在则更新,负责则新建
ex_group_params = {
:publish_time => exercise_publish_time,
:end_time => exercise_end_time
}
exercise_group_sets = exercise_groups.find_in_exercise_group("course_group_id",common_group)
the_group_setting = exercise_group_sets.first
if the_group_setting.present?
the_group_setting_status = set_exercise_status(the_group_setting.publish_time,the_group_setting.end_time)
if the_group_setting_status == 2
ex_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => exercise_end_time
}
elsif the_group_setting_status == 3
ex_group_params = {
:publish_time => the_group_setting.publish_time,
:end_time => the_group_setting.end_time
}
end
end
exercise_group_sets.update_all(ex_group_params)
end
if new_group_ids.size > 0
new_group_ids.each do |c|
exercise_group_params = {
:exercise_id => @exercise.id,
:course_group_id => c,
:course_id => @course.id,
:publish_time => exercise_publish_time,
:end_time => exercise_end_time
}
new_exercise_group = ExerciseGroupSetting.new(exercise_group_params)
new_exercise_group.save
end
end
end
end
if error_count > 0
error_count == 0
normal_status(-1,"已发布/已截止的试卷不允许修改时间")
else
if old_exercise_groups.size > 0
old_all_ex_groups = exercise_groups.find_in_exercise_group("course_group_id",old_exercise_groups)
old_all_ex_groups.destroy_all
end
#试卷更新为exercise_group_setting的发布时间最小截止时间最大
e_time_present = exercise_groups.end_time_no_null.map(&:end_time)
p_time_present = exercise_groups.publish_time_no_null.map(&:publish_time)
e_time = e_time_present.size > 0 ? e_time_present.max : nil
p_time = p_time_present.size > 0 ? p_time_present.min : nil
exercise_status = 1
if p_time.nil? #发布时间为空,则表示问卷未发布
exercise_status = 1
elsif p_time.present? && e_time.present?
exercise_status = set_exercise_status(p_time,e_time)
end
exercise_params = {
:unified_setting => unified_setting,
:show_statistic => show_statistic,
:time => exercise_time,
:question_random => question_random,
:choice_random => choice_random,
:score_open => score_open,
:answer_open => answer_open,
:exercise_status => exercise_status,
:publish_time => p_time,
:end_time => e_time
}
@exercise.update_attributes(exercise_params)
if @exercise.exercise_status == Exercise::PUBLISHED
if @exercise.course_acts.size == 0
@exercise.course_acts << CourseActivity.new(:user_id => @exercise.user_id,:course_id => @exercise.course_id)
end
end
normal_status(0, "试卷设置成功!")
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("提交出现错误!")
raise ActiveRecord::Rollback
end
end
end
#我的题库
def my_exercises
ActiveRecord::Base.transaction do
begin
## 我的试卷题库
@current_user_exercises = current_user.exercise_banks.find_by_c_type("Exercise")
if @current_user_exercises.present?
if params[:search].present?
search_type = params[:search].to_s.strip
@current_user_exercises = @current_user_exercises.exercise_bank_search(search_type)
end
page = params[:page] || 1
limit = params[:limit] || 15
@my_exercises_count = @current_user_exercises.size
@current_user_exercises = @current_user_exercises.page(page).per(limit)
else
@current_user_exercises = []
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
end
end
end
# 公共题库
def public_exercises
ActiveRecord::Base.transaction do
begin
if current_user.is_certification_teacher
@user_certification = 1 #用户已通过认证
@public_exercises = ExerciseBank.find_by_c_type("Exercise").public_exercises
if @public_exercises.present?
if params[:search].present?
search_type = params[:search].to_s.strip
@public_exercises = @public_exercises.exercise_bank_search(search_type)
end
page = params[:page] || 1
limit = params[:limit] || 15
@public_exercises_count = @public_exercises.size
@public_exercises = @public_exercises.page(page).per(limit)
else
@public_exercises_count = 0
@public_exercises = []
end
else
@user_certification = 0 #用户未通过认证
@public_exercises_count = 0
@public_exercises = []
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("题库调用失败!")
raise ActiveRecord::Rollback
end
end
end
#立即发布的弹窗内容
def publish_modal
ActiveRecord::Base.transaction do
begin
exercise_ids = params[:check_ids]
if exercise_ids.count > 0
@course_groups = get_user_permission_course(exercise_ids,1)
else
@course_groups = []
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
end
end
end
#首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。
def publish
tip_exception("缺少截止时间参数") if params[:end_time].blank?
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
ActiveRecord::Base.transaction do
begin
check_ids = Exercise.where(id: params[:check_ids])
ex_end_time = params[:end_time].blank? ? Time.at(((1.month.since.to_i)/3600.0).ceil * 3600) : params[:end_time].to_time
check_ids.each do |exercise|
if exercise.present?
if exercise.unified_setting
ex_status = exercise.exercise_status #则为试卷的状态
else
ex_status = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",params[:group_ids])
.exercise_group_not_published.present? ? 1 : 0
end
if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过
g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改
if g_course
user_course_groups = @course.charge_group_ids(current_user)
if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则试卷不用分组,且试卷设定为统一设置,否则则分组设置
exercise.exercise_group_settings.destroy_all
ex_unified = true
e_time = ex_end_time
else
ex_unified = false
g_course.each do |i|
exercise_group_setting = exercise.exercise_group_settings.find_in_exercise_group("course_group_id",i).first #根据课堂分班的id寻找试卷所在的班级
if exercise_group_setting #如果该试卷分组存在,则更新,否则新建
exercise_group_setting.update_attributes(publish_time:Time.now,end_time:ex_end_time)
else
p_course_group = {
:exercise_id => exercise.id,
:course_group_id => i,
:course_id => exercise.course.id,
:publish_time => Time.now,
:end_time => ex_end_time,
}
new_exercise_group = exercise.exercise_group_settings.new p_course_group
new_exercise_group.save
end
end
# group_ids = params[:group_ids]
e_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time).max
end
else
exercise.exercise_group_settings.destroy_all
ex_unified = true
e_time = ex_end_time
end
ex_status = set_exercise_status(Time.now,e_time)
exercise_params = {
:publish_time => Time.now,
:end_time => e_time,
:exercise_status => ex_status,
:unified_setting => ex_unified
}
exercise.update_attributes(exercise_params)
if exercise.course_acts.size == 0
exercise.course_acts << CourseActivity.new(:user_id => exercise.user_id,:course_id => exercise.course_id)
end
ExercisePublishNotifyJob.perform_later(exercise.id, g_course)
end
end
end
normal_status(0, "试卷发布成功!")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷发布失败")
raise ActiveRecord::Rollback
end
end
end
#立即截止的弹窗内容
def end_modal
ActiveRecord::Base.transaction do
begin
exercise_ids = params[:check_ids]
if exercise_ids.count > 0
@course_groups = get_user_permission_course(exercise_ids,3)
else
@course_groups = []
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
end
end
end
# 首页批量或单独 立即截止,截止时间为当前时间
def end_exercise
ActiveRecord::Base.transaction do
begin
check_ids = Exercise.where(id:params[:check_ids])
course_students = @course.students #课堂的全部学生数
check_ids.each do |exercise|
exercise_status= exercise.get_exercise_status(current_user)
if exercise_status == Exercise::PUBLISHED #跳过已截止的或未发布的
g_course = params[:group_ids]
if g_course.present?
teacher_course_group_ids = @course.charge_group_ids(current_user)
if g_course.map(&:to_i).sort == teacher_course_group_ids.sort #开始为统一设置
exercise.exercise_group_settings.destroy_all
new_ex_status = set_exercise_status(exercise.publish_time,Time.now)
exercise.update_attributes(:end_time => Time.now,:unified_setting => true,:exercise_status => new_ex_status)
exercise_users = exercise.exercise_users
else
course_members_ids = course_students.course_find_by_ids("course_group_id",g_course).pluck(:user_id).uniq #该班级的全部学生
exercise_users = exercise.exercise_users.exercise_commit_users(course_members_ids) #参与答题的学生数
ex_group_setting = exercise.exercise_group_settings
old_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id",g_course) #试卷的分组设置
left_course_groups = teacher_course_group_ids - g_course
left_exercise_groups = ex_group_setting.find_in_exercise_group("course_group_id",left_course_groups)
if left_exercise_groups.blank? && exercise.unified_setting
if left_course_groups.size > 0 #开始为统一设置但是立即截止为分班。则创建没有立即截止的班级的exercise_group_setting
left_course_groups.each do |g|
ex_group_options = {
:exercise_id => exercise.id,
:course_group_id => g,
:course_id => @course.id,
:publish_time => exercise.publish_time,
:end_time => exercise.end_time
}
ExerciseGroupSetting.create(ex_group_options)
end
end
end
if old_exercise_groups.present?
old_exercise_groups.update_all(:end_time => Time.now)
else
g_course.each do |g|
ex_group_options = {
:exercise_id => exercise.id,
:course_group_id => g,
:course_id => @course.id,
:publish_time => exercise.publish_time,
:end_time => Time.now
}
ExerciseGroupSetting.create(ex_group_options)
end
end
new_end_time = exercise.exercise_group_settings.end_time_no_null.map(&:end_time) # 试卷结束时间不为空的
new_end_time_s = new_end_time.count > 0 ? new_end_time.max : Time.now
new_ex_status = set_exercise_status(exercise.publish_time,new_end_time_s)
exercise.update_attributes(:end_time => new_end_time_s,:exercise_status => new_ex_status,:unified_setting => false)
end
else
exercise_users = exercise.exercise_users
exercise.update_attributes(:exercise_status => 3, :end_time => Time.now,:unified_setting => true)
end
exercise_users.each do |user|
if user.commit_status == 0 && user.start_at.present?
objective_score = calculate_student_score(exercise,user.user)[:total_score]
user_sub_score = user.subjective_score
subjective_score = user_sub_score < 0.0 ? 0.0 : user_sub_score
total_score = objective_score + subjective_score
commit_option = {
:status => 1,
:commit_status => 1,
:end_at => Time.now,
:objective_score => objective_score,
:score => total_score,
:subjective_score => user_sub_score
}
user.update_attributes(commit_option)
end
end
end
end
normal_status(0, "试卷截止成功!")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("立即截止失败!")
raise ActiveRecord::Rollback
end
end
end
#学生撤销回答
def cancel_exercise
ActiveRecord::Base.transaction do
begin
ex_question_ids = @exercise.exercise_questions.pluck(:id)
exercise_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first
if exercise_user.present?
if exercise_user.commit_status == 1 && @exercise.get_exercise_status(current_user) == Exercise::PUBLISHED #用户已提交且试卷提交中
if @exercise.time == -1 || ((Time.now.to_i - exercise_user.start_at.to_i) < @exercise.time.to_i * 60)
exercise_user.update_attributes(:score => nil, :end_at => nil, :status => nil, :commit_status => 0,
:objective_score => 0.0, :subjective_score => -1.0)
exercise_user.user.exercise_shixun_answers.search_shixun_answers("exercise_question_id",ex_question_ids).destroy_all
exercise_answers = exercise_user.user.exercise_answers.search_answer_users("exercise_question_id",ex_question_ids)
exercise_answers.update_all(:score => -1.0)
all_answer_comment = ExerciseAnswerComment.search_answer_comments("exercise_question_id",ex_question_ids)
.search_answer_comments("exercise_answer_id",exercise_answers.pluck(:id))
all_answer_comment.destroy_all
normal_status(0,"撤销回答成功")
else
normal_status(-1,"用户答题时间已到")
end
else
normal_status(-1,"用户未提交/试卷不是提交中")
end
else
normal_status(-1,"当前用户未答题")
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败")
raise ActiveRecord::Rollback
end
end
end
#打回重做modal
def redo_modal
ActiveRecord::Base.transaction do
begin
#搜索
if params[:realname].present?
search_name = params[:realname]
#搜索用户的nickname,如果存在则返回,否则继续查询用户的真实姓名或学生号
@exercise_users = @exercise_users.includes(:user).where("LOWER(concat(users.lastname, users.firstname)) like ?",
"%#{search_name}%")
end
if params[:student_id].present?
search_st_id = params[:student_id].to_i
@exercise_users = @exercise_users.includes(user: [:user_extension])
.where('user_extensions.student_id like ?',"%#{search_st_id}%")
end
sort = params[:sort] ? params[:sort] : "asc"
@exercise_users = @exercise_users.order("score #{sort}")
@exercise_users_size = @exercise_users.size
# 分页
page = params[:page] || 1
limit = params[:limit] || 15
@exercise_users = @exercise_users.page(page).per(limit)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
end
end
end
#打回重做确认
def redo_exercise
ActiveRecord::Base.transaction do
begin
user_ids = params[:user_ids]
if user_ids.present?
redo_option = {
:score => 0.0,
:start_at => nil,
:end_at => nil,
:status => nil,
:commit_status => 0,
:objective_score => 0.0,
:subjective_score => -1.0
}
redo_exercise_users = @exercise_users.exercise_commit_users(user_ids)
redo_exercise_users.update_all(redo_option)
exercise_question_ids = @exercise.exercise_questions.pluck(:id).uniq
ExerciseAnswer.search_answer_users("user_id",user_ids)
.search_answer_users("exercise_question_id",exercise_question_ids).destroy_all
ExerciseShixunAnswer.search_shixun_answers("user_id",user_ids)
.search_shixun_answers("exercise_question_id",exercise_question_ids).destroy_all
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 start_answer
ActiveRecord::Base.transaction do
begin
ex_users_current = ExerciseUser.where(user_id:@exercise_current_user_id,exercise_id:@exercise.id) #不能用@exercise.exercise_users因为exercise_users删除时只是状态改变未删除
@exercise_user_current = ex_users_current&.first
if ex_users_current.exists?
if @exercise_user_current.start_at.blank?
@exercise_user_current.update_attribute("start_at",Time.now)
end
else
if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候不创建exercise_user表理论上老师是不能进入答题的
exercise_user_params = {
:user_id => @exercise_current_user_id,
:exercise_id => @exercise.id,
:start_at => Time.now
}
exercise_user_current = ExerciseUser.new(exercise_user_params)
exercise_user_current.save
end
end
@t_user_exercise_status = @exercise.get_exercise_status(current_user)
@user_left_time = nil
if @user_course_identity < Course::STUDENT || (@t_user_exercise_status == 3) ||
(ex_users_current.exists? && @exercise_user_current.commit_status == 1)
@user_exercise_status = 1 #当前用户为老师/试卷已截止/试卷已提交不可编辑
else
@user_left_time = get_exercise_left_time(@exercise,current_user)
@user_exercise_status = 0 #可编辑
end
@exercise_questions = @exercise.exercise_questions
if @exercise.question_random
@exercise_questions = @exercise_questions.order("RAND()")
else
@exercise_questions = @exercise_questions.order("question_number ASC")
end
# 判断问题是否已回答还是未回答
@exercise_questions = @exercise_questions.includes(:exercise_shixun_challenges,
:exercise_shixun_answers,
:exercise_answers,
:exercise_standard_answers)
if @t_user_exercise_status == Exercise::DEADLINE
get_each_student_exercise(@exercise.id,@exercise_questions,@exercise_current_user_id)
end
get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,@t_user_exercise_status)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
end
end
end
#提交试卷前的弹窗
def begin_commit
ActiveRecord::Base.transaction do
begin
if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时
@exercise_questions = @exercise.exercise_questions
@shixun_undo = 0
@ques_undo = 0
ex_answer_time = @exercise.time.to_i
@ex_end_time = @exercise.get_exercise_end_time(current_user.id)
if ex_answer_time > 0
exercise_end_time = @exercise.exercise_users.exercise_commit_users(current_user.id)
if exercise_end_time.present?
ex_end_times = exercise_end_time.first.start_at.nil? ? Time.now : exercise_end_time.first.start_at
@ex_end_time = ex_end_times + ex_answer_time.minutes
end
end
@exercise_questions.each do |q|
if q.question_type == Exercise::PRACTICAL #当为实训题时
user_myshixun = q.shixun.myshixuns.search_myshixun_user(current_user.id)
if user_myshixun.blank? || user_myshixun.first.status != Exercise::UNPUBLISHED #当前用户的实训是否做完
@shixun_undo += 1
end
else
ques_vote = q.exercise_answers.search_exercise_answer("user_id",current_user.id)
if ques_vote.blank?
@ques_undo += 1
end
end
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷提交失败!")
raise ActiveRecord::Rollback
end
end
end
# 学生提交试卷
def commit_exercise
ActiveRecord::Base.transaction do
begin
if @user_course_identity > Course::ASSISTANT_PROFESSOR #为学生时
objective_score = calculate_student_score(@exercise,current_user)[:total_score]
subjective_score = @answer_committed_user.subjective_score
total_score_subjective_score = subjective_score < 0.0 ? 0.0 : subjective_score
total_score = objective_score + total_score_subjective_score
commit_option = {
:status => 1,
:commit_status => 1,
:end_at => Time.now,
:objective_score => objective_score,
:score => total_score,
:subjective_score => subjective_score
}
@answer_committed_user.update_attributes(commit_option)
normal_status(0,"试卷提交成功!")
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("试卷提交失败!")
raise ActiveRecord::Rollback
end
end
end
#教师评阅试卷 及学生查看试卷
def review_exercise
ActiveRecord::Base.transaction do
begin
# 1 老师权限0 学生权限
@is_teacher_or = (@user_course_identity < Course::STUDENT) ? 1 : 0
@student_status = 2
@exercise_questions = @exercise.exercise_questions.includes(:exercise_shixun_challenges,:exercise_standard_answers,:exercise_answers,:exercise_shixun_answers).order("question_number ASC")
@question_status = []
get_exercise_status = @exercise.get_exercise_status(current_user) #当前用户的试卷状态
@ex_answer_status = @exercise.get_exercise_status(@ex_user&.user) #当前试卷用户的试卷状态
if @ex_user.present? && @is_teacher_or == 0
if get_exercise_status == Exercise::PUBLISHED #当前用户已提交,且试卷未截止
if @ex_user.commit_status == 0 #学生未提交,且当前为学生
@student_status = 0
else
@student_status = 1
get_user_answer_status(@exercise_questions,@exercise_current_user_id,@exercise,get_exercise_status)
end
end
end
if @student_status == 2
get_each_student_exercise(@exercise.id,@exercise_questions,@exercise_current_user_id)
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
end
end
end
#答题列表
def exercise_lists
ActiveRecord::Base.transaction do
begin
@current_user_id = current_user.id
exercise_ids = [@exercise.id]
@exercise_status = @exercise.get_exercise_status(current_user)
@course_all_members = @course.students
@c_group_counts = @course.course_groups_count
question_types = @exercise.exercise_questions.pluck(:question_type).uniq
@exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).count #判断是否有已发布的分班
@exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).count #判断是否有未发布的分班
if (question_types.size > 1) && question_types.include?(Exercise::SUBJECTIVE) #是否包含主观题,或者是否大于1
@subjective_type = 1
else
@subjective_type = 0
end
#初始化值
@exercise_users_list = [] #答题用户列表
@exercise_course_groups = [] #当前用户有权限的班级
@exercise_unanswers = 0 # 未答用户数
@exercise_answers = 0 #已答用户数
@exercise_users_count = 0 #全部用户数
@teacher_review_count = 0 #已评数
@teacher_unreview_count = 0 #未评数
#试卷的答题列表页的显示用户
if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的试卷
@exercise_current_user_status = 0
unless @exercise_status == Exercise::UNPUBLISHED
ex_common_ids = @exercise.common_published_ids(current_user.id)
@exercise_course_groups = @course.get_ex_published_course(ex_common_ids)
@exercise_users_list = @exercise.all_exercise_users(current_user.id) #当前老师所在班级的全部学生
get_exercise_answers(@exercise_users_list, @exercise_status)
end
else #当前为学生或者有过答题的
@ex_user_end_time = @exercise.get_exercise_end_time(current_user.id) #当前用户所看到的剩余时间
@exercise_all_users = @exercise.get_stu_exercise_users
get_exercise_answers(@exercise_all_users, @exercise_status) # 未答和已答的
exercise_current_user = @exercise_all_users.exercise_commit_users(current_user.id)
if exercise_current_user.exists? #表示为课堂学生或已回答的
@exercise_current_user_status = 1
if @exercise.score_open && @exercise_status == Exercise::DEADLINE #勾选了成绩公开且试卷已截止的
all_user_ids = @exercise_all_users.pluck(:user_id)
all_user_ids.delete(current_user.id) #删除了当前用户的ID
@exercise_users_list = @exercise_all_users.exercise_commit_users(all_user_ids).distinct
@current_user_ex_answers = exercise_current_user #当前用户的回答
else
@exercise_users_list = exercise_current_user
end
else #表示为未回答的,或未非课堂成员的
@exercise_current_user_status = 2 #当前用户非课堂成员
end
end
if @exercise_unanswers < 0
@exercise_unanswers = 0
end
#筛选/分类,排序
order = params[:order]
if @exercise_users_list.present? && @exercise_users_list.size > 0
@exercise_users_count = @exercise_users_list.size #当前显示的全部成员数量
teacher_reviews = @exercise_users_list.exercise_review
teacher_unreviews = @exercise_users_list.exercise_unreview
@teacher_review_count = teacher_reviews.size #已评阅
@teacher_unreview_count = teacher_unreviews.size #未评阅
#是否评阅
if params[:review].present?
review_type = params[:review].first.to_i #已评则数据为1未评则数据为0,前端传过来的为数组
if review_type == 1
@exercise_users_list = teacher_reviews
else
@exercise_users_list = teacher_unreviews
end
end
#答题状态的选择
if params[:commit_status].present?
choose_type = params[:commit_status]
@exercise_users_list = @exercise_users_list.commit_exercise_by_status(choose_type)
end
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) #试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_users_list = @exercise_users_list.exercise_commit_users(user_ids)
end
#搜索
if params[:search].present?
@exercise_users_list = @exercise_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
exercise_user_joins = @exercise_users_list.joins(user: :user_extension)
if order == "student_id"
@exercise_users_list = exercise_user_joins.order("user_extensions.student_id DESC")
elsif order == "score"
@exercise_users_list = exercise_user_joins.order("#{order} DESC")
else
@exercise_users_list = exercise_user_joins.order("end_at DESC, start_at DESC")
end
@export_ex_users = @exercise_users_list
@exercise_users_size = @exercise_users_list.size
# 分页
@page = params[:page] || 1
@limit = params[:limit] || 20
@exercise_users_list = @exercise_users_list.page(@page).per(@limit)
else
@exercise_users_list = []
@export_ex_users = @exercise_users_list
@exercise_users_size = 0
end
if params[:format] == "xlsx"
if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作")
elsif @exercise_status == Exercise::UNPUBLISHED
normal_status(-1,"试卷未发布")
elsif (@exercise_users_size == 0) || ( @export_ex_users&.exercise_user_committed.size == 0)
normal_status(-1,"暂无用户提交")
else
respond_to do |format|
format.xlsx{
get_export_users(@exercise,@course,@export_ex_users)
exercise_export_name_ =
"#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{exercise_export_name_.strip.first(30)}",template: "exercises/exercise_lists.xlsx.axlsx",locals: {table_columns:@table_columns,exercise_users:@user_columns}
}
end
end
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
raise ActiveRecord::Rollback
end
end
end
#导出空白试卷
def export_exercise
@request_url = request.base_url
@exercise_questions = @exercise.exercise_questions.includes(:exercise_choices).order("question_number ASC")
filename_ = "#{@exercise.user.real_name}_#{@course.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.pdf"
stylesheets = "#{Rails.root}/app/templates/exercise_export/exercise_export.css"
render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets
end
#空白试卷预览页面,仅供测试使用,无其他任何用途
# def blank_exercise
# ActiveRecord::Base.transaction do
# begin
# @exercise_questions = @exercise.exercise_questions.order("question_number ASC")
# challenge_ids = @exercise_questions.joins(:exercise_shixun_challenges).pluck("exercise_shixun_challenges.challenge_id")
# get_each_student_exercise(@exercise.id,@exercise_questions,31798)
# @games = @exercise_user.user.games.ch_games(challenge_ids)
# respond_to do |format|
# format.html
# end
# rescue Exception => e
# uid_logger_error(e.message)
# tip_exception("没有权限")
# raise ActiveRecord::Rollback
# end
# end
# end
#学生的统计结果
def exercise_result
ActiveRecord::Base.transaction do
begin
exercise_ids = [@exercise.id]
@exercise_publish_count = get_user_permission_course(exercise_ids,Exercise::PUBLISHED).size #判断是否有已发布的分班
@exercise_unpublish_count = get_user_permission_course(exercise_ids,Exercise::UNPUBLISHED).size #判断是否有未发布的分班
@course_all_members = @course.students #课堂的全部学生
@exercise_all_users = @exercise.exercise_users
ex_common_ids = @exercise.common_published_ids(current_user.id)
@exercise_course_groups = @course.get_ex_published_course(ex_common_ids)
#班级的选择
if params[:exercise_group_id].present?
group_id = params[:exercise_group_id]
exercise_students = @course_all_members.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@exercise_all_users = @exercise.exercise_users.exercise_commit_users(user_ids)
@course_all_members_count = @exercise_all_users.size
else
@exercise_users_list = @exercise.all_exercise_users(current_user.id)
@course_all_members_count = @exercise_users_list.size
end
@exercise_commit_users = @exercise_all_users.commit_exercise_by_status(1) #试卷的已提交用户
@exercise_commit_user_ids = @exercise_commit_users.pluck(:user_id).uniq #已提交试卷的全部用户id
@exercise_commit_user_counts = @exercise_commit_users.size #试卷的已提交用户人数
@exercise_status = @exercise.get_exercise_status(current_user)
#提交率
if @course_all_members_count == 0
commit_percent = 0.00
min_score = 0.0
max_score = 0.0
average_score = 0.0
fail_counts = 0
pass_counts = 0
good_counts = 0
best_counts = 0
else
commit_percent = (@exercise_commit_user_counts / @course_all_members_count.to_f).round(3)
exercise_scores = @exercise_commit_users.pluck(:score).reject(&:blank?)
min_score = exercise_scores.min.present? ? exercise_scores.min : 0.0
max_score = exercise_scores.max.present? ? exercise_scores.max : 0.0
total_score = exercise_scores.sum.present? ? exercise_scores.sum : 0.0
average_score = @exercise_commit_user_counts > 0 ? (total_score / @exercise_commit_user_counts).round(1) : 0.0
fail_counts = exercise_scores.count{|a| a < 60.0}
pass_counts = exercise_scores.count{|a| a < 70.0 && a >= 60.0}
good_counts = exercise_scores.count{|a| a < 90.0 && a >= 70.0}
best_counts = exercise_scores.count{|a| a >= 90.0 && a <= 100.0}
end
@counts_array = {
:commit_percent => commit_percent,
:min_score => min_score.to_s,
:max_score => max_score.to_s,
:average_score => average_score.to_s,
:fail_counts => fail_counts,
:pass_counts => pass_counts,
:good_counts => good_counts,
:best_counts => best_counts,
}
@exercise_questions = @exercise.exercise_questions&.includes(:exercise_choices,:exercise_answers,:exercise_standard_answers,:exercise_shixun_challenges,:exercise_shixun_answers)
@paging_type = "percent"
# 按题型排序
if params[:sort].present?
@paging_type = params[:sort].to_s
end
ques_result_all = exercise_commit_result(@exercise_questions,@exercise_commit_user_ids)
if @paging_type == "percent"
@question_result_hash = ques_result_all.sort_by{|s| s[:percent]}
else
@question_result_hash = ques_result_all.sort_by{|s| s[:"#{@paging_type}"]}
end
@exercise_questions_count = @exercise_questions.size
@page = params[:page] || 1
@limit = params[:limit] || 10
@question_result_hash = Kaminari.paginate_array(@question_result_hash).page(@page).per(@limit)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
raise ActiveRecord::Rollback
end
end
end
private
def exercise_params
params.require(:exercise).permit(:exercise_name, :exercise_description, :course_id, :exercise_status, :user_id, :time,
:publish_time, :end_time, :show_result, :question_random, :choice_random, :is_public,
:score_open, :answer_open, :exercise_bank_id, :unified_setting, :show_statistic)
end
def is_course_teacher
unless @user_course_identity < Course::STUDENT #为老师/助教/管理员
normal_status(403, "...")
end
end
#检查传入的参数内容是否符合
def validates_exercise_params
normal_status(-1, "试卷标题不能为空!") if params[:exercise_name].blank?
normal_status(-1, "试卷标题不能超过60个字符") if (params[:exercise_name].length > 60)
normal_status(-1, "试卷须知不能超过100个字符") if (params[:exercise_description].present? &&
params[:exercise_description].length > 100)
end
#判断设置的时间是否合理
def validate_publish_time
# 截止时间存在,且截止时间必须大于当前时间或发布时间
unified_setting = params[:unified_setting]
publish_course = params[:publish_time_groups]
if @course.is_end
normal_status(-1,"课堂已结束不能再修改")
elsif unified_setting
ex_group_settings = @exercise.exercise_group_settings
if ex_group_settings.present?
p_time_present = ex_group_settings.publish_time_no_null.map(&:publish_time).min
if p_time_present < Time.now
normal_status(-1,"设置失败,存在已发布的分班")
end
elsif params[:publish_time].blank?
normal_status(-1,"发布时间不允许为空")
end
elsif unified_setting.present? && !unified_setting #非统一设置,分班不能为空
if publish_course.present?
course_ids = publish_course.map{|a| a[:course_group_id]}.sum
publish_t = publish_course.map{|a| a[:publish_time]}
if course_ids.include?(nil) || course_ids.count == 0
normal_status(-1,"请选择分班")
elsif publish_t.include?(nil) || publish_t.count == 0
normal_status(-1,"发布时间不允许为空")
end
else
normal_status(-1,"请选择分班")
end
end
end
def get_exercise
@exercise = Exercise.find_by(id:params[:id])
if @exercise.blank?
normal_status(404,"试卷不存在")
else
@course = @exercise.course
normal_status(404,"课堂不存在") if @course.blank?
end
end
def get_exercise_question_counts #获取试卷的问题数及总分数
exercise_questions = @exercise.exercise_questions
@exercise_ques_count = exercise_questions.size # 全部的题目数
@exercise_ques_scores = exercise_questions.pluck(:question_score).sum
#单选题的数量及分数
exercise_single_ques = exercise_questions.find_by_custom("question_type",Exercise::SINGLE)
@exercise_single_ques_count = exercise_single_ques.size
@exercise_single_ques_scores = exercise_single_ques.pluck(:question_score).sum
#多选题的数量及分数
exercise_double_ques = exercise_questions.find_by_custom("question_type",Exercise::MULTIPLE)
@exercise_double_ques_count = exercise_double_ques.size
@exercise_double_ques_scores = exercise_double_ques.pluck(:question_score).sum
# 判断题数量及分数
exercise_ques_judge = exercise_questions.find_by_custom("question_type",Exercise::JUDGMENT)
@exercise_ques_judge_count = exercise_ques_judge.size
@exercise_ques_judge_scores = exercise_ques_judge.pluck(:question_score).sum
#填空题数量及分数
exercise_ques_null = exercise_questions.find_by_custom("question_type",Exercise::COMPLETION)
@exercise_ques_null_count = exercise_ques_null.size
@exercise_ques_null_scores = exercise_ques_null.pluck(:question_score).sum
#简答题数量及分数
exercise_ques_main = exercise_questions.find_by_custom("question_type",Exercise::SUBJECTIVE)
@exercise_ques_main_count = exercise_ques_main.size
@exercise_ques_main_scores = exercise_ques_main.pluck(:question_score).sum
#实训题数量及分数
exercise_ques_shixun = exercise_questions.find_by_custom("question_type",Exercise::PRACTICAL)
@exercise_ques_shixun_count = exercise_ques_shixun.size
@exercise_ques_shixun_scores = exercise_ques_shixun.pluck(:question_score).sum
@exercise_questions = @exercise_questions&.includes(:exercise_choices,:exercise_shixun_challenges,:exercise_answers,:exercise_shixun_answers,:exercise_answer_comments,:exercise_standard_answers)
end
#获取用户有权限的分班
def get_user_permission_course(exercise_ids,status)
exercise_status = status.to_i #传入的试卷发布状态
unpublish_group = []
course_groups = []
user_groups_id = @course.charge_group_ids(current_user)
exercises_all = Exercise.includes(:exercise_group_settings).where(id:exercise_ids)
exercises_all.each do |exercise|
if exercise.present?
if exercise.unified_setting #统一设置只有两种情况,全部发布,全部截止
exercise_user_status = exercise.get_exercise_status(current_user) #当前用户的能看到的试卷
if (exercise_user_status == exercise_status) || exercise_status == Exercise::DEADLINE #未发布的情况
unpublish_group = unpublish_group + user_groups_id
end
else
ex_all_group_settings = exercise.exercise_group_settings
ex_group_settings = ex_all_group_settings.exercise_group_published.pluck(:course_group_id).uniq #问卷设置的班级
if exercise_status == Exercise::UNPUBLISHED
unpublish_group = user_groups_id - ex_group_settings
elsif exercise_status == Exercise::DEADLINE
ex_ended_groups = ex_all_group_settings.exercise_group_ended.pluck(:course_group_id).uniq
ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班
unpublish_group = unpublish_group + ex_and_user - ex_ended_groups #已发布的全部班级减去截止的全部班级
else
ex_and_user = user_groups_id & ex_group_settings #用户已设置的分班
unpublish_group = unpublish_group + ex_and_user
end
end
end
end
unpublish_group = unpublish_group.uniq
if unpublish_group.count > 0
course_groups = CourseGroup.by_group_ids(unpublish_group)
end
course_groups
end
def set_exercise_status(publish_time,end_time)
time_now_i = Time.now
if publish_time.present? && (publish_time <= time_now_i) && (end_time > time_now_i)
2
elsif publish_time.nil? || (publish_time.present? && publish_time > time_now_i)
1
elsif end_time.present? && (end_time <= time_now_i)
3
elsif end_time.present? && publish_time.present? && (end_time < publish_time)
normal_status(-1,"时间设置错误!")
else
1
end
end
def check_course_public
unless @course.is_public == 1 # 0为私有1为公开
normal_status(403,"...")
end
end
def check_user_id_start_answer #判断用户在开始答题时是否有用户id传入,如果为老师则id必需否则为当前用户的id
user_login = params[:login]
# exercise_current_user_id = params[:user_id]
if user_login.blank? && @user_course_identity < Course::STUDENT #id不存在且当前为老师/管理员等
normal_status(-1,"请输入学生登陆名!")
else
@ex_answerer = User.find_by(login: user_login) #回答者
if @ex_answerer.blank?
normal_status(404,"答题用户不存在")
else
@exercise_current_user_id = @ex_answerer.id || current_user.id
end
end
end
## 判断开始答题页面的用户权限
def check_user_on_answer
if @user_course_identity == Course::STUDENT && @exercise.get_exercise_status(current_user) == Exercise::UNPUBLISHED #试卷未发布,且当前用户不为老师/管理员
normal_status(-1, "未发布试卷!")
elsif @user_course_identity > Course::STUDENT && (!@exercise.is_public || (@exercise.is_public && !@exercise.unified_setting)) ##不为课堂成员,且试卷不为公开的,或试卷公开,但不是统一设置的
normal_status(-1, "试卷暂未公开!")
end
end
def check_exercise_time
@answer_committed_user = @exercise.exercise_users.exercise_commit_users(current_user.id)&.first
if @answer_committed_user.blank?
normal_status(404,"答题用户不存在")
end
end
#打回重做时的初步判断
def check_exercise_status
@exercise_users = @exercise.all_exercise_users(current_user.id).commit_exercise_by_status(1) #当前教师所在分班的全部已提交的学生数
if @exercise.get_exercise_status(current_user) != Exercise::PUBLISHED
normal_status(-1,"非提交中的试卷不允许打回重做!")
elsif @exercise_users.count < 1
normal_status(-1,"暂无人提交试卷!")
end
end
#查看试题页面,当为学生时,除非试卷已截止,或已提交才可以查看
def check_exercise_is_end
ex_status = @exercise.get_exercise_status(current_user)
@ex_user = @exercise.exercise_users.find_by(user_id:@exercise_current_user_id) #该试卷的回答者
if @user_course_identity > Course::ASSISTANT_PROFESSOR
if ex_status == Exercise::UNPUBLISHED
normal_status(-1,"试卷未发布")
elsif @ex_user.present? && @ex_user.commit_status == 0
normal_status(-1,"试卷未提交")
elsif params[:user_id].present? && current_user.id != params[:user_id]
normal_status(-1,"不能查看他人的试卷")
end
end
end
#查看试卷是否选择为公开统计
def check_exercise_public
if @user_course_identity > Course::ASSISTANT_PROFESSOR #当前为学生,试卷公开统计,且已截止,且已提交
ex_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first
unless @exercise.get_exercise_status(current_user) == Exercise::DEADLINE && ex_user.present? && ex_user.commit_status == 1 &&
@exercise.show_statistic
normal_status(-1,"学生暂不能查看")
end
end
end
def get_left_banner_id
left_banner_content = @course.course_modules.search_by_module_type("exercise")
if left_banner_content.present?
@left_banner_id = left_banner_content.first.id
@left_banner_name = left_banner_content.first.module_name
else
normal_status(404,"左侧导航不存在")
end
end
def get_user_answer_status(exercise_questions,user_id,exercise,exercise_user_status)
@question_status = []
@exercise_all_questions = []
ex_question_random = exercise.question_random
question_answered = 0
exercise_questions.each_with_index do |q,index|
if ex_question_random && exercise_user_status != Exercise::DEADLINE
ques_number = index + 1
else
ques_number = q.question_number
end
if q.question_type != Exercise::PRACTICAL
ques_vote = q.exercise_answers.search_exercise_answer("user_id",user_id)
else
ques_vote = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id)
end
ques_status = 0
if ques_vote.present?
if q.question_type == Exercise::PRACTICAL
if ques_vote.pluck(:exercise_shixun_challenge_id).sort == q.exercise_shixun_challenges.pluck(:id).sort #用户的总得分等于问题的分数
ques_status = 1 #全部回答了,才算已答
question_answered += 1
end
else #其他题目,需回答的有内容,才会为已答,否则如内容为空,视为未答
vote_answer_id = ques_vote.pluck(:exercise_choice_id).reject(&:blank?)
vote_text_count = ques_vote.pluck(:answer_text).reject(&:blank?).size
if q.question_type <= Exercise::JUDGMENT #选择题和判断题的时候,需要有选项,才算回答
if vote_answer_id.size > 0
ques_status = 1
question_answered += 1
end
elsif q.question_type == Exercise::COMPLETION #填空题的时候,需要有选项和内容,才算回答
if vote_answer_id.uniq.sort == q.exercise_standard_answers.pluck(:exercise_choice_id).uniq.sort
ques_status = 1
question_answered += 1
end
else
if vote_text_count > 0 #主观题,必选有内容,才算回答
ques_status = 1
question_answered += 1
end
end
end
end
question_status = {
:ques_id => q.id,
:ques_number => ques_number, #仅问题的显示位置变化但是问题的question_number 不会变化与之相关的choice/standard_answer/answer不会变化
:ques_status => ques_status,
}
question_options = {
:question => q,
:ques_number => ques_number,
}
@question_status = @question_status.push(question_status).sort_by {|k| k[:ques_number]}
@exercise_all_questions = @exercise_all_questions.push(question_options).sort_by {|k| k[:ques_number]}
end
end
#下一步也有check_on_users再进行判断
def only_student_in
if @user_course_identity < Course::STUDENT
normal_status(-1,"老师身份不允许进入")
end
end
#判断实训是否已选择
def commit_shixun_present
question_shixun_ids = @exercise.exercise_questions.pluck(:shixun_id).reject(&:blank?)
shixun_id = params[:shixun_id]
@shixun = Shixun.find_by(id: shixun_id)
if shixun_id.present? && question_shixun_ids.include?(shixun_id)
normal_status(-1,"该实训已选择!")
elsif @shixun.blank?
normal_status(-1,"该实训不存在!")
end
end
end