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 = q_type == Exercise::MULTIPLE ? answers_content.first.score : answers_content.last.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].to_s.strip
            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?   #学生有回答时
            if q.question_type == 0 || q.question_type == 2 ## 单选、判断题的算分与多选题分开计算
              user_answer = answers_content.last.exercise_choice.choice_position
              standard_answer = q.exercise_standard_answers.first&.exercise_choice_id
              if standard_answer.present? && user_answer == standard_answer
                q_score_1 = q.question_score
                score1 = score1 + q.question_score
              else
                q_score_1 = -1.0
              end
              answers_content.last.update!(score: q_score_1)
            else
              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
            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.nil? || 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