From dd974ffd29229d383ad71b21fa1a65359411e82d Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Wed, 17 Apr 2019 15:59:57 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E5=AE=9E=E8=AE=AD=E9=A2=98?= =?UTF-8?q?=E6=94=B9=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/exercise_controller.rb | 203 ++++++++++-------- app/helpers/exercise_helper.rb | 25 ++- app/models/exercise.rb | 29 ++- app/models/exercise_level_setting.rb | 5 + app/models/exercise_question.rb | 4 + app/models/exercise_user.rb | 2 + app/models/exercise_user_question.rb | 6 + app/views/exercise/_exercise_student.html.erb | 4 +- .../_exercise_student_result.html.erb | 6 +- ...17024319_create_exercise_level_settings.rb | 19 ++ ..._add_exercise_level_setting_to_question.rb | 12 ++ .../20190417024736_create_question_count.rb | 13 ++ ...17033935_create_exercise_user_questions.rb | 14 ++ spec/factories/exercise_level_settings.rb | 8 + spec/factories/exercise_user_questions.rb | 7 + spec/models/exercise_level_setting_spec.rb | 5 + spec/models/exercise_user_question_spec.rb | 5 + 17 files changed, 263 insertions(+), 104 deletions(-) create mode 100644 app/models/exercise_level_setting.rb create mode 100644 app/models/exercise_user_question.rb create mode 100644 db/migrate/20190417024319_create_exercise_level_settings.rb create mode 100644 db/migrate/20190417024510_add_exercise_level_setting_to_question.rb create mode 100644 db/migrate/20190417024736_create_question_count.rb create mode 100644 db/migrate/20190417033935_create_exercise_user_questions.rb create mode 100644 spec/factories/exercise_level_settings.rb create mode 100644 spec/factories/exercise_user_questions.rb create mode 100644 spec/models/exercise_level_setting_spec.rb create mode 100644 spec/models/exercise_user_question_spec.rb diff --git a/app/controllers/exercise_controller.rb b/app/controllers/exercise_controller.rb index 65a0b9e9..2dfc2601 100644 --- a/app/controllers/exercise_controller.rb +++ b/app/controllers/exercise_controller.rb @@ -73,8 +73,14 @@ class ExerciseController < ApplicationController @exercise_user = ExerciseUser.where("user_id=? and exercise_id=?", User.current.id, @exercise.id).first if @exercise_user.nil? @exercise_user = ExerciseUser.create(:user_id => User.current.id, :exercise_id => @exercise.id, :start_at => Time.now, :status => false, :commit_status => 0) + if @exercise.exercise_level_settings.where("num != exercise_questions_count").count > 0 + @exercise.create_user_question_list(@exercise_user) + end # @exercise_user = ExerciseUser.where("user_id=? and exercise_id=?", User.current.id, @exercise.id).first elsif @exercise_user.start_at.nil? + if @exercise.exercise_level_settings.where("num != exercise_questions_count").count > 0 + @exercise.create_user_question_list(@exercise_user) + end @exercise_user.update_attributes(:start_at => Time.now) end @@ -103,7 +109,9 @@ class ExerciseController < ApplicationController @exercise_user = ExerciseUser.where("user_id=? and exercise_id=?", params[:user_id], @exercise.id).first @can_edit_excercise = false end - Rails.logger.info("###########can_edit_excercise:#{@can_edit_excercise}") + + @exercise_questions = user_question_list @exercise_user.id + # @percent = get_percent(@exercise,User.current) #@exercise_questions = @exercise.exercise_questions respond_to do |format| @@ -139,11 +147,13 @@ class ExerciseController < ApplicationController else none_shixun_ids = ShixunSchool.where("school_id != #{User.current.user_extensions.try(:school_id)}").pluck(:shixun_id) end - @shixuns = Shixun.where("status = 2 and id not in (#{none_shixun_ids.join(",")})").where("name like ?", "%#{search}%").select{|shixun| shixun.challenges.where(:st => 1).count == 0} + @shixuns = Shixun.where("status = 2 and challenges_count = 1 and id not in (#{none_shixun_ids.join(",")})"). + where("name like ?", "%#{search}%").select{|shixun| shixun.challenges.where(:st => 1).count == 0} @limit = 8 @shixuns = paginateHelper @shixuns, @limit respond_to do |format| format.js + render json: exercise_shixun_json_data(@shixuns) end end @@ -977,118 +987,122 @@ class ExerciseController < ApplicationController # 已提交过的且是限时的则不允许答题 exercise_user = ExerciseUser.where(:exercise_id => @exercise.id, :user_id => User.current.id).first - if (exercise_user && exercise_user.commit_status == 1) || @exercise.end_time < Time.now - render :json => {:text => "Over"} - return - end - if eq.question_type == 1 - # 单选题 - ea = ExerciseAnswer.find_by_exercise_question_id_and_user_id(params[:exercise_question_id],User.current.id) - if ea.nil? - # 尚未答该题,添加答案 - ea = ExerciseAnswer.new - ea.user_id = User.current.id - ea.exercise_question_id = params[:exercise_question_id] - end - #修改该题对应答案 - ea.exercise_choice_id = params[:exercise_choice_id] - if ea.save - # 保存成功返回成功信息及当前以答题百分比 - uncomplete_question = get_uncomplete_question(@exercise, User.current) - if uncomplete_question.count < 1 - complete = 1; - else - complete = 0; - end - @percent = get_percent(@exercise,User.current) - render :json => {:text => "ok" ,:complete => complete,:percent => format("%.2f" ,@percent)} - else - #返回失败信息 - render :json => {:text => "failure"} + if exercise_user + if (exercise_user && exercise_user.commit_status == 1) || @exercise.end_time < Time.now + render :json => {:text => "Over"} + return end - elsif eq.question_type == 2 - #多选题 - ea = ExerciseAnswer.find_by_exercise_choice_id_and_user_id(params[:exercise_choice_id],User.current.id) - if ea.nil? - #尚未答该题,添加答案 - ea = ExerciseAnswer.new - ea.user_id = User.current.id - ea.exercise_question_id = params[:exercise_question_id] + if eq.question_type == 1 + # 单选题 + ea = ExerciseAnswer.find_by_exercise_question_id_and_user_id(params[:exercise_question_id],User.current.id) + if ea.nil? + # 尚未答该题,添加答案 + ea = ExerciseAnswer.new + ea.user_id = User.current.id + ea.exercise_question_id = params[:exercise_question_id] + end + #修改该题对应答案 ea.exercise_choice_id = params[:exercise_choice_id] if ea.save - uncomplete_question = get_uncomplete_question(@exercise, User.current) + # 保存成功返回成功信息及当前以答题百分比 + uncomplete_question = get_uncomplete_question(@exercise, exercise_user) if uncomplete_question.count < 1 complete = 1; else complete = 0; end - is_answer = User.current.exercise_answer.where(:exercise_question_id => params[:exercise_question_id].to_i).count > 0 - @percent = get_percent(@exercise,User.current) - render :json => {:text => "ok",:complete => complete,:percent => format("%.2f" ,@percent),:is_answer => is_answer} - else - render :json => {:text => "failure"} - end - else - #pv不为空,则当前选项之前已被选择,再次点击则是不再选择该项,故删除该答案 - if ea.delete - is_answer = User.current.exercise_answer.where(:exercise_question_id => params[:exercise_question_id].to_i).count > 0 - @percent = get_percent(@exercise, User.current) - render :json => {:text => "false" ,:percent => format("%.2f" , @percent),:is_answer => is_answer} + @percent = get_percent(@exercise, exercise_user) + render :json => {:text => "ok" ,:complete => complete,:percent => format("%.2f" ,@percent)} else + #返回失败信息 render :json => {:text => "failure"} end - end - elsif eq.question_type == 3 || eq.question_type == 4 - #单行文本,多行文本题 - ea = ExerciseAnswer.find_by_exercise_question_id_and_user_id(params[:exercise_question_id], User.current.id) - if ea.nil? - # ea为空之前尚未答题,添加答案 - if params[:answer_text].nil? || params[:answer_text].blank? - #用户提交空答案,视作不作答 - @percent = get_percent(@exercise,User.current) - render :json => {:text => "",:percent => format("%.2f", @percent)} - else - #添加答案 + elsif eq.question_type == 2 + #多选题 + ea = ExerciseAnswer.find_by_exercise_choice_id_and_user_id(params[:exercise_choice_id],User.current.id) + if ea.nil? + #尚未答该题,添加答案 ea = ExerciseAnswer.new ea.user_id = User.current.id ea.exercise_question_id = params[:exercise_question_id] - ea.answer_text = params[:answer_text] + ea.exercise_choice_id = params[:exercise_choice_id] if ea.save - uncomplete_question = get_uncomplete_question(@exercise, User.current) + uncomplete_question = get_uncomplete_question(@exercise, exercise_user) if uncomplete_question.count < 1 complete = 1; else complete = 0; end - @percent = get_percent(@exercise,User.current) - render :json => {:text => ea.answer_text,:complete => complete,:percent => format("%.2f",@percent)} + is_answer = User.current.exercise_answer.where(:exercise_question_id => params[:exercise_question_id].to_i).count > 0 + @percent = get_percent(@exercise, exercise_user) + render :json => {:text => "ok",:complete => complete,:percent => format("%.2f" ,@percent),:is_answer => is_answer} else render :json => {:text => "failure"} end - end - - else - # ea不为空说明用户之前已作答 - if params[:answer_text].nil? || params[:answer_text].blank? - # 用户提交空答案,视为删除答案 + else + #pv不为空,则当前选项之前已被选择,再次点击则是不再选择该项,故删除该答案 if ea.delete - @percent = get_percent(@exercise,User.current) - render :json => {:text => "",:percent => format("%.2f", @percent)} + is_answer = User.current.exercise_answer.where(:exercise_question_id => params[:exercise_question_id].to_i).count > 0 + @percent = get_percent(@exercise, exercise_user) + render :json => {:text => "false" ,:percent => format("%.2f" , @percent),:is_answer => is_answer} else render :json => {:text => "failure"} end + end + elsif eq.question_type == 3 || eq.question_type == 4 + #单行文本,多行文本题 + ea = ExerciseAnswer.find_by_exercise_question_id_and_user_id(params[:exercise_question_id], User.current.id) + if ea.nil? + # ea为空之前尚未答题,添加答案 + if params[:answer_text].nil? || params[:answer_text].blank? + #用户提交空答案,视作不作答 + @percent = get_percent(@exercise, exercise_user) + render :json => {:text => "",:percent => format("%.2f", @percent)} + else + #添加答案 + ea = ExerciseAnswer.new + ea.user_id = User.current.id + ea.exercise_question_id = params[:exercise_question_id] + ea.answer_text = params[:answer_text] + if ea.save + uncomplete_question = get_uncomplete_question(@exercise, exercise_user) + if uncomplete_question.count < 1 + complete = 1; + else + complete = 0; + end + @percent = get_percent(@exercise, exercise_user) + render :json => {:text => ea.answer_text,:complete => complete,:percent => format("%.2f",@percent)} + else + render :json => {:text => "failure"} + end + end + else - #用户修改答案 - ea.answer_text = params[:answer_text] - if ea.save - @percent = get_percent(@exercise,User.current) - render :json => {:text => ea.answer_text,:percent => format("%.2f", @percent)} + # ea不为空说明用户之前已作答 + if params[:answer_text].nil? || params[:answer_text].blank? + # 用户提交空答案,视为删除答案 + if ea.delete + @percent = get_percent(@exercise, exercise_user) + render :json => {:text => "",:percent => format("%.2f", @percent)} + else + render :json => {:text => "failure"} + end else - render :json => {:text => "failure"} + #用户修改答案 + ea.answer_text = params[:answer_text] + if ea.save + @percent = get_percent(@exercise, exercise_user) + render :json => {:text => ea.answer_text,:percent => format("%.2f", @percent)} + else + render :json => {:text => "failure"} + end end end - end + else + render :json => {:text => "failure"} + end else render :json => {:text => "failure"} end @@ -1165,9 +1179,10 @@ class ExerciseController < ApplicationController # 获取学生未答情况 def get_student_uncomplete_question + exercise_user = @exercise.exercise_users.where(:user_id => User.current).first time_limit = @exercise.time == -1 || @exercise.time.nil? - uncomplete_count = get_uncomplete_question(@exercise, User.current).count - uncomplete_shixun = get_uncomplete_shixun(@exercise, User.current).count + uncomplete_count = get_uncomplete_question(@exercise, exercise_user).count + uncomplete_shixun = get_uncomplete_shixun(@exercise, exercise_user).count render :json => {:time_limit => time_limit, :uncomplete_count => uncomplete_count, :uncomplete_shixun => uncomplete_shixun} end @@ -1241,8 +1256,8 @@ class ExerciseController < ApplicationController @is_teacher = params[:pdf] ? true : User.current.allowed_to?(:as_teacher,@course) || User.current.admin? if @is_teacher || (User.current.member_of_course?(@exercise.course) && @exercise.exercise_status > 2) @user = User.find params[:user_id] - @exercise_questions = @exercise.exercise_questions @exercise_user = ExerciseUser.where("user_id =? and exercise_id=?", @user.id, @exercise.id).first + @exercise_questions = @exercise.user_question_list @exercise_user.id respond_to do |format| if params[:pdf] format.html { render :layout => "pdf" } @@ -1305,7 +1320,8 @@ class ExerciseController < ApplicationController score2 = 0 score3 = 0 score4 = 0 - exercise_qustions = exercise.exercise_questions + exercise_user = exercise.exercise_users.where(user_id: user.id).first + exercise_qustions = exercise.user_question_list(exercise_user.try(:id)) exercise_qustions.each do |question| if question.question_type != 5 answer = get_user_answer(question, user) @@ -1608,11 +1624,11 @@ class ExerciseController < ApplicationController standard_answer end # 是否完成了答题 - def get_complete_question(exercise,user) - questions = exercise.exercise_questions.includes(:exercise_answers) + def get_complete_question(exercise, exercise_user) + questions = exercise.user_question_list(exercise_user.id).includes(:exercise_answers) complete_question = [] questions.each do |question| - answers = question.exercise_answers.select{|e| e.user_id == user.id} + answers = question.exercise_answers.select{|e| e.user_id == exercise_user.user_id} if !(answers.nil? || answers.count < 1) complete_question << question end @@ -1621,12 +1637,13 @@ class ExerciseController < ApplicationController end # 获取答题百分比 - def get_percent exercise,user - complete_count = get_complete_question(exercise,user).count - if exercise.exercise_questions.count == 0 + def get_percent exercise, exercise_user + complete_count = get_complete_question(exercise,exercise_user).count + questions = exercise.user_question_list(exercise_user.id) + if questions.count == 0 return 0 else - return (complete_count.to_f / exercise.exercise_questions.count.to_f)*100 + return (complete_count.to_f / questions.count.to_f)*100 end end diff --git a/app/helpers/exercise_helper.rb b/app/helpers/exercise_helper.rb index b5a56020..cdea7b88 100644 --- a/app/helpers/exercise_helper.rb +++ b/app/helpers/exercise_helper.rb @@ -1,5 +1,18 @@ # encoding: utf-8 module ExerciseHelper + def exercise_shixun_json_data shixuns + shixuns.map do |shixun| + shixun_owner = shixun.owner.try(:show_name) + shixun_path = shixun_path(shixun) + shixun_level = shixun.shixun_level + shixun.attributes.dup.except("gpid", "identifier", "major_id", "webssh", "homepage_show", "fork_from", "git_url", + "mirror_script_id", "repo_name", "pod_life").merge({ + shixun_owner: shixun_owner, + shixun_level: shixun_level, + shixun_path: shixun_path + }) + end + end def un_commit_num exercise course = exercise.course @@ -266,12 +279,13 @@ module ExerciseHelper end #获取未完成的题目 - def get_uncomplete_question exercise,user + def get_uncomplete_question exercise, exercise_user # all_questions = exercise.exercise_questions.includes(:exercise_answers).where("question_type != 5") uncomplete_question = [] - exercise.exercise_questions.includes(:exercise_answers).where("question_type != 5").each do |question| + questions = exercise.user_question_list(exercise_user.id) + questions.includes(:exercise_answers).where("question_type != 5").each do |question| # answers = get_user_answer(question, user) - answers = question.exercise_answers.select{|e| e.user_id == user.id} + answers = question.exercise_answers.select{|e| e.user_id == exercise_user.user_id} if answers.empty? uncomplete_question << question end @@ -280,8 +294,9 @@ module ExerciseHelper end # 获取未通关的实训 - def get_uncomplete_shixun exercise,user - all_questions = exercise.exercise_questions.where("question_type = 5") + def get_uncomplete_shixun exercise, exercise_user + questions = exercise.user_question_list(exercise_user.try(:id)) + all_questions = questions.where("question_type = 5") uncomplete_shixun = [] all_questions.each do |question| myshixun = Myshixun.where(:shixun_id => question.shixun_id, :user_id => user.id).first diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 47993cf9..a8452df0 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -5,13 +5,17 @@ class Exercise < ActiveRecord::Base belongs_to :course ,:touch => true belongs_to :exercise_bank has_many :exercise_group_settings, :dependent => :destroy - has_many :exercise_questions, :dependent => :destroy,:order => "#{ExerciseQuestion.table_name}.question_number" + has_many :exercise_questions, :dependent => :destroy has_many :exercise_users, :dependent => :destroy, :conditions => "exercise_users.is_delete = 0" has_many :users, :through => :exercise_users #该测试被哪些用户提交答案过 has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy # 课程消息 has_many :tidings, as: :container, dependent: :destroy has_many :course_messages, :class_name =>'CourseMessage', :as => :course_message, :dependent => :destroy + + has_many :exercise_level_settings, :dependent => :destroy + has_many :exercise_user_questions + after_create :acts_as_course_message def acts_as_course_message if self.course @@ -24,4 +28,27 @@ class Exercise < ActiveRecord::Base end end end + + def create_user_question_list exercise_user_id + self.exercise_questions.where("question_type != 5").each do |question| + self.exercise_user_questions << ExerciseUserQuestion.new(exercise_user_id: exercise_user_id, + exercise_question_id: question) + end + self.exercise_level_settings.each do |setting| + # 每个级别中随机挑选num个实训题 + setting.exercise_questions.pluck(:id).sample(setting.num).each do |question_id| + self.exercise_user_questions << ExerciseUserQuestion.new(exercise_user_id: exercise_user_id, + exercise_question_id: question_id) + end + end + end + + def user_question_list exercise_user_id + if self.exercise_user_questions.where(exercise_user_id: exercise_user_id).count == 0 + self.exercise_questions + else + self.exercise_questions.where(id: self.exercise_user_questions.where(exercise_user_id: exercise_user_id). + pluck(:exercise_question_id)) + end + end end diff --git a/app/models/exercise_level_setting.rb b/app/models/exercise_level_setting.rb new file mode 100644 index 00000000..3e687d8c --- /dev/null +++ b/app/models/exercise_level_setting.rb @@ -0,0 +1,5 @@ +class ExerciseLevelSetting < ActiveRecord::Base + belongs_to :exercise + has_many :exercise_questions + # attr_accessible :level, :num, :score +end diff --git a/app/models/exercise_question.rb b/app/models/exercise_question.rb index cadc67fc..63d9cdf9 100644 --- a/app/models/exercise_question.rb +++ b/app/models/exercise_question.rb @@ -1,6 +1,7 @@ #encoding: utf-8 class ExerciseQuestion < ActiveRecord::Base include Redmine::SafeAttributes + default_scope :order => 'question_number' belongs_to :exercise belongs_to :shixun @@ -11,6 +12,9 @@ class ExerciseQuestion < ActiveRecord::Base has_many :exercise_answer_comments, :dependent => :destroy has_many :exercise_standard_answers, :dependent => :destroy + belongs_to :exercise_level_setting, counter_cache: true + has_many :exercise_user_questions, :dependent => :destroy + def question_type_name case self.question_type when 1 diff --git a/app/models/exercise_user.rb b/app/models/exercise_user.rb index c675f35a..8609ba26 100644 --- a/app/models/exercise_user.rb +++ b/app/models/exercise_user.rb @@ -4,4 +4,6 @@ class ExerciseUser < ActiveRecord::Base belongs_to :user belongs_to :exercise + + has_many :exercise_user_questions end diff --git a/app/models/exercise_user_question.rb b/app/models/exercise_user_question.rb new file mode 100644 index 00000000..136a187f --- /dev/null +++ b/app/models/exercise_user_question.rb @@ -0,0 +1,6 @@ +class ExerciseUserQuestion < ActiveRecord::Base + belongs_to :exercise + belongs_to :exercise_user + belongs_to :exercise_question + # attr_accessible :title, :body +end diff --git a/app/views/exercise/_exercise_student.html.erb b/app/views/exercise/_exercise_student.html.erb index d361c200..5d12c301 100644 --- a/app/views/exercise/_exercise_student.html.erb +++ b/app/views/exercise/_exercise_student.html.erb @@ -134,9 +134,9 @@ <% if @exercise.question_random == 1 %> - <% question_list = @exercise.exercise_questions.includes(:exercise_shixun_answers, :exercise_choices => [:exercise_answers]).shuffle %> + <% question_list = @exercise_questions.includes(:exercise_shixun_answers, :exercise_choices => [:exercise_answers]).shuffle %> <% else %> - <% question_list = @exercise.exercise_questions.includes(:exercise_shixun_answers, :exercise_choices => [:exercise_answers]) %> + <% question_list = @exercise_questions.includes(:exercise_shixun_answers, :exercise_choices => [:exercise_answers]) %> <% end %> diff --git a/app/views/exercise/_exercise_student_result.html.erb b/app/views/exercise/_exercise_student_result.html.erb index b5336cdb..8c1de5ea 100644 --- a/app/views/exercise/_exercise_student_result.html.erb +++ b/app/views/exercise/_exercise_student_result.html.erb @@ -76,7 +76,7 @@