socialforge/app/controllers/exercise_controller.rb

714 lines
29 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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]
@exercise.course_messages.each do |message|
if User.current.id == message.user_id && message.viewed == 0
message.update_attributes(:viewed => true) if message.viewed == 0
end
end
@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