|
|
class Shixun < ApplicationRecord
|
|
|
# status: 0:编辑 1:申请发布 2:正式发布 3:关闭 -1:软删除
|
|
|
has_many :challenges, dependent: :destroy
|
|
|
has_many :myshixuns, :dependent => :destroy
|
|
|
has_many :shixun_members, dependent: :destroy
|
|
|
has_many :users, through: :shixun_members
|
|
|
has_many :discusses, as: :dis, dependent: :destroy
|
|
|
has_many :evaluate_records, dependent: :destroy
|
|
|
has_many :shixun_mirror_repositories
|
|
|
has_many :mirror_repositories, through: :shixun_mirror_repositories
|
|
|
|
|
|
has_many :shixun_schools, :dependent => :destroy
|
|
|
has_many :schools, :through => :shixun_schools
|
|
|
|
|
|
has_many :shixun_tag_repertoires, dependent: :destroy
|
|
|
has_many :tag_repertoires, through: :shixun_tag_repertoires
|
|
|
has_one :first_shixun_tag_repertoire, class_name: 'ShixunTagRepertoire'
|
|
|
has_one :first_tag_repertoire, through: :first_shixun_tag_repertoire, source: :tag_repertoire
|
|
|
|
|
|
|
|
|
#实训的关卡
|
|
|
has_many :exercise_shixun_challenges, :dependent => :destroy
|
|
|
has_many :exercise_bank_shixun_challenges, :dependent => :destroy
|
|
|
|
|
|
# 注意:这个地方是一张关联表,关联三张表(多对多关系)
|
|
|
has_many :stage_shixuns, dependent: :destroy
|
|
|
has_many :stages, through: :stage_shixuns
|
|
|
has_many :subjects, through: :stage_shixuns
|
|
|
|
|
|
has_one :shixun_info, dependent: :destroy
|
|
|
|
|
|
belongs_to :user
|
|
|
|
|
|
|
|
|
scope :search_by_name, ->(keyword) { where("name like ? or description like ? ",
|
|
|
"%#{keyword}%", "%#{keyword}%") }
|
|
|
|
|
|
#scope :include_user, ->(user_id) { where(id: Myshixun.where(user_id: user_id).pluck(:shixun_id))}
|
|
|
|
|
|
scope :filter_tag, ->(tag_level, tag_id) {
|
|
|
case tag_level
|
|
|
when 1 #大类
|
|
|
where(id: Repertoire.find(tag_id).tag_repertoires.joins(:shixun_tag_repertoires).pluck("shixun_tag_repertoires.shixun_id"))
|
|
|
when 2 #子类
|
|
|
where(id: SubRepertoire.find(tag_id).tag_repertoires.joins(:shixun_tag_repertoires).pluck("shixun_tag_repertoires.shixun_id"))
|
|
|
when 3 #tag
|
|
|
where(id: TagRepertoire.find(tag_id).shixun_tag_repertoires.pluck(:shixun_id))
|
|
|
end
|
|
|
}
|
|
|
|
|
|
scope :visible, -> { where("status != -1") }
|
|
|
scope :published, lambda{ where(status: 2) }
|
|
|
scope :unhidden, lambda{ where(hidden: 0, status: 2) }
|
|
|
scope :field_for_recommend, lambda{ select([:id, :name, :identifier, :myshixuns_count]) }
|
|
|
scope :find_by_ids,lambda{|k| where(id:k)}
|
|
|
|
|
|
# REDO:
|
|
|
def propaedeutics
|
|
|
shixun_info.try(:propaedeutics)
|
|
|
end
|
|
|
|
|
|
def description
|
|
|
shixun_info.try(:description)
|
|
|
end
|
|
|
|
|
|
def evaluate_script
|
|
|
shixun_info.try(:evaluate_script)
|
|
|
end
|
|
|
|
|
|
# 实训用户tag
|
|
|
def user_tags_name(user = User.current)
|
|
|
challenge_ids = challenges.pluck(:id)
|
|
|
user_challenge_ids = user.games.where(challenge_id: challenge_ids, status: 2).pluck(:challenge_id)
|
|
|
ChallengeTag.where(challenge_id: user_challenge_ids).pluck(:name).uniq
|
|
|
end
|
|
|
|
|
|
# 实训关卡tag
|
|
|
def challenge_tags_name
|
|
|
ChallengeTag.where(challenge_id: challenges.pluck(:id)).pluck(:name).uniq
|
|
|
end
|
|
|
|
|
|
def repo_path
|
|
|
"#{repo_name}.git"
|
|
|
end
|
|
|
|
|
|
# 实训对应的镜像主类别名(已选)
|
|
|
def main_mirror_name
|
|
|
mirror_repositories.published_main_mirror.first.try(:type_name) || ""
|
|
|
end
|
|
|
|
|
|
def main_mirror_id
|
|
|
mirror_repositories.published_main_mirror.first.try(:id) || -1
|
|
|
end
|
|
|
|
|
|
# 实训对应的镜像小类别名(已选)
|
|
|
def small_mirror_name
|
|
|
mirror_repositories.published_small_mirror.map(&:type_name)
|
|
|
end
|
|
|
|
|
|
def small_mirror_id
|
|
|
mirror_repositories.published_small_mirror.map(&:id)
|
|
|
end
|
|
|
|
|
|
# 实训镜像名
|
|
|
def mirror_name
|
|
|
names = mirror_repositories.map(&:type_name)
|
|
|
names.blank? ? '' : names
|
|
|
end
|
|
|
|
|
|
def script_tag
|
|
|
return unless mirror_script_id
|
|
|
|
|
|
MirrorScript.find_by_id(mirror_script_id)
|
|
|
end
|
|
|
|
|
|
def standrad_script
|
|
|
mirrors_id = mirror_repositories.map(&:id)
|
|
|
mirror_scripts = MirrorScript.where(mirror_repository_id: mirrors_id)
|
|
|
mirror_scripts.map { |ms| { scptname: ms.script_type, id: ms.id } }
|
|
|
end
|
|
|
|
|
|
def owner
|
|
|
User.find(self.user_id)
|
|
|
end
|
|
|
|
|
|
def is_published?
|
|
|
status > 1
|
|
|
end
|
|
|
|
|
|
# 当前用户开启的实训
|
|
|
def current_myshixun(user_id)
|
|
|
myshixuns.find_by(user_id: user_id)
|
|
|
end
|
|
|
|
|
|
# 实训技术平台
|
|
|
def show_shixun_mirror
|
|
|
mirror_repositories.map(&:type_name).join(';')
|
|
|
end
|
|
|
|
|
|
# 实训评分 cnt-评分次数 sum-总评分
|
|
|
def shixun_preference
|
|
|
game_star_info = Game.find_by_sql("select g.star from
|
|
|
(games g left join (myshixuns m join shixuns s on s.id = m.shixun_id) on m.id = g.myshixun_id)
|
|
|
where g.star != 0 and s.id = #{self.id}")
|
|
|
if game_star_info.present?
|
|
|
cnt = game_star_info.count
|
|
|
sum = game_star_info.sum(&:star).to_f
|
|
|
(sum / cnt.to_f).round(1)
|
|
|
else
|
|
|
5.0
|
|
|
end
|
|
|
end
|
|
|
|
|
|
# 实训评分信息
|
|
|
# return [实训评分, 5星评分比例, 4星评分比例, 3星评分比例, 2星评分比例, 1星评分比例]
|
|
|
def shixun_preference_info
|
|
|
game_star_info = Game.find_by_sql("select g.star from
|
|
|
(games g left join (myshixuns m join shixuns s on s.id = m.shixun_id) on m.id = g.myshixun_id)
|
|
|
where g.star != 0 and s.id = #{self.id}")
|
|
|
star_info = []
|
|
|
if game_star_info.present?
|
|
|
5.downto(1) do |i|
|
|
|
star_info << ((game_star_info.select{|s| s.star == i}.count / game_star_info.count.to_f) * 100).round
|
|
|
end
|
|
|
sum = star_info.sum
|
|
|
max = star_info.max
|
|
|
# 四舍五入引起5星比例超过100%, 将最大的比例的评分做出调整
|
|
|
if sum > 100
|
|
|
star_info = star_info.map{|s| s == max ? s - 1 : s}
|
|
|
elsif sum < 100
|
|
|
star_info = star_info.map{|s| s == max ? s + 1 : s}
|
|
|
end
|
|
|
cnt = game_star_info.count
|
|
|
sum = game_star_info.sum(&:star)
|
|
|
star_info.unshift((sum / cnt.to_f).round(1))
|
|
|
else
|
|
|
star_info = [5.0, 100, 0, 0, 0, 0]
|
|
|
end
|
|
|
|
|
|
star_info
|
|
|
end
|
|
|
|
|
|
|
|
|
# 实训关卡的总分(由于大部分是实践题,因此没关联查choose表)
|
|
|
# 提前加载问题:由于选择题比较少,所以几乎不会触发选择题的查询,所以没必要提前载入choose_score
|
|
|
def all_score
|
|
|
sum = 0
|
|
|
challenges.each do |challenge|
|
|
|
sum += challenge.st == 0 ? challenge.score : challenge.choose_score
|
|
|
end
|
|
|
sum
|
|
|
end
|
|
|
|
|
|
### fork 数量
|
|
|
def fork_count
|
|
|
self.class.where(fork_from: id).count
|
|
|
end
|
|
|
|
|
|
# 学员等级
|
|
|
def shixun_trainee
|
|
|
case trainee
|
|
|
when 1 then '初级学员'
|
|
|
when 2 then '中级学员'
|
|
|
when 3 then '高级学员'
|
|
|
when 4 then '顶级学员'
|
|
|
else ''
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def shixun_level
|
|
|
case trainee
|
|
|
when 1 then '初级'
|
|
|
when 2 then '中级'
|
|
|
when 3 then '高级'
|
|
|
when 4 then '顶级'
|
|
|
else ''
|
|
|
end
|
|
|
end
|
|
|
|
|
|
# 纯选择提类型
|
|
|
def is_choice_type?
|
|
|
challenges_count == challenges.where(st: 1).count
|
|
|
end
|
|
|
|
|
|
# 实训受用学校个数
|
|
|
def school_count
|
|
|
UserExtension.find_by_sql("select count(distinct ue.school_id) school_count from user_extensions ue right join myshixuns
|
|
|
on ue.user_id = myshixuns.user_id where myshixuns.shixun_id = #{self.id}").first.try(:school_count).to_i
|
|
|
end
|
|
|
|
|
|
def has_manager?(user)
|
|
|
return true if user.admin?
|
|
|
|
|
|
shixun_members.where(role: [1, 2]).exists?(user_id: user.id)
|
|
|
end
|
|
|
|
|
|
def finished_challenges_count(user)
|
|
|
Game.joins(:myshixun).where(user_id: user.id, status: 2, myshixuns: { shixun_id: id }).count
|
|
|
end
|
|
|
end
|