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/models/shixun.rb

245 lines
7.5 KiB

6 years ago
class Shixun < ApplicationRecord
# TODO: ES feature
# include Searchable::Shixun
6 years ago
# status: 0编辑 1申请发布 2正式发布 3关闭 -1软删除
# hide_code 隐藏代码窗口
# code_hidden: 隐藏代码目录
6 years ago
has_many :challenges, dependent: :destroy
has_many :challenge_tags, through: :challenges
6 years ago
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
# 实训服务配置
has_many :shixun_service_configs, :dependent => :destroy
6 years ago
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.not(status: -1) }
6 years ago
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)
5 years ago
Shixun.joins(challenges: [:challenge_tags, :games]).where(games: {status: 2, user_id: user.id}, shixuns: {id:id})
.pluck("challenge_tags.name").uniq
6 years ago
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.joins(challenge: :shixun).where(shixuns: {id: id}).where.not(games: {star: 0}).pluck(:star)
6 years ago
star_info = []
if game_star_info.present?
5.downto(1) do |i|
star_info << ((game_star_info.select{|s| s == i}.count / game_star_info.count.to_f) * 100).round
6 years ago
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
6 years ago
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
6 years ago
end