From 83d63dcfaf947306a999d32726e7b6bdbfd79180 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Fri, 16 Aug 2019 16:52:02 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=91=E8=AF=BE=E8=AF=95=E5=8D=B7=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/tasks/excellent_course_exercise.rake | 198 ++++++++++++++++++++--- 1 file changed, 175 insertions(+), 23 deletions(-) diff --git a/lib/tasks/excellent_course_exercise.rake b/lib/tasks/excellent_course_exercise.rake index 9f1484027..a607c24a0 100644 --- a/lib/tasks/excellent_course_exercise.rake +++ b/lib/tasks/excellent_course_exercise.rake @@ -1,34 +1,186 @@ #coding=utf-8 -# 执行示例 bundle exec rake excellent_course_exercise:student_answer args=149,2903 +# 执行示例 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: 2933) - - participant_count = 1042 - pass_count = 823 - - members_1 = course.students.order("id asc").limit(987) - members_2 = course.students.order("id asc").limit(1042) - members_1 = course.students.order("id asc").limit(322) - - exercise_1884 = course.exercises.find_by(id: 1884) - members_1.each_with_index do |member, index| - if index < 821 - exercise_1884.exercise_questions.where.not(question_type: 5).each do |question| - answer_option = { - :user_id => current_user.id, - :exercise_question_id => @exercise_question.id, - :exercise_choice_id => choice_id, - :answer_text => "" - } - ex_a = ExerciseAnswer.new(answer_option) - ex_a.save! - end + course = Course.find_by(id: course_id) + + course.exercises.each_with_index do |exercise, index| + # 第一个试卷的参与人数和通过人数都是传的数据,后续的随机 + 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 - 423)..participant_count) + new_pass_count = rand((new_participant_count - 113)..new_participant_count) + + members = course.students.order("id asc").limit(new_participant_count) + update_exercise_user(exercise, members, new_pass_count) + 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 + if exercise_question_ids.length == 20 + rand_num = index < pass_count - 1 ? 20 : rand(1..16) + elsif exercise_question_ids.length == 17 + rand_num = index < pass_count - 1 ? rand(13..17) : rand(1..11) else + rand_num = exercise_question_ids.length + end + if exercise_user && exercise_user.commit_status == 0 + exercise_question_ids = exercise_question_ids.sample(rand_num) + questions = exercise.exercise_questions.where(id: exercise_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 #该问题的标准答案,可能有多个 + 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 + 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 \ No newline at end of file