module ExercisesHelper
# include GitHelper
#获取每个学生对每个题的答案状态
def get_each_student_exercise ( exercise_id , exercise_questions , user_id )
@exercise_user = ExerciseUser . current_exercise_user ( user_id , exercise_id ) & . first
exercise_obj_status = exercise_questions . find_objective_questions
@ex_obj_array = [ ]
exercise_obj_status . each do | q |
q_type = q . question_type
if q_type == Exercise :: PRACTICAL
answers_content = q . exercise_shixun_answers . select { | answer | answer . user_id == user_id }
else
answers_content = q . exercise_answers . select { | answer | answer . user_id == user_id }
end
if q_type < = Exercise :: JUDGMENT
if answers_content . present? #学生有回答时,分数已经全部存到exercise_answer 表,所以可以直接取第一个值
ques_score = answers_content . first . score
ques_score = ques_score < 0 ? 0 . 0 : ques_score
# answer_choice_array = []
# answers_content.each do |a|
# answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
# end
# user_answer_content = answer_choice_array.sort
# standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
# if q_type == Exercise::MULTIPLE && standard_answer.size == 1 # 老数据的问题
# ques_score = answers_content.first.score
# else
#
# end
# if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
# ques_score = q.question_score
# else
# ques_score = 0.0
# end
else
ques_score = 0 . 0
end
elsif q_type == Exercise :: COMPLETION
ques_score = answers_content . select { | answer | answer . score > = 0 . 0 } . pluck ( :score ) . sum
if ques_score . to_s . split ( " . " ) . last == " 9 "
ques_score = ques_score . to_f + 0 . 1
end
else
ques_score = answers_content . select { | answer | answer . score > = 0 . 0 } . pluck ( :score ) . sum
end
if ques_score > = q . question_score #满分作答为正确
ques_score = q . question_score
stand_answer = 1
elsif ques_score > 0 . 0 #部分作答
stand_answer = 2
else
stand_answer = 0
end
ques_option = {
" q_id " :q . id , #该问题的id
" q_type " :q . question_type ,
" q_position " :q . question_number , #该问题的位置
" stand_status " :stand_answer , #用户是否回答
" user_score " :ques_score . round ( 1 ) . to_s #每个问题的总得分
}
@ex_obj_array . push ( ques_option )
end
exercise_sub_status = exercise_questions . find_by_custom ( " question_type " , Exercise :: SUBJECTIVE ) #主观题
@ex_sub_array = [ ] #主观题的已答/未答
exercise_sub_status . each do | s |
sub_answer = s . exercise_answers . select { | answer | answer . user_id == user_id } #主观题只有一个回答
if sub_answer . present? && sub_answer . first . score > = 0 . 0
if s . question_score < = sub_answer . first . score
stand_status = 1
else
stand_status = 2
end
sub_answer_score = sub_answer . first . score
else
stand_status = 0
sub_answer_score = nil
end
sub_score = {
" q_id " :s . id ,
" q_type " :s . question_type ,
" q_position " :s . question_number ,
" stand_status " :stand_status ,
" user_score " :sub_answer_score . present? ? sub_answer_score . round ( 1 ) . to_s : nil
}
@ex_sub_array . push ( sub_score )
end
@ex_obj_array = @ex_obj_array . sort_by { | k | k [ :q_position ] }
@ex_sub_array = @ex_sub_array . sort_by { | k | k [ :q_position ] }
end
#试卷的统计结果页面计算各题的。选择题和判断题原来是按: 已回答了本题的人数来计算的。现需要按已提交试卷的人数来计算。2019-8-23
def exercise_commit_result ( questions , user_ids )
question_infos = [ ]
percent = 0 . 0
commit_user_ids = user_ids . size
questions . includes ( :exercise_choices ) . each do | ex |
ex_total_score = commit_user_ids * ex & . question_score . to_f #该试卷的已回答的总分
# ex_answers = ex.exercise_answers
if ex . question_type != Exercise :: PRACTICAL
ques_title = ex . question_title
ques_less_title = nil
ex_answers = ex . exercise_answers
effictive_users = ex_answers . search_answer_users ( " user_id " , user_ids )
effictive_users_count = effictive_users . where ( " exercise_choice_id is not null or (answer_text is not null and answer_text !='') " ) . pluck ( :user_id ) . uniq . size if ex . question_type != Exercise :: COMPLETION
else
ques_title = ex . shixun . name
ques_less_title = ex . question_title
ex_answers = ex . exercise_shixun_answers
effictive_users = ex_answers . search_shixun_answers ( " user_id " , user_ids )
effictive_users_count = effictive_users . pluck ( :user_id ) . uniq . size
end
# effictive_users_count = effictive_users.size #有效回答数, 可能有重复的用户id, 这里仅统计是否回答这个问题的全部人数
#
if ex . question_type > Exercise :: COMPLETION #当为主观题和实训题时,
ex_answered_scores = effictive_users . score_reviewed . pluck ( :score ) . sum #该问题的全部得分
percent = ( ex_total_score == 0 . 0 ? 0 . 0 : ( ex_answered_scores / ex_total_score . to_f ) . round ( 3 ) * 100 ) #正确率
end
question_answer_infos = [ ]
if ex . question_type < = Exercise :: JUDGMENT #选择题和判断题
ex_choices = ex . exercise_choices
standard_answer = ex . exercise_standard_answers . pluck ( :exercise_choice_id ) . sort #标准答案的位置
#该问题的正确率
if ex . question_type == Exercise :: MULTIPLE #多选题
if standard_answer . size == 1 #以前的多选题答案存在一个表里
standard_answer = standard_answer . first . to_s . split ( " " ) . map ( & :to_i )
end
right_user_ids = user_ids
standard_answer . each do | choice_position |
standard_answer_choice_id = ex_choices . select { | ec | ec . choice_position == choice_position } . first & . id
right_user_ids = right_user_ids & effictive_users . select { | answer | answer . exercise_choice_id == standard_answer_choice_id } . pluck ( :user_id )
end
right_users_count = right_user_ids . size
# right_users_scores = right_users_count * ex&.question_score.to_f
else #单选题和判断题
standard_answer_choice_id = ex_choices . select { | ec | ec . choice_position == standard_answer . first } . first & . id
right_users_count = effictive_users . select { | answer | answer . exercise_choice_id == standard_answer_choice_id } . size
# right_users_scores = right_users_count * ex&.question_score.to_f
end
# percent = (ex_total_score == 0.0 ? 0.0 : (right_users_scores / ex_total_score.to_f).round(3) * 100) #正确率
percent = commit_user_ids > 0 ? ( right_users_count / commit_user_ids . to_f ) . round ( 3 ) * 100 : 0 . 0
#每个选项的正确率
ex_choices . each do | c |
right_answer = standard_answer . include? ( c . choice_position ) #选项的标准答案为选项的位置
answer_users_count = effictive_users . select { | answer | answer . exercise_choice_id == c . id } . size
answer_percent = ( effictive_users_count == 0 ? 0 . 0 : ( answer_users_count / effictive_users_count . to_f ) . round ( 3 ) )
answer_option = {
:choice_position = > c . choice_position ,
:choice_text = > c . choice_text ,
:choice_users_count = > answer_users_count ,
:choice_percent = > answer_percent . round ( 2 ) . to_s ,
:right_answer = > right_answer
}
question_answer_infos . push ( answer_option )
end
elsif ex . question_type == Exercise :: COMPLETION #填空题
effictive_users_ids = effictive_users . where ( " answer_text is not null and answer_text !='' " ) . pluck ( :user_id ) . uniq
effictive_users_count = effictive_users_ids . size
user_wrong_count = 0
effictive_users_ids . each do | s |
user_score = effictive_users . where ( user_id : s ) . pluck ( :score ) . sum
if user_score . to_f < ex & . question_score . to_f
user_wrong_count = user_wrong_count + 1
end
end
# user_wrong_ids = effictive_users.where()
# user_wrong_count = (user_wrong_ids & effictive_users_ids).uniq.size
ex_ordered = ex . is_ordered
null_standard_answer = ex . exercise_standard_answers
null_stand_choice = null_standard_answer . pluck ( :exercise_choice_id ) #一个exercise_choice_id可能对应多个answer_text
null_stand_text = null_standard_answer . pluck ( :answer_text )
standard_answer_count = 0
each_null_score = null_stand_choice . size > 0 ? ( ex & . question_score . to_f / null_stand_choice . uniq . size ) . round ( 3 ) : 0 . 0
all_user_count = 0
if ex_ordered
all_user_answers = effictive_users . pluck ( :answer_text )
null_stand_choice . each_with_index do | s , index |
s_choice_text = null_stand_text [ index ]
user_count = 0
# user_count = user_count + effictive_users.where("exercise_choice_id = ? and answer_text = ?",s,s_choice_text).pluck(:user_id).uniq.size
user_count = user_count + effictive_users . select { | answer | answer . exercise_choice_id == s && answer . answer_text == s_choice_text } . size
answer_percent = ( ( effictive_users_count == 0 ) ? 0 . 0 : ( user_count / effictive_users_count . to_f ) . round ( 3 ) )
answer_option = {
:choice_position = > index + 1 ,
:choice_text = > s_choice_text ,
:choice_users_count = > user_count ,
:choice_percent = > answer_percent . round ( 2 ) . to_s ,
:right_answer = > true
}
question_answer_infos . push ( answer_option )
all_user_count += user_count
standard_answer_count += 1
all_user_answers = all_user_answers - [ s ]
end
else
# cycled_stand = {}
null_stand_text . uniq . each_with_index do | stand , index |
user_count = 0
user_count = user_count + effictive_users . where ( " answer_text = ? " , stand ) . pluck ( :user_id ) . uniq . size
answer_percent = ( ( effictive_users_count == 0 ) ? 0 . 0 : ( user_count / effictive_users_count . to_f ) . round ( 3 ) )
answer_option = {
:choice_position = > index + 1 ,
:choice_text = > stand ,
:choice_users_count = > user_count ,
:choice_percent = > answer_percent . round ( 2 ) . to_s ,
:right_answer = > true
}
question_answer_infos . push ( answer_option )
all_user_count += user_count
standard_answer_count += 1
end
end
answer_user_score = all_user_count * each_null_score
percent = ( ex_total_score == 0 . 0 ? 0 . 0 : ( answer_user_score / ex_total_score . to_f ) . round ( 3 ) * 100 ) #正确率
if effictive_users_count > 0 && user_wrong_count > = 0
wrong_percent = ( user_wrong_count / effictive_users_count . to_f ) . round ( 3 )
else
wrong_percent = 0 . 0
end
wrong_answer_position = {
:choice_position = > ( standard_answer_count + 1 ) ,
:choice_text = > " wrong " ,
:choice_users_count = > user_wrong_count ,
:choice_percent = > wrong_percent . round ( 2 ) . to_s ,
:right_answer = > false
}
question_answer_infos . push ( wrong_answer_position )
elsif ex . question_type == Exercise :: SUBJECTIVE #主观题
ex_score = ex & . question_score
full_scores = effictive_users . search_exercise_answer ( " score " , ex_score ) . size #满分人数
no_full_scores = effictive_users . exercise_no_full_scores ( ex_score ) . size #部分分数人数
zero_scores = effictive_users . search_exercise_answer ( " score " , 0 . 0 ) . size #包含为0分的, 及未评阅的
un_review_scores = effictive_users_count - full_scores - no_full_scores - zero_scores #未评阅数
if un_review_scores < 0
un_review_scores = 0
end
main_scores_array = [ full_scores , no_full_scores , zero_scores , un_review_scores ]
main_scores_array . each_with_index do | s , index |
right_answer = ( index == 0 )
if effictive_users_count == 0 || s < 0
s = 0
score_percent = 0 . 0
else
score_percent = ( s . to_i / effictive_users_count . to_f ) . round ( 3 )
end
answer_option = {
:choice_position = > index + 1 ,
:choice_text = > index + 1 ,
:choice_users_count = > s ,
:choice_percent = > score_percent . round ( 2 ) . to_s ,
:right_answer = > right_answer
}
question_answer_infos . push ( answer_option )
end
elsif ex . question_type == Exercise :: PRACTICAL #实训题
ex . exercise_shixun_challenges . each do | c |
cha_score = c & . question_score
cha_shixun_answer = effictive_users . search_shixun_keys ( " exercise_shixun_challenge_id " , c . id )
effictive_users_count = cha_shixun_answer . size #实训题的每个关卡的有效填写量
full_scores = cha_shixun_answer . search_shixun_keys ( " score " , cha_score ) . size #满分人数
no_full_scores = cha_shixun_answer . shixun_no_full_scores ( cha_score ) . size #部分分数人数c
all_zero_scores = cha_shixun_answer . search_shixun_keys ( " score " , 0 . 0 ) . size #零分人数
shixun_scores = user_ids . count * cha_score
shixun_answered_scores = cha_shixun_answer . score_reviewed . pluck ( :score ) . sum #该问题的全部得分
game_percent = ( shixun_answered_scores == 0 . 0 ? 0 . 0 : ( shixun_answered_scores / shixun_scores . to_f ) . round ( 3 ) * 100 ) #正确率
shixun_score_array = [ full_scores , no_full_scores , all_zero_scores ]
shixun_chas = [ ]
shixun_score_array . each_with_index do | s , index |
right_answer = ( index == 0 )
score_percent = ( effictive_users_count == 0 ? 0 . 0 : ( s . to_i / effictive_users_count . to_f ) . round ( 3 ) )
answer_option = {
:choice_position = > index + 1 ,
:choice_text = > index + 1 ,
:choice_users_count = > s ,
:choice_percent = > score_percent . round ( 2 ) . to_s ,
:right_answer = > right_answer
}
shixun_chas . push ( answer_option )
end
shixun_new_chas = {
:cha_id = > c . challenge_id ,
:cha_name = > c . challenge . subject ,
:cha_position = > c . position ,
:cha_details = > shixun_chas ,
:cha_percent = > game_percent . round ( 2 ) . to_s
}
question_answer_infos . push ( shixun_new_chas )
end
end
ques_option = {
:ques_title = > ques_title ,
:ques_less_title = > ques_less_title , #副标题,仅实训题才有
:type = > ex . question_type ,
:position = > ex . question_number ,
:percent = > percent . round ( 2 ) . to_s ,
:ques_effictive_counts = > effictive_users_count ,
:ques_details = > question_answer_infos
}
question_infos . push ( ques_option )
end
question_infos
end
#获取试卷的已答/未答人数
def get_exercise_answers ( ex_users , status )
@exercise_answers = 0
@exercise_unanswers = 0
unless status == Exercise :: UNPUBLISHED
@exercise_answers = ex_users . commit_exercise_by_status ( 1 ) . size #表示已经提交了的用户
course_all_members_count = ex_users . size
@exercise_unanswers = ( course_all_members_count - @exercise_answers )
end
end
def exercise_index_show ( exercise , course , is_teacher_or , user )
# lock_icon 0出现锁, 1不出现锁
ex_show_text = [ ]
if course . is_end #课堂停止后,试卷显示为已结束
exercise_status = 4
elsif is_teacher_or == 1 #当前为老师的时候,显示的是老师身份的对应试卷的状态,因为该试卷,可能对应老师的多个分班
exercise_status = exercise . exercise_status
else
exercise_status = exercise . get_exercise_status ( user ) #当前用户查看的试卷的发布状态
end
case exercise_status
when 2
ex_show_text . push ( " 提交中 " )
when 3
ex_show_text . push ( " 已截止 " )
when 4
ex_show_text . push ( " 已结束 " )
else
ex_show_text
end
if is_teacher_or == 1
exercise_users_list = exercise . all_exercise_users ( user . id ) #当前老师所在班级的全部学生
unreview_count = exercise_status == 1 ? 0 : exercise_users_list . exercise_unreview . size
get_exercise_answers ( exercise_users_list , exercise_status )
ex_pb_time = exercise . get_exercise_times ( user . id , true )
exercise_publish_time = ex_pb_time [ :publish_time ]
exercise_end_time = ex_pb_time [ :end_time ]
current_status = 3
lock_icon = 0
if exercise_status == 1
ex_show_text . push ( " 未发布 " )
elsif exercise_status == 3
ex_show_text . push ( " 评阅中 " )
end
elsif is_teacher_or == 2
exercise_users_list = exercise . get_stu_exercise_users
get_exercise_answers ( exercise_users_list , exercise_status ) # 未答和已答的
unreview_count = exercise_status == 1 ? 0 : exercise_users_list . exercise_unreview . size
ex_pb_time = exercise . get_exercise_times ( user . id , false )
exercise_publish_time = ex_pb_time [ :publish_time ]
exercise_end_time = ex_pb_time [ :end_time ]
current_status = exercise . check_user_answer_status ( user )
lock_icon = 0
if current_status == 4
ex_show_text . push ( " 未提交 " )
end
else
exercise_users_list = exercise . get_stu_exercise_users
get_exercise_answers ( exercise_users_list , exercise_status ) # 未答和已答的
exercise_publish_time = exercise . publish_time
exercise_end_time = exercise . end_time
unreview_count = nil
if exercise . is_public
current_status = exercise . check_user_answer_status ( user )
lock_icon = 1 #不出现锁
if current_status == 4
ex_show_text . push ( " 未提交 " )
end
else
current_status = 4
lock_icon = 0
end
end
if ( course . is_public == 1 ) && exercise . is_public
lock_icon = 1
end
if exercise_status > 1
show_unreview_count = unreview_count
else
show_unreview_count = nil
end
if exercise_status == 2 && exercise_end_time . present?
ex_left_time = how_much_time ( exercise_end_time )
else #已截止后不显示时间
ex_left_time = nil
end
{
" publish_time " :exercise_publish_time ,
" end_time " :exercise_end_time ,
" exercise_answer " :@exercise_answers ,
" exercise_unanswer " :@exercise_unanswers ,
" current_status " :current_status ,
" lock_icon " :lock_icon ,
" unreview_count " : show_unreview_count ,
" ex_status " :exercise_status ,
" ex_tips " :ex_show_text ,
" ex_left_time " : ex_left_time
}
end
#计算试卷的总分和试卷的答题状态
def calculate_student_score ( exercise , user , end_time )
score1 = 0 . 0 #选择题/判断题
score2 = 0 . 0 #填空题
score5 = 0 . 0 #实训题
ques_stand = [ ] #问题是否正确
exercise_end_time = end_time || Time . now
exercise_questions = exercise . exercise_questions . includes ( :exercise_standard_answers , :exercise_shixun_challenges )
exercise_questions & . each do | q |
begin
if q . question_type != 5
answers_content = q . exercise_answers . where ( user_id : user . id ) #学生的答案
else
answers_content = q . exercise_shixun_answers . where ( user_id : user . id ) #学生的答案
end
if q . question_type < = 2 #为选择题或判断题时
if answers_content . present? #学生有回答时
answer_choice_array = [ ]
answers_content . each do | a |
answer_choice_array . push ( a . exercise_choice . choice_position ) #学生答案的位置
end
user_answer_content = answer_choice_array . sort
standard_answer = q . exercise_standard_answers . pluck ( :exercise_choice_id ) . sort #该问题的标准答案,可能有多个
#TODO: 旧版多选题的标准答案是放在一个里面的, 新版又做成了一个题有多个标准答案( exercise_choice_id存放的是标准答案的位置..)
if q . question_type == 1 && standard_answer . size == 1
standard_answer = standard_answer . first . to_s . split ( " " ) . map ( & :to_i ) . sort
end
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
if standard_answer . size > 0
q_score_1 = q . question_score
# q_score_1 = (q.question_score.to_f / standard_answer.count) #当多选答案正确时, 每个answer的分数均摊。
else
q_score_1 = 0 . 0
end
answers_content . update_all ( :score = > q_score_1 )
score1 = score1 + q . question_score
else
answers_content . update_all ( :score = > - 1 . 0 )
score1 += 0 . 0
end
else
score1 += 0 . 0
end
elsif q . question_type == 3 #填空题
if answers_content . present?
null_standard_answer = q . exercise_standard_answers
standard_answer_array = null_standard_answer . select ( :exercise_choice_id , :answer_text )
standard_answer_ids = standard_answer_array . pluck ( :exercise_choice_id ) . reject ( & :blank? ) . uniq #标准答案的exercise_choice_id数组
standard_answer_count = standard_answer_ids . count
if standard_answer_count > 0 #存在标准答案时才有分数
q_score_2 = ( q . question_score . to_f / standard_answer_count ) #每一空的得分
else
q_score_2 = 0 . 0
end
if q . is_ordered
answers_content . each do | u |
i_standard_answer = standard_answer_array . where ( exercise_choice_id : u . exercise_choice_id ) . pluck ( :answer_text ) . reject ( & :blank? ) . map { | a | a . strip . downcase } #该选项的全部标准答案
if i_standard_answer . include? ( u . answer_text . strip . downcase ) #该空的标准答案包含用户的答案才有分数
u . update_column ( 'score' , q_score_2 )
score2 = score2 + q_score_2
else
u . update_column ( 'score' , - 1 . 0 )
score2 += 0 . 0
end
end
else
st_answer_text = standard_answer_array . pluck ( :answer_text ) . reject ( & :blank? ) . map { | a | a . strip . downcase } . uniq
answers_content . each do | u |
u_answer_text = u . answer_text . strip . downcase
if st_answer_text . size == 1
if st_answer_text . first == u_answer_text
u . update_column ( " score " , q_score_2 )
score2 = score2 + q_score_2
else
u . update_column ( 'score' , - 1 . 0 )
score2 += 0 . 0
end
else
if st_answer_text . include? ( u_answer_text ) #只要标准答案包含用户的答案,就有分数。同时,下一次循环时,就会删除该标准答案。防止用户的相同答案获分
u . update_column ( " score " , q_score_2 )
score2 = score2 + q_score_2
st_answer_text . delete ( u_answer_text )
else
u . update_column ( 'score' , - 1 . 0 )
score2 += 0 . 0
end
end
end
end
else
score2 += 0 . 0
end
elsif q . question_type == 5 #实训题时,主观题这里不评分
q . exercise_shixun_challenges & . each do | exercise_cha |
user_shixun_score = exercise_cha & . exercise_shixun_answers & . where ( user_id : user . id , exercise_question_id : q . id )
if user_shixun_score . present?
score5 += user_shixun_score & . first . score
else
game = Game . user_games ( user . id , exercise_cha . challenge_id ) & . first #当前用户的关卡
if game . present?
exercise_cha_score = 0 . 0
answer_status = 0
# if game.status == 2 && game.final_score >= 0
if game . final_score > 0 && game . end_time && game . end_time < exercise_end_time
exercise_cha_score = game . real_score ( exercise_cha . question_score )
# exercise_cha_score = exercise_cha.question_score #每一关卡的得分
answer_status = 1
end
ex_shixun_answer_content = answers_content & . where ( exercise_shixun_challenge_id : exercise_cha . id )
code = nil
if exercise_cha . challenge & . path . present?
cha_path = challenge_path ( exercise_cha . challenge & . path )
game_challenge = game . game_codes . search_challenge_path ( cha_path ) & . first
if game_challenge . present?
game_code = game_challenge
code = game_code . try ( :new_code )
else
begin
code = git_fle_content ( game . myshixun . repo_path , cha_path )
rescue
code = " "
end
end
end
if ex_shixun_answer_content . blank? #把关卡的答案存入试卷的实训里
### Todo 实训题的_shixun_details里的代码是不是直接从这里取出就可以了? 涉及到code的多个版本库的修改
sx_option = {
:exercise_question_id = > q . id ,
:exercise_shixun_challenge_id = > exercise_cha . id ,
:user_id = > user . id ,
:score = > exercise_cha_score . round ( 1 ) ,
:answer_text = > code ,
:status = > answer_status
}
ExerciseShixunAnswer . create ( sx_option )
else
ex_shixun_answer_content . first . update_attributes ( score : exercise_cha_score . round ( 1 ) , answer_text : code )
end
score5 += exercise_cha_score
else
score5 += 0 . 0
end
end
end
end
user_scores = answers_content . blank? ? 0 . 0 : answers_content . score_reviewed . pluck ( :score ) . sum
if user_scores > 0 . 0
stand_answer = 1
else
stand_answer = 0
end
ques_option = {
" q_id " :q . id , #该问题的id
" q_type " :q . question_type ,
" q_position " :q . question_number , #该问题的位置
" stand_status " :stand_answer , #该问题是否正确,1为正确, 0为错误
" user_score " :user_scores . round ( 1 ) #每个问题的总得分
}
ques_stand . push ( ques_option )
rescue Exception = > e
Rails . logger . info ( " calcuclate_score_have_error____________________________ #{ e } " )
next
end
end
total_score = score1 + score2 + score5
{
" total_score " :total_score . round ( 1 ) ,
" stand_status " :ques_stand
}
end
#当单个问题的分数更新时,更新用户的总分
def update_single_score ( q , user_id , standard_answer )
score1 = 0 . 0 #用户的新得分
origin_score = 0 . 0 #用户的原来该问题的得分
answers_content = q & . exercise_answers & . where ( user_id : user_id ) #学生的答案
if answers_content . present? #用户回答了该题,才会改分数
if q . question_type < = 2 #为选择题或判断题时
origin_score = answers_content . first . score
answer_choice_array = [ ]
answers_content . each do | a |
answer_choice_array . push ( a . exercise_choice . choice_position ) #学生答案的位置
end
user_answer_content = answer_choice_array . sort
#TODO: 旧版多选题的标准答案是放在一个里面的, 新版又做成了一个题有多个标准答案( exercise_choice_id存放的是标准答案的位置..)
if q . question_type == 1 && standard_answer . size == 1
standard_answer = standard_answer . first . to_s . split ( " " ) . map ( & :to_i )
end
if user_answer_content == standard_answer . sort #答案一致,多选或单选才给分,答案不对不给分
if standard_answer . size > 0
q_score_1 = q . question_score
else
q_score_1 = 0 . 0
end
answers_content . update_all ( :score = > q_score_1 )
score1 = q_score_1
else
answers_content . update_all ( :score = > - 1 . 0 )
end
elsif q . question_type == 3 #填空题
origin_score = answers_content . score_reviewed . pluck ( :score ) . sum
standard_answer_count = standard_answer . count
if standard_answer_count > 0 #存在标准答案时才有分数
q_score_2 = ( q . question_score . to_f / standard_answer_count ) #每一空的得分
else
q_score_2 = 0 . 0
end
if q . is_ordered
answers_content . each do | u |
i_standard_answer = [ ]
standard_answer . each do | a |
if a [ :choice_id ] == u . exercise_choice_id
i_standard_answer += a [ :answer_text ]
end
end
i_standard_answer = i_standard_answer . map { | a | a . strip . downcase }
if i_standard_answer . include? ( u . answer_text . strip . downcase ) #该空的标准答案包含用户的答案才有分数
u . update_column ( 'score' , q_score_2 )
score1 = score1 + q_score_2
else
u . update_column ( 'score' , - 1 . 0 )
score1 += 0 . 0
end
end
else
st_answer_text = standard_answer . pluck ( :answer_text ) . sum . map { | a | a . strip . downcase }
answers_content . each do | u |
u_answer_text = u . answer_text . downcase
if st_answer_text . include? ( u_answer_text ) #只要标准答案包含用户的答案,就有分数。同时,下一次循环时,就会删除该标准答案。防止用户的相同答案获分
u . update_column ( " score " , q_score_2 )
score1 = score1 + q_score_2
st_answer_text . delete ( u_answer_text )
else
u . update_column ( 'score' , - 1 . 0 )
score1 += 0 . 0
end
end
end
end
end
origin_score = origin_score < 0 . 0 ? 0 . 0 : origin_score
score1 - origin_score
end
#获取用户的相关信息
def exercise_use_info ( ex_user , user_status , exercise )
course = exercise . course
current_user_group_id = " "
current_user_group_name = " "
ex_user_user = ex_user . user
exercise_user_name = ex_user_user . real_name
exercise_user_id = ex_user_user . id
ex_user_exercise_status = exercise . get_exercise_status ( ex_user_user )
ex_user_student_id = ex_user_user . student_id
if ex_user . start_at . present? && ( ex_user . commit_status == 0 ) #用户已回答,但未提交
commit_status = 2 #继续答题
else
commit_status = ex_user . commit_status
end
ex_user_end_at = ex_user . end_at
course_member = course . students . course_find_by_ids ( " user_id " , ex_user . user . id )
current_user_group_id = course_member . first . course_group_id if course_member . present?
if current_user_group_id == 0
current_user_group_name = " 未分班 "
else
course_group = course . course_groups . by_group_ids ( current_user_group_id )
current_user_group_name = course_group . first . name if course_group . present?
end
teacher_review = ex_user . subjective_score < 0 . 0 ? false : true
if ( user_status == 0 && commit_status == 1 ) || ( user_status == 1 && ex_user_exercise_status == 3 && commit_status == 1 ) #老师都可以看,学生,需在试卷已提交,且已截止的情况下看
ex_object_score = ex_user . objective_score < 0 . 0 ? 0 . 0 : ex_user . objective_score . round ( 1 ) . to_s
ex_subject_score = ex_user . subjective_score < 0 . 0 ? nil : ex_user . subjective_score . round ( 1 ) . to_s
score = ex_user . score . present? ? ex_user . score . round ( 1 ) . to_s : 0 . 0 . to_s
else
ex_object_score = nil
ex_subject_score = nil
score = nil
end
{
" user_name " :exercise_user_name ,
" login " :ex_user_user . login ,
" user_group_id " :current_user_group_id ,
" user_group_name " :current_user_group_name ,
" teacher_review " :teacher_review ,
" ex_object_score " :ex_object_score ,
" ex_subject_score " :ex_subject_score ,
" score " :score ,
" user_id " :exercise_user_id ,
" commit_status " :commit_status ,
" student_id " :ex_user_student_id ,
" end_at " :ex_user_end_at
}
end
#公用tab页的相关信息
def ex_common_header ( is_teacher_or , exercise )
exercise_url_status = [ ]
if is_teacher_or == 1 #当为老师的
common_tabs = %w( 1 2 3 4 )
else
if exercise . show_statistic #开启了公开统计
common_tabs = %w( 1 2 )
else
common_tabs = %w( 1 )
end
end
common_tabs . each do | c |
if request . url . include? ( " exercise_lists " )
active_status = 1
elsif request . url . include? ( " exercises_result " )
active_status = 1
elsif request . url . include? ( " exercise_setting " )
active_status = 1
elsif request . url == exercise_path ( exercise )
active_status = 1
else
active_status = 0
end
common_tab = {
:common_tab = > c ,
:active_status = > active_status
}
exercise_url_status . push ( common_tab )
end
exercise_url_status
end
#试卷/问卷 设置页面的发布规则返回内容
def get_user_setting_course ( user_published_setting , user_course_groups )
loop_course_publish_time = [ ]
total_array_groups = [ ]
user_published_setting . each do | u |
new_json_array_group = { }
setting_group_name = user_course_groups . detect { | g | g [ :group_id ] == u . course_group_id }
if loop_course_publish_time . length > 0
time_length = loop_course_publish_time . length #问卷发布时间和截止时间相同的集合
( 1 .. time_length ) . each do | i |
if ( loop_course_publish_time [ i - 1 ] [ :publish_time ] == u . publish_time ) && ( loop_course_publish_time [ i - 1 ] [ :end_time ] == u . end_time ) #当起止时间已存在时,直接更新
loop_course_ids = total_array_groups [ i - 1 ] [ :course_group_id ] + [ u . course_group_id ]
loop_course_names = total_array_groups [ i - 1 ] [ :course_group_name ] + [ setting_group_name [ :group_name ] ]
new_json_array_group = {
" loop_times " :i - 1 ,
" course_group_id " :loop_course_ids ,
" course_group_name " :loop_course_names ,
}
end
end
if new_json_array_group . length > 0
loop_times = new_json_array_group [ :loop_times ]
total_array_groups [ loop_times ] [ :course_group_id ] = new_json_array_group [ :course_group_id ]
total_array_groups [ loop_times ] [ :course_group_name ] = new_json_array_group [ :course_group_name ]
else
loop_course_times = {
" publish_time " :u . publish_time ,
" end_time " : u . end_time
}
loop_course_publish_time . push ( loop_course_times )
json_array_group = {
" course_group_id " : [ u . course_group_id ] ,
" course_group_name " : [ setting_group_name [ :group_name ] ] ,
" course_publish_time " :u . publish_time ,
" course_end_time " :u . end_time
}
total_array_groups . push ( json_array_group )
end
else #第一次循环获得初始值 第一步
loop_course_times = {
" publish_time " :u . publish_time ,
" end_time " : u . end_time
}
loop_course_publish_time . push ( loop_course_times )
json_array_group = { #第一个问卷发布规则的第一条记录
" course_group_id " : [ u . course_group_id ] ,
" course_group_name " : [ setting_group_name [ :group_name ] ] ,
" course_publish_time " :u . publish_time ,
" course_end_time " :u . end_time
}
total_array_groups . push ( json_array_group )
end
end
total_array_groups
end
#学生的分数状态及回答的内容
def user_question_answers ( q , ex_answerer_id , student_status , is_teacher_or , ex_status , ques_type , ex_type )
answered_content = [ ]
user_score = nil
shixun_type = 0
question_comment = [ ]
# user_score_pre = nil
if ques_type == 5
exercise_answers = q . exercise_shixun_answers . select { | answer | answer . user_id == ex_answerer_id }
else
exercise_answers = q . exercise_answers . select { | answer | answer . user_id == ex_answerer_id } #试卷用户的回答
end
if student_status == 2 #当前为老师,或为学生且已提交
user_score_pre = exercise_answers . select { | answer | answer . score > = 0 . 0 }
if ques_type == 4 #主观题时, 且没有大于0的分数时, 为空
user_score = user_score_pre . present? ? user_score_pre . pluck ( :score ) . sum : nil
elsif ques_type == 5
user_score = user_score_pre . present? ? user_score_pre . pluck ( :score ) . sum : 0 . 0
elsif ques_type == 3 #填空题时, 需小心出现9.9分
user_score = user_score_pre . present? ? user_score_pre . pluck ( :score ) . sum : 0 . 0
if user_score > 0 . 0
if user_score . to_s . split ( " . " ) . last == " 9 "
user_score = user_score . to_f + 0 . 1
end
end
# user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : 0.0
else #选择题,判断题根据第一个记录查分
user_score = user_score_pre . present? ? user_score_pre . first . score : 0 . 0
# if exercise_answers.present? #判断题和选择题时,
# answer_choice_array = []
# exercise_answers.each do |a|
# answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
# end
# user_answer_content = answer_choice_array.sort
# standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
# if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
# user_score = q.question_score
# else
# user_score = 0.0
# end
# else
# user_score = 0.0
# end
end
end
if user_score . present? && ( user_score > q . question_score )
user_score = q . question_score
end
if ques_type < = 2
answered_content = exercise_answers & . pluck ( :exercise_choice_id )
elsif ques_type == 3
exercise_answers & . each do | a |
u_answer = {
" choice_id " :a . exercise_choice_id ,
" answer_text " : a . answer_text
}
answered_content . push ( u_answer )
end
elsif ques_type == 4
answered_content = exercise_answers & . pluck ( :answer_text )
end
if ques_type == 5 #存在实训题,及已经做了实训题的
if ex_status == 3 || is_teacher_or == 1 #如果试卷已截止,则可以看到分数,否则不能查看分数
shixun_type = 2
elsif ex_status == 2 && q . exercise_shixun_answers . present? #试卷未截止,且用户已回答的,则能看到答题的状态
shixun_type = 1
end
end
if ex_type == 4 #填空题/主观题/实训题有评论的
q_answer_id = exercise_answers . present? ? exercise_answers . first . id : nil
question_comment = q . exercise_answer_comments . select { | comment | comment . exercise_answer_id == q_answer_id }
end
{
" user_score " : ( user_score . present? ? user_score . round ( 1 ) . to_s : nil ) ,
" answered_content " :answered_content ,
" shixun_type " :shixun_type ,
" question_comment " :question_comment
}
end
def convert_to_char ( str )
result = " "
length = str . length
unless str . nil?
if length === 1
result += ( str . to_i + 64 ) . chr
return result
elsif length > 1
for i in 0 ... length
result += ( str [ i ] . to_i + 64 ) . chr
end
return result
end
end
result
end
def get_exercise_left_time ( exercise , user )
ex_time = exercise . time
user_left_time = nil
time_now_i = Time . now . to_i
if ex_time > 0
exercise_user = exercise . exercise_users . find_by ( user_id : user . id )
time_mill = ex_time * 60 #转为秒
exercise_end_time = exercise . get_exercise_end_time ( user . id ) #没有考虑分班的情况
# exercise_end_time = exercise.end_time.present? ? exercise.end_time.to_i : 0
exercise_user_start = exercise_user & . start_at . present? ? exercise_user . start_at . to_i : 0
#用户未开始答题时, 即exercise_user_start为0
if exercise_user_start == 0
if ( exercise_end_time . to_i - time_now_i ) > time_mill
user_left_time = time_mill
else
user_left_time = ( exercise_end_time . to_i < time_now_i ) ? nil : ( exercise_end_time . to_i - time_now_i )
end
else
if ( exercise_user_start + time_mill ) > exercise_end_time . to_i
time_mill = exercise_end_time . to_i - exercise_user_start . to_i #如果开始答题时间加试卷的限时长大于试卷的截止时间,则以试卷的截止时间到开始答题时间为试卷的限时
end
exercise_user_left_time = time_now_i - exercise_user_start . to_i #用户已回答的时间
user_left_time = ( time_mill < exercise_user_left_time ) ? nil : ( time_mill - exercise_user_left_time ) #当前用户对试卷的回答剩余时间
end
end
user_left_time
end
#实训题学生代码的行数
def content_line ( content )
content . split ( / \ r? \ n / ) . length + 1
end
end