|  |  | class Exercise < ApplicationRecord
 | 
						
						
						
							|  |  |   belongs_to :course, counter_cache: true
 | 
						
						
						
							|  |  |   belongs_to :exercise_bank, optional: true
 | 
						
						
						
							|  |  |   belongs_to :user
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   has_many :exercise_users, -> { where("is_delete = 0") }, :dependent => :delete_all
 | 
						
						
						
							|  |  |   has_many :score_exercise_users, -> { where("is_delete = 0 and commit_status != 0").order("score desc") }, class_name: "ExerciseUser"
 | 
						
						
						
							|  |  |   has_many :exercise_questions, :dependent => :delete_all
 | 
						
						
						
							|  |  |   has_many :exercise_group_settings, :dependent => :delete_all
 | 
						
						
						
							|  |  |   has_many :published_settings, -> { exercise_group_published }, class_name: "ExerciseGroupSetting"
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   has_many :tidings, as: :container
 | 
						
						
						
							|  |  |   has_many :course_acts, class_name: 'CourseActivity', as: :course_act, :dependent => :delete_all
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   scope :is_exercise_published, -> { where("exercise_status > ? ",1)}
 | 
						
						
						
							|  |  |   scope :unified_setting, -> { where("unified_setting = ?",true) }
 | 
						
						
						
							|  |  |   scope :exercise_by_ids, lambda { |ids| where(id: ids) unless ids.blank? }
 | 
						
						
						
							|  |  |   scope :exercise_by_status, lambda { |s| where(exercise_status: s) unless s.blank? }
 | 
						
						
						
							|  |  |   scope :exercise_search, lambda { |keywords|
 | 
						
						
						
							|  |  |     where("exercise_name LIKE ?", "%#{keywords}%") unless keywords.blank?}
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   validates :exercise_name, length: { maximum: 60, too_long: "60 characters is the maximum allowed" }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   after_create :create_exercise_list
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # 试卷的问题类型
 | 
						
						
						
							|  |  |   SINGLE = 0   #单选题
 | 
						
						
						
							|  |  |   MULTIPLE = 1  #多选题
 | 
						
						
						
							|  |  |   JUDGMENT = 2  #判断题
 | 
						
						
						
							|  |  |   COMPLETION = 3 # 填空题
 | 
						
						
						
							|  |  |   SUBJECTIVE = 4 # 主观题
 | 
						
						
						
							|  |  |   PRACTICAL = 5  #实训题
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # 试卷的状态
 | 
						
						
						
							|  |  |   UNPUBLISHED = 1  #未发布
 | 
						
						
						
							|  |  |   PUBLISHED = 2    #已发布
 | 
						
						
						
							|  |  |   DEADLINE = 3    #已截止
 | 
						
						
						
							|  |  |   ENDED = 4      #课堂已结束
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   def question_scores
 | 
						
						
						
							|  |  |     exercise_questions.pluck(:question_score).sum
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   def subjective_score
 | 
						
						
						
							|  |  |     exercise_questions.where(question_type: [4]).pluck(:question_score).sum
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   def objective_score
 | 
						
						
						
							|  |  |     exercise_questions.where(question_type: [0, 1, 2, 3, 5]).pluck(:question_score).sum
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   def create_exercise_list
 | 
						
						
						
							|  |  |     str = ""
 | 
						
						
						
							|  |  |     # TODO: 一次性为所有学生创建数据是否存在问题?
 | 
						
						
						
							|  |  |     self.course.students.find_each do |student|
 | 
						
						
						
							|  |  |       str += "," if str != ""
 | 
						
						
						
							|  |  |       str += "(#{student.user_id}, #{self.id}, 0, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')"
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     if str != ""
 | 
						
						
						
							|  |  |       sql = "insert into exercise_users (user_id, exercise_id, commit_status, created_at, updated_at) values" + str
 | 
						
						
						
							|  |  |       ActiveRecord::Base.connection.execute sql
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   #获取学生视角的试卷用户
 | 
						
						
						
							|  |  |   def get_stu_exercise_users
 | 
						
						
						
							|  |  |     if unified_setting  #试卷统一设置
 | 
						
						
						
							|  |  |       exercise_users
 | 
						
						
						
							|  |  |     else
 | 
						
						
						
							|  |  |       ex_group_setting_ids = published_settings.pluck(:course_group_id)
 | 
						
						
						
							|  |  |       exercise_users.joins("join course_members on exercise_users.user_id=course_members.user_id").
 | 
						
						
						
							|  |  |           where(course_members: {course_group_id: ex_group_setting_ids})
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   def get_exercise_end_time(user_id)
 | 
						
						
						
							|  |  |     if unified_setting
 | 
						
						
						
							|  |  |       self&.end_time
 | 
						
						
						
							|  |  |     else
 | 
						
						
						
							|  |  |       user_course_group = course.students.find_by(user_id: user_id)&.course_group_id
 | 
						
						
						
							|  |  |       exercise_group_settings.find_by(course_group_id:user_course_group)&.end_time
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # 根据是否统一发布获取作业的作品列表
 | 
						
						
						
							|  |  |   def all_works
 | 
						
						
						
							|  |  |     ex_users = self.unified_setting ? exercise_users :
 | 
						
						
						
							|  |  |                         exercise_users.joins("join course_members on exercise_users.user_id=course_members.user_id").
 | 
						
						
						
							|  |  |                             where(course_members: {course_group_id: published_settings.pluck(:course_group_id)})
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # 分班权限的老师可见的作品列表
 | 
						
						
						
							|  |  |   def all_exercise_users(user_id)
 | 
						
						
						
							|  |  |     # member = course.course_member(user_id)
 | 
						
						
						
							|  |  |     teacher_course_groups = course.teacher_course_groups.where(user_id:user_id)
 | 
						
						
						
							|  |  |     ex_users = self.all_works
 | 
						
						
						
							|  |  |     # 有分班权限的统计管理的分班且已发布的学生情况
 | 
						
						
						
							|  |  |     if teacher_course_groups.exists?
 | 
						
						
						
							|  |  |       group_ids = teacher_course_groups.pluck(:course_group_id)
 | 
						
						
						
							|  |  |       ex_users = ex_users.joins("join course_members on exercise_users.user_id=course_members.user_id").
 | 
						
						
						
							|  |  |           where(course_members: {course_group_id: group_ids})
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |     ex_users
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   # #统一设置,为当前老师有权限的分班学生,分班设置,也为当前老师有权限的分班的学生
 | 
						
						
						
							|  |  |   # def all_exercise_users(user_id)
 | 
						
						
						
							|  |  |   #   ex_users = exercise_users
 | 
						
						
						
							|  |  |   #   group_ids = common_published_ids(user_id)
 | 
						
						
						
							|  |  |   #   if group_ids.present?
 | 
						
						
						
							|  |  |   #     ex_users = ex_users.joins("join course_members on exercise_users.user_id=course_members.user_id").
 | 
						
						
						
							|  |  |   #         where(course_members: {course_group_id: group_ids})
 | 
						
						
						
							|  |  |   #   end
 | 
						
						
						
							|  |  |   #   ex_users
 | 
						
						
						
							|  |  |   # end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   #当前用户已发布的班级id和试卷分组已发布的班级id的交集
 | 
						
						
						
							|  |  |   def common_published_ids(user_id)
 | 
						
						
						
							|  |  |     current_user_groups = course.teacher_course_ids(user_id)
 | 
						
						
						
							|  |  |     if unified_setting
 | 
						
						
						
							|  |  |       published_group_ids = current_user_groups
 | 
						
						
						
							|  |  |     else
 | 
						
						
						
							|  |  |       ex_group_setting = exercise_group_settings.select(:course_group_id).pluck("course_group_id").uniq
 | 
						
						
						
							|  |  |       common_all_ids = ex_group_setting & current_user_groups  #当前用户有权限的已发布的分班id #非统一设置时,为当前用户有权限的且已发布分班的id
 | 
						
						
						
							|  |  |       published_group_ids = common_all_ids.uniq
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |     published_group_ids
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   #判断用户是否属于试卷分班的学生中
 | 
						
						
						
							|  |  |   def check_user_in_course(user_id,user_identity)
 | 
						
						
						
							|  |  |     ex_group_settings = exercise_group_settings.pluck(:course_group_id)
 | 
						
						
						
							|  |  |     member = course.course_members.course_find_by_ids("user_id",user_id)
 | 
						
						
						
							|  |  |     member_group_id = member.pluck(:course_group_id).uniq
 | 
						
						
						
							|  |  |     ((member_group_id & ex_group_settings).size > 0 || user_identity < Course::STUDENT) ? true : false
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   #判断是否为分班,如果分班,试卷的截止时间为当前分班时间,否则为试卷的截止时间
 | 
						
						
						
							|  |  |   def get_exercise_status(user)
 | 
						
						
						
							|  |  |     if course.is_end
 | 
						
						
						
							|  |  |       status = 4
 | 
						
						
						
							|  |  |     else
 | 
						
						
						
							|  |  |       if user.present? && user.student_of_course?(course)   #当为学生的时候,需根据分班来判断试卷状态
 | 
						
						
						
							|  |  |         ex_time = get_exercise_times(user.id,false)
 | 
						
						
						
							|  |  |         pb_time = ex_time[:publish_time]
 | 
						
						
						
							|  |  |         ed_time = ex_time[:end_time]
 | 
						
						
						
							|  |  |         if pb_time.present? && ed_time.present? && pb_time <= Time.now && ed_time > Time.now
 | 
						
						
						
							|  |  |           status = Exercise::PUBLISHED
 | 
						
						
						
							|  |  |         elsif ed_time.present? && ed_time <= Time.now
 | 
						
						
						
							|  |  |           status = Exercise::DEADLINE
 | 
						
						
						
							|  |  |         else
 | 
						
						
						
							|  |  |           status = Exercise::UNPUBLISHED
 | 
						
						
						
							|  |  |         end
 | 
						
						
						
							|  |  |       else
 | 
						
						
						
							|  |  |         status = exercise_status   #当为老师的时候,则为试卷的总状态
 | 
						
						
						
							|  |  |       end
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |     status
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   #获取试卷的发布时间和截止时间。teacher 为boolean,当为true时,表示的是当前为老师
 | 
						
						
						
							|  |  |   def get_exercise_times(user_id,teacher)
 | 
						
						
						
							|  |  |     if unified_setting || teacher    #当试卷为统一设置或当前为老师的时候
 | 
						
						
						
							|  |  |       pb_time = publish_time
 | 
						
						
						
							|  |  |       en_time = end_time
 | 
						
						
						
							|  |  |       # if (exercise_status != 3) && en_time.present? && (en_time <= Time.now)
 | 
						
						
						
							|  |  |       #   update_column("exercise_status",3)
 | 
						
						
						
							|  |  |       # end
 | 
						
						
						
							|  |  |     else
 | 
						
						
						
							|  |  |       # ex_group_setting = exercise_group_settings
 | 
						
						
						
							|  |  |       user_group = course.students.where(user_id:user_id).select(:course_group_id)
 | 
						
						
						
							|  |  |       if user_group.exists?
 | 
						
						
						
							|  |  |         user_group_id = user_group.first&.course_group_id
 | 
						
						
						
							|  |  |         user_ex_group_setting = exercise_group_settings.where(course_group_id:user_group_id).select(:publish_time,:end_time)
 | 
						
						
						
							|  |  |         pb_time = user_ex_group_setting.first&.publish_time
 | 
						
						
						
							|  |  |         en_time = user_ex_group_setting.first&.end_time
 | 
						
						
						
							|  |  |       else
 | 
						
						
						
							|  |  |         pb_time = nil
 | 
						
						
						
							|  |  |         en_time = nil
 | 
						
						
						
							|  |  |       end
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |         "publish_time":pb_time,
 | 
						
						
						
							|  |  |         "end_time":en_time
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   #判断当前用户的答题状态
 | 
						
						
						
							|  |  |   def check_user_answer_status(user)
 | 
						
						
						
							|  |  |     ex_answer_user = exercise_users.where(user_id: user.id).select(:start_at,:end_at,:commit_status)
 | 
						
						
						
							|  |  |     user_ex_status = get_exercise_status(user)
 | 
						
						
						
							|  |  |     user_status = 2
 | 
						
						
						
							|  |  |     if ex_answer_user.present? && (ex_answer_user.first&.start_at.present? || ex_answer_user.first&.end_at.present?)   #学生有过答题的,或者立即截止,但学生未做试卷的
 | 
						
						
						
							|  |  |       user_status = ex_answer_user.first.commit_status
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |     if ex_answer_user.present? && ex_answer_user.first&.start_at.blank? && user_ex_status == 3
 | 
						
						
						
							|  |  |       user_status = 4
 | 
						
						
						
							|  |  |     end
 | 
						
						
						
							|  |  |     user_status
 | 
						
						
						
							|  |  |   end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | end
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 |