|
|
|
@ -0,0 +1,756 @@
|
|
|
|
|
class StudentWork < ApplicationRecord
|
|
|
|
|
#学生提交作品表 #work_status :0 未提交 1 已提交 2 迟交 -1重做中
|
|
|
|
|
# compelete_status 实训作业完成状态: -1重做中 0未开启 1未通关 2按时通关 3迟交通关 4是截止通关
|
|
|
|
|
|
|
|
|
|
module WORK_STATUS
|
|
|
|
|
UNSUBMITTED = 0
|
|
|
|
|
SUBMITTED = 1
|
|
|
|
|
LATE_SUBMITTED = 2
|
|
|
|
|
REDO = -1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
belongs_to :user
|
|
|
|
|
belongs_to :commit_user, class_name: 'User', foreign_key: :commit_user_id, optional: true
|
|
|
|
|
belongs_to :update_user, class_name: 'User', foreign_key: :update_user_id, optional: true
|
|
|
|
|
belongs_to :homework_common #, touch: true
|
|
|
|
|
belongs_to :myshixun, optional: true
|
|
|
|
|
has_many :score_details, dependent: :destroy
|
|
|
|
|
has_many :student_works_evaluation_distributions, dependent: :destroy
|
|
|
|
|
has_many :student_works_scores, dependent: :destroy
|
|
|
|
|
has_many :shixun_work_comments, dependent: :destroy
|
|
|
|
|
has_many :student_work_hacks, dependent: :destroy
|
|
|
|
|
has_many :my_hacks, through: :student_work_hacks, source: :hack
|
|
|
|
|
#问题反馈
|
|
|
|
|
has_many :student_work_feedbacks
|
|
|
|
|
|
|
|
|
|
has_many :histories, class_name: 'StudentWorkHistory', dependent: :destroy
|
|
|
|
|
|
|
|
|
|
COMPLETE_STATUS_STR_TO_NUM = { '未开启' => 0, '未通关' => 1, '按时通关' => 2, '迟交通关' => 3, '截止后通关' => 4 }
|
|
|
|
|
WORK_STATUS_STR_TO_NUM = { '未提交' => 0, '按时提交' => 1, '延时提交' => 2}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def hack_user_codes
|
|
|
|
|
HackUserCode.without_description.where(user_id: self.user_id, homework_common_id: self.homework_common_id)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def teacher_score_details
|
|
|
|
|
homework_common.score_detail_names.map do |name|
|
|
|
|
|
score_details.where(name: name, reviewer_role: 1).first.try(:score) || "未评分"
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def teaching_asistant_score_details
|
|
|
|
|
homework_common.score_detail_names.map do |name|
|
|
|
|
|
score_details.where(name: name, reviewer_role: 2).first.try(:score) || "未评分"
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def student_score_details
|
|
|
|
|
homework_common.score_detail_names.map do |name|
|
|
|
|
|
score_details.where(name: name, reviewer_role: 3).first.try(:score) || "未评分"
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def deal_score_details(reviewer_role, score_details_params)
|
|
|
|
|
# reviewer_role 1:老师 2:助教 3:学生
|
|
|
|
|
# create_table :score_details do |t|
|
|
|
|
|
# t.float :score, comment: '分数'
|
|
|
|
|
# t.name :string, content: '评分项'
|
|
|
|
|
# t.float :score_percent, comment: '分数百分比'
|
|
|
|
|
# t.integer :reviewer_role, comment: '评分项类型 1教师,2助教,3学生'
|
|
|
|
|
# t.integer :parent_id
|
|
|
|
|
# t.integer :user_id
|
|
|
|
|
# t.integer :homework_common_id
|
|
|
|
|
# t.integer :student_work_id
|
|
|
|
|
#
|
|
|
|
|
# t.timestamps
|
|
|
|
|
# end
|
|
|
|
|
score_details_params = score_details_params.is_a?(Array) ? score_details_params : Array(score_details_params)
|
|
|
|
|
score_details_params = score_details_params.compact
|
|
|
|
|
score_details.where(reviewer_role: reviewer_role).destroy_all
|
|
|
|
|
score_details_params.each do |score_detail|
|
|
|
|
|
score_details.create(
|
|
|
|
|
score: score_detail[:score],
|
|
|
|
|
name: score_detail[:name],
|
|
|
|
|
reviewer_role: reviewer_role,
|
|
|
|
|
user_id: User.current.id
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def score_details_with_settings_change(total_score, score_details_params, create_box)
|
|
|
|
|
score_details_params = score_details_params.is_a?(Array) ? score_details_params : Array(score_details_params)
|
|
|
|
|
score_details_params = score_details_params.compact
|
|
|
|
|
teacher_score = self.teacher_score.to_f
|
|
|
|
|
teaching_asistant_score = self.teaching_asistant_score.to_f
|
|
|
|
|
student_score = self.student_score.to_f
|
|
|
|
|
# score_details.delete_all
|
|
|
|
|
if teacher_score > 0
|
|
|
|
|
get_score = 0
|
|
|
|
|
score_details_params.each_with_index do |score_detail, index|
|
|
|
|
|
score = if index == score_details_params.size - 1
|
|
|
|
|
teacher_score - get_score
|
|
|
|
|
else
|
|
|
|
|
(score_detail[:score].to_f / total_score * teacher_score).round(2)
|
|
|
|
|
end
|
|
|
|
|
get_score += score
|
|
|
|
|
create_box << score_details.new(
|
|
|
|
|
score: score,
|
|
|
|
|
name: score_detail[:name],
|
|
|
|
|
reviewer_role: 1,
|
|
|
|
|
user_id: User.current.id
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if teaching_asistant_score > 0
|
|
|
|
|
get_score = 0
|
|
|
|
|
score_details_params.each_with_index do |score_detail, index|
|
|
|
|
|
score = if index == score_details_params.size - 1
|
|
|
|
|
teaching_asistant_score - get_score
|
|
|
|
|
else
|
|
|
|
|
(score_detail[:score].to_f / total_score * teaching_asistant_score).round(2)
|
|
|
|
|
end
|
|
|
|
|
get_score += score
|
|
|
|
|
create_box << score_details.new(
|
|
|
|
|
score: score,
|
|
|
|
|
name: score_detail[:name],
|
|
|
|
|
reviewer_role: 2,
|
|
|
|
|
user_id: User.current.id
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if student_score > 0
|
|
|
|
|
get_score = 0
|
|
|
|
|
score_details_params.each_with_index do |score_detail, index|
|
|
|
|
|
score = if index == score_details_params.size - 1
|
|
|
|
|
student_score - get_score
|
|
|
|
|
else
|
|
|
|
|
(score_detail[:score].to_f / total_score * student_score).round(2)
|
|
|
|
|
end
|
|
|
|
|
get_score += score
|
|
|
|
|
create_box << score_details.new(
|
|
|
|
|
score: score,
|
|
|
|
|
name: score_detail[:name],
|
|
|
|
|
reviewer_role: 3,
|
|
|
|
|
user_id: User.current.id
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
StudentWorksScore.unscoped.where(student_work: self).each do |sw|
|
|
|
|
|
create_box = sw.score_details_with_settings_change(total_score, score_details_params, create_box)
|
|
|
|
|
end
|
|
|
|
|
create_box
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def deal_score_details_with_settings(reviewer_role, score_details_params)
|
|
|
|
|
create_box = []
|
|
|
|
|
t_score = case reviewer_role
|
|
|
|
|
when 1
|
|
|
|
|
self.teacher_score.to_f
|
|
|
|
|
when 2
|
|
|
|
|
self.teaching_asistant_score.to_f
|
|
|
|
|
when 3
|
|
|
|
|
self.student_score.to_f
|
|
|
|
|
end
|
|
|
|
|
score_details.where(reviewer_role: reviewer_role).delete_all
|
|
|
|
|
get_score = 0
|
|
|
|
|
score_details_params.each_with_index do |score_detail, index|
|
|
|
|
|
score = if index == score_details_params.size - 1
|
|
|
|
|
t_score - get_score
|
|
|
|
|
else
|
|
|
|
|
(score_detail[:score].to_f / 100 * t_score).round(2)
|
|
|
|
|
end
|
|
|
|
|
get_score += score
|
|
|
|
|
create_box << score_details.create(
|
|
|
|
|
score: score,
|
|
|
|
|
name: score_detail[:name],
|
|
|
|
|
reviewer_role: reviewer_role,
|
|
|
|
|
user_id: User.current.id
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
belongs_to :project, optional: true
|
|
|
|
|
|
|
|
|
|
# attachtype: 1(正常提交的附件), 7(补交的附件), 8(打回重做的附件)
|
|
|
|
|
has_many :attachments, as: :container, dependent: :destroy
|
|
|
|
|
|
|
|
|
|
has_many :tidings, as: :container, dependent: :destroy
|
|
|
|
|
|
|
|
|
|
has_many :challenge_work_scores, dependent: :destroy
|
|
|
|
|
|
|
|
|
|
before_save :set_work_score
|
|
|
|
|
|
|
|
|
|
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符" }
|
|
|
|
|
|
|
|
|
|
scope :has_committed, lambda { where("work_status > 0") }
|
|
|
|
|
# 重做
|
|
|
|
|
scope :redoing, -> {where(work_status: -1)}
|
|
|
|
|
# 未提交
|
|
|
|
|
scope :unfinished, -> {where(work_status: 0)}
|
|
|
|
|
# 按时提交
|
|
|
|
|
scope :finished, -> {where(work_status: 1)}
|
|
|
|
|
# 延迟提交
|
|
|
|
|
scope :delay_finished, -> {where(work_status: 2)}
|
|
|
|
|
# 有效(未被删除的)学生用户
|
|
|
|
|
scope :undeletes, -> { where(is_delete: 0) }
|
|
|
|
|
|
|
|
|
|
#按用户id查找
|
|
|
|
|
scope :homework_by_user, lambda{|ids| where(user_id: ids)}
|
|
|
|
|
|
|
|
|
|
#根据homework_common_id查找
|
|
|
|
|
scope :find_by_homework, lambda{|ids| where(homework_common_id: ids)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_unfinish?
|
|
|
|
|
work_status == 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def is_redoing?
|
|
|
|
|
work_status == -1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def is_delay_finished?
|
|
|
|
|
work_status == 2
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def is_finished?
|
|
|
|
|
work_status == 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def is_commit?
|
|
|
|
|
work_status > 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def myshixun_consume
|
|
|
|
|
self.myshixun && self.myshixun.passed_count > 0 ? self.myshixun.total_spend_time : "--"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def myshixun_consume_second
|
|
|
|
|
self.myshixun && self.myshixun.passed_count > 0 ? self.myshixun.total_spend_time_second : 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 助教评分次数
|
|
|
|
|
def ta_comment_count
|
|
|
|
|
self.student_works_scores.select{|score| score.reviewer_role == 2}.group_by(&:user_id).count
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 匿评次数(被别人评阅)
|
|
|
|
|
def student_comment_num
|
|
|
|
|
homework_common.homework_detail_manual.comment_status > 0 && work_status > 0 ? self.student_works_scores.select{|score| score.reviewer_role == 3}.group_by(&:user_id).size : 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 学生评阅作品数(评阅别人,按作品)
|
|
|
|
|
def user_comment_num
|
|
|
|
|
if homework_common.homework_detail_manual.comment_status > 0 && work_status > 0
|
|
|
|
|
count = homework_common.student_works_scores.select{|score| score.reviewer_role == 3 && score.user_id == user_id}.group_by(&:student_work_id).size
|
|
|
|
|
else
|
|
|
|
|
count = 0
|
|
|
|
|
end
|
|
|
|
|
count
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 分配匿评总数
|
|
|
|
|
def anonymous_comment_count
|
|
|
|
|
self.student_works_evaluation_distributions.count
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 匿评用户ids
|
|
|
|
|
def anonymous_comment_users
|
|
|
|
|
self.student_works_evaluation_distributions.pluck("student_works_evaluation_distributions.user_id").uniq
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 匿评申诉总条数
|
|
|
|
|
def appeal_all_count
|
|
|
|
|
homework_common.homework_detail_manual.comment_status >= 3 ? self.student_works_scores.
|
|
|
|
|
select{|score| score.reviewer_role == 3 && score.appeal_status != 0}.group_by(&:user_id).count : 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 匿评申诉待处理条数
|
|
|
|
|
def appeal_deal_count
|
|
|
|
|
homework_common.homework_detail_manual.comment_status >= 3 ? self.student_works_scores.
|
|
|
|
|
select{|score| score.reviewer_role == 3 && score.appeal_status == 1}.group_by(&:user_id).count : 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 当前用户对该作业的评语数量
|
|
|
|
|
def my_comment_all_count user_id
|
|
|
|
|
student_works_scores.select{|score| score.reviewer_role == 3 && score.user_id == user_id}.size
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 当前用户对该作业的申诉状态
|
|
|
|
|
def my_appeal_status user_id
|
|
|
|
|
last_score = student_works_scores.joins(:student_works_scores_appeal).select{|score| score.reviewer_role == 3 && score.is_invalid = 0 && score.user_id == user_id}.last
|
|
|
|
|
last_score.nil? ? -1 : last_score.appeal_status
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 当前用户对该作业是否采用整组同评(旧评语数据展示"--")
|
|
|
|
|
def group_comment user_id
|
|
|
|
|
old_time = "2024-05-10 00:00:00".to_time
|
|
|
|
|
last_comment = student_works_scores.select{|score| score.reviewer_role == 3 && score.is_invalid = 0 && score.user_id == user_id }.last
|
|
|
|
|
last_comment.nil? || (last_comment.created_at < old_time) ? '--' : (last_comment.group_comment ? "是" : "否")
|
|
|
|
|
end
|
|
|
|
|
# 当前用户该作品的匿评申诉总条数
|
|
|
|
|
def my_appeal_all_count user_id
|
|
|
|
|
student_works_scores.select{|score| score.reviewer_role == 3 && score.appeal_status != 0 && score.user_id == user_id}.size
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 当前用户该作品的匿评申诉总条数
|
|
|
|
|
def my_appeal_deal_count user_id
|
|
|
|
|
student_works_scores.select{|score| score.reviewer_role == 3 && score.appeal_status == 1 && score.user_id == user_id}.size
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def new_appeal_all_count
|
|
|
|
|
student_works_scores.joins(:student_works_scores_appeal).select{|score| score.reviewer_role == 3 }.length
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def new_appeal_deal_count
|
|
|
|
|
student_works_scores.joins(:student_works_scores_appeal).select{|score| score.reviewer_role == 3 && score.appeal_status == 1 }.length
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 代码差异行数
|
|
|
|
|
def diff_code_count(challenge)
|
|
|
|
|
return 0 if self.diff_code_json.blank?
|
|
|
|
|
return 0 if challenge.path.blank?
|
|
|
|
|
paths = challenge.path.split(";")
|
|
|
|
|
data = JSON.parse(self.diff_code_json)
|
|
|
|
|
details = data["details"].select { |d| paths.include?(d["path"]) }
|
|
|
|
|
details.map{|d| d["totalLines"]}.sum
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 分组名
|
|
|
|
|
def work_group_name
|
|
|
|
|
self.group_id == 0 ? "--" : "分组#{self.group_id}"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 助教评分
|
|
|
|
|
def ta_score ta_mode
|
|
|
|
|
if ta_mode == 1
|
|
|
|
|
ts_score = StudentWorksScore.find_by_sql("SELECT AVG(score) AS score FROM (SELECT * FROM
|
|
|
|
|
(SELECT * FROM student_works_scores WHERE student_work_id = #{self.id}
|
|
|
|
|
AND reviewer_role = 2 AND score IS NOT NULL ORDER BY created_at DESC)
|
|
|
|
|
AS t GROUP BY user_id) AS a")
|
|
|
|
|
score = ts_score.first.score.nil? ? nil : ts_score.first.score.to_f.try(:round, 2)
|
|
|
|
|
else
|
|
|
|
|
score = StudentWorksScore.where("student_work_id = #{self.id} AND reviewer_role = 2 AND score IS NOT NULL").last.try(:score)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 缺评次数
|
|
|
|
|
def absence_count
|
|
|
|
|
absence_penalty_count = self.user.student_works_evaluation_distributions.joins(:student_work).
|
|
|
|
|
where("homework_common_id = #{self.homework_common_id}").count -
|
|
|
|
|
self.user.student_works_scores.joins(:student_work).where("homework_common_id = #{self.homework_common_id}
|
|
|
|
|
and reviewer_role = 3").select("distinct student_work_id").count
|
|
|
|
|
absence_penalty_count = absence_penalty_count < 0 ? 0 : absence_penalty_count
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 违规匿评次数
|
|
|
|
|
def appeal_count
|
|
|
|
|
appeal_count = self.user.student_works_scores.joins(:student_work).where("student_works.homework_common_id = #{self.homework_common_id}
|
|
|
|
|
and appeal_status = 3").select("distinct student_work_id").count
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def delete_atta atta
|
|
|
|
|
last_score = student_works_scores.last
|
|
|
|
|
(atta.author_id == User.current.id) && (last_score.blank? || last_score.try(:created_at) < atta.created_on)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 作品总体评价
|
|
|
|
|
def overall_appraisal
|
|
|
|
|
return "--" if work_status <= 0
|
|
|
|
|
case (self.work_score.to_f / homework_common.total_score).round(2)
|
|
|
|
|
when (0.90..1.00)
|
|
|
|
|
'优秀'
|
|
|
|
|
when (0.70...0.90)
|
|
|
|
|
'良好'
|
|
|
|
|
when (0.60...0.70)
|
|
|
|
|
'及格'
|
|
|
|
|
when (0.00...0.60)
|
|
|
|
|
'不及格'
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 实训作业的作品状态 0:未提交,1:未通关,2:按时通关(提交截止前通关),3:迟交通关(提交截止-补交截止间通关)
|
|
|
|
|
def real_work_status
|
|
|
|
|
status = work_status
|
|
|
|
|
if status > 0 && myshixun
|
|
|
|
|
if myshixun.status != 1
|
|
|
|
|
status = 1
|
|
|
|
|
else
|
|
|
|
|
homework_end_time = homework_common.homework_group_setting(user_id)&.end_time
|
|
|
|
|
if homework_end_time.present? && homework_end_time > myshixun.passed_time
|
|
|
|
|
status = 2
|
|
|
|
|
elsif homework_end_time.present? && homework_common.allow_late && homework_common.late_time > myshixun.passed_time
|
|
|
|
|
status = 3
|
|
|
|
|
else
|
|
|
|
|
status = 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
status
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 更新作品成绩
|
|
|
|
|
def set_work_score
|
|
|
|
|
if work_status > 0 && homework_common && !homework_common.is_export_type?
|
|
|
|
|
case homework_common.homework_type
|
|
|
|
|
when "normal", "group"
|
|
|
|
|
#如果是图文jupyter实训作业
|
|
|
|
|
tea_ass_proportion = homework_common.homework_detail_manual.ta_proportion
|
|
|
|
|
tea_proportion = homework_common.homework_detail_manual.te_proportion
|
|
|
|
|
gr_leader_proportion = 0
|
|
|
|
|
gr_leader_proportion = homework_common.homework_detail_manual.gr_proportion if homework_common.homework_detail_manual.is_group_grade?
|
|
|
|
|
#是否有评分设置 教师、助教、学生评分
|
|
|
|
|
# teacher_score_setting = tea_proportion.to_f > 0 ? !student_work.teacher_score.nil? : false
|
|
|
|
|
# teaching_asistant_score_setting = tea_ass_proportion.to_f > 0 ? !student_work.teaching_asistant_score.nil? : false
|
|
|
|
|
# student_score_setting = (1 - tea_proportion - tea_ass_proportion) > 0 ? !student_work.student_score.nil? : false
|
|
|
|
|
# is_score_setting = (teacher_score_setting || teaching_asistant_score_setting || student_score_setting) ? true : false
|
|
|
|
|
# return if homework_common.homework_type == "normal" && HomeworkCommonsShixun.exists?(homework_common_id: homework_common.id) && self.ultimate_score
|
|
|
|
|
if !homework_common&.homework_detail_manual&.final_mode
|
|
|
|
|
if self.teacher_score
|
|
|
|
|
if self.teaching_asistant_score.nil?
|
|
|
|
|
if self.group_leader_score.nil?
|
|
|
|
|
if self.student_score.nil?
|
|
|
|
|
#只有老师评分
|
|
|
|
|
self.final_score = self.teacher_score
|
|
|
|
|
else
|
|
|
|
|
#有老师、学生评分 没有组长、助教
|
|
|
|
|
te_proportion = tea_proportion + (tea_ass_proportion + gr_leader_proportion) / 2
|
|
|
|
|
final_te_score = BigDecimal.new("#{self.teacher_score}") * BigDecimal.new("#{te_proportion}")
|
|
|
|
|
final_s_score = BigDecimal.new("#{self.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{te_proportion}"))
|
|
|
|
|
final_score = final_te_score + final_s_score
|
|
|
|
|
self.final_score = format("%.2f", final_score.to_f)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
if self.student_score.nil?
|
|
|
|
|
#有老师 和 组长评分 没有助教 学生
|
|
|
|
|
te_proportion = tea_proportion + (tea_ass_proportion) / 2
|
|
|
|
|
gr_proportion = gr_leader_proportion + (tea_ass_proportion) / 2
|
|
|
|
|
final_te_score = BigDecimal.new("#{self.teacher_score}") * BigDecimal.new("#{te_proportion}")
|
|
|
|
|
final_gr_score = BigDecimal.new("#{self.group_leader_score}") * BigDecimal.new("#{gr_proportion}")
|
|
|
|
|
final_score = final_te_score + final_gr_score
|
|
|
|
|
self.final_score = format("%.2f",final_score.to_f)
|
|
|
|
|
else
|
|
|
|
|
#有老师、组长、学生评分 没有助教
|
|
|
|
|
te_proportion = tea_proportion + (tea_ass_proportion) / 3
|
|
|
|
|
gr_proportion = gr_leader_proportion + (tea_ass_proportion) / 3
|
|
|
|
|
final_te_score = BigDecimal.new("#{self.teacher_score}") * BigDecimal.new("#{te_proportion}")
|
|
|
|
|
final_gr_score = BigDecimal.new("#{self.group_leader_score}") * BigDecimal.new("#{gr_proportion}")
|
|
|
|
|
final_s_score = BigDecimal.new("#{self.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{te_proportion}") - BigDecimal.new("#{gr_proportion}"))
|
|
|
|
|
final_score = final_te_score + final_gr_score + final_s_score
|
|
|
|
|
self.final_score = format("%.2f",final_score.to_f)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
if self.group_leader_score.nil?
|
|
|
|
|
if self.student_score.nil?
|
|
|
|
|
#有老师、助教评分 没有组长、学生
|
|
|
|
|
te_proportion = tea_proportion + (1.0 - tea_proportion - tea_ass_proportion) / 2
|
|
|
|
|
final_te_score = BigDecimal.new("#{self.teacher_score}") * BigDecimal.new("#{te_proportion}")
|
|
|
|
|
final_ta_score = BigDecimal.new("#{self.teaching_asistant_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{te_proportion}"))
|
|
|
|
|
final_score = final_te_score + final_ta_score
|
|
|
|
|
self.final_score = format("%.2f",final_score.to_f)
|
|
|
|
|
else
|
|
|
|
|
#有老师、助教、学生评分 没有组长
|
|
|
|
|
te_proportion = tea_proportion + (gr_leader_proportion) / 3
|
|
|
|
|
ta_proportion = tea_ass_proportion + (gr_leader_proportion) / 3
|
|
|
|
|
final_te_score = BigDecimal.new("#{self.teacher_score}") * BigDecimal.new("#{te_proportion}")
|
|
|
|
|
final_ta_score = BigDecimal.new("#{self.teaching_asistant_score}") * BigDecimal.new("#{ta_proportion}")
|
|
|
|
|
final_s_score = BigDecimal.new("#{self.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{te_proportion}") - BigDecimal.new("#{ta_proportion}"))
|
|
|
|
|
final_score = final_te_score + final_ta_score + final_s_score
|
|
|
|
|
self.final_score = format("%.2f",final_score.to_f)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
if self.student_score.nil?
|
|
|
|
|
#有老师、助教、组长评分 没有学生
|
|
|
|
|
te_proportion = tea_proportion + (1.0 - tea_proportion - tea_ass_proportion - gr_leader_proportion) / 3
|
|
|
|
|
ta_proportion = tea_ass_proportion + (1.0 - tea_proportion - tea_ass_proportion - gr_leader_proportion) / 3
|
|
|
|
|
gr_proportion = gr_leader_proportion + (1.0 - tea_proportion - tea_ass_proportion - gr_leader_proportion) / 3
|
|
|
|
|
final_te_score = BigDecimal.new("#{self.teacher_score}") * BigDecimal.new("#{te_proportion}")
|
|
|
|
|
final_ta_score = BigDecimal.new("#{self.teaching_asistant_score}") * BigDecimal.new("#{ta_proportion}")
|
|
|
|
|
final_gr_score = BigDecimal.new("#{self.group_leader_score}") * BigDecimal.new("#{gr_proportion}")
|
|
|
|
|
final_score = final_te_score + final_ta_score + final_gr_score
|
|
|
|
|
self.final_score = format("%.2f",final_score.to_f)
|
|
|
|
|
else
|
|
|
|
|
#有老师、助教、组长、学生评分
|
|
|
|
|
final_te_score = BigDecimal.new("#{self.teacher_score}") * BigDecimal.new("#{tea_proportion}")
|
|
|
|
|
final_ta_score = BigDecimal.new("#{self.teaching_asistant_score}") * BigDecimal.new("#{tea_ass_proportion}")
|
|
|
|
|
final_gr_score = BigDecimal.new("#{self.group_leader_score}") * BigDecimal.new("#{gr_leader_proportion}")
|
|
|
|
|
final_s_score = BigDecimal.new("#{self.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{tea_proportion}") - BigDecimal.new("#{tea_ass_proportion}") - BigDecimal.new("#{gr_leader_proportion}"))
|
|
|
|
|
final_score = final_te_score + final_ta_score + final_gr_score + final_s_score
|
|
|
|
|
self.final_score = format("%.2f",final_score.to_f)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
if self.teaching_asistant_score.nil?
|
|
|
|
|
if self.group_leader_score.nil?
|
|
|
|
|
#没有老师、助教、组长
|
|
|
|
|
self.final_score = self.student_score
|
|
|
|
|
elsif self.student_score.nil?
|
|
|
|
|
#没有老师、助教、学生、有组长
|
|
|
|
|
self.final_score = self.group_leader_score
|
|
|
|
|
else
|
|
|
|
|
#没有老师、助教 有组长、学生
|
|
|
|
|
gr_proportion = gr_leader_proportion + (tea_proportion + tea_ass_proportion) / 2
|
|
|
|
|
final_gr_score = BigDecimal.new("#{self.group_leader_score}") * BigDecimal.new("#{gr_proportion}")
|
|
|
|
|
final_s_score = BigDecimal.new("#{self.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{gr_proportion}"))
|
|
|
|
|
final_score = final_gr_score + final_s_score
|
|
|
|
|
self.final_score = format("%.2f", final_score.to_f)
|
|
|
|
|
end
|
|
|
|
|
elsif self.group_leader_score.nil?
|
|
|
|
|
if self.student_score.nil?
|
|
|
|
|
#有助教 没有老师、组长、学生
|
|
|
|
|
self.final_score = self.teaching_asistant_score
|
|
|
|
|
else
|
|
|
|
|
#有助教、学生 没有老师、组长
|
|
|
|
|
tea_proportion = tea_ass_proportion + (tea_proportion + gr_leader_proportion) / 2
|
|
|
|
|
final_tea_score = BigDecimal.new("#{self.teaching_asistant_score}") * BigDecimal.new("#{tea_proportion}")
|
|
|
|
|
final_s_score = BigDecimal.new("#{self.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{tea_proportion}"))
|
|
|
|
|
final_score = final_tea_score + final_s_score
|
|
|
|
|
self.final_score = format("%.2f", final_score.to_f)
|
|
|
|
|
end
|
|
|
|
|
elsif self.student_score.nil?
|
|
|
|
|
#有助教、组长 没有老师 学生
|
|
|
|
|
tea_proportion = tea_ass_proportion + (1.0 - tea_ass_proportion - gr_leader_proportion) / 2
|
|
|
|
|
gr_proportion = gr_leader_proportion + (1.0 - tea_ass_proportion - gr_leader_proportion) / 2
|
|
|
|
|
final_tea_score = BigDecimal.new("#{self.teaching_asistant_score}") * BigDecimal.new("#{tea_proportion}")
|
|
|
|
|
final_gr_score = BigDecimal.new("#{self.group_leader_score}") * BigDecimal.new("#{gr_proportion}")
|
|
|
|
|
final_score = final_tea_score + final_gr_score
|
|
|
|
|
self.final_score = format("%.2f", final_score.to_f)
|
|
|
|
|
else
|
|
|
|
|
#有助教、组长、学生 没有老师
|
|
|
|
|
tea_proportion = tea_ass_proportion + (tea_proportion) / 3
|
|
|
|
|
gr_proportion = gr_leader_proportion + (tea_proportion) / 3
|
|
|
|
|
final_tea_score = BigDecimal.new("#{self.teaching_asistant_score}") * BigDecimal.new("#{tea_proportion}")
|
|
|
|
|
final_gr_score = BigDecimal.new("#{self.group_leader_score}") * BigDecimal.new("#{gr_proportion}")
|
|
|
|
|
final_s_score = BigDecimal.new("#{self.student_score}") * (BigDecimal.new('1.0') - BigDecimal.new("#{tea_proportion}") - BigDecimal.new("#{gr_proportion}"))
|
|
|
|
|
final_score = final_tea_score + final_gr_score + final_s_score
|
|
|
|
|
self.final_score = format("%.2f", final_score.to_f)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
self.final_score = self.teacher_score ? self.teacher_score :
|
|
|
|
|
(self.teaching_asistant_score ? self.teaching_asistant_score : (self.group_leader_score ? self.group_leader_score : self.student_score) )
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 作品最终得分work_score 等于作品得分 - 缺评扣分 - 迟交扣分 - 申诉扣分
|
|
|
|
|
|
|
|
|
|
if self.final_score
|
|
|
|
|
score = self.final_score.to_f - self.absence_penalty.to_f - self.late_penalty.to_f - self.appeal_penalty.to_f
|
|
|
|
|
score = score - self.repeat_minus_score.to_f if homework_common.is_repeat_minus
|
|
|
|
|
else
|
|
|
|
|
score = nil
|
|
|
|
|
end
|
|
|
|
|
self.work_score = score ? format("%.2f", (score < 0 ? 0 : score).to_f) : nil
|
|
|
|
|
|
|
|
|
|
when "practice"
|
|
|
|
|
# 作品最终得分work_score 等于作品关卡得分 + 效率分 - 迟交扣分
|
|
|
|
|
if self.final_score
|
|
|
|
|
work_score = self.final_score + self.eff_score.to_f - self.late_penalty.to_f
|
|
|
|
|
work_score = work_score - self.repeat_minus_score.to_f if homework_common.is_repeat_minus?
|
|
|
|
|
else
|
|
|
|
|
work_score = nil
|
|
|
|
|
end
|
|
|
|
|
self.work_score = work_score ? format("%.2f", work_score < 0 ? 0 : work_score) : nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 实训作品是否已被评阅过
|
|
|
|
|
def shixun_has_comment?
|
|
|
|
|
shixun_work_comments.present? || student_works_scores.select{|item| item.is_invalid }.present? || challenge_work_scores.present?
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#编程作业是否已被评阅
|
|
|
|
|
#app/models/student_work.rb:365 编程作业 has_comment的值
|
|
|
|
|
def hack_has_comment?
|
|
|
|
|
shixun_work_comments.size > 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 普通/分组作品是否已被评阅过(只统计老师是否评阅过)
|
|
|
|
|
def work_has_comment?
|
|
|
|
|
student_works_scores.where(is_invalid: 0).select{|score| score.reviewer_role < 3}.size > 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 普通/分组作品是否已被评阅过(老师、学生任一角色评阅过的都算)
|
|
|
|
|
def work_has_comment_all_role?
|
|
|
|
|
student_works_scores.where(is_invalid: 0).size > 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def scored?
|
|
|
|
|
student_works_scores.where(is_invalid: 0).where.not(reviewer_role: 3, score: nil).exists?
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def work_challenge_score game, score, challenge_id
|
|
|
|
|
game_score = 0
|
|
|
|
|
adjust_score = challenge_work_scores.select{|t|t.challenge_id == challenge_id}.last
|
|
|
|
|
if adjust_score.present?
|
|
|
|
|
game_score = adjust_score.score
|
|
|
|
|
elsif game.present?
|
|
|
|
|
setting = homework_common.homework_group_setting game.user_id
|
|
|
|
|
group_late_setting = homework_common.home_group_late_settings_export game.user_id
|
|
|
|
|
if game.status == 2 && ((game.end_time && setting.end_time && game.end_time < setting.end_time) || (homework_common.allow_late && group_late_setting.late_time && game.end_time && game.end_time < group_late_setting.late_time))
|
|
|
|
|
answer_open_evaluation = homework_common.homework_detail_manual.answer_open_evaluation
|
|
|
|
|
percentage = homework_common.homework_detail_manual.game_deduct_score_percentage
|
|
|
|
|
game_score = answer_open_evaluation ? (game.view_answer ? Util::UUID.custom_deduct_percentage(score, percentage) : score ) : (game.final_score > 0 ? game.real_score(score) : 0)
|
|
|
|
|
elsif game.final_score > 0 && ((game.end_time && setting.end_time && game.end_time < setting.end_time) || (homework_common.allow_late && group_late_setting.late_time && game.end_time && game.end_time < group_late_setting.late_time))
|
|
|
|
|
game_score = game.real_score(score)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
game_score
|
|
|
|
|
end
|
|
|
|
|
def work_challenge_score_for_export game, score, challenge_id, homework_group_setting
|
|
|
|
|
game_score = 0
|
|
|
|
|
adjust_score = challenge_work_scores.select{|t|t.challenge_id == challenge_id}.last
|
|
|
|
|
if adjust_score.present?
|
|
|
|
|
game_score = adjust_score.score
|
|
|
|
|
elsif game.present?
|
|
|
|
|
setting = homework_group_setting
|
|
|
|
|
group_late_setting = homework_common.home_group_late_settings_export game.user_id
|
|
|
|
|
if game.status == 2 && ((game.end_time && setting.end_time && game.end_time < setting.end_time) || (homework_common.allow_late && group_late_setting.late_time && game.end_time && game.end_time < group_late_setting.late_time))
|
|
|
|
|
answer_open_evaluation = homework_common.homework_detail_manual.answer_open_evaluation
|
|
|
|
|
percentage = homework_common.homework_detail_manual.game_deduct_score_percentage
|
|
|
|
|
game_score = answer_open_evaluation ? (game.view_answer ? Util::UUID.custom_deduct_percentage(score, percentage) : score ) : (game.final_score > 0 ? game.real_score(score) : 0)
|
|
|
|
|
elsif game.final_score > 0 && ((game.end_time && setting.end_time && game.end_time < setting.end_time) || (homework_common.allow_late && group_late_setting.late_time && game.end_time && game.end_time < group_late_setting.late_time))
|
|
|
|
|
game_score = game.real_score(score)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
game_score
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#是否通关
|
|
|
|
|
def has_passed?
|
|
|
|
|
compelete_status == 2 || compelete_status == 3 || compelete_status == 4
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def unstart?
|
|
|
|
|
compelete_status == 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 是否E为截止通关
|
|
|
|
|
def deadline_passed?
|
|
|
|
|
compelete_status == 4
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# def my_hacks
|
|
|
|
|
# Hack.where(id: self.student_work_hacks.pluck(:hack_id))
|
|
|
|
|
# end
|
|
|
|
|
|
|
|
|
|
def hacks
|
|
|
|
|
if homework_common.send_type == 1
|
|
|
|
|
return self.my_hacks if self.my_hacks.present?
|
|
|
|
|
hack_ids = []
|
|
|
|
|
hacks = homework_common.hacks
|
|
|
|
|
settings_arr = homework_common.difficult_settings
|
|
|
|
|
return Hack.none if settings_arr.blank?
|
|
|
|
|
# index = Random.new(self.id).rand(self.user_id)
|
|
|
|
|
arr = hacks.select { |d| d.difficult == 1 }.pluck(:id).uniq
|
|
|
|
|
hack_ids << arr.sample(settings_arr[0].to_i)
|
|
|
|
|
arr = hacks.select { |d| d.difficult == 2 }.pluck(:id).uniq
|
|
|
|
|
hack_ids << arr.sample(settings_arr[1].to_i)
|
|
|
|
|
arr = hacks.select { |d| d.difficult == 3 }.pluck(:id).uniq
|
|
|
|
|
hack_ids << arr.sample(settings_arr[2].to_i)
|
|
|
|
|
hacks = Hack.where(id: hack_ids.flatten)
|
|
|
|
|
self.my_hacks = hacks
|
|
|
|
|
hacks
|
|
|
|
|
else
|
|
|
|
|
homework_common.hacks
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 分组作业学生端使用
|
|
|
|
|
# 学生创建的issue数量
|
|
|
|
|
def statistical_issues_count
|
|
|
|
|
return "" if self.project.blank?
|
|
|
|
|
|
|
|
|
|
self.project.issues.where("author_id = ? OR assigned_to_id= ?", self.user_id, self.user_id).size
|
|
|
|
|
end
|
|
|
|
|
def pull_requests_count
|
|
|
|
|
return "--" if self.work_status == 0
|
|
|
|
|
return "--" if self.project.blank?
|
|
|
|
|
self.project.pull_requests_count
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 分组作业使用
|
|
|
|
|
# 获取关联项目相关信息,如提交代码数量、代码行数等
|
|
|
|
|
# params code_stats
|
|
|
|
|
def get_code_lines_count(code_stats)
|
|
|
|
|
return "" if self.project_id.blank? || self.project_id == 0 || code_stats.blank? || code_stats[self.project_id].blank?
|
|
|
|
|
|
|
|
|
|
project_user = self.user
|
|
|
|
|
result = code_stats[self.project_id]["authors"]&.select {|item| item["name"] == project_user.login || item["name"] == project_user.lastname || item["email"] == project_user.mail}&.first
|
|
|
|
|
|
|
|
|
|
result.present? ? result['additions'] : ""
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def update_code_time(code_line)
|
|
|
|
|
return if project.blank?
|
|
|
|
|
if code_line.present? && code_lines_count != code_line.to_i
|
|
|
|
|
project.code_update_time = Time.now
|
|
|
|
|
self.code_lines_count = code_line.to_i
|
|
|
|
|
project.save
|
|
|
|
|
self.save
|
|
|
|
|
# 兼容之前的
|
|
|
|
|
elsif code_line.present? && code_lines_count == code_line.to_i && project.code_update_time.blank?
|
|
|
|
|
project.code_update_time = project.updated_on
|
|
|
|
|
project.save
|
|
|
|
|
end
|
|
|
|
|
project.code_update_time
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 提交次数
|
|
|
|
|
def submit_size
|
|
|
|
|
#return 0 if homework_common.submit_num.blank? || homework_common.submit_num.zero?
|
|
|
|
|
# 这里加一的原因是 第一次提交不创建历史记录s
|
|
|
|
|
if self.histories.blank? && work_status == 0
|
|
|
|
|
return 0
|
|
|
|
|
end
|
|
|
|
|
size = 1
|
|
|
|
|
histories&.size.to_i + size
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 提交批次
|
|
|
|
|
def submit_num(history_id)
|
|
|
|
|
return 0 if history_id.to_i == 0
|
|
|
|
|
histories.where("id < #{history_id}").size + 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# 判断学生是否能提交作品 用于图文作业和分组作业
|
|
|
|
|
def can_submit?
|
|
|
|
|
# 是否开启提交限制
|
|
|
|
|
if self.homework_common.can_submit
|
|
|
|
|
# 没有提交记录代表可以提交
|
|
|
|
|
return true if self.histories.blank?
|
|
|
|
|
# 这里加一的原因是 第一次提交不创建历史记录
|
|
|
|
|
size = 0
|
|
|
|
|
size = 1 if self.homework_common.late_duration # 如果在补交阶段
|
|
|
|
|
(homework_common.submit_num + size) > self.histories.size + 1
|
|
|
|
|
else
|
|
|
|
|
true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 每次提交时,增加一条记录
|
|
|
|
|
def create_history!
|
|
|
|
|
if project.present? && project.code_update_time.present? && work_status == 0
|
|
|
|
|
history_work_status = 3
|
|
|
|
|
else
|
|
|
|
|
history_work_status = work_status
|
|
|
|
|
end
|
|
|
|
|
student_work_history = StudentWorkHistory.new(self.attributes.except('id').merge(
|
|
|
|
|
student_work_id: self.id,
|
|
|
|
|
attachment_ids: self.attachments.pluck(:id),
|
|
|
|
|
work_status: history_work_status
|
|
|
|
|
))
|
|
|
|
|
student_work_history.save!
|
|
|
|
|
|
|
|
|
|
self.update_user_id = User.current&.id
|
|
|
|
|
self.update_time = Time.now
|
|
|
|
|
self.save!
|
|
|
|
|
end
|
|
|
|
|
end
|