You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
educoder/lib/tasks/excellent_course_exercise.rake

203 lines
8.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#coding=utf-8
# 执行示例 bundle exec rake excellent_course_exercise:student_answer args=2933,1042,823
# args 第一个是course_id, 第二个是参与人数, 第三个是通过人数
desc "同步精品课的学生试卷数据"
namespace :excellent_course_exercise do
if ENV['args']
course_id = ENV['args'].split(",")[0] # 对应课堂的id
participant_count = ENV['args'].split(",")[1].to_i # 表示参与人数
pass_count = ENV['args'].split(",")[2].to_i # 表示通过人数
end
task :student_answer => :environment do
course = Course.find_by(id: course_id)
course.exercises.each_with_index do |exercise, index|
if exercise.exercise_users.where(commit_status: 1).count == 0
# 第一个试卷的参与人数和通过人数都是传的数据,后续的随机
if index == 0
members = course.students.order("id asc").limit(participant_count)
update_exercise_user(exercise, members, pass_count)
else
new_participant_count = rand((participant_count - 20)..participant_count)
new_pass_count = rand((new_participant_count - 30)..new_participant_count)
members = course.students.order("id asc").limit(new_participant_count)
update_exercise_user(exercise, members, new_pass_count)
end
end
end
end
def update_exercise_user exercise, members, pass_count
exercise_question_ids = exercise.exercise_questions.where(question_type: 0).pluck(:id)
# index < pass_count 之前的学生都是通关的,之后的未通过
members.each_with_index do |member, index|
exercise_user = exercise.exercise_users.where(user_id: member.user_id).take
question_length = exercise_question_ids.length
if question_length == 20
rand_num = index < pass_count - 1 ? rand(15..20) : rand(1..10)
elsif question_length == 17
rand_num = index < pass_count - 1 ? rand(12..17) : rand(1..9)
elsif question_length == 39
rand_num = index < pass_count - 1 ? rand(30..39) : rand(1..18)
else
rand_num = index < pass_count - 1 ? rand((question_length-3)..question_length) : rand(1..(question_length-8))
end
if exercise_user && exercise_user.commit_status == 0
question_ids = exercise_question_ids.sample(rand_num)
questions = exercise.exercise_questions.where(id: question_ids)
create_exercise_answer questions, member.user_id
total_score = calculate_student_score(exercise, member.user)
commit_option = {
:status => 1,
:commit_status => 1,
:start_at => exercise.publish_time,
:end_at => exercise.end_time,
:objective_score => total_score,
:score => total_score,
:subjective_score => 0
}
exercise_user.update_columns(commit_option)
end
end
end
def create_exercise_answer questions, user_id
questions.each do |question|
choice_position = question.exercise_standard_answers.take&.exercise_choice_id
choice = question.exercise_choices.where(choice_position: choice_position).take
answer_option = {
:user_id => user_id,
:exercise_question_id => question.id,
:exercise_choice_id => choice&.id,
:answer_text => ""
}
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
end
#计算试卷的总分和试卷的答题状态
def calculate_student_score(exercise,user)
score1 = 0.0 #选择题/判断题
score2 = 0.0 #填空题
score5 = 0.0 #实训题
total_score = 0.0
ques_stand = [] #问题是否正确
exercise_questions = exercise.exercise_questions.includes(:exercise_answers,:exercise_shixun_answers,: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)
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 == 5 #实训题时,主观题这里不评分
q.exercise_shixun_challenges&.each do |exercise_cha|
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
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 #8-23,hs
code = git_fle_content(game.myshixun.repo_path,cha_path)
rescue
code = ""
end
# code = git_fle_content(game.myshixun.repo_path,cha_path)
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
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
end
end