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

369 lines
18 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.

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
homework.position = course.practice_homeworks.first&.position.to_i + 1
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
max_efficiency = homework.student_works.where("compelete_status != 0").pluck(:efficiency).max
homework.update_column("max_efficiency", max_efficiency)
homework.student_works.where("compelete_status != 0").each do |student_work|
eff_score = student_work.efficiency / 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.select{|work_score| work_score.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
else
adjust_score = work.challenge_work_scores.select{|work_score| work_score.challenge_id == game.challenge_id}.last
final_score += adjust_score.score if adjust_score.present?
end
end
myshixun_endtime = games.select{|game| game.status == 2}.size == games.size ? games.map(&:end_time).max : nil
is_complete = myshixun_endtime && (myshixun_endtime < setting_time.end_time)
# if work.work_status == 0
# if is_complete || (myshixun.created_at < setting_time.end_time && (!homework.allow_late || setting_time.end_time >= Time.now))
# work.work_status = 1
# elsif homework.allow_late && myshixun.created_at < homework.late_time
# work.work_status = 2
# end
# end
if !homework.allow_late || is_complete
work.work_status = 1
elsif myshixun.created_at < homework.late_time
work.work_status = 2
end
if work.work_status != 0
if myshixun_endtime.present?
work_cost_time = myshixun_endtime.to_i - setting_time.publish_time.to_i
work.cost_time = work_cost_time > 0 ? work_cost_time : games.select{|game| game.status == 2}.pluck(:cost_time).sum
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
# 2是按时通关 3是迟交通关
work.compelete_status = myshixun_endtime < setting_time.end_time ? 2 : 3
# 如果作业的最大效率值有变更则更新所有作品的效率分
if homework.work_efficiency && homework.max_efficiency < work.efficiency
homework.max_efficiency = work.efficiency
homework.save(validate: false)
end
else
work.compelete_status = 1 # 未通关
end
else
work.compelete_status = 1 # 未通关
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
work.update_time = if myshixun_endtime.present? && myshixun_endtime <= homework_end_or_late_time
myshixun_endtime
elsif myshixun.updated_at > homework_end_or_late_time
last_pass_time = games.select{|game| game.status == 2 && game.end_time < homework_end_or_late_time}.map(&:end_time).max
last_pass_time.present? ? last_pass_time : myshixun.created_at
else
myshixun.updated_at
end
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(validate: false)
end
end
end