class ExerciseController < ApplicationController layout "base_courses" before_filter :find_exercise_and_course, :only => [:create_exercise_question, :edit, :update, :show, :destroy, :commit_exercise, :commit_answer,:publish_exercise,:republish_exercise, :show_student_result,:student_exercise_list] before_filter :find_course, :only => [:index,:new,:create] include ExerciseHelper def index publish_exercises = Exercise.where("publish_time is not null and exercise_status = 1 and publish_time <=?",Time.now) publish_exercises.each do |exercise| exercise.update_column('exercise_status', 2) course = exercise.course course.members.each do |m| exercise.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => course.id, :viewed => false, :status => 2) end end if @course.is_public == 0 && !(User.current.member_of_course?(@course)||User.current.admin?) render_403 return end remove_invalid_exercise(@course) @is_teacher = User.current.allowed_to?(:as_teacher,@course) if @is_teacher || User.current.admin? exercises = @course.exercises.order("created_at asc") else exercises = @course.exercises.where("exercise_status <> 1").order("created_at asc") end @exercises = paginateHelper exercises,20 #分页 respond_to do |format| format.html end end def show publish_exercises = Exercise.where("publish_time is not null and exercise_status = 1 and publish_time <=?",Time.now) publish_exercises.each do |exercise| exercise.update_column('exercise_status', 2) course = exercise.course course.members.each do |m| exercise.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => course.id, :viewed => false, :status => 2) end end unless User.current.member_of_course?(@course) || User.current.admin? render_403 return end @exercise = Exercise.find params[:id] @is_teacher = User.current.allowed_to?(:as_teacher,@course) || User.current.admin? exercise_end = @exercise.end_time > Time.now if @exercise.time == -1 @can_edit_excercise = exercise_end else @can_edit_excercise = !has_commit_exercise?(@exercise.id,User.current.id)&& exercise_end end unless @is_teacher @exercise_user = ExerciseUser.where("user_id=? and exercise_id=?", User.current.id, @exercise.id).first if @exercise_user.nil? eu = ExerciseUser.create(:user_id => User.current.id, :exercise_id => @exercise.id, :start_at => Time.now, :status => false) @exercise_user = ExerciseUser.where("user_id=? and exercise_id=?", User.current.id, @exercise.id).first end score = calculate_student_score(@exercise, User.current) @exercise_user.update_attributes(:score => score) end # @percent = get_percent(@exercise,User.current) @exercise_questions = @exercise.exercise_questions respond_to do |format| format.html {render :layout => 'base_courses'} end #end end def new option = { :exercise_name => "", :course_id => @course.id, :exercise_status => 1, :user_id => User.current.id, :time => "", :end_time => "", :publish_time => "", :exercise_description => "", :show_result => 1 } @exercise = Exercise.create option if @exercise redirect_to edit_exercise_url @exercise.id end end def create if params[:exercise] exercise = Exercise.find(params[:exercise_id]) if params[:exercise_id] exercise ||= Exercise.new exercise.exercise_name = params[:exercise][:exercise_name] exercise.exercise_description = params[:exercise][:exercise_description] exercise.end_time = Time.at(params[:exercise][:end_time].to_time.to_i + 16*60*60 -1) exercise.publish_time = params[:exercise][:publish_time] exercise.user_id = User.current.id exercise.time = params[:exercise][:time] exercise.course_id = params[:course_id] exercise.exercise_status = 1 if exercise.save @exercise = exercise respond_to do |format| format.js end end end end def edit respond_to do |format| format.html{render :layout => 'base_courses'} end end def update @exercise.exercise_name = params[:exercise][:exercise_name] @exercise.exercise_description = params[:exercise][:exercise_description] @exercise.time = params[:exercise][:time].blank? ? -1 : params[:exercise][:time] @exercise.end_time = Time.at(params[:exercise][:end_time].to_time.to_i + 16*60*60 -1) @exercise.publish_time = params[:exercise][:publish_time] @exercise.show_result = params[:exercise][:show_result].blank? ? 1 : params[:exercise][:show_result] if @exercise.save respond_to do |format| format.js end else render_404 end end def destroy @is_teacher = User.current.allowed_to?(:as_teacher,@course) || User.current.admin? if @exercise && @exercise.destroy if @is_teacher exercises = Exercise.where("course_id =?", @course.id) else exercises = Exercise.where("course_id =? and exercise_status =?", @course.id, 2) end @exercises = paginateHelper exercises,20 #分页 respond_to do |format| format.js end end end # 统计结果 def statistics_result @exercise = Exercise.find(params[:id]) exercise_questions = @exercise.exercise_questions @exercise_questions = paginateHelper exercise_questions, 5 respond_to do |format| format.html{render :layout => 'base_courses'} end end # 添加题目 # question_type 1:单选 2:多选 3:填空题 def create_exercise_question question_title = params[:question_title].nil? || params[:question_title].empty? ? l(:label_enter_single_title) : params[:question_title] option = { :question_title => question_title, :question_type => params[:question_type] || 1, :question_number => params[:question_type] == "1"? @exercise.exercise_questions.where("question_type = 1").count + 1 : (params[:question_type] == "2" ? (@exercise.exercise_questions.where("question_type = 2").count + 1) : @exercise.exercise_questions.where("question_type = 3").count + 1), :question_score => params[:question_score] } @exercise_questions = @exercise.exercise_questions.new option # params[:question_answer] 题目选项 if params[:question_answer] for i in 1..params[:question_answer].count answer = (params[:question_answer].values[i-1].nil? || params[:question_answer].values[i-1].empty?) ? l(:label_new_answer) : params[:question_answer].values[i-1] question_option = { :choice_position => i, :choice_text => answer } @exercise_questions.exercise_choices.new question_option end end # 如果是插入的话,那么从插入的这个id以后的question_num都将要+1 if params[:quest_id] @is_insert = true if @exercise_questions.question_type == 1 ExerciseQuestion.where("question_number>? and question_type=?",params[:quest_num].to_i, 1).update_all(" question_number = question_number + 1") #@exercise.exercise_questions.where("question_number > #{params[:quest_num].to_i} and question_type == 1").update_all(" question_number = question_number + 1") elsif @exercise_questions.question_type == 2 ExerciseQuestion.where("question_number>? and question_type=?",params[:quest_num].to_i, 2).update_all(" question_number = question_number + 1") else ExerciseQuestion.where("question_number>? and question_type=?",params[:quest_num].to_i, 3).update_all(" question_number = question_number + 1") end # @exercise_question_num = params[:quest_num].to_i @exercise_questions.question_number = params[:quest_num].to_i + 1 end if @exercise_questions.save # params[:exercise_choice] 标准答案参数 # 问答题标准答案有三个,单独处理 if @exercise_questions.question_type == 3 for i in 1..params[:exercise_choice].count standart_answer = ExerciseStandardAnswer.new standart_answer.exercise_question_id = @exercise_questions.id standart_answer.answer_text = params[:exercise_choice].values[i-1] standart_answer.save end else standart_answer = ExerciseStandardAnswer.new standart_answer.exercise_question_id = @exercise_questions.id if @exercise_questions.question_type == 1 standart_answer.exercise_choice_id = sigle_selection_standard_answer(params[:exercise_choice]) else standart_answer.exercise_choice_id = multiselect_standard_answer(params[:exercise_choice]) end standart_answer.save end respond_to do |format| format.js end end end # 修改题目 # params[:exercise_question] The id of exercise_question # params[:question_answer] eg:A、B、C选项 def update_exercise_question @exercise_question = ExerciseQuestion.find params[:exercise_question] @exercise_question.question_title = params[:question_title].nil? || params[:question_title].empty? ? l(:label_enter_single_title) : params[:question_title] @exercise_question.question_score = params[:question_score] # 处理选项:如果选了某个选项,那么则要删除之前的选项 if params[:question_answer] @exercise_question.exercise_choices.each do |answer| answer.destroy unless params[:question_answer].keys.include? answer.id.to_s end for i in 1..params[:question_answer].count question = @exercise_question.exercise_choices.find_by_id params[:question_answer].keys[i-1] answer = (params[:question_answer].values[i-1].nil? || params[:question_answer].values[i-1].empty?) ? l(:label_new_answer) : params[:question_answer].values[i-1] if question question.choice_position = i question.choice_text = answer question.save else question_option = { :choice_position => i, :choice_text => answer } @exercise_question.exercise_choices.new question_option end end end # 更新标准答案 if params[:exercise_choice] if @exercise_question.question_type == 3 # 删除不合理的选项 @exercise_question.exercise_standard_answers.each do |answer| answer.destroy unless params[:exercise_choice].keys.include? answer.id.to_s end for i in 1..params[:exercise_choice].count # 找到对应的标准答案 question_standart = @exercise_question.exercise_standard_answers.find_by_id params[:exercise_choice].keys[i-1] # 标准答案值 answer_standart = (params[:exercise_choice].values[i-1].nil? || params[:exercise_choice].values[i-1].empty?) ? l(:label_new_answer) : params[:exercise_choice].values[i-1] if question_standart question_standart.answer_text = answer_standart question_standart.save else standart_answer_option = { :answer_text => answer_standart } @exercise_question.exercise_standard_answers.new standart_answer_option end end else answer_standart = @exercise_question.exercise_standard_answers.first answer_standart.exercise_choice_id = @exercise_question.question_type == 1 ? sigle_selection_standard_answer(params[:exercise_choice]) : multiselect_standard_answer(params[:exercise_choice]) answer_standart.save end @exercise_question.save respond_to do |format| format.js end end end # 删除题目 def delete_exercise_question @exercise_question = ExerciseQuestion.find params[:exercise_question] @exercise = @exercise_question.exercise if @exercise_question.question_type == 1 ExerciseQuestion.where("question_number>? and question_type=?",params[:quest_num].to_i, 1).update_all(" question_number = question_number - 1") #@exercise.exercise_questions.where("question_number > #{params[:quest_num].to_i} and question_type == 1").update_all(" question_number = question_number + 1") elsif @exercise_question.question_type == 2 ExerciseQuestion.where("question_number>? and question_type=?",params[:quest_num].to_i, 2).update_all(" question_number = question_number - 1") else ExerciseQuestion.where("question_number>? and question_type=?",params[:quest_num].to_i, 3).update_all(" question_number = question_number - 1") end # @exercise_question_num = params[:quest_num].to_i # @exercise_questions.question_number = params[:quest_num].to_i - 1 # # exercise_questions = @exercise.exercise_questions.where("question_number > #{@exercise_question.question_number}") # exercise_questions.each do |question| # question.question_number -= 1 # question.save # end if @exercise_question && @exercise_question.destroy respond_to do |format| format.js end end end # 发布试卷 def publish_exercise @is_teacher = User.current.allowed_to?(:as_teacher,@course) @index = params[:index] @exercise.exercise_status = 2 @exercise.publish_time = Time.now if @exercise.save @exercise.course.members.each do |m| @exercise.course_messages << CourseMessage.create(:user_id =>m.user_id, :course_id => @exercise.course.id, :viewed => false,:status=>2) end #redirect_to exercise_index_url(:course_id=> @course.id) respond_to do |format| format.js end end end # 重新发布试卷 # 重新发布的时候会删除所有的答题 def republish_exercise @is_teacher = User.current.allowed_to?(:as_teacher,@course) @index = params[:index] @exercise.exercise_questions.each do |exercise_question| exercise_question.exercise_answers.destroy_all end @exercise.course_messages.destroy_all @exercise.exercise_users.destroy_all @exercise.exercise_status = 1 @exercise.publish_time = nil @exercise.save respond_to do |format| format.js end end def student_exercise_list =begin if @exercise.end_time <= Time.now @course.student.each do |student| if ExerciseUser.where("user_id = ? && exercise_id = ?",student.student_id,@exercise.id).empty? ExerciseUser.create(:user_id => student.student_id, :exercise_id => @exercise.id, :start_at => @exercise.end_time, :status => true,:score=>0) end s_score = calculate_student_score(@exercise, student.student) exercise_user = ExerciseUser.where("user_id =? and exercise_id=?", student.student_id, @exercise.id).first exercise_user.update_attributes(:score => s_score) end end =end @is_teacher = User.current.allowed_to?(:as_teacher,@course) || User.current.admin? @all_exercises = @course.exercises.where("exercise_status > 1").order("created_at desc") @exercise_count = @exercise.exercise_users.where('score is not NULL').count if @is_teacher || (!@exercise.exercise_users.where(:user_id => User.current.id).empty? && @exercise.end_time <= Time.now) @exercise_users_list = @exercise.exercise_users.where('score is not NULL') @show_all = true; elsif !@exercise.exercise_users.where(:user_id => User.current.id).empty? && @exercise.end_time > Time.now @exercise_users_list = @exercise.exercise_users.where("user_id = ? and score is not NULL",User.current.id) else @exercise_users_list = [] end respond_to do |format| format.html format.xls { filename = "#{@course.teacher.lastname.to_s + @course.teacher.firstname}_#{@course.name}_#{@course.time.to_s + @course.term}_#{@exercise.exercise_name}#{l(:excel_exercise_list)}.xls" send_data(exercise_to_xls(@exercise_users_list), :type => "text/excel;charset=utf-8; header=present", :filename => filename_for_content_disposition(filename)) } end end # 学生提交答卷,选中答案的过程中提交 def commit_answer eq = ExerciseQuestion.find(params[:exercise_question_id]) # 已提交过的且是限时的则不允许答题 if (has_commit_exercise?(@exercise.id,User.current.id) && (!User.current.admin?) && @exercise.time != -1) || @exercise.end_time < Time.now render :json => {:text => "failure"} 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"} 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] 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"} end else #pv不为空,则当前选项之前已被选择,再次点击则是不再选择该项,故删除该答案 if ea.delete @percent = get_percent(@exercise, User.current) render :json => {:text => "false" ,:percent => format("%.2f" , @percent)} else render :json => {:text => "failure"} end end elsif eq.question_type == 3 #单行文本,多行文本题 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 #添加答案 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, User.current) 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)} else render :json => {:text => "failure"} end end else # ea不为空说明用户之前已作答 if params[:answer_text].nil? || params[:answer_text].blank? # 用户提交空答案,视为删除答案 if ea.delete @percent = get_percent(@exercise,User.current) render :json => {:text => "",:percent => format("%.2f", @percent)} else render :json => {:text => "failure"} 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)} else render :json => {:text => "failure"} end end end else render :json => {:text => "failure"} end end # 提交问卷 def commit_exercise # 老师不需要提交 if User.current.allowed_to?(:as_teacher,@course) if @exercise.publish_time.nil? @exercise.update_attributes(:show_result => params[:show_result]) @exercise.update_attributes(:exercise_status => 2) @exercise.update_attributes(:publish_time => Time.now) course = @exercise.course course.members.each do |m| @exercise.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => course.id, :viewed => false, :status => 2) end redirect_to exercise_url(@exercise) return elsif @exercise.publish_time > Time.now @exercise.update_attributes(:show_result => params[:show_result]) redirect_to exercise_url(@exercise) return end @exercise.update_attributes(:show_result => params[:show_result]) redirect_to exercise_url(@exercise) # REDO: 提示提交成功 else # 更新提交状态 cur_exercise_user = ExerciseUser.where("user_id =? and exercise_id=?", User.current, @exercise.id).first cur_exercise_user.update_attributes(:status => 1) # 答题过程中需要统计完成量 @uncomplete_question = get_uncomplete_question(@exercise, User.current) # 获取改学生的考试得分 @score = calculate_student_score(@exercise, User.current) # @score = 100 if @uncomplete_question.count < 1 # 查看是否有已提交记录 cur_exercise_user.score = @score if cur_exercise_user.save #redirect_to poll_index_path(:polls_group_id => @course.id,:polls_type => 'Course') @status = 0 #提交成功 else @status = 2 #未知错误 end else @status = 1 #有未做得必答题 end @save = params[:save].to_i if params[:save] respond_to do |format| format.js end end end #查看学生的答卷情况 def show_student_result @user = User.find params[:user_id] @can_edit_excercise = false @exercise_questions = @exercise.exercise_questions score = calculate_student_score(@exercise, @user) eu = get_exercise_user(@exercise.id, @user.id) eu.update_attributes(:score => score) @exercise_user = ExerciseUser.where("user_id =? and exercise_id=?", @user.id, @exercise.id).first respond_to do |format| format.html {render :layout => 'base_courses'} end end # 计算学生得分 def calculate_student_score(exercise, user) score = 0 score1 = 0 score2 = 0 score3 = 0 exercise_qustions = exercise.exercise_questions exercise_qustions.each do |question| answer = get_user_answer(question, user) standard_answer = get_user_standard_answer(question, user) unless answer.empty? # 问答题有多个答案 if question.question_type == 3 && !standard_answer.empty? if standard_answer.include?(answer.first.answer_text) score1 = score1+ question.question_score unless question.question_score.nil? end elsif question.question_type == 1 && !standard_answer.nil? if answer.first.exercise_choice.choice_position == standard_answer.exercise_choice_id score2 = score2 + question.question_score unless question.question_score.nil? end elsif question.question_type == 2 && !standard_answer.nil? arr = get_mulscore(question, user) if arr.to_i == standard_answer.exercise_choice_id score3 = score3 + question.question_score unless question.question_score.nil? end # ecs = ExerciseAnswer.where("user_id =? and exercise_question_id =?", user.id, question.id) # arr = [] # ecs.each do |ec| # arr << ec.exercise_choice.choice_position # end # arr.sort # arr = arr.join("") # if arr.to_i == standard_answer.exercise_choice_id # score3 = score + question.question_score unless question.question_score.nil? # end end end end score = score1 + score2 + score3 end private #测验列表转换为excel def exercise_to_xls items xls_report = StringIO.new book = Spreadsheet::Workbook.new sheet1 = book.create_worksheet :name => "exercise" blue = Spreadsheet::Format.new :color => :blue, :weight => :bold, :size => 10 sheet1.row(0).default_format = blue sheet1.row(0).concat([l(:excel_user_id),l(:excel_user_name),l(:excel_nickname),l(:excel_student_id),l(:excel_mail),l(:excel_class),l(:excel_f_score),l(:excel_commit_time)]) count_row = 1 items.each do |exercise| sheet1[count_row,0]=exercise.user.id sheet1[count_row,1] = exercise.user.lastname.to_s + exercise.user.firstname.to_s sheet1[count_row,2] = exercise.user.login sheet1[count_row,3] = exercise.user.user_extensions.student_id sheet1[count_row,4] = exercise.user.mail sheet1[count_row,5] = "" sheet1[count_row,6] = exercise.score sheet1[count_row,7] = format_time(exercise.created_at) count_row += 1 end book.write xls_report xls_report.string end # ExerciseUser记录用户是否已提交问卷有对应的记录则已提交,没有则新建一个 def get_exercise_user exercise_id,user_id eu = ExerciseUser.find_by_exercise_id_and_user_id(exercise_id,user_id) if eu.nil? eu = ExerciseUser.new end eu end # 获取当前学生回答问题的答案 def get_user_answer(question,user) # user_answer = ExerciseAnswer.where("user_id=? and exercise_question_id=?", user.id, question.id).first user_answer = question.exercise_answers.where("#{ExerciseAnswer.table_name}.user_id = #{user.id}") user_answer end # 获取问题的标准答案 def get_user_standard_answer(question,user) if question.question_type == 3 standard_answer =[] question.exercise_standard_answers.each do |answer| standard_answer << answer.answer_text end else standard_answer = question.exercise_standard_answers.first end standard_answer end # 是否完成了答题 def get_complete_question(exercise,user) questions = exercise.exercise_questions complete_question = [] questions.each do |question| answers = get_user_answer(question,user) if !(answers.nil? || answers.count < 1) complete_question << question end end complete_question end # 获取答题百分比 def get_percent exercise,user complete_count = get_complete_question(exercise,user).count if exercise.exercise_questions.count == 0 return 0 else return (complete_count.to_f / exercise.exercise_questions.count.to_f)*100 end end def remove_invalid_exercise(course) exercises = course.exercises.where("exercise_name=?","") unless exercises.empty? exercises.each do |exercise| if exercise.exercise_questions.empty? exercise.destroy end end end end def find_exercise_and_course @exercise = Exercise.find params[:id] @course = Course.find @exercise.course_id rescue Exception => e render_404 end def find_course @course = Course.find params[:course_id] rescue Exception => e render_404 end end