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/app/services/ecs/calculate_course_evaluation...

125 lines
4.9 KiB

class Ecs::CalculateCourseEvaluationService < ApplicationService
attr_reader :ec_course
def initialize(ec_course)
@ec_course = ec_course
end
def call
ActiveRecord::Base.transaction do
clear_student_score!
calculate_student_score_target!
calculate_graduation_requirement!
end
end
private
def clear_student_score!
ec_course.ec_course_student_scores.destroy_all
end
def requirement_passed?(standard_value, real_value)
standard_value && real_value && real_value >= standard_value ? 1 : 0
end
def calculate_student_score_target!
complete_target_count = 0
course_targets = ec_course.ec_course_targets.includes(ec_achievement_evaluation_relates: :ec_course_achievement_method)
course_targets.find_each do |target|
target.ec_achievement_evaluation_relates.each do |relate|
achievement_method = relate.ec_course_achievement_method
total = achievement_method.ec_achievement_evaluation_relates.count
percentage = total.zero? ? 0 : achievement_method.percentage.fdiv(total)
achievements = EcStudentAchievement.where(ec_course_evaluation_id: achievement_method.ec_course_evaluation_id)
achievements =
if relate.ec_course_evaluation_subitem_id.blank? || relate.ec_course_evaluation_subitem_id == -1
achievements.where(position: relate.position)
else
achievements.where(ec_course_evaluation_subitem_id: relate.ec_course_evaluation_subitem_id)
end
# 遍历学生成绩统计数据
achievements.find_each do |achievement|
student_score = EcCourseStudentScore.find_or_initialize_by(
ec_course_id: ec_course.id,
ec_year_student_id: achievement.ec_year_student_id
)
score = achievement_method.score.zero? || achievement.score.nil? ? 0 : (achievement.fdiv(achievement_method.score) * percentage).round(3)
if student_score.new_record?
student_score.student_name = achievement.student_name
student_score.student_number = achievement.student_number
student_score.save!
create_params = {
ec_course_id: ec_course.id, ec_year_student_id: achievement.ec_year_student_id,
ec_course_target_id: target.id, eaer_id: relate.id,
ec_target_position: target.position, score: score
}
student_score.ec_student_score_targets.create!(create_params)
else
score_target = EcStudentScoreTarget.find_or_initialize_by(
ec_course_id: ec_course.id,
ec_year_student_id: achievement.ec_year_student_id,
ec_course_student_score_id: student_score.id,
ec_course_target_id: target.id,
ec_target_position: target.position,
eaer_id: relate.id
)
score_target.score = score_target.score.to_f + score
score_target.save!
end
end
end
# 计算该课程目标是否完成
count = target.ec_student_score_targets.count
score = target.ec_student_score_targets.sum(:score)
average = count.zero? ? 0 : score.fdiv(count)
complete_target_count += 1 if target.standard_grade && target.standard_grade <= average
end
ec_course.update!(complete_target_count: complete_target_count)
end
def calculate_graduation_requirement!
student_scores = ec_course.ec_course_student_scores.joins(:ec_course_target).group(:ec_course_target_id)
student_scores = student_scores.select('AVG(score) as average_score, ec_course_target_id')
student_score_map = student_scores.group_by { |item| item.ec_course_target_id }
subitem_targets = ec_course.ec_graduation_subitem_course_targets.includes(:ec_graduation_subitem, :ec_course_target)
subitem_targets.group_by { |subitem_target| subitem_target.ec_graduation_subitem }.each do |subitem, subitem_target_arr|
support = subitem.ec_course_supports.find_by(ec_course_id: ec_course.id)
next if support.blank?
total_weight = 0.0
total_score = 0.0
subitem_target_arr.each do |subitem_target|
target = subitem_target.ec_course_target
student_score = student_score_map[target.id].first
total_weight += target.weigths.to_f
total_score += student_score.average_score.round(2) * target.weigths.to_f
end
target_value = support.weights.to_f * ec_course.ec_year.calculation_value.to_f
real_value = total_weight.zero? ? 0 : (total_score * support.weights.to_f) / (total_weight * 100)
cal = support.ec_graduation_requirement_calculation || support.build_ec_graduation_requirement_calculation
cal.target_value = target_value.round(3)
cal.real_value = real_value.round(3)
cal.status = requirement_passed?(target_value, real_value)
cal.save!
end
end
end