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/homeworks_service.rb

338 lines
17 KiB

class HomeworksService
# 创建实训作业
def create_homework shixun, course, category, current_user
ActiveRecord::Base.transaction do
homework = HomeworkCommon.new(name: shixun.name, description: shixun.description, homework_type: 4,
user_id: current_user.id, course_id: course.id,
course_second_category_id: category.try(:id).to_i)
homework_detail_manual = HomeworkDetailManual.new
homework.homework_detail_manual = homework_detail_manual
if homework.save!
homework_detail_manual.save! if homework_detail_manual
HomeworkCommonsShixun.create!(homework_common_id: homework.id, shixun_id: shixun.id)
HomeworksService.new.create_shixun_homework_cha_setting(homework, shixun)
HomeworksService.new.create_works_list(homework, course)
end
homework
end
end
#更新实训作业的状态
def update_shixun_work_status homework
shixun = homework.shixuns.first
student_works = homework.student_works.unfinished
homework_challenge_settings = homework.homework_challenge_settings
challeng_ids = homework_challenge_settings.map(&:challenge_id)
# 取已发布的作品
if homework.unified_setting
student_works = student_works
else
setting = homework.homework_group_settings.group_published
if setting.blank?
student_works = student_works.none
else
users = homework.course.course_members.course_find_by_ids("course_group_id",setting.map(&:course_group_id))
student_works = student_works.homework_by_user(users.map(&:user_id))
end
end
# 已发布作品且状态为未提交的作品 如果有开启过实训则更新状态
myshixuns = Myshixun.where(:shixun_id => shixun.id, :user_id => student_works.map(&:user_id))
myshixuns.each do |myshixun|
work = student_works.homework_by_user(myshixun.user_id).first
setting_time = homework.homework_group_setting myshixun.user_id
games = myshixun.games.where(:challenge_id => challeng_ids)
myshixun_endtime = games.select{|game| game.status == 2}.size == games.size ? games.map(&:end_time).max : nil
compelete_status = 0
if myshixun_endtime.present? && myshixun_endtime < setting_time.end_time
if myshixun_endtime < setting_time.publish_time
compelete_status = 2
else
compelete_status = 1
end
end
if setting_time.end_time > Time.now
work.update_attributes(:work_status => 1, :late_penalty => 0, :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id, :compelete_status => compelete_status)
else
work.update_attributes(:work_status => ((myshixun.is_complete? && (myshixun.done_time < setting_time.end_time)) ? 1 : 2), :late_penalty => (myshixun.is_complete? && (myshixun.done_time < setting_time.end_time) ? 0 : homework.late_penalty), :commit_time => myshixun.updated_at, :update_time => myshixun.updated_at, :myshixun_id => myshixun.id, :compelete_status => compelete_status)
end
set_shixun_final_score work
end
# 更新所有学生的效率分
HomeworksService.new.update_student_eff_score HomeworkCommon.where(:id => homework.id).first
end
# 实训作业的评分
def set_shixun_final_score student_work
homework = student_work.homework_common
answer_open_evaluation = homework.homework_detail_manual.answer_open_evaluation
myshixun = student_work.myshixun
if student_work.work_status != 0 && myshixun.present?
final_score = 0
compelete = true
max_endtime = ""
user_total_score = 0
pass_consume_time = 0
homework.homework_challenge_settings.each do |setting|
game = myshixun.games.find_by(challenge_id: setting.challenge_id, status: 2)
unless game.nil?
pass_consume_time += (game.cost_time / 60.0).to_f
user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i
adjust_score = student_work.challenge_work_scores.where(challenge_id: setting.challenge_id).last
final_score += adjust_score.present? ? adjust_score.score : (answer_open_evaluation ? setting.score : (game.final_score > 0 ? game.real_score(setting.score) : 0))
max_endtime = max_endtime == "" ? game.end_time : (game.end_time > max_endtime ? game.end_time : max_endtime)
else
compelete = false
end
end
if compelete && max_endtime != ""
homework = student_work.homework_common
setting_time = homework.homework_group_setting student_work.user_id
if setting_time.publish_time.present? && setting_time.end_time.present?
if max_endtime < setting_time.publish_time
student_work.compelete_status = 2
else
if max_endtime < setting_time.end_time || (homework.allow_late && (homework.course.end_date.nil? ||
max_endtime < homework.course.end_date.end_of_day))
student_work.compelete_status = 1
student_work.cost_time = max_endtime.to_i - setting_time.publish_time.to_i
else
student_work.compelete_status = 0
end
end
end
efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0))
student_work.efficiency = efficiency < 0 ? 0 : format("%.2f", efficiency)
if homework.work_efficiency
if homework.max_efficiency < student_work.efficiency
# homework.max_efficiency = student_work.efficiency
homework.update_column("max_efficiency", student_work.efficiency)
end
# eff_score = homework.max_efficiency == 0 ? 0 : student_work.efficiency / homework.max_efficiency * homework.eff_score
# student_work.eff_score = format("%.2f", eff_score)
# else
# student_work.eff_score = 0
end
elsif !compelete
student_work.compelete_status = 0
end
student_work.final_score = format("%.2f", final_score.to_f)
student_work.late_penalty = student_work.work_status == 1 ? 0 : homework.late_penalty
score = student_work.final_score + student_work.eff_score - student_work.late_penalty
student_work.work_score = format("%.2f", score < 0 ? 0 : score.to_f) unless student_work.ultimate_score
student_work.save!
end
end
# 计算实训作品学生的效率分
def update_student_eff_score homework
if homework.work_efficiency && homework.max_efficiency != 0
homework.student_works.where("compelete_status != 0").each do |student_work|
eff_score = student_work.efficiency / homework.max_efficiency * homework.eff_score
student_work.eff_score = format("%.2f", eff_score)
student_work.late_penalty = student_work.work_status == 1 ? 0 : homework.late_penalty
unless student_work.ultimate_score
work_score = student_work.final_score.to_f + student_work.eff_score - student_work.late_penalty
student_work.work_score = format("%.2f", work_score < 0 ? 0 : work_score)
end
student_work.save!
end
else
homework.student_works.where("compelete_status != 0").each do |student_work|
student_work.eff_score = 0
student_work.late_penalty = student_work.work_status == 1 ? 0 : homework.late_penalty
unless student_work.ultimate_score
work_score = student_work.final_score.to_f + student_work.eff_score - student_work.late_penalty
student_work.work_score = format("%.2f", work_score < 0 ? 0 : work_score)
end
student_work.save!
end
end
end
# 用户评测时更新实训作业成绩
def update_myshixun_work_score_old myshixun
ActiveRecord::Base.transaction do
student_works = myshixun.student_works.where(user_id: myshixun.user_id)
#logger.info("#############student_works_count: #{student_works.count}")
if student_works.count > 0
student_works.each do |work|
homework = work.homework_common
#logger.info("#############member_course_group_id: #{member.try(:course_group_id)}")
setting_time = homework.homework_group_setting work.user_id
if setting_time.end_time.present? && (setting_time.end_time > Time.now || (homework.allow_late && homework.late_time && homework.late_time > Time.now))
#logger.info("#############setting_time: #{setting_time.end_time}")
user_total_score = 0
pass_consume_time = 0
final_score = 0
homework.homework_challenge_settings.each do |setting|
game = myshixun.games.where(:challenge_id => setting.challenge_id, :status => 2).first
unless game.nil?
pass_consume_time += (game.cost_time / 60.0).to_f
user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i
adjust_score = work.challenge_work_scores.where(:challenge_id => setting.challenge_id).last
final_score += adjust_score.present? ? adjust_score.score : (homework.homework_detail_manual.answer_open_evaluation ? setting.score : (game.final_score > 0 ? game.real_score(setting.score) : 0))
end
end
if work.work_status == 0
is_complete = myshixun.is_complete? && (myshixun.done_time < setting_time.end_time)
work.work_status = setting_time.end_time > Time.now ? 1 : (is_complete ? 1 : 2)
work.late_penalty = setting_time.end_time > Time.now ? 0 : (is_complete ? 0 : homework.late_penalty)
work.commit_time = myshixun.created_at > setting_time.publish_time ? setting_time.publish_time : myshixun.created_at
work.myshixun_id = myshixun.id
end
games = myshixun.games.where(:challenge_id => homework.homework_challenge_settings.map(&:challenge_id))
myshixun_endtime = games.select{|game| game.status == 2}.size == games.size ? games.map(&:end_time).max : nil
if myshixun_endtime.present?
min_efficiency_changed = min_efficiency_changed.present? ? min_efficiency_changed : false
work.compelete_status = 1
work.cost_time = myshixun_endtime.to_i - setting_time.publish_time.to_i
efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0))
work.efficiency = format("%.2f", efficiency)
# 如果作业的最大效率值有变更则更新所有作品的效率分
if homework.work_efficiency && homework.max_efficiency < work.efficiency
homework.update_column("max_efficiency", work.efficiency)
end
end
work.update_time = Time.now
work.final_score = final_score
score = work.final_score + work.eff_score - work.late_penalty
work.work_score = format("%.2f",(score < 0 ? 0 : score).to_f) unless work.ultimate_score
#logger.info("#############work_score: #{score}")
work.save!
end
end
end
end
end
# 用户开启实训时更新作品状态
def update_myshixun_work_status myshixun
student_works = StudentWork.find_by_sql("SELECT sw.* FROM student_works sw, homework_commons_shixuns hcs WHERE
sw.user_id = #{myshixun.user_id} AND sw.`homework_common_id` = hcs.`homework_common_id`
AND hcs.`shixun_id` = #{myshixun.shixun_id} and sw.work_status = 0")
Rails.logger.info("#############student_works_count: #{student_works.count}")
if student_works.count > 0
student_works.each do |work|
homework = work.homework_common
setting_time = homework.homework_group_setting work.user_id
if setting_time.end_time.present? &&
(setting_time.end_time > Time.now || (homework.allow_late && homework.late_time && homework.late_time > Time.now))
work.work_status = setting_time.end_time > Time.now ? 1 : 2
work.late_penalty = setting_time.end_time > Time.now ? 0 : homework.late_penalty
work.update_time = Time.now
work.commit_time = Time.now
work.myshixun_id = myshixun.id
work.save!
end
end
end
end
# 实训作业的关卡设置
def create_shixun_homework_cha_setting homework, shixun
if shixun.present?
sum_score = 0
shixun.challenges.each_with_index do |challeng, index|
if index < shixun.challenges.length - 1
score = ((100.0 / shixun.challenges.length) * 100).floor / 100.0
sum_score += score
else
score = 100 - sum_score
end
HomeworkChallengeSetting.create!(homework_common_id: homework.id, challenge_id: challeng.id,
shixun_id: shixun.id, score: score)
end
end
end
# 为课堂学生创建作品
def create_works_list homework, course
if course.present? && CourseMember.students(course).size > 0
str = ""
CourseMember.students(course).each do |student|
str += "," if str != ""
str += "(#{homework.id},#{student.user_id}, '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}', '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}')"
end
if str != ""
sql = "insert into student_works (homework_common_id, user_id, created_at, updated_at) values" + str
ActiveRecord::Base.connection.execute sql
end
end
end
# 计算实训作品成绩
def update_myshixun_work_score work, myshixun, games, homework, challenge_settings
user_total_score = 0
pass_consume_time = 0
final_score = 0
setting_time = homework.homework_group_setting myshixun.user_id
homework_end_or_late_time = homework.allow_late ? homework.late_time : setting_time.end_time
games.each do |game|
# 在截止时间前通关的关卡才考虑得分
if game.status == 2 && game.end_time <= homework_end_or_late_time
challenge_setting = challenge_settings.select{|setting| setting.challenge_id == game.challenge_id}.first
pass_consume_time += (game.cost_time / 60.0).to_f
user_total_score += game.final_score.to_i < 0 ? 0 : game.challenge.score.to_i
adjust_score = work.challenge_work_scores.where(:challenge_id => game.challenge_id).last
final_score += if adjust_score.present?
adjust_score.score
elsif homework.homework_detail_manual.answer_open_evaluation
challenge_setting.score
elsif game.final_score > 0
game.real_score(challenge_setting.score)
else
0
end
end
end
myshixun_endtime = games.select{|game| game.status == 2}.size == games.size ? games.map(&:end_time).max : nil
if myshixun_endtime.present?
work.cost_time = myshixun_endtime.to_i - setting_time.publish_time.to_i
efficiency = (pass_consume_time == 0 ? 0 : Math.log((user_total_score / pass_consume_time.to_f) + 1.0))
work.efficiency = format("%.2f", efficiency)
if myshixun_endtime <= homework_end_or_late_time
work.compelete_status = myshixun_endtime < setting_time.publish_time ? 2 : 1
# 如果作业的最大效率值有变更则更新所有作品的效率分
homework.update_column("max_efficiency", work.efficiency) if homework.work_efficiency && homework.max_efficiency < work.efficiency
end
end
if work.work_status == 0
is_complete = myshixun_endtime && (myshixun_endtime < setting_time.end_time)
if is_complete || (!homework.allow_late && myshixun.created_at < setting_time.end_time)
work.work_status = 1
elsif homework.allow_late && myshixun.created_at < homework.late_time
work.work_status = 2
end
work.late_penalty = work.work_status == 2 ? homework.late_penalty : 0
work.commit_time = myshixun.created_at > setting_time.publish_time ? setting_time.publish_time : myshixun.created_at
work.myshixun_id = myshixun.id
end
work.update_time = myshixun.updated_at
work.final_score = final_score
score = work.final_score + work.eff_score - work.late_penalty
work.work_score = format("%.2f",(score < 0 ? 0 : score).to_f) unless work.ultimate_score
#logger.info("#############work_score: #{score}")
work.calculation_time = Time.now
work.save!
end
end