杨树林 5 years ago
commit 8719793491

121
.gitignore vendored

@ -1,57 +1,64 @@
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# mac
*.DS_Store
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# Ignore uploaded files in development
/storage/*
/node_modules
/yarn-error.log
# /public/assets
.byebug_history
# Ignore master key for decrypting credentials and more.
/config/master.key
/config/database.yml
/.idea/*
# Ignore react node_modules
/public/react/build
/public/react/build/
/public/react/.cache
/public/react/node_modules/
/public/react/config/stats.json
/public/react/stats.json
/public/npm-debug.log
# avatars
/public/images/avatars
/config/secrets.yml
/files/archiveZip/*
/files/cache_store/*
public/upload.html
/config/configuration.yml
/config/initializers/gitlab_config.rb
/db/schema.rb
.vscode/
vendor/bundle/
.ruby-version
.ruby-gemset
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# mac
*.DS_Store
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# Ignore uploaded files in development
/storage/*
/node_modules
/yarn-error.log
# /public/assets
.byebug_history
# Ignore master key for decrypting credentials and more.
/config/master.key
/config/database.yml
/.idea/*
# Ignore react node_modules
/public/react/.cache
/public/react/build
/public/react/build/
/public/react/node_modules/
/public/react/config/stats.json
/public/react/stats.json
/public/npm-debug.log
# avatars
/public/images/avatars
/config/secrets.yml
/config/redis.yml
/config/elasticsearch.yml
public/upload.html
/config/configuration.yml
/config/environments/production.rb
/config/initializers/gitlab_config.rb
/db/schema.rb
.vscode/
vendor/bundle/
.ruby-version
.ruby-gemset
/files
/public/images/avatars
/public/files
/workspace
/log

@ -39,6 +39,8 @@ gem 'pdfkit'
gem 'wkhtmltopdf-binary'
#gem 'iconv'
# markdown 转html
gem 'redcarpet', '~> 3.4'
gem 'rqrcode', '~> 0.10.1'
gem 'rqrcode_png'
@ -46,11 +48,13 @@ gem 'rqrcode_png'
gem 'acts-as-taggable-on', '~> 6.0'
group :development, :test do
#group :'development.rb.example', :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'rspec-rails', '~> 3.8'
end
group :development do
#group :'development.rb.example' do
gem 'awesome_print'
gem 'web-console', '>= 3.3.0'
gem 'listen', '>= 3.0.5', '< 3.2'
@ -80,7 +84,12 @@ gem 'rails-i18n', '~> 5.1'
# job
gem 'sidekiq'
gem 'sinatra'
# batch insert
gem 'bulk_insert'
# elasticsearch
gem 'searchkick'
gem 'aasm'

@ -8,6 +8,8 @@ PATH
GEM
remote: https://gems.ruby-china.com/
specs:
aasm (5.0.5)
concurrent-ruby (~> 1.0)
actioncable (5.2.1)
actionpack (= 5.2.1)
nio4r (~> 2.0)
@ -90,6 +92,14 @@ GEM
connection_pool (2.2.2)
crass (1.0.4)
diff-lcs (1.3)
elasticsearch (7.2.0)
elasticsearch-api (= 7.2.0)
elasticsearch-transport (= 7.2.0)
elasticsearch-api (7.2.0)
multi_json
elasticsearch-transport (7.2.0)
faraday
multi_json
erubi (1.7.1)
execjs (2.7.0)
faraday (0.15.4)
@ -100,6 +110,7 @@ GEM
grape-entity (0.7.1)
activesupport (>= 4.0)
multi_json (>= 1.3.2)
hashie (3.6.0)
htmlentities (4.3.4)
httparty (0.16.2)
multi_xml (>= 0.5.2)
@ -142,6 +153,7 @@ GEM
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
mustermann (1.0.3)
mysql2 (0.5.2)
nio4r (2.3.1)
nokogiri (1.8.4)
@ -193,6 +205,7 @@ GEM
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rchardet (1.8.0)
redcarpet (3.4.0)
redis (4.1.0)
redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6)
@ -253,6 +266,10 @@ GEM
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
searchkick (3.1.3)
activemodel (>= 4.2)
elasticsearch (>= 5)
hashie
selenium-webdriver (3.14.0)
childprocess (~> 0.5)
rubyzip (~> 1.2)
@ -264,6 +281,11 @@ GEM
simple_xlsx_reader (1.0.4)
nokogiri
rubyzip
sinatra (2.0.5)
mustermann (~> 1.0)
rack (~> 2.0)
rack-protection (= 2.0.5)
tilt (~> 2.0)
spreadsheet (1.2.3)
ruby-ole (>= 1.0)
spring (2.0.2)
@ -304,6 +326,7 @@ PLATFORMS
ruby
DEPENDENCIES
aasm
active_decorator
acts-as-taggable-on (~> 6.0)
awesome_print
@ -328,6 +351,7 @@ DEPENDENCIES
rails (~> 5.2.0)
rails-i18n (~> 5.1)
rchardet (~> 1.8)
redcarpet (~> 3.4)
redis-rails
roo-xls
rqrcode (~> 0.10.1)
@ -336,9 +360,11 @@ DEPENDENCIES
ruby-ole
rubyzip
sass-rails (~> 5.0)
searchkick
selenium-webdriver
sidekiq
simple_xlsx_reader
sinatra
spreadsheet
spring
spring-watcher-listen (~> 2.0.0)

@ -62,3 +62,8 @@ testeduplus2.educoder.net/games/*
# 文件上传ActiveStorage
# 新能bootsnap
# 注意事项:
# 第一次部署需要执行一些rake任务
# 配置redis地址
# 配置gitlab/intializers/gitlab_config.yml

@ -0,0 +1,7 @@
class AdminConstraint
def matches?(request)
return false unless request.session[:user_id]
user = User.find request.session[:user_id]
user && user.admin?
end
end

@ -1,6 +1,5 @@
class AccountsController < ApplicationController
include ErrorCommon
#skip_before_action :check_account, :only => [:logout]
def index
@ -31,20 +30,21 @@ class AccountsController < ApplicationController
phone = nil
verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
end
uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.created_at.to_i}")
check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
unless check_code
tip_exception("验证码无效")
end
uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
code = generate_identifier User, 8
login = pre + code
@user = User.new(admin: false, login: login, mail: email, phone: phone)
@user = User.new(admin: false, login: login, mail: email, phone: phone, type: "User")
@user.password = params[:password]
# 现在因为是验证码,所以在注册的时候就可以激活
@user.activate
# 必须要用save操作密码的保存是在users中
if @user.save!
# todo user_extension
UserExtension.create!(user_id: @user.id)
# 注册完成手机号或邮箱想可以奖励500金币
RewardGradeService.call(
@user,
@ -52,6 +52,13 @@ class AccountsController < ApplicationController
container_type: pre == 'p' ? 'Phone' : 'Mail',
score: 500
)
# 注册时,记录是否是引流用户
ip = request.remote_ip
ua = UserAgent.find_by_ip(ip)
ua.update_column(:agent_type, UserAgent::USER_REGISTER) if ua
successful_authentication(@user)
session[:user_id] = @user.id
normal_status("注册成功")
end
rescue Exception => e
uid_logger_error(e.message)
@ -62,6 +69,15 @@ class AccountsController < ApplicationController
# 用户登录
def login
@user = User.try_to_login(params[:login], params[:password])
if @user
# user is already in local database
return normal_status(-2, "违反平台使用规范,账号已被锁定") if @user.locked?
return normal_status(-2, "错误的账号或密码") unless @user.check_password?(params[:password].to_s)
else
return normal_status(-2, "错误的账号或密码")
end
@user.update_column(:last_login_on, Time.now)
successful_authentication(@user)
@ -83,20 +99,17 @@ class AccountsController < ApplicationController
email = params[:login]
verifi_code = VerificationCode.where(email: email, code: code, code_type: 3).last
user = User.find_by_mail(email) #这里有问题应该是为email,而不是mail 6.13-hs
end
check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
unless check_code
tip_exception("验证码无效")
end
return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip
return normal_status(-2, "验证码已失效") if !verifi_code&.effective?
user.password, user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if user.save!
sucess_status
end
# rescue Exception => e
# uid_logger_error(e.message)
# tip_exception("密码重置失败,请稍后再试")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("密码重置失败")
end
end
@ -107,7 +120,10 @@ class AccountsController < ApplicationController
# generate a key and set cookie if autologin
set_autologin_cookie(user)
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id))
UserAction.create(:action_id => user.try(:id), :action_type => "Login", :user_id => user.try(:id), :ip => request.remote_ip)
# 注册完成后有一天的试用申请
UserDayCertification.create(user_id: user.id, status: 1)
end
def set_autologin_cookie(user)
@ -127,7 +143,7 @@ class AccountsController < ApplicationController
end
def logout
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id)
UserAction.create(action_id: User.current.id, action_type: "Logout", user_id: User.current.id, :ip => request.remote_ip)
session[:user_id] = nil
logout_user
render :json => {status: 1, message: "退出成功!"}
@ -143,7 +159,7 @@ class AccountsController < ApplicationController
# params[:login] 手机号或者邮箱号
# params[:type]为事件通知类型 1用户注册注册 2忘记密码 3: 绑定手机 4: 绑定邮箱 # 如果有新的继续后面加
# 发送验证码send_type 1注册手机验证码 2找回密码手机验证码 3找回密码邮箱验证码 4绑定手机 5绑定邮箱
# 6手机验证码登录 7邮箱验证码登录 8邮箱注册验证码
# 6手机验证码登录 7邮箱验证码登录 8邮箱注册验证码 9: 验收手机号有效
def get_verification_code
code = %W(0 1 2 3 4 5 6 7 8 9)
value = params[:login]
@ -152,6 +168,8 @@ class AccountsController < ApplicationController
send_type = verify_type(login_type, type)
verification_code = code.sample(6).join
logger.info("########get_verification_code: login_type #{login_type} send_type#{send_type}, ")
# 记录验证码
check_verification_code(verification_code, send_type, value)
sucess_status

@ -0,0 +1,15 @@
class AddDepartmentAppliesController < ApplicationController
before_action :require_login, :check_auth
def create
CreateAddDepartmentApplyService.call(current_user, create_params)
render_ok
rescue CreateAddDepartmentApplyService::Error => ex
render_error(ex.message)
end
private
def create_params
params.permit(:name, :school_id, :remarks)
end
end

@ -0,0 +1,16 @@
class AddSchoolAppliesController < ApplicationController
before_action :require_login, :check_auth
def create
CreateAddSchoolApplyService.call(current_user, create_params)
render_ok
rescue CreateAddSchoolApplyService::Error => ex
render_error(ex.message)
end
private
def create_params
params.permit(:name, :province, :city, :address, :remarks)
end
end

@ -5,6 +5,8 @@ class ApplicationController < ActionController::Base
include RenderExpand
include RenderHelper
include ControllerRescueHandler
include GitHelper
include LoggerHelper
protect_from_forgery prepend: true, unless: -> { request.format.json? }
@ -17,8 +19,19 @@ class ApplicationController < ActionController::Base
# 全局配置参数
# 返回name对应的value
def edu_setting name
EduSetting.find_by_name(name).try(:value)
def edu_setting(name)
EduSetting.get(name)
end
# 实训的访问权限
def shixun_access_allowed
if !current_user.shixun_permission(@shixun)
tip_exception(403, "..")
end
end
def admin_or_business?
User.current.admin? || User.current.business?
end
def user_course_identity
@ -33,15 +46,16 @@ class ApplicationController < ActionController::Base
# 判断用户的邮箱或者手机是否可用
# params[:type] 1: 注册2忘记密码
def check_mail_and_phone_valid login, type
unless login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ || login =~ /^1\d{10}$/
tip_exception("请输入正确的手机号或邮箱")
unless login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ || login =~ /^1\d{10}$/ ||
login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
tip_exception(-2, "请输入正确的手机号或邮箱")
end
# 考虑到安全参数问题多一次查询去掉Union
user = User.where(phone: login).first || User.where(mail: login).first
if type.to_i == 1 && !user.nil?
tip_exception("该手机号码或邮箱已被注册")
tip_exception(-2, "该手机号码或邮箱已被注册")
elsif type.to_i == 2 && user.nil?
tip_exception("该手机号码或邮箱未注册")
tip_exception(-2, "该手机号码或邮箱未注册")
end
sucess_status
end
@ -55,7 +69,7 @@ class ApplicationController < ActionController::Base
# 手机类型的发送
sigle_para = {phone: value}
status = Educoder::Sms.send(mobile: value, code: code)
tip_exception(code_msg(status)) if status != 0
tip_exception(-2, code_msg(status)) if status != 0
when 8, 3, 5
# 邮箱类型的发送
sigle_para = {email: value}
@ -63,8 +77,8 @@ class ApplicationController < ActionController::Base
UserMailer.register_email(value, code).deliver_now
# Mailer.run.email_register(code, value)
rescue Exception => e
uid_logger_error(e.message)
tip_exception("邮件发送失败,请稍后重试")
logger_error(e)
tip_exception(-2,"邮件发送失败,请稍后重试")
end
end
ver_params = {code_type: send_type, code: code}.merge(sigle_para)
@ -124,27 +138,26 @@ class ApplicationController < ActionController::Base
end
end
# 课堂教师、课堂管理员、超级管理员的权限(不包含助教)
def teacher_or_admin_allowed
unless current_user.course_identity(@course) < Course::ASSISTANT_PROFESSOR
normal_status(403, "")
end
end
def require_admin
normal_status(403, "") unless User.current.admin?
end
def require_business
normal_status(403, "") unless admin_or_business?
end
# 前端会捕捉401,弹登录弹框
# 未授权的捕捉407弹试用申请弹框
def require_login
#6.13 -hs
if User.current.logged?
if !current_user.profile_completed?
info_url = "#{edu_setting('old_edu_host')}/account/user_info"
tip_exception(402, info_url)
# render :json => { status: 402, url: info_url }
elsif current_user.certification != 1
day_cer = UserDayCertification.where(user_id: current_user.id).last
tip_exception(407, "系统未授权") unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400
end
else
tip_exception(401, "..")
end
tip_exception(401, "..") unless User.current.logged?
end
# 异常提醒
@ -172,85 +185,18 @@ class ApplicationController < ActionController::Base
end
# 系统全局认证
#
def check_auth
old_edu_host = edu_setting('old_edu_host')
ue = current_user.user_extension
if current_user.lastname.blank? || ue.school_id.blank? || ue.identity.blank? || current_user.mail.blank?
info_url = old_edu_host + '/account/user_info'
render :json => { status: 402, url: info_url }
if current_user.certification != 1 && current_user.apply_actions.exists?(container_type: 'TrialAuthorization', status: 0)
tip_exception(408, "您的试用申请正在审核中,请耐心等待")
elsif current_user.certification != 1
day_cer = UserDayCertification.where(user_id: current_user.id).last
unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400
account_url = old_edu_host + "/my/account"
render :json => { status: 402, url: account_url }
end
day_cer = UserDayCertification.find_by(user_id: current_user.id)
tip_exception(407, "系统未授权") unless (Time.now.to_i - day_cer.try(:created_at).to_i) < 86400
elsif !current_user.profile_completed?
info_url = '/account/profile'
tip_exception(402, info_url)
end
end
# 身份资料的认证:
# 如果试用过期则弹框提示认证,先跳入个人资料页面完善资料,资料完成后,弹框提醒用户试用申请
def check_account
# # todo user_extension
# if User.current.logged?
# ue = current_user.user_extension
# if current_user.lastname.blank? || ue.school_id.blank? || ue.identity.blank? || current_user.mail.blank?
# info_url = "#{edu_setting('old_edu_host')}/account/user_info"
# render :json => { status: 402, url: info_url }
# end
# end
end
# 版本库目录空间
def repo_namespace(user_login, shixun_identifier)
"#{user_login}/#{shixun_identifier}.git"
end
# 版本库文件内容,带转码
def git_fle_content(repo_path, path)
begin
content = GitService.file_content(repo_path: repo_path, path: path)["content"]
logger.info("@@@@@@@@@@@@@@@@@@#{content}")
decode_content = nil
if content.present?
content = Base64.decode64(content)
cd = CharDet.detect(content)
logger.info "encoding: #{cd['encoding']} confidence: #{cd['confidence']}"
decode_content =
if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8
content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '})
else
content.force_encoding('UTF-8')
end
end
decode_content
rescue Exception => e
uid_logger_error(e.message)
raise Educoder::TipException.new("文档内容获取异常")
end
end
# 更新文件代码
# content 文件内容message提交描述
def update_file_content(content, repo_path, path, mail, username, message)
GitService.update_file(repo_path: repo_path, file_path: path, message: message,
content: content, author_name: username, author_email: mail)
end
# 版本库Fork功能
def project_fork(container, original_rep_path, username)
raise Educoder::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank?
# 将要生成的仓库名字
new_repo_name = "#{username}/#{container.try(:identifier)}#{ Time.now.strftime("%Y%m%d%H%M%S")}"
uid_logger("start fork container: repo_name is #{new_repo_name}")
GitService.fork_repository(repo_path: original_rep_path, fork_repository_path: (new_repo_name + ".git"))
container.update_attributes!(:repo_name => new_repo_name)
end
def start_user_session(user)
session[:user_id] = user.id
session[:ctime] = Time.now.utc.to_i
@ -258,20 +204,26 @@ class ApplicationController < ActionController::Base
end
def user_setup
# reacct静态资源加载不需要走这一步
return if params[:controller] == "main"
# Find the current user
User.current = find_current_user
uid_logger("user_step: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
if !User.current.logged? && Rails.env.development?
User.current = User.find 12
end
# User.current = User.find 81403
if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
User.current = User.find 49610
User.current = User.find 81403
elsif params[:debug] == 'student'
User.current = User.find 8686
elsif params[:debug] == 'admin'
User.current = User.find 1
elsif params[:debug]
User.current = User.find_by_login params[:debug]
end
end
@ -289,6 +241,7 @@ class ApplicationController < ActionController::Base
# Returns the current user or nil if no user is logged in
# and starts a session if needed
def find_current_user
uid_logger("user setup start: session[:user_id] is #{session[:user_id]}")
if session[:user_id]
# existing session
(User.active.find(session[:user_id]) rescue nil)
@ -330,16 +283,6 @@ class ApplicationController < ActionController::Base
end
end
# 以用户id开始的日志定义
def uid_logger(message)
Rails.logger.info("##:#{current_user.try(:id)} --#{message}")
end
# 以用户id开始的日志定义
def uid_logger_error(message)
Rails.logger.error("##:#{current_user.try(:id)} --#{message}")
end
## 输出错误信息
def error_status(message = nil)
@status = -1
@ -403,12 +346,6 @@ class ApplicationController < ActionController::Base
end
end
#实训题的关卡url初始化
def challenge_path(path)
cha_path = path.present? ? path.split("") : []
cha_path.reject(&:blank?)[0].try(:strip)
end
# 适用与已经用url_safe编码后回调字符串形式
def tran_base64_decode64(str)
s_size = str.size % 4
@ -472,6 +409,24 @@ class ApplicationController < ActionController::Base
container.to_json
end
# 实训中间层pod配置
def shixun_container_limit shixun
container = []
shixun.shixun_service_configs.each do |config|
mirror = config.mirror_repository
if mirror.name.present?
container << {:image => mirror.name,
:cpuLimit => config.cpu_limit,
:cpuRequest => config.lower_cpu_limit,
:memoryLimit => "#{config.memory_limit}M",
:memoryRequest => "#{config.request_limit}M",
:resourceLimit => "#{config.resource_limit}K",
:type => mirror.try(:main_type) == "1" ? "main" : "sub"}
end
end
container.to_json
end
# 毕设任务列表的赛选
def course_work(task, **option)
logger.info("#############{option}")

@ -2,10 +2,9 @@
#
# 文件上传
class AttachmentsController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :find_file, only: %i[show destroy]
include ErrorCommon
include ApplicationHelper
def show
@ -15,7 +14,7 @@ class AttachmentsController < ApplicationController
update_downloads(@file)
redirect_to @file.cloud_url and return
end
send_file absolute_path(local_path(@file)), type: @file.content_type
send_file absolute_path(local_path(@file)), type: @file.content_type.presence || 'application/octet-stream'
update_downloads(@file)
end
@ -25,51 +24,50 @@ class AttachmentsController < ApplicationController
# 2. 上传到云
upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
if upload_file
folder = edu_setting('attachment_folder')
raise "存储目录未定义" unless folder.present?
raise "未上传文件" unless upload_file
month_folder = current_month_folder
save_path = File.join(folder, month_folder)
folder = edu_setting('attachment_folder')
raise "存储目录未定义" unless folder.present?
ext = file_ext(upload_file.original_filename)
month_folder = current_month_folder
save_path = File.join(folder, month_folder)
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
ext = file_ext(upload_file.original_filename)
content_type = upload_file.content_type.presence || 'application/octet-stream'
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
content_type = upload_file.content_type.presence || 'application/octet-stream'
logger.info "local_path: #{local_path}"
logger.info "remote_path: #{remote_path}"
# remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
logger.info "local_path: #{local_path}"
logger.info "remote_path: #{remote_path}"
disk_filename = local_path[save_path.size + 1, local_path.size]
#存数据库
#
@attachment = Attachment.where(disk_filename: disk_filename,
author_id: current_user.id,
cloud_url: remote_path).first
unless @attachment.present?
@attachment = Attachment.new
@attachment.filename = upload_file.original_filename
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
@attachment.filesize = upload_file.tempfile.size
@attachment.content_type = content_type
@attachment.digest = digest
@attachment.author_id = current_user.id
@attachment.disk_directory = month_folder
@attachment.cloud_url = remote_path
@attachment.save!
else
logger.info "文件已存在id = #{@attachment.id}, filename = #{@attachment.filename}"
end
disk_filename = local_path[save_path.size + 1, local_path.size]
#存数据库
#
@attachment = Attachment.where(disk_filename: disk_filename,
author_id: current_user.id,
cloud_url: remote_path).first
render_json
if @attachment.blank?
@attachment = Attachment.new
@attachment.filename = upload_file.original_filename
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
@attachment.filesize = upload_file.tempfile.size
@attachment.content_type = content_type
@attachment.digest = digest
@attachment.author_id = current_user.id
@attachment.disk_directory = month_folder
@attachment.cloud_url = remote_path
@attachment.save!
else
raise "未上传文件"
logger.info "文件已存在id = #{@attachment.id}, filename = #{@attachment.filename}"
end
render_json
end
def destroy

@ -0,0 +1,24 @@
class BiddingUsersController < ApplicationController
before_action :require_login, :check_auth
def create
ProjectPackages::BiddingService.call(current_package, current_user)
render_ok
rescue ProjectPackages::BiddingService::Error => ex
render_error(ex.message)
end
def win
package = current_user.project_packages.find(params[:project_package_id])
ProjectPackages::WinBiddingService.call(package, params)
render_ok
rescue ProjectPackages::WinBiddingService::Error => ex
render_error(ex.message)
end
private
def current_package
@_current_package ||= ProjectPackage.find(params[:project_package_id])
end
end

@ -1,54 +1,47 @@
class BoardsController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :find_course, only: [:create]
before_action :set_board, except: [:create]
before_action :teacher_allowed
before_action :teacher_or_admin_allowed
def index
@boards = @course.boards.includes(messages: [:last_reply, :author]);
@boards = @course.boards.includes(messages: [:last_reply, :author])
end
def show
end
def new
end
def create
ActiveRecord::Base.transaction do
begin
board = @course.course_board
new_board = Board.new(board_params)
new_board.course_id = @course.id
new_board.project_id = -1
new_board.parent_id = board.try(:id)
new_board.position = board.children.count + 1
new_board.save!
normal_status(0, "添加成功")
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
board = @course.course_board
new_board = Board.new(board_params)
new_board.course_id = @course.id
new_board.project_id = -1
new_board.parent_id = board.try(:id)
new_board.position = board.children.count + 1
new_board.save!
end
normal_status(0, "添加成功")
end
# 子目录的拖动
def move_category
tip_exception("移动失败") if params[:position].blank?
unless params[:position].to_i == @board.position
course_board = @course.course_board
return normal_status(-1, "位置没有变化") if params[:position].to_i == @board.position
course_board = @course.course_board
ActiveRecord::Base.transaction do
if params[:position].to_i < @board.position
course_board.children.where("position < #{@board.position} and position >= ?", params[:position]).update_all("position = position + 1")
course_board.children.where("position < ? and position >= ?", @board.position, params[:position])
.update_all("position = position + 1")
else
course_board.children.where("position > #{@board.position} and position <= ?", params[:position]).update_all("position = position - 1")
course_board.children.where("position > ? and position <= ?", @board.position, params[:position])
.update_all("position = position - 1")
end
@board.update_attributes(position: params[:position])
normal_status(0, "移动成功")
else
normal_status(-1, "位置没有变化")
end
normal_status(0, "移动成功")
end
def destroy

@ -1,12 +1,14 @@
class ChallengesController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :find_shixun, only: [:new, :create, :index]
skip_before_action :verify_authenticity_token, only: [:create, :update, :create_choose_question, :crud_answer]
before_action :find_challenge, only: [:edit, :show, :update, :create_choose_question, :index_down, :index_up,
:edit_choose_question, :show_choose_question, :destroy_challenge_choose,
:update_choose_question, :destroy, :crud_answer, :answer]
# before_action :allowed, except: [:index, :show, :edit_choose_question, :edit]
# 关卡更新和操作的权限控制
before_action :update_allowed, except: [:index]
# 关卡访问的权限控制
before_action :shixun_access_allowed, only: [:index]
include ShixunsHelper
include ChallengesHelper
@ -136,7 +138,7 @@ class ChallengesController < ApplicationController
# tab 0,nil 过关任务, 1 评测设置, 2 参考答案
def edit
@tab = params[:tab].to_i
@power = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0
@power = @shixun.status == 0
challenge_num = Challenge.where(:shixun_id => @shixun).count
@position = @challenge.position
@chooses = @challenge.challenge_chooses
@ -148,16 +150,17 @@ class ChallengesController < ApplicationController
def index
uid_logger("identifier: #{params}")
# 通过调试发现 这里includes(:games)性能会慢10倍
@challenges = @shixun.challenges.fields_for_list
@editable = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0
@challenges = Challenge.fields_for_list.where(shixun_id: @shixun.id)
@editable = @shixun.status == 0 # before_action有判断权限如果没发布则肯定是管理人员
@user = current_user
end
def show
@tab = params[:tab].nil? ? 1 : params[:tab].to_i
challenge_num = Challenge.where(shixun_id: @shixun).count
@power = current_user.manager_of_shixun?(@shixun) && @shixun.status == 0
challenge_num = @shixun.challenges_count
@power = @shixun.status == 0 # 之前验证走过了是不是管理员,因此这里只用判断是否发布
@position = @challenge.position
if @position < challenge_num
@next_challenge = Challenge.where(:shixun_id => @shixun, :position => @position + 1).first
@ -206,7 +209,7 @@ class ChallengesController < ApplicationController
end
# 关卡评测执行文件如果被修改,需要修改脚本内容
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script)
@shixun.shixun_info.update_column(:evaluate_script, script)
# TODO:
# if path != params[:challenge][:path]
# shixun_modify_status_without_publish(@shixun, 1)
@ -246,8 +249,7 @@ class ChallengesController < ApplicationController
next_challenge.update_attribute(:position, next_challenge.position - 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script)
@shixun.shixun_info.update_column(:evaluate_script, script)
end
def index_up
@ -257,7 +259,7 @@ class ChallengesController < ApplicationController
last_challenge.update_attribute(:position, last_challenge.position + 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script)
@shixun.shixun_info.update_column(:evaluate_script, script)
end
def destroy
@ -268,7 +270,7 @@ class ChallengesController < ApplicationController
@challenge.destroy
# 关卡位置被删除,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script)
@shixun.shixun_info.update_column(:evaluate_script, script)
end
@ -287,7 +289,7 @@ class ChallengesController < ApplicationController
def challenge_params
params.require(:challenge).permit(:subject, :task_pass, :difficulty, :score, :st, :modify_time, :test_set_average,
:path, :exec_path, :show_type, :original_picture_path, :test_set_score,
:expect_picture_path, :picture_path, :web_route, :answer)
:expect_picture_path, :picture_path, :web_route, :answer, :exec_time)
end
def chooce_params
@ -295,9 +297,8 @@ class ChallengesController < ApplicationController
:standard_answer, :score, :difficult)
end
def allowed
# 实训为发布前,除实训的管理者外,其他人都不人都不允许访问
if !current_user.manager_of_shixun?(@shixun) && (@shixun.status < 1 || @shixun.hidden == 1)
def update_allowed
unless current_user.manager_of_shixun?(@shixun)
raise Educoder::TipException.new(403, "..")
end
end

@ -1,7 +1,7 @@
class CommonsController < ApplicationController
OBJECT_TYPE = %W[message journals_for_message]
before_action :require_login
before_action :require_login, :check_auth
before_action :validate_object_type
before_action :find_object
before_action :validate_power
@ -42,7 +42,24 @@ class CommonsController < ApplicationController
end
def validate_power
tip_exception(403, "无操作权限") unless current_user.admin?
code =
case params[:object_type].strip
when 'message'
if current_user.course_identity(@object.board.course) >= Course::STUDENT && @object.author != current_user
403
else
200
end
when 'journals_for_message'
if current_user.course_identity(@object.jour.course) >= Course::STUDENT && @object.user != current_user
403
else
200
end
else
current_user.admin? ? 200 : 403
end
return normal_status(code, "你没有权限操作!") if code == 403
end
def action(flag)

@ -0,0 +1,11 @@
class Competitions::BaseController < ApplicationController
include PaginateHelper
before_action :require_login
helper_method :current_competition
def current_competition
@_current_competition ||= Competition.find_by!(identifier: params[:competition_id])
end
end

@ -0,0 +1,38 @@
class Competitions::CompetitionModulesController < Competitions::BaseController
skip_before_action :require_login, only: [:index, :show]
before_action :require_business, only: [:update]
def index
@modules = current_competition.unhidden_competition_modules.order(position: :asc)
end
def show
@module = current_module
end
def update
md = current_module.competition_module_md_content || current_module.build_competition_module_md_content
md.name = params[:md_name]
md.content = params[:md_content]
ActiveRecord::Base.transaction do
md.save!
attachment_ids = Array.wrap(params[:attachment_ids]).map(&:to_i)
old_attachment_ids = md.attachments.pluck(:id)
destroy_ids = old_attachment_ids - attachment_ids
md.attachments.where(id: destroy_ids).delete_all
Attachment.where(id: attachment_ids - old_attachment_ids).update_all(container: md)
end
render_ok
end
private
def current_module
@_current_module ||= current_competition.unhidden_competition_modules.find(params[:id])
end
end

@ -0,0 +1,4 @@
class Competitions::CompetitionStaffsController < Competitions::BaseController
def show
end
end

@ -0,0 +1,70 @@
class Competitions::CompetitionTeamsController < Competitions::BaseController
def index
admin_or_business? ? all_competition_teams : user_competition_teams
end
def create
if current_competition.personal? # 个人赛报名
Competitions::CreatePersonalTeamService.call(current_competition, current_user)
else
team = current_competition.competition_teams.new(user: current_user)
Competitions::SaveTeamService.call(team, save_params)
end
render_ok
rescue Competitions::CreatePersonalTeamService::Error => ex
render_error(ex.message)
end
def update
team = current_competition.competition_teams.where(user: current_user).find(params[:id])
Competitions::SaveTeamService.call(team, save_params)
render_ok
end
def join
Competitions::JoinTeamService.call(current_competition, current_user, params)
render_ok
rescue Competitions::JoinTeamService::Error => ex
render_error(ex.message)
end
def leave
team = current_competition.competition_teams.find(params[:id])
member = team.team_members.find_by(user_id: current_user.id)
return render_error('您不是该战队的成员') if member.blank?
if member.user_id == team.user_id
team.destroy! # 队长退出,战队解散
else
member.destroy!
end
render_ok
end
private
def all_competition_teams
teams = current_competition.competition_teams
keyword = params[:keyword].to_s.strip
if keyword.present?
teams = teams.joins(users: { user_extension: :school }).where('schools.name LIKE ?', "%#{keyword}%")
end
@count = teams.count
@teams = paginate(teams.includes(:user, users: { user_extension: :school }))
end
def user_competition_teams
teams = current_competition.competition_teams
teams = teams.joins(:team_members).where(team_members: { user_id: current_user.id })
@teams = teams.includes(:user, users: { user_extension: :school }).to_a
@count = @teams.size
end
def save_params
params.permit(:name, teacher_ids: [], member_ids: [])
end
end

@ -0,0 +1,38 @@
class Competitions::CompetitionsController < Competitions::BaseController
skip_before_action :require_login
def index
# 已上架 或者 即将上架
competitions = Competition.where(status: true).or(Competition.where.not(published_at: nil))
competitions =
case params[:category]
when 'nearly_published' then competitions.where(status: false)
when 'progressing' then competitions.where('end_time > NOW()')
when 'ended' then competitions.where('end_time < NOW()')
else competitions
end
@count = competitions.count
competitions = competitions.order(published_at: :desc, online_time: :desc)
@competitions = paginate(competitions.includes(current_stage_section: :competition_stage))
ids = @competitions.map(&:id)
@member_count_map = TeamMember.where(competition_id: ids).group(:competition_id).count
@stage_count_map = CompetitionStage.where(competition_id: ids).group(:competition_id).count
end
def show
unless current_competition.published? || admin_or_business?
render_forbidden
return
end
end
private
def current_competition
@_current_competition ||= Competition.find_by!(identifier: params[:id])
end
end

@ -0,0 +1,22 @@
class Competitions::StudentsController < Competitions::BaseController
def index
keyword = params[:keyword].to_s.strip
if keyword.blank?
@students = []
return
end
students = User.joins(:user_extension).where(status: 1, user_extensions: { identity: 1 })
students = students.where.not(id: params[:student_ids]) if params[:student_ids].present?
students = students.where('LOWER(CONCAT(lastname, firstname, login, nickname)) LIKE ?', "%#{keyword}%")
@students = students.includes(user_extension: :school).limit(20)
# 队员多次报名限制
if current_competition.member_multiple_limited?
ids = @students.map(&:id)
members = current_competition.team_members.where(user_id: ids)
members = members.where.not(competition_team_id: params[:team_id]) if params[:team_id].present?
@enrolled_map = members.group(:user_id).count
end
end
end

@ -0,0 +1,22 @@
class Competitions::TeachersController < Competitions::BaseController
def index
keyword = params[:keyword].to_s.strip
if keyword.blank?
@teachers = []
return
end
teachers = User.joins(:user_extension).where(status: 1, user_extensions: { identity: 0 })
teachers = teachers.where.not(id: params[:teacher_ids]) if params[:teacher_ids].present?
teachers = teachers.where('LOWER(CONCAT(lastname, firstname, login, nickname)) LIKE ?', "%#{keyword}%")
@teachers = teachers.includes(user_extension: :school).limit(10)
# 老师多次报名限制
if current_competition.teacher_multiple_limited?
ids = @teachers.map(&:id)
members = current_competition.team_members.where(user_id: ids)
members = members.where.not(competition_team_id: params[:team_id]) if params[:team_id].present?
@enrolled_map = members.group(:user_id).count
end
end
end

@ -2,6 +2,10 @@ module ControllerRescueHandler
extend ActiveSupport::Concern
included do
rescue_from Exception do |e|
logger.error e
render json: {status: -1, message: e.message}
end
# rescue_from ActionView::MissingTemplate, with: :object_not_found
# rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
rescue_from Educoder::TipException, with: :tip_show
@ -12,5 +16,8 @@ module ControllerRescueHandler
rescue_from ActiveModel::ValidationError do |ex|
render_error(ex.model.errors.full_messages.join(','))
end
rescue_from ActiveRecord::RecordInvalid do |ex|
render_error(ex.record.errors.full_messages.join(','))
end
end
end

@ -1,10 +0,0 @@
module ErrorCommon
extend ActiveSupport::Concern
included do
rescue_from Exception do |e|
logger.error e
render json: {status: -1, message: e.message}
end
end
end

@ -28,7 +28,6 @@ module GitCommon
end
def file_content
logger.info("#################{@repo_path}, #{@path}")
@content = git_fle_content @repo_path, @path
end

@ -0,0 +1,62 @@
module GitHelper
extend ActiveSupport::Concern
# 版本库目录空间
def repo_namespace(user_login, shixun_identifier)
"#{user_login}/#{shixun_identifier}.git"
end
# 版本库文件内容,带转码
def git_fle_content(repo_path, path)
begin
Rails.logger.info("git file content: repo_path is #{repo_path}, path is #{path}")
content = GitService.file_content(repo_path: repo_path, path: path)
Rails.logger.info("git file content: content is #{content}")
decode_content = nil
if content.present?
content = content["content"] #6.24 -hs 这个为新增,因为当实训题里含有选择题时,这里会报错,undefined method `[]' for nil:NilClass
content = Base64.decode64(content)
cd = CharDet.detect(content)
Rails.logger.info "encoding: #{cd['encoding']} confidence: #{cd['confidence']}"
decode_content =
if cd["encoding"] == 'GB18030' && cd['confidence'] > 0.8
content.encode('UTF-8', 'GBK', {:invalid => :replace, :undef => :replace, :replace => ' '})
else
content.force_encoding('UTF-8')
end
end
decode_content
rescue Exception => e
Rails.logger.error(e.message)
raise Educoder::TipException.new("文档内容获取异常")
end
end
# 更新文件代码
# content 文件内容message提交描述
def update_file_content(content, repo_path, path, mail, username, message)
GitService.update_file(repo_path: repo_path, file_path: path, message: message,
content: content, author_name: username, author_email: mail)
end
# 版本库Fork功能
def project_fork(container, original_rep_path, username)
raise Educoder::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank?
# 将要生成的仓库名字
new_repo_name = "#{username}/#{container.try(:identifier)}#{ Time.now.strftime("%Y%m%d%H%M%S")}"
uid_logger("start fork container: repo_name is #{new_repo_name}")
GitService.fork_repository(repo_path: original_rep_path, fork_repository_path: (new_repo_name + ".git"))
container.update_attributes!(:repo_name => new_repo_name)
end
#实训题的关卡url初始化
def challenge_path(path)
cha_path = path.present? ? path.split("") : []
cha_path.reject(&:blank?)[0].try(:strip)
end
end

@ -0,0 +1,16 @@
module LoggerHelper
extend ActiveSupport::Concern
extend LoggerHelper
# 以用户id开始的日志定义
def uid_logger(message)
Rails.logger.info("##:#{current_user.try(:id)} --#{message}")
end
# 以用户id开始的日志定义
def uid_logger_error(message)
Rails.logger.error("##:#{current_user.try(:id)} --#{message}")
end
end

@ -0,0 +1,8 @@
module PaginateHelper
def paginate(objs, **opts)
page = params[:page].to_i <= 0 ? 1 : params[:page].to_i
per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 20
Kaminari.paginate_array(objs).page(page).per(per_page)
end
end

@ -16,4 +16,8 @@ module RenderHelper
render json: { status: 403, message: message }
# render status: 403, json: { errors: errors }
end
def render_unauthorized(message = I18n.t('error.unauthorized'))
render json: { status: 401, message: message }
end
end

@ -1,8 +1,8 @@
class CourseGroupsController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :set_group, except: [:create]
before_action :find_course, only: [:create]
before_action :teacher_allowed
before_action :teacher_or_admin_allowed
def create
tip_exception("分班名称不能为空") if params[:name].blank?

@ -1,8 +1,8 @@
class CourseModulesController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :set_module, except: [:unhidden_modules]
before_action :find_course, only: [:unhidden_modules]
before_action :teacher_allowed
before_action :teacher_or_admin_allowed
# 模块置顶
def sticky_module
@ -16,6 +16,7 @@ class CourseModulesController < ApplicationController
# 模块隐藏
def hidden_module
tip_exception("请至少保留一个课堂模块") if @course.none_hidden_course_modules.where.not(id: @course_module.id).size == 0
@course_module.update_attributes(hidden: 1)
normal_status(0, "更新成功")
end

@ -1,7 +1,7 @@
class CourseSecondCategoriesController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :set_category
before_action :teacher_allowed
before_action :teacher_or_admin_allowed
# 目录重命名
def rename_category

@ -2,8 +2,6 @@ class CoursesController < ApplicationController
include MessagesHelper
include ExportHelper
rescue_from ::ActionView::MissingTemplate, with: :missing_template
rescue_from ActiveRecord::RecordNotFound, with: :object_not_found
# model validation error
rescue_from ActiveRecord::RecordInvalid do |ex|
render_error(ex.record.errors.full_messages.join(','))
@ -13,9 +11,9 @@ class CoursesController < ApplicationController
render_error(ex.model.errors.full_messages.join(','))
end
before_action :require_login, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups]
before_action :require_login, :check_auth, except: [:index, :show, :students, :teachers, :board_list, :mine, :all_course_groups, :left_banner, :top_banner]
before_action :set_course, :user_course_identity, only: [:show, :update, :destroy, :settings, :set_invite_code_halt,
:set_public_or_private, :search_teacher_candidate, :teachers,
:set_public_or_private, :search_teacher_candidate, :teachers, :apply_teachers,
:top_banner, :left_banner, :add_teacher_popup, :add_teacher,
:graduation_group_list, :create_graduation_group, :join_graduation_group,
:course_group_list, :set_course_group, :change_course_admin, :change_course_teacher,
@ -27,11 +25,11 @@ class CoursesController < ApplicationController
before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate,
:transfer_to_course_group, :delete_from_course,
:search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup, :add_teacher]
before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private,
:set_course_group, :change_course_admin, :change_course_teacher,
:delete_course_teacher, :teacher_application_review, :create_group_by_importing_file]
before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin,
:set_course_group, :delete_course_teacher, :create_group_by_importing_file]
before_action :teacher_or_admin_allowed, only: [:graduation_group_list, :create_graduation_group, :join_graduation_group,
:export_member_scores_excel, :course_group_list]
:change_course_teacher, :export_member_scores_excel, :course_group_list,
:teacher_application_review, :apply_teachers]
before_action :validate_course_name, only: [:create, :update]
before_action :find_board, only: :board_list
before_action :validate_page_size, only: :mine
@ -49,47 +47,55 @@ class CoursesController < ApplicationController
@order = params[:order].present? ? params[:order] : "all"
order_str = @order != "course_members_count" && @order != "created_at" ? "updated_at" : @order
if @order == "all"
# @course = Course.where(is_delete: 0, is_hidden: 0).find_by_sql("select c.name, c.id, s.name, u.last_name from
# courses c, users u, user_extensions ue, schools s where c.is_delete=0 and c.tea_id=u.id and
# u.id=ue.user_id and ue.school_id=s.id limit 10;")
# if @order == "all"
# @course = Course.where(is_delete: 0, is_hidden: 0).select("select c.name, c.id, s.name, u.login, ifnull(concat(u.lastname,u.firstname),
# u.login), s.name from courses c, users u, user_extensions ue, schools s where c.is_delete=0 and
# c.tea_id=u.id and u.id=ue.user_id and ue.school_id=s.id")
@courses = Course.where(is_delete: 0, is_hidden: 0).select("courses.id, courses.tea_id, courses.name, courses.exercises_count, courses.polls_count,
courses.is_public, courses.is_end, courses.visits, courses.course_members_count,courses.homework_commons_count,(SELECT MAX(created_at)
FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a")
.order("courses.id = 1309 desc, a desc")
elsif @order == "mine"
# @courses = Course.where(is_delete: 0, is_hidden: 0)
# .order("courses.id = 1309 desc, courses.created_at desc")
# @courses = Course.where(is_delete: 0, is_hidden: 0).select("courses.id, courses.tea_id, courses.name, courses.exercises_count, courses.polls_count,
# courses.is_public, courses.is_end, courses.visits, courses.course_members_count,courses.homework_commons_count,(SELECT MAX(created_at)
# FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a")
# .order("courses.id = 1309 desc, a desc")
if @order == "mine"
tip_exception(401, "..") unless current_user.logged?
@courses = Course.joins(:course_members)
.where("is_delete = 0 AND is_hidden = 0 AND course_members.user_id = ?", @user.id)
.order("courses.id = 1309 DESC, courses.#{order_str} DESC")
.where("is_delete = 0 AND is_hidden = 0 AND course_members.user_id = ?", @user.id).distinct
elsif @order == "created_at"
# REDO:Extension
@courses = Course.joins(teacher: :user_extension)
.where(is_delete: 0, is_hidden: 0, is_end: 0)
.order("courses.id = 1309 DESC, courses.#{order_str} DESC")
@courses = Course.where(is_delete: 0, is_hidden: 0, is_end: 0).distinct
else
# REDO:Extension
@courses = Course.joins(teacher: :user_extension)
.where(is_delete: 0, is_hidden: 0)
.order("courses.id = 1309 DESC, courses.#{order_str} DESC")
@courses = Course.where(is_delete: 0, is_hidden: 0).distinct
end
# 根据搜索关键字进一步筛选
if params[:search].present?
# REDO:Extension
user_ids = User.includes(user_extension: :school).where("schools.name like ?", "%#{params[:search]}%").pluck(:id)
course_ids = CourseMember.includes(:user, :course).where("course_members.course_id in (?) and course_members.role in (1,2,3)
and CONCAT(users.lastname, users.firstname) like ?", @courses.map(&:id), "%#{params[:search]}%")
.pluck(:course_id)
@courses = @courses.where("name like ?", "%#{params[:search]}%").or(@courses.where(tea_id: user_ids)).or(@courses.where(id: course_ids))
#user_ids = User.includes(user_extension: :school).where("schools.name like ?", "%#{params[:search]}%").pluck(:id)
#course_ids = CourseMember.includes(:user, :course).where("course_members.course_id in (?) and course_members.role in (1,2,3)
# and CONCAT(users.lastname, users.firstname) like ?", @courses.map(&:id), "%#{params[:search]}%")
# .pluck(:course_id)
#@courses = @courses.where("name like ?", "%#{params[:search]}%").or(@courses.where(tea_id: user_ids)).or(@courses.where(id: course_ids))
# 6:21 daiao
sql = %Q{
(course_members.role in(1,2,3) and CONCAT(users.lastname, users.firstname) like :keyword) or courses.name like :keyword
or schools.name like :keyword
}
@courses = @courses.joins(:school, course_members: :user)
.where("#{sql}", keyword: "%#{params[:search]}%").distinct
end
@courses_count = @courses.size
@courses_count = @courses.count("courses.id")
@courses = @courses.order("courses.id = 1309 DESC, courses.#{order_str} DESC")
# 分页
page = params[:page] || 1
limit = params[:limit] || 16
@courses= @courses.page(page).per(limit)
@courses = @courses.page(page).per(limit)
@courses = @courses.preload(:school, :none_hidden_course_modules, teacher: :user_extension)
end
def visits_plus_one
@ -101,6 +107,7 @@ class CoursesController < ApplicationController
# GET /courses/1
# GET /courses/1.json
def show
# render :json => {first_category_url: module_url(course.course_modules.where.not(module_type: "activity").where(hidden: 0).first, course)}
end
# GET /courses/new
@ -241,44 +248,52 @@ class CoursesController < ApplicationController
if @course.try(:id) != 1309 || current_user.admin? || current_user.try(:id) == 15582
@teacher_list = @course.course_members.joins(:user).where("course_members.role in (1, 2, 3)
and LOWER(concat(users.lastname, users.firstname)) LIKE '%#{@search_str}%'")
and LOWER(concat(users.lastname, users.firstname)) LIKE ?", "%#{@search_str}%")
else
@teacher_list = @course.course_members.joins(:user).where("(course_members.role in (1, 3) or (course_members.user_id = #{current_user.id}
and course_members.role = 2)) and LOWER(concat(users.lastname, users.firstname))
LIKE '%#{@search_str}%'")
LIKE ?", "%#{@search_str}%")
end
@teacher_list_size = @teacher_list.size
@has_graduation_design = @course.course_modules.graduation_module_not_hidden.any?
sort = params[:sort] || "desc"
@order = params[:order].to_i
if @order.present?
case @order
when 1
@teacher_list = @teacher_list.includes(:user).order("CONVERT(CONCAT(users.lastname, users.firstname) USING gbk) COLLATE gbk_chinese_ci asc")
@teacher_list = @teacher_list.order("role #{sort}")
when 2
@teacher_list = @teacher_list.order("created_at")
@teacher_list = @teacher_list.includes(:user).order("CONVERT(CONCAT(users.lastname, users.firstname) USING gbk) COLLATE gbk_chinese_ci #{sort}")
when 3
@teacher_list = @teacher_list.includes(:course, :graduation_group).order("graduation_groups.name")
@teacher_list = @teacher_list.includes(:course, :graduation_group).order("graduation_groups.name #{sort}")
else
@teacher_list = @teacher_list.order("created_at")
@teacher_list = @teacher_list.order("role #{sort}")
end
else
if @has_graduation_design
@teacher_list = @teacher_list.includes(:course, :graduation_group).order("graduation_groups.name")
else
@teacher_list = @teacher_list.order("created_at")
end
@teacher_list = @teacher_list.order("role #{sort}")
end
@is_admin = current_user.creator_of_course? @course
@is_admin = @user_course_identity < Course::PROFESSOR
@applications= CourseMessage.unhandled_join_course_requests_by_course(@course)
@applications_size = CourseMessage.unhandled_join_course_requests_by_course(@course).size
page = params[:page] || 1
limit = params[:limit] || 20
@teacher_list = @teacher_list.page(page).per(limit)
@teacher_list = @teacher_list.preload(:graduation_group, :user, :teacher_course_groups)
end
def apply_teachers
search_str = params[:search].present? ? params[:search].strip : ""
@applications = CourseMessage.unhandled_join_course_requests_by_course(@course).
joins("join users on course_messages.course_message_id=users.id").
where("LOWER(concat(users.lastname, users.firstname)) LIKE ?", "%#{search_str}%")
@teacher_list_size = @course.teachers.size
@applications_size = CourseMessage.unhandled_join_course_requests_by_course(@course).size
@is_admin = @user_course_identity < Course::PROFESSOR
end
# 打开添加教师或助教弹窗时访问的接口(需要返回该课堂所有答辩组和所有)
@ -538,6 +553,7 @@ class CoursesController < ApplicationController
course_teacher = CourseMember.find_by(user_id: current_user.id, role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR], course_id: @course.id)
course_student.destroy!
course_teacher.update_attributes(is_active: 1) if course_teacher.present? && !course_teacher.is_active
CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, [current_user.id])
normal_status(0, "退出成功")
end
@ -566,6 +582,18 @@ class CoursesController < ApplicationController
end
new_teacher.save!
# 课堂管理员才有分配权限且课堂分班数大于0
if @user_course_identity < Course::PROFESSOR && @course.course_groups_count > 0 && params[:group_id] && params[:group_id].size > 0
# 分班全选则是不限,不需要做处理
unless @course.course_groups.where(id: params[:group_id]).size == @course.course_groups_count
@course.course_groups.where(id: params[:group_id]).each do |group|
unless TeacherCourseGroup.where(course_id: @course.id, user_id: applier_user.id, course_group_id: group.id, course_member_id: new_teacher.id).exists?
TeacherCourseGroup.create(course_id: @course.id, user_id: applier_user.id, course_member_id: new_teacher.id, course_group_id: group.id)
end
end
end
end
elsif approval == 2
course_message.reject!
else
@ -625,7 +653,8 @@ class CoursesController < ApplicationController
page = params[:page] || 1
limit = params[:limit] || 20
@students= Kaminari.paginate_array(@students).page(page).per(limit)
@students= @students.page(page).per(limit)
@students = @students.includes(:course_group, user: :user_extension)
end
# 获取当前课程所有分班
@ -674,11 +703,16 @@ class CoursesController < ApplicationController
ActiveRecord::Base.transaction do
begin
students = params[:students]
student_ids = []
students.each do |student|
course_member = CourseMember.find_by!(id: student[:course_member_id].to_i, course_id: @course.id)
course_member.destroy!
course_member = CourseMember.find_by(id: student[:course_member_id].to_i, course_id: @course.id)
if course_member.present?
student_ids << course_member.user_id
course_member.destroy!
end
end
CourseDeleteStudentDeleteWorksJob.perform_later(@course.id, student_ids) if student_ids.present?
normal_status(0, "操作成功")
rescue => e
uid_logger(e.message)
@ -701,7 +735,7 @@ class CoursesController < ApplicationController
student_ids = []
user_ids.each do |user_id|
existing_course_member = CourseMember.find_by(user_id: user_id.to_i, course_id: @course.id)
existing_course_member = @course.course_members.find_by(user_id: user_id.to_i)
new_student = CourseMember.new(user_id: user_id.to_i, course_id: @course.id, course_group_id: course_group_id, role: 4)
if existing_course_member.present?
@ -710,6 +744,7 @@ class CoursesController < ApplicationController
else
new_student.is_active = 0 if existing_course_member.is_active
new_student.save!
student_ids << user_id
end
else
new_student.save!
@ -717,6 +752,7 @@ class CoursesController < ApplicationController
end
end
CourseAddStudentCreateWorksJob.perform_later(@course.id, student_ids) if student_ids.present?
TeacherInviteJoinCourseNotifyJob.perform_later(current_user.id, @course.id, 10, student_ids) if student_ids.present?
normal_status(0, "添加成功")
rescue => e
@ -727,11 +763,11 @@ class CoursesController < ApplicationController
end
end
# 获取历史课堂,即用户管理的所有课堂以及课堂下的分班
# 获取历史课堂,即用户管理的所有课堂以及课堂下的分班(去除当前课堂)
def get_historical_courses
user_id = current_user.id
@courses = Course.includes(:course_groups).where(tea_id: user_id, is_delete: 0)
@courses = Course.where.not(id: @course.id).joins(:course_members).
where(is_delete: 0, course_members: {user_id: current_user.id, role: %i[CREATOR PROFESSOR ASSISTANT_PROFESSOR]}).includes(:course_groups)
# @courses = Course.includes(:course_groups).where(id: current_user.course_members, is_delete: 0)
end
# 根据历史课堂的课堂id和分班id获取所有学生
@ -744,6 +780,7 @@ class CoursesController < ApplicationController
@students = @students.where(course_group_id: course_group_id)
end
@students = @students.includes(user: [user_extension: :school])
@students_count = @students.size
end
@ -765,7 +802,7 @@ class CoursesController < ApplicationController
name = attachment.disk_filename
if name.split(".").last == "xls"
begin
attachment_folder = Rails.configuration.educoder['attachment_folder']
attachment_folder = edu_setting('attachment_folder')
full_path = "#{attachment_folder}/#{path}/#{name}"
xls = Roo::Spreadsheet.open(full_path, extension: :xls)
worksheet = xls.sheet(0)
@ -788,6 +825,8 @@ class CoursesController < ApplicationController
uid_logger_error(e.message)
normal_status(-1, "无法完成导入,原因:文件内容无法读取")
end
else
normal_status(-1, "只支持xls文件的导入")
end
end
end
@ -841,6 +880,13 @@ class CoursesController < ApplicationController
return normal_status(-1, "同一课堂不允许申请多个教师身份")
end
# 验证是否存在同学号的学生
u_extension = current_user.user_extension
if params[:student].present? && u_extension.student?
same_student_id_users = UserExtension.where.not(user_id: current_user.id).where(student_id: u_extension.student_id, identity: %i[student], school_id: u_extension.school_id).pluck(:user_id)
tip_exception("该课堂已存在同学号的学生,暂时无法加入,请联系老师") if course.students.exists?(user_id: same_student_id_users)
end
# 创建学生身份
if params[:student].present?
existing_student = CourseMember.find_by(course_id: course.id, role: %i[STUDENT], user_id: current_user.id)
@ -855,6 +901,7 @@ class CoursesController < ApplicationController
new_student.course_group_id = course_group.id if course_group.present?
new_student.save!
CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id])
StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id)
end
end
@ -895,15 +942,15 @@ class CoursesController < ApplicationController
def top_banner
@user = current_user
@is_teacher = @user.teacher_of_course?(@course)
@is_student = @course.course_members.where(user_id: @user.id, role: 4, is_active: 1).present?
@is_teacher = @user_course_identity < Course::STUDENT
@is_student = @user_course_identity == Course::STUDENT
@course.increment!(:visits)
end
def left_banner
@user = current_user
@is_teacher = @user.teacher_of_course?(@course)
@course_modules = @course.course_modules.where.not(module_type: "activity").where(hidden: 0)
@is_teacher = @user_course_identity < Course::ASSISTANT_PROFESSOR
@course_modules = @course.course_modules.where(hidden: 0)
@hidden_modules = @course.course_modules.where(hidden: 1)
@second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group"]
end
@ -930,7 +977,7 @@ class CoursesController < ApplicationController
@page = params[:page] || 1
@page_size = params[:page_size] || 15
@courses = Course.by_user(current_user).hidden(false).ended(false).deleted(0).by_keywords(params[:search]).distinct
@courses = Course.by_user(current_user).hidden(false).processing.not_deleted.by_keywords(params[:search]).distinct
# @total_count = @courses.count
# offset = 0
@ -946,34 +993,33 @@ class CoursesController < ApplicationController
def export_member_scores_excel
ActiveRecord::Base.transaction do
begin
name = params[:name] ? "#{params[:name].strip}" : "" #用户名或学生学号id搜索
search = params[:search] ? "#{params[:search].strip}" : "" #用户名或学生学号id搜索
group_id = params[:group_id] #分班的班级id
if group_id && group_id != "0" && group_id != "-1"
@all_members = @course.students.course_find_by_ids("course_group_id",group_id)
elsif group_id && group_id == "0" # 未分班
@all_members = @course.course_members.ungroup_students
else
@all_members = @course.students
end
if name.present?
nick_name_search = @all_members.joins(:user).where("nickname like ?","%#{name}%")
if nick_name_search.present?
@all_members = nick_name_search
else
@all_members = @all_members.joins(user: [:user_extension]).where('user_extensions.student_id like ? OR user_extensions.student_realname like ?',"%#{name}%","%#{name}%")
end
end
@c_homeworks = @course.homework_commons.homework_published.order("publish_time asc, created_at asc")
@c_exercises = @course.exercises.is_exercise_published.order("publish_time asc, created_at asc")
@c_polls = @course.polls.publish_or_not.order("publish_time asc, created_at asc")
@c_tasks = @course.graduation_tasks.task_published.order("publish_time asc, created_at asc")
# if group_id && group_id != "0" && group_id != "-1"
# @all_members = @course.students.course_find_by_ids("course_group_id",group_id)
# elsif group_id && group_id == "0" # 未分班
# @all_members = @course.course_members.ungroup_students
# else
# @all_members = @course.students
# end
# if name.present?
# @all_members = @all_members.joins(user: [:user_extension]).where('concat(users.lastname, users.firstname) like ? or user_extensions.student_id like ?',"%#{name}%","%#{name}%")
# end
@all_members = student_act_score group_id, search
@c_homeworks = @course.homework_commons.homework_published.order("homework_commons.publish_time asc, homework_commons.created_at asc")
@c_exercises = @course.exercises.is_exercise_published.order("exercises.publish_time asc, exercises.created_at asc")
# @c_polls = @course.polls.publish_or_not.order("polls.publish_time asc, polls.created_at asc")
@c_tasks = @course.graduation_tasks.task_published.order("graduation_tasks.publish_time asc, graduation_tasks.created_at asc")
if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作")
elsif @all_members.size == 0
normal_status(-1,"课堂暂时没有学生")
else
member_to_xlsx(@course,@all_members,@c_homeworks,@c_exercises,@c_tasks,@c_polls)
filename = current_user.real_name + "_" + @course.name + "_全部成绩" + Time.now.strftime('%Y%m%d_%H%M%S')
render xlsx: "#{filename.strip.first(30)}",template: "courses/export_member_scores_excel.xlsx.axlsx",
member_to_xlsx(@course, @all_members, @c_homeworks, @c_exercises, @c_tasks)
filename_ = "#{current_user.real_name}_#{@course.name}_全部成绩"
render xlsx: "#{format_sheet_name filename_.strip.first(30)}",template: "courses/export_member_scores_excel.xlsx.axlsx",
locals: {course_info:@course_info, activity_level:@user_activity_level,
course_scores:@course_user_scores,shixun_works:@shixun_work_arrays,
common_works:@common_work_arrays,group_works:@group_work_arrays,task_works:@task_work_arrays,
@ -981,12 +1027,26 @@ class CoursesController < ApplicationController
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
def search_slim
courses = current_user.manage_courses.not_deleted.processing
keyword = params[:keyword].to_s.strip
if keyword.present?
courses = courses.where('name LIKE ?', "%#{keyword}%")
end
count = courses.count
courses = paginate(courses)
render_ok(count: count, courses: courses.select(:id, :name).as_json)
end
private
# Use callbacks to share common setup or constraints between actions.
@ -1005,6 +1065,7 @@ class CoursesController < ApplicationController
tip_exception("课堂名称应以课程名称开头命名") unless params[:course][:name].index(params[:course_list_name]) &&
params[:course][:name].index(params[:course_list_name]) == 0
tip_exception("课堂所属单位不能为空!") if params[:school].blank?
tip_exception("请至少添加一个课堂模块") if params[:course_module_types].blank?
@school = School.find_by!(name: params[:school].strip)
end
@ -1029,16 +1090,72 @@ class CoursesController < ApplicationController
end
end
def member_to_xlsx(course,all_members,homeworks,exercises,tasks,polls)
def student_act_score group_id, search
sql_select = %Q{SELECT cm.*,(
SELECT SUM(student_works.work_score)
FROM student_works,homework_commons
WHERE student_works.homework_common_id = homework_commons.id
AND homework_commons.course_id = #{@course.id}
AND student_works.user_id = cm.user_id
) AS score,
(SELECT max(student_id) FROM user_extensions WHERE user_extensions.user_id = cm.user_id) AS student_id,
(SELECT count(messages.id) FROM messages join boards on messages.board_id = boards.id WHERE boards.course_id = #{@course.id}
AND messages.author_id = cm.user_id and messages.parent_id is null) AS message_num,
(SELECT count(messages.id) FROM messages join boards on messages.board_id = boards.id WHERE boards.course_id = #{@course.id}
AND messages.author_id = cm.user_id and messages.parent_id is not null) AS message_reply_num,
(SELECT count(attachments.id) FROM attachments WHERE container_id = #{@course.id} and container_type = "Course"
AND attachments.author_id = cm.user_id) AS resource_num,
(SELECT count(jfm.id) FROM journals_for_messages AS jfm, homework_commons hs WHERE jfm.jour_id = hs.id AND
jfm.user_id = cm.user_id and jfm.jour_type = "HomeworkCommon" and hs.course_id = #{@course.id}) AS homework_journal_num,
(SELECT COUNT(gw.id) FROM graduation_works AS gw, graduation_tasks AS gt WHERE gw.graduation_task_id = gt.id AND
gt.course_id = #{@course.id} AND gw.work_status != 0 AND gw.user_id = cm.user_id) AS graduation_num,
(SELECT COUNT(ss.id) FROM student_works AS ss ,homework_commons AS hc WHERE ss.homework_common_id = hc.id AND
hc.course_id = #{@course.id} AND ss.work_status != 0 AND ss.user_id = cm.user_id) AS homework_num,
(SELECT COUNT(eu.id) FROM exercise_users AS eu,exercises WHERE eu.exercise_id = exercises.id AND exercises.course_id = #{@course.id}
AND eu.commit_status = 1 AND eu.user_id = cm.user_id) AS exercise_num,
(SELECT COUNT(pu.id) FROM poll_users AS pu, polls WHERE pu.poll_id = polls.id AND polls.course_id = #{@course.id}
AND pu.commit_status = 1 AND pu.user_id = cm.user_id) AS poll_num
FROM course_members cm}
if search.present? && group_id.present?
sql_select += %Q{ join users on cm.user_id = users.id
joins user_extensions ue on ue.user_id = users.id
WHERE cm.role = 4 and cm.course_id = #{@course.id} and cm.course_group_id = #{group_id} and
(concat(users.lastname, users.firstname) like '%#{search}%' or ue.student_id like '%#{search}%') ORDER BY score desc}
elsif search.present?
sql_select += %Q{ join users on cm.user_id = users.id
joins user_extensions ue on ue.user_id = users.id
WHERE cm.role = 4 and
(concat(users.lastname, users.firstname) like '%#{search}%' or ue.student_id like '%#{search}%') ORDER BY score desc}
elsif group_id.present?
sql_select += %Q{ WHERE cm.role = 4 and cm.course_id = #{@course.id} and cm.course_group_id = #{group_id} ORDER BY score desc}
else
sql_select += %Q{ WHERE cm.role = 4 and cm.course_id = #{@course.id} ORDER BY score desc}
end
act_scores = CourseMember.find_by_sql(sql_select)
act_scores
end
def member_to_xlsx(course,all_members,homeworks,exercises,tasks)
#课堂的作业信息
shixun_homeworks = homeworks.search_homework_type(4) #全部实训作业
shixun_homeworks = homeworks.search_homework_type(4) #全部实训作业
shixun_titles = shixun_homeworks.pluck(:name) + ["总得分"]
common_homeworks = homeworks.search_homework_type(1) #全部普通作业
shixun_homeworks = shixun_homeworks&.includes(score_student_works: :user)
common_homeworks = homeworks.search_homework_type(1) #全部普通作业
common_titles = common_homeworks.pluck(:name)+ ["总得分"]
common_homeworks = common_homeworks&.includes(score_student_works: :user)
group_homeworks = homeworks.search_homework_type(3) #全部分组作业
group_titles = group_homeworks.pluck(:name)+ ["总得分"]
task_titles = tasks.pluck(:name)+ ["总得分"]
exercise_titles = exercises.pluck(:exercise_name)+ ["总得分"]
group_homeworks = group_homeworks&.includes(score_student_works: :user)
task_titles = tasks.pluck(:name) + ["总得分"]
tasks = tasks&.includes(user: :user_extension, score_graduation_works: :user)
exercise_titles = exercises.pluck(:exercise_name) + ["总得分"]
exercises = exercises&.includes(user: :user_extension, score_exercise_users: :user)
total_user_score_array = [] #学生总成绩集合
#课堂信息
@ -1047,13 +1164,13 @@ class CoursesController < ApplicationController
course_id = course.id
course_name = course.name
course_list_name = course.course_list.present? ? course.course_list.name : "--"
course_assistants = course.course_members.course_user_role(%i[PROFESSOR ASSISTANT_PROFESSOR])
course_assistants_count = course_assistants&.count
course_assistants = course.teachers
course_assistants_count = course_assistants&.size
course_assistants_name = course_assistants_count > 0 ? course_assistants.map{|m| m.user.real_name}.join('、') : "--"
course_teacher_member = course.course_members.course_user_role(%i[CREATOR])
course_teacher = course_teacher_member.present? ? course_teacher_member.first.user.real_name : "--"
course_class_counts = course.course_groups_count
course_students_count = course.students.count
course_students_count = course.students.size
course_1 = ["课堂编号",course_id]
course_2 = ["课程名称",course_list_name]
course_3 = ["课堂名称",course_name]
@ -1064,25 +1181,32 @@ class CoursesController < ApplicationController
course_main_info = [course_1,course_2,course_3,course_4,course_5,course_6,course_7]
course_group_info_head = %w(序号 分班名称 邀请码 学生数量)
course_group_info_body = []
if course.course_groups.present?
none_group_counts = course.none_group_count
#当有未分班时,应该也做个统计
if none_group_counts > 0
none_group_index = 2
no_group_array = [1,"未分班",course.invite_code,none_group_counts]
course_group_info_body.push(no_group_array)
else
none_group_index = 1
end
if course.course_groups.exists?
course.course_groups.each_with_index do |group, index|
group_index = (index+1)
group_index = (index+none_group_index)
group_name = group.name
group_code = group.invite_code
group_count = group.course_members_count
group_array = [group_index,group_name,group_code,group_count]
course_group_info_body.push(group_array)
end
end
course_group_info = [course_group_info_head,course_group_info_body]
@course_info += [course_info_title,course_main_info,course_group_info]
#课堂活跃度
course_homework_ids = homeworks.pluck(:id) #该课堂的全部作业id
course_graduate_task_ids = tasks.pluck(:id) #该课堂的全部毕业任务id
course_exercise_ids = exercises.pluck(:id) #课堂的全部试卷数
course_poll_ids = polls.pluck(:id) #课堂的全部问卷数
course_board_ids = course.boards.pluck(:id) #课堂的全部讨论区
@user_activity_level = []
course_user_level = []
course_activity_title = "课堂活跃度统计"
@ -1093,27 +1217,26 @@ class CoursesController < ApplicationController
user_login = user.login
user_name = user.real_name
user_mail = user.mail
user_stu_id = user.student_id.present? ? (user.student_id.to_s + "\t") : "--"
user_stu_id = u.student_id.present? ? (u.student_id.to_s + "\t") : "--"
user_course_group = u.course_group_name
user_info_array = [user_login,user_name,user_mail,user_stu_id,user_course_group] #用户的信息集合
user_work_scores = []
#课堂活跃度统计
user_homeworks_num = user.student_works.find_by_homework(course_homework_ids).has_committed.count #完成的作业数
user_graduate_num = user.graduation_works.find_by_task(course_graduate_task_ids).has_committed.count #毕业任务完成数
user_exercise_num = user.exercise_users.search_by_exercise(course_exercise_ids).commit_exercise_by_status(1).count #根据试卷的id来查找
user_poll_num = user.poll_users.search_by_poll(course_poll_ids).commit_by_status(1).count #已完成问卷
user_file_num = user.attachments.search_by_container(course.id).count
user_messages = user.messages
user_messages_num = user_messages.root_nodes.find_by_boards(course_board_ids).count #帖子发布数
user_reply_num = user_messages.reply_nodes.find_by_boards(course_board_ids).count #帖子回复数
user_work_reply_num = user.journals_for_messages.search_by_jour_type("HomeworkCommon",course_homework_ids).count #作业回复数的数量
user_homeworks_num = u.homework_num.to_i #完成的作业数
user_graduate_num = u.graduation_num.to_i #毕业任务完成数
user_exercise_num = u.exercise_num.to_i #根据试卷的id来查找
user_poll_num = u.poll_num.to_i #已完成问卷
user_file_num = u.resource_num.to_i
user_messages_num = u.message_num.to_i #帖子发布数
user_reply_num = u.message_reply_num.to_i #帖子回复数
user_work_reply_num = u.homework_journal_num.to_i #作业回复数的数量
c_works_num = (user_homeworks_num + user_graduate_num)*10
c_exercise_num = user_exercise_num*10
c_poll_num = user_poll_num*7
c_file_num = user_file_num*5
c_message_num = user_messages_num*2
c_reply_num = user_reply_num*2
c_reply_num = user_reply_num
user_activity_levels = c_works_num + c_exercise_num + c_poll_num + c_file_num + c_message_num + c_reply_num + user_work_reply_num
user_ac_level = {
u_1: user_name,
@ -1145,14 +1268,13 @@ class CoursesController < ApplicationController
exercise_score_array = []
#实训作业
if shixun_homeworks.count > 0
if shixun_homeworks.size > 0
shixun_homeworks.each do |s|
user_student_work = s.student_works.homework_by_user(user.id) #当前用户的对该作业的回答
if user_student_work.blank?
user_student_work = s.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
if user_student_work.nil?
h_score = 0.0 #该作业的得分为0
else
user_stu_work = user_student_work.first
h_score = user_stu_work.work_score.nil? ? 0.0 : user_stu_work.work_score #用户对该作业的分数
h_score = user_student_work.work_score.nil? ? 0.0 : user_student_work.work_score #用户对该作业的分数
end
shixun_score_array.push(h_score)
end
@ -1162,14 +1284,13 @@ class CoursesController < ApplicationController
user_work_scores += user_info_array + shixun_score_array #单个用户的实训作业得分信息
#普通作业
if common_homeworks.count > 0
if common_homeworks.size > 0
common_homeworks.each do |c|
user_student_work_1 = c.student_works.homework_by_user(user.id) #当前用户的对该作业的回答
if user_student_work_1.blank?
user_student_work_1 = c.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
if user_student_work_1.nil?
h_score_1 = 0.0 #该作业的得分为0
else
user_stu_work_1 = user_student_work_1.first
h_score_1 = user_stu_work_1.work_score.nil? ? 0.0 : user_stu_work_1.work_score #用户对该作业的分数
h_score_1 = user_student_work_1.work_score.nil? ? 0.0 : user_student_work_1.work_score #用户对该作业的分数
end
common_score_array.push(h_score_1)
end
@ -1179,14 +1300,13 @@ class CoursesController < ApplicationController
user_work_scores += common_score_array #单个用户的普通作业得分信息
#分组作业
if group_homeworks.count > 0
if group_homeworks.size > 0
group_homeworks.each do |g|
user_student_work_3 = g.student_works.homework_by_user(user.id) #当前用户的对该作业的回答
if user_student_work_3.blank?
user_student_work_3 = g.score_student_works.select{|work| work.user_id == user.id}.first #当前用户的对该作业的回答
if user_student_work_3.nil?
h_score_3 = 0.0 #该作业的得分为0
else
user_stu_work_3 = user_student_work_3.first
h_score_3 = user_stu_work_3.work_score.nil? ? 0.0 : user_stu_work_3.work_score #用户对该作业的分数
h_score_3 = user_student_work_3.work_score.nil? ? 0.0 : user_student_work_3.work_score #用户对该作业的分数
end
group_score_array.push(h_score_3)
end
@ -1196,13 +1316,13 @@ class CoursesController < ApplicationController
user_work_scores += group_score_array #单个用户的分组作业得分信息
#毕设作业
if tasks.count > 0
if tasks.size > 0
tasks.each do |task|
graduation_works = task.graduation_works.find_by_task_user(user.id)
if graduation_works.empty?
graduation_work = task.score_graduation_works.select{|work| work.user_id == user.id}.first
if graduation_work.nil?
t_score = 0.0
else
t_score = graduation_works.first.work_score.nil? ? 0.0 : graduation_works.first.work_score
t_score = graduation_work.work_score.nil? ? 0.0 : graduation_work.work_score
end
task_score_array.push(t_score)
end
@ -1212,13 +1332,13 @@ class CoursesController < ApplicationController
user_work_scores += task_score_array #单个用户的分组作业得分信息
#试卷
if exercises.count > 0
if exercises.size > 0
exercises.each do |ex|
exercise_works = ex.exercise_users.exercise_commit_users(user.id)
if exercise_works.empty?
exercise_work = ex.score_exercise_users.select{|work| work.user_id == user.id}.first
if exercise_work.nil?
e_score = 0.0
else
e_score = exercise_works.first.score.nil? ? 0.0 : exercise_works.first.score
e_score = exercise_work.score.nil? ? 0.0 : exercise_work.score
end
exercise_score_array.push(e_score)
end
@ -1250,73 +1370,60 @@ class CoursesController < ApplicationController
@common_work_arrays = []
@task_work_arrays = []
@exercise_work_arrays = []
count_1 = shixun_homeworks.count
count_2 = common_homeworks.count
count_3 = group_homeworks.count
count_4 = tasks.count
count_5 = exercises.count
count_1 = shixun_homeworks.size
count_2 = common_homeworks.size
count_3 = group_homeworks.size
count_4 = tasks.size
#实训作业
if count_1 > 0
shixun_homeworks.each_with_index do |s,index|
all_student_works = s.student_works.has_committed.order("work_score desc") #该实训题的全部用户回答
title_no = index.to_i + 1
student_work_to_xlsx(all_student_works,s)
shixun_work_display_name = (title_no.to_s + "." + s.name).strip.first(30)
shixun_work_content = [shixun_work_display_name,@work_head_cells,@work_cells_column]
@shixun_work_arrays.push(shixun_work_content)
end
shixun_homeworks.each_with_index do |s,index|
all_student_works = s.score_student_works #该实训题的全部用户回答
title_no = index.to_i + 1
student_work_to_xlsx(all_student_works,s)
shixun_work_display_name = format_sheet_name (title_no.to_s + "." + s.name).strip.first(30)
shixun_work_content = [shixun_work_display_name,@work_head_cells,@work_cells_column]
@shixun_work_arrays.push(shixun_work_content)
end
#普通作业
if count_2 > 0
common_homeworks.each_with_index do |c,index|
all_student_works = c.student_works.has_committed.order("work_score desc") #当前用户的对该作业的回答
title_no = count_1 + index.to_i + 1
student_work_to_xlsx(all_student_works,c)
work_name = (title_no.to_s + "." + c.name).strip.first(30)
work_content = [work_name,@work_head_cells,@work_cells_column]
@common_work_arrays.push(work_content)
title_no
end
common_homeworks.each_with_index do |c,index|
all_student_works = c.score_student_works #当前用户的对该作业的回答
title_no = count_1 + index.to_i + 1
student_work_to_xlsx(all_student_works,c)
work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30)
work_content = [work_name,@work_head_cells,@work_cells_column]
@common_work_arrays.push(work_content)
title_no
end
#分组作业
if count_3 > 0
group_homeworks.each_with_index do |c,index|
all_student_works = c.student_works.has_committed.order("work_score desc") #当前用户的对该作业的回答
title_no = count_1 + count_2 + index.to_i + 1
student_work_to_xlsx(all_student_works,c)
work_name = (title_no.to_s + "." + c.name).strip.first(30)
work_content = [work_name,@work_head_cells,@work_cells_column]
@group_work_arrays.push(work_content)
end
group_homeworks.each_with_index do |c,index|
all_student_works = c.score_student_works #当前用户的对该作业的回答
title_no = count_1 + count_2 + index.to_i + 1
student_work_to_xlsx(all_student_works,c)
work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30)
work_content = [work_name,@work_head_cells,@work_cells_column]
@group_work_arrays.push(work_content)
end
#毕设任务
if count_4 > 0
tasks.each_with_index do |c,index|
all_student_works = c.graduation_works.has_committed.order("work_score desc") #当前用户的对该作业的回答
title_no = count_1 + count_2 + count_3 + index.to_i + 1
graduation_work_to_xlsx(all_student_works,c,current_user)
work_name = (title_no.to_s + "." + c.name).strip.first(30)
# work_content = [work_name,@work_head_cells,@work_cells_column]
work_content = [work_name,@head_cells_column,@task_cells_column]
@task_work_arrays.push(work_content)
end
tasks.each_with_index do |c,index|
all_student_works = c.score_graduation_works #当前用户的对该作业的回答
title_no = count_1 + count_2 + count_3 + index.to_i + 1
graduation_work_to_xlsx(all_student_works,c,current_user)
work_name = format_sheet_name (title_no.to_s + "." + c.name).strip.first(30)
work_content = [work_name,@head_cells_column,@task_cells_column]
@task_work_arrays.push(work_content)
end
#试卷的导出
if count_5 > 0
exercises.each_with_index do |c,index|
all_student_works = c.exercise_users.exercise_user_committed #当前用户的对该作业的回答
title_no = count_1 + count_2 + count_3 + count_4 + index.to_i + 1
get_export_users(c,course,all_student_works)
work_name = (title_no.to_s + "." + c.exercise_name).strip.first(30)
# work_content = [work_name,@work_head_cells,@work_cells_column]
work_content = [work_name,@table_columns,@user_columns]
@exercise_work_arrays.push(work_content)
end
exercises.each_with_index do |c,index|
all_student_works = c.score_exercise_users #当前用户的对该作业的回答
title_no = count_1 + count_2 + count_3 + count_4 + index.to_i + 1
get_export_users(c,course,all_student_works)
work_name = format_sheet_name (title_no.to_s + "." + c.exercise_name).strip.first(30)
work_content = [work_name,@table_columns,@user_columns]
@exercise_work_arrays.push(work_content)
end
end
end

@ -0,0 +1,11 @@
class DepartmentsController < ApplicationController
def for_option
render_ok(departments: Department.cached_names_data(current_school))
end
private
def current_school
@_current_school ||= School.find(params[:id])
end
end

@ -7,9 +7,24 @@ class DiscussesController < ApplicationController
page = params[:page].to_i
offset = page * LIMIT
# 总数,分页使用
@disscuss_count = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil).count
@discusses = Discuss.limit(LIMIT).where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil).
includes(:user, :praise_tread).offset(offset)
if current_user.admin?
@disscuss_count = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s, :root_id => nil).count
disscusses = Discuss.where(:dis_id => @container.id, :dis_type => @container.class.to_s,
:root_id => nil)
else
disscusses = Discuss.where("dis_id = :dis_id and dis_type = :dis_type and root_id is null and
(discusses.hidden = :hidden or discusses.user_id = :user_id)",
{dis_id: @container.id, dis_type: @container.class.to_s, hidden: false, user_id: current_user.id})
@disscuss_count = disscusses.count("discusses.id")
end
@manger = @container.has_manager?(current_user)
if @manger
@discusses = disscusses.limit(LIMIT).joins("left join games on discusses.challenge_id = games.challenge_id and discusses.user_id = games.user_id")
.select("discusses.*, games.identifier").includes(:user, :praise_treads).offset(offset)
else
@discusses = disscusses.limit(LIMIT).includes(:user, :praise_treads).offset(offset)
end
@current_user = current_user
end
@ -23,8 +38,10 @@ class DiscussesController < ApplicationController
def create
begin
@discuss = Discuss.create!(:dis_id => params[:container_id], :dis_type => params[:container_type], :content => params[:content].gsub("&nbsp\;", "").strip,
:user_id => current_user.id, :praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id])
@discuss = Discuss.create!(:dis_id => params[:container_id], :dis_type => params[:container_type],
:content => params[:content].gsub("&nbsp\;", "").strip, :user_id => current_user.id,
:praise_count => 0, :position => params[:position], :challenge_id => params[:challenge_id],
:hidden => !current_user.admin?) # 管理员回复的能够显示
rescue Exception => e
uid_logger_error("create discuss failed : #{e.message}")
raise Educoder::TipException.new("评论异常")

@ -1,15 +1,6 @@
class Ecs::BaseController < ApplicationController
# model validation error
rescue_from ActiveRecord::RecordInvalid do |ex|
render_error(ex.record.errors.full_messages.join(','))
end
# form validation error
rescue_from ActiveModel::ValidationError do |ex|
render_error(ex.model.errors.full_messages.join(','))
end
before_action :require_login
before_action :require_login, :check_auth
before_action :check_user_permission!
helper_method :current_user, :current_school

@ -1,6 +1,7 @@
class ExerciseAnswersController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :get_exercise_question
include ExercisesHelper
def create #每一次答案的点击,请求一次,实训题不在这里回答
ActiveRecord::Base.transaction do
@ -8,11 +9,11 @@ class ExerciseAnswersController < ApplicationController
q_type = @exercise_question.question_type #试卷的类型
choice_id = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : ""
answer_text = params[:answer_text].present? ? params[:answer_text] : "" #为字符串
if q_type < 4 && choice_id.blank?
if q_type < Exercise::SUBJECTIVE && (q_type != Exercise::MULTIPLE) && choice_id.blank?
normal_status(-1,"请选择序号")
else
ea = @exercise_question.exercise_answers.search_answer_users("user_id",current_user.id) #试卷的当前用户的答案
if q_type == 0 || q_type == 2 #选择题(单选)/判断题
if q_type == Exercise::SINGLE || q_type == Exercise::JUDGMENT #选择题(单选)/判断题
ea_choice = ea.search_exercise_answer("exercise_choice_id",choice_id).first
answer_option = {
:user_id => current_user.id,
@ -29,8 +30,9 @@ class ExerciseAnswersController < ApplicationController
ex_a = ExerciseAnswer.new(answer_option)
ex_a.save!
end
elsif q_type == 1 #多选题的
elsif q_type == Exercise::MULTIPLE #多选题的
choice_ids = params[:exercise_choice_id].present? ? params[:exercise_choice_id] : []
ea_ids = ea.pluck(:exercise_choice_id)
common_answer_ids = choice_ids & ea_ids #已经存在的试卷选项id
new_ids = choice_ids - common_answer_ids # 新增的id
@ -51,7 +53,7 @@ class ExerciseAnswersController < ApplicationController
ea_answer = ea.search_answer_users("exercise_choice_id",old_ids)
ea_answer.destroy_all
end
elsif q_type == 3 #填空题
elsif q_type == Exercise::COMPLETION #填空题
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id,
@ -65,7 +67,7 @@ class ExerciseAnswersController < ApplicationController
ex_new = ExerciseAnswer.new(answer_option)
ex_new.save!
end
elsif q_type == 4 #简答题
elsif q_type == Exercise::SUBJECTIVE #简答题
answer_option = {
:user_id => current_user.id,
:exercise_question_id => @exercise_question.id
@ -92,9 +94,10 @@ class ExerciseAnswersController < ApplicationController
def get_exercise_question
@exercise_question = ExerciseQuestion.find_by_id(params[:exercise_question_id])
@exercise = @exercise_question.exercise
@course = @exercise.course
@exercise_user = @exercise.exercise_users.exercise_commit_users(current_user.id).first #当前用户
@exercise = @exercise_question&.exercise
@course = @exercise&.course
@exercise_user = @exercise&.exercise_users.find_by(user_id: current_user.id) #当前用户
@exercise_user_status = @exercise.get_exercise_status(current_user)
if @exercise_question.blank?
normal_status(-1,"试卷问题不存在!")
@ -102,15 +105,28 @@ class ExerciseAnswersController < ApplicationController
normal_status(-1,"试卷不存在!")
elsif @course.blank?
normal_status(-1,"该课堂不存在!")
elsif (@exercise_user.present? && @exercise_user.commit_status == 1) || (@exercise.end_time.present? && @exercise.end_time < Time.now) #已提交答案的/时间已结束的试卷不允许再修改
elsif @exercise_user.blank?
normal_status(-1,"试卷用户不存在!")
elsif @exercise_user.commit_status == 1
normal_status(-1,"已提交/已结束的试卷不允许修改!")
elsif @exercise.time > 0
user_start_at = @exercise.exercise_users.exercise_commit_users(current_user.id).first.start_at
exercise_time = @exercise.time.to_i
if (user_start_at + exercise_time.minutes) < Time.now
normal_status(-1,"限时试卷已结束!")
else
if (@exercise_user_status == Exercise::DEADLINE && @exercise_user.commit_status == 0) || (@exercise.time > 0 && @exercise_user.start_at.present? && ((@exercise_user.start_at + (@exercise.time.to_i + 1).minutes) < Time.now))
objective_score = calculate_student_score(@exercise,current_user)[:total_score]
subjective_score = @exercise_user.subjective_score < 0.0 ? 0.0 : @exercise_user.subjective_score
total_score = objective_score + subjective_score
commit_option = {
:status => 1,
:commit_status => 1,
:end_at => Time.now,
:objective_score => objective_score,
:score => total_score,
:subjective_score => subjective_score
}
@exercise_user.update_attributes(commit_option)
normal_status(-1,"试卷提交时间已截止!")
end
end
end
end

@ -1,5 +1,5 @@
class ExerciseQuestionsController < ApplicationController
before_action :require_login #用户需登陆
before_action :require_login, :check_auth #用户需登陆
before_action :get_exercise,only:[:new,:create] #获取试卷
before_action :get_exercise_question,except: [:new,:create] #获取试卷的问题及试卷
before_action :is_course_teacher #是否为老师
@ -47,7 +47,7 @@ class ExerciseQuestionsController < ApplicationController
if @exercise_question.save
#为选择题(包括单选和多选)的时候,创建问题选项
ques_type = @exercise_question.question_type
if ques_type <= 1
if ques_type <= Exercise::MULTIPLE
choices_array = params[:question_choices]
choices_count= choices_array.count
standard_answer = params[:standard_answers] #为数组格式,因为可能会有单选和多选,标准答案,已提前判断不能为空,
@ -70,13 +70,13 @@ class ExerciseQuestionsController < ApplicationController
}
question_standard_answer = ExerciseStandardAnswer.new(standard_option)
question_standard_answer.save
if standard_answer.count > 1 && ques_type == 0 #当标准答案数大于1且不为多选时修改为多选
@exercise_question.update_attribute("question_type",1)
elsif standard_answer.count == 1 && ques_type == 1
@exercise_question.update_attribute("question_type",0)
if standard_answer.count > 1 && ques_type == Exercise::SINGLE #当标准答案数大于1且不为多选时修改为多选
@exercise_question.update_attribute("question_type",Exercise::MULTIPLE)
elsif standard_answer.count == 1 && ques_type == Exercise::MULTIPLE
@exercise_question.update_attribute("question_type",Exercise::SINGLE)
end
end
elsif ques_type == 2 #这个为判断题
elsif ques_type == Exercise::JUDGMENT #这个为判断题
choices_array = params[:question_choices] #判断的选项,对/错等等
choices_count= choices_array.count
(1..choices_count).each do |c|
@ -95,7 +95,7 @@ class ExerciseQuestionsController < ApplicationController
}
question_standard_answer = ExerciseStandardAnswer.new(standard_option)
question_standard_answer.save
elsif ques_type == 3 #填空题,每空的参考答案有多个,那么以位置对应
elsif ques_type == Exercise::COMPLETION #填空题,每空的参考答案有多个,那么以位置对应
standard_answer = params[:standard_answers]
standard_answer.each do |a|
null_choice_id = a[:choice_id]
@ -110,7 +110,7 @@ class ExerciseQuestionsController < ApplicationController
question_standard_answer.save
end
end
elsif ques_type == 4 #简答题
elsif ques_type == Exercise::SUBJECTIVE #简答题
if params[:standard_answers].present? && params[:standard_answers].reject(&:blank?).count > 0
standard_answer = params[:standard_answers]
standard_answer.each do |a|
@ -122,12 +122,12 @@ class ExerciseQuestionsController < ApplicationController
question_standard_answer.save
end
end
elsif ques_type == 5 #实训题
elsif ques_type == Exercise::PRACTICAL #实训题
shixun = Shixun.find_by(id: params[:shixun_id])
shixun_scores = params[:question_scores] #试卷有多个的分值有多个分数表,所以为分数的数组
shixun_name = params[:shixun_name] || shixun.name
question_score = 0
shixun.challenges.each_with_index do |challenge,index|
shixun.challenges.try(:each_with_index) do |challenge,index|
shixun_option = {
:challenge_id => challenge.id,
:shixun_id => shixun.id,
@ -223,16 +223,14 @@ class ExerciseQuestionsController < ApplicationController
end
end
#试卷未发布时,当标准答案存在时,可修改标准答案内容,可增删标准答案,否则只能修改标准答案,不能增删标准答案
st_count = 0
@exercise_answers_array = @exercise_question.exercise_standard_answers #问卷的全部标准答案
if standard_answer.present?
if @exercise_question.question_type <= 2 #选择题/判断题,标准答案为一个或多个
if @exercise_question.question_type <= Exercise::JUDGMENT #选择题/判断题,标准答案为一个或多个
exercise_standard_choices = @exercise_answers_array.pluck(:exercise_choice_id) #问题以前的全部标准答案选项位置
common_standard_choices = standard_answer & exercise_standard_choices # 传入的标准答案的选项位置和以前的并集,即表示不用做更改的
old_left_standard_choices = exercise_standard_choices - common_standard_choices # 以前的差集共同的,剩余的表示需要删掉
new_left_standard_choices = standard_answer - common_standard_choices # 传入的标准答案差集共同的,剩余的表示需要新建
if old_left_standard_choices.count > 0
st_count += 1
@exercise_answers_array.standard_by_ids(old_left_standard_choices).destroy_all
end
if new_left_standard_choices.count > 0 #新建标准答案
@ -246,19 +244,18 @@ class ExerciseQuestionsController < ApplicationController
end
end
if standard_answer.count > 1 && @exercise_question.question_type == 0 #当标准答案数大于1且不为多选时修改为多选
@exercise_question.update_attribute("question_type",1)
elsif standard_answer.count == 1 && @exercise_question.question_type == 1
@exercise_question.update_attribute("question_type",0)
if standard_answer.count > 1 && @exercise_question.question_type == Exercise::SINGLE #当标准答案数大于1且不为多选时修改为多选
@exercise_question.update_attribute("question_type",Exercise::MULTIPLE)
elsif standard_answer.count == 1 && @exercise_question.question_type == Exercise::MULTIPLE
@exercise_question.update_attribute("question_type",Exercise::SINGLE)
end
elsif @exercise_question.question_type == 3 #填空题
elsif @exercise_question.question_type == Exercise::COMPLETION #填空题
old_ex_answer = @exercise_question.exercise_standard_answers #当前问题的全部标准答案
old_ex_answer_choice_ids = old_ex_answer.pluck(:exercise_choice_id).uniq #全部的答案数组序号
new_ex_answer_choice_ids = standard_answer.map {|a| a[:choice_id]}.uniq #新传入的答案数组序号
#删除多余的选项
if old_ex_answer_choice_ids.count > new_ex_answer_choice_ids.count #有减少的填空
st_count += 1
delete_ex_answer_choice_ids = old_ex_answer_choice_ids - new_ex_answer_choice_ids
old_ex_answer.standard_by_ids(delete_ex_answer_choice_ids).destroy_all
end
@ -284,7 +281,6 @@ class ExerciseQuestionsController < ApplicationController
ex_answer_pre[n-1].update(standard_option)
end
if new_add_choice.count > 0 #表示有新增的
st_count += 1
new_add_choice.each do |i|
standard_option = {
:exercise_question_id => @exercise_question.id,
@ -306,7 +302,6 @@ class ExerciseQuestionsController < ApplicationController
ex_answer_pre[index].update(standard_option)
end
if new_delete_choice.count > 0 #表示填空题的答案有删减的
st_count += 1
new_delete_choice.each do |d|
ex_answer_pre[d-1].destroy
end
@ -326,7 +321,7 @@ class ExerciseQuestionsController < ApplicationController
end
end
end
if @exercise_question.question_type == 4 #主观题
if @exercise_question.question_type == Exercise::SUBJECTIVE #主观题
main_standard_answer = standard_answer.present? ? standard_answer.first : nil
if @exercise_answers_array.present?
@exercise_answers_array.first.update_attribute("answer_text",main_standard_answer)
@ -338,7 +333,7 @@ class ExerciseQuestionsController < ApplicationController
question_standard_answer = ExerciseStandardAnswer.new(standard_option)
question_standard_answer.save
end
elsif @exercise_question.question_type == 5
elsif @exercise_question.question_type == Exercise::PRACTICAL
question_score = 0
shixun_name = params[:shixun_name] || @exercise_question.shixun_name
@exercise_question.exercise_shixun_challenges.each_with_index do |challenge, index|
@ -350,8 +345,9 @@ class ExerciseQuestionsController < ApplicationController
@exercise_question.shixun_name = shixun_name
end
#当标准答案修改时,如有已提交的学生,需重新计算分数
if st_count > 0
#当试卷已发布时(试卷的总状态),当标准答案修改时,如有已提交的学生,需重新计算分数.
if @exercise.exercise_status == Exercise::PUBLISHED
ex_users_committed = @exercise.exercise_users.exercise_user_committed
if ex_users_committed.size > 0
ex_users_committed.each do |ex_user|
@ -364,12 +360,7 @@ class ExerciseQuestionsController < ApplicationController
end
end
end
if @exercise_question.save
normal_status(0,"试卷更新成功!")
else
normal_status(-1,"试卷更新失败!")
end
normal_status(0,"试卷更新成功!")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
@ -384,24 +375,22 @@ class ExerciseQuestionsController < ApplicationController
begin
opr = params[:opr]
current_q_p = @exercise_question.question_number.to_i #问题的当前位置
# last_q_p = @exercise.exercise_questions.find_by_custom("question_number",(current_q_p - 1)).first # 当前问题的前一个问题
# next_q_p = @exercise.exercise_questions.find_by_custom("question_number",(current_q_p + 1)).first # 当前问题的后一个问题
last_q_p = @exercise.exercise_questions.last_exercise(current_q_p) # 当前问题的前一个问题
next_q_p = @exercise.exercise_questions.next_exercise(current_q_p) # 当前问题的后一个问题
if @exercise.exercise_status.to_i == 1
if @exercise.exercise_status.to_i == Exercise::UNPUBLISHED
if opr.present?
if opr.to_s == "up"
last_q_p = @exercise.exercise_questions.find_by(question_number: (current_q_p - 1)) # 当前问题的前一个问题
if last_q_p.present?
@exercise_question.update_attribute('question_number', (current_q_p - 1))
last_q_p.update_attribute('question_number', (@exercise_question.question_number.to_i + 1)) # 重新获取当前问题的位置
last_q_p.update_attribute('question_number', current_q_p) # 重新获取当前问题的位置
normal_status(0, "问题上移成功!")
else
normal_status(-1, "移动失败,已经是第一个问题了!")
end
elsif opr.to_s == "down"
next_q_p = @exercise.exercise_questions.find_by(question_number: (current_q_p + 1)) # 当前问题的前一个问题
if next_q_p.present?
@exercise_question.update_attribute('question_number', (current_q_p + 1))
next_q_p.update_attribute('question_number', (@exercise_question.question_number.to_i - 1))
next_q_p.update_attribute('question_number', current_q_p)
normal_status(0, "问题下移成功!")
else
normal_status(-1, "移动失败,已经是最后一个问题了!")
@ -426,14 +415,9 @@ class ExerciseQuestionsController < ApplicationController
begin
choice_d_id = params[:choice_no].to_i # 选项的当前位置
question_choices = @exercise_question.exercise_choices
delete_answer = question_choices.find_choice_custom("choice_position",choice_d_id).first
left_choice = question_choices.left_choice_choose("choice_position",choice_d_id)
if left_choice.present?
left_choice.each do |p|
p.choice_position -= 1
p.save
end
end
delete_answer = question_choices.find_by(choice_position: choice_d_id)
left_choices = question_choices.where("choice_position > ? ",choice_d_id)
left_choices.update_all("choice_position = choice_position - 1") if left_choices
if delete_answer.destroy
normal_status(0, "答案删除成功!")
else
@ -452,13 +436,8 @@ class ExerciseQuestionsController < ApplicationController
begin
question_d_id = @exercise_question.question_number.to_i #问题的当前位置
exercise_questions = @exercise.exercise_questions
left_question = exercise_questions.left_question_choose("question_number",question_d_id)
if left_question.present?
left_question.each do |q|
q.question_number -= 1
q.save
end
end
left_questions = exercise_questions.where("question_number > ?", question_d_id)
left_questions.update_all("question_number = question_number - 1") if left_questions
if @exercise_question.destroy
normal_status(0, "问题删除成功!")
else
@ -478,9 +457,9 @@ class ExerciseQuestionsController < ApplicationController
ex_obj_score = @exercise_current_user.objective_score #全部客观题得分
ex_subj_score = @exercise_current_user.subjective_score < 0.0 ? 0.0 : @exercise_current_user.subjective_score #全部主观题得分
ex_answers = @exercise_question.exercise_answers.search_answer_users("user_id",@user_id) #当前用户答案的得分
if @exercise_question.question_type == 3 #当为填空题,更新问题的总分,
if @exercise_question.question_type == Exercise::COMPLETION #当为填空题,更新问题的总分,
ex_answer_old = ex_answers.score_reviewed.pluck(:score).sum #每一关的得分总和
each_right_score = (@c_score / ex_answers.count.to_f).round(1) #调分后,平均每关的分数
each_right_score = (@c_score / ex_answers.count.to_f) #调分后,平均每关的分数
new_obj_score = ex_obj_score - ex_answer_old + @c_score
total_scores = new_obj_score + ex_subj_score
ex_scores = {
@ -489,8 +468,8 @@ class ExerciseQuestionsController < ApplicationController
}
@exercise_current_user.update_attributes(ex_scores)
ex_answers.update_all(:score => each_right_score) #所有的正确选项需重新更新
elsif @exercise_question.question_type == 4 #当为主观题时
if ex_answers.present?
elsif @exercise_question.question_type == Exercise::SUBJECTIVE #当为主观题时
if ex_answers.exists?
ex_answers_old_score = ex_answers.first.score > 0.0 ? ex_answers.first.score : 0.0 #原分数小于0取0
new_sub_score = ex_subj_score - ex_answers_old_score + @c_score #原全部主观题总分减去原该主观题得分再加调分后的分数,即为当前全部主观题得分
ex_answers.first.update_attribute("score",@c_score)
@ -502,7 +481,7 @@ class ExerciseQuestionsController < ApplicationController
:answer_text => ""
}
ExerciseAnswer.create(answer_option)
new_sub_score = @c_score
new_sub_score = ex_subj_score + @c_score
end
total_scores = ex_obj_score + new_sub_score
ex_scores = {
@ -511,8 +490,7 @@ class ExerciseQuestionsController < ApplicationController
}
@exercise_current_user.update_attributes(ex_scores)
elsif @exercise_question.question_type == 5
# ex_answers = @exercise_question.exercise_shixun_answers.search_shixun_answers("user_id",@user_id).search_shixun_answers("exercise_shixun_challenge_id",@shixun_a_id)
elsif @exercise_question.question_type == Exercise::PRACTICAL
ex_answers = @exercise_question.exercise_shixun_answers.where(user_id:@user_id,exercise_shixun_challenge_id:@shixun_a_id)
if ex_answers.present? #当为实训题时
@ -599,23 +577,23 @@ class ExerciseQuestionsController < ApplicationController
if @exercise_question.present?
@exercise = @exercise_question.exercise
if @exercise.blank?
tip_exception(404)
tip_exception(404,"试卷不存在")
else
@course = @exercise.course
if @course.blank?
tip_exception(404)
tip_exception(404,"课堂不存在")
end
end
else
tip_exception(404)
tip_exception(404,"试卷问题不存在")
end
end
def validate_params
normal_status(-1,"题目不允许为空!") if (params[:question_title].blank? && params[:question_type].to_i !=5 ) #除了实训题,其余题目必需有题干
normal_status(-1,"题目不允许为空!") if (params[:question_title].blank? && params[:question_type].to_i != Exercise::PRACTICAL ) #除了实训题,其余题目必需有题干
normal_status(-1,"问题类型不允许为空!" ) if params[:question_type].blank?
normal_status(-1,"分值不允许为空!" ) if params[:question_score].blank? && params[:question_scores].blank? #分值的数组或参数必需存在一个
if params[:question_score].present? && params[:question_score].to_f.round(1) <= 0.0 #问题类型存在,则分值不能为空,且必需大于0
if params[:question_score].present? && params[:question_score].to_f <= 0.0 #问题类型存在,则分值不能为空,且必需大于0
normal_status(-1,"分值必需大于0")
elsif (params[:question_score].present? && params[:question_score].to_f.round(1) > 100.0) || (params[:question_scores].present? && (params[:question_scores].map{|a| a.to_f.round(1)}.max > 100.0))
normal_status(-1,"分值不能超过100分")
@ -628,7 +606,7 @@ class ExerciseQuestionsController < ApplicationController
elsif params[:question_type].to_i == 2 && (params[:standard_answers].count > 1 || params[:question_choices].blank? || params[:question_choices].include?("")) #判断题的标准答案不能大于1个选项不能为空
normal_status(-1,"判断题选项不能为空/标准答案不能大于1个")
elsif params[:question_type].to_i <= 1 && (params[:question_choices].blank? || params[:question_choices].include?("") || params[:question_choices].count < 2) #选择题选项不能为空,且不能小于2
normal_status(-1,"选择题选项内容不能为空,且不能少于3个!")
normal_status(-1,"选择题选项内容不能为空,且不能少于2个!")
elsif params[:question_type].to_i == 3 && (params[:standard_answers].blank? || params[:standard_answers].count > 5 ) #填空题选项最多为5个,且如果为1个的话不允许修改is_ordered
normal_status(-1,"填空题标准答案不能为空/不能超过5个")
elsif params[:question_type].to_i == 4 && params[:standard_answers].count > 2 #简单题参考答案最多为1个
@ -643,16 +621,16 @@ class ExerciseQuestionsController < ApplicationController
end
def check_exercise_status
normal_status(-1,"不能更改试卷问题!") if @exercise.exercise_status != 1
normal_status(-1,"不能更改试卷问题!") if @exercise.exercise_status != Exercise::UNPUBLISHED
end
#更新时不能修改的内容
def cannot_change_column
#已发布的/已截止的/评阅中的状态时,不能修改分数,不能增删问题和答案,不能修改标准答案,可以修改选项内容/题目内容,这里仅指单个问题
if @exercise.exercise_status != 1
if @exercise.exercise_status != Exercise::UNPUBLISHED
question_score = @exercise_question.question_score #原来的分数
update_question_score = params[:question_score].to_f.round(1) #传入的分数
choices_count = @exercise_question.exercise_choices.count #原来的选项个数
choices_count = @exercise_question.exercise_choices.size #原来的选项个数
exercise_choice_ids = @exercise_question.exercise_standard_answers.pluck(:exercise_choice_id).uniq
standard_answers_text = @exercise_question.exercise_standard_answers.pluck(:answer_text).uniq
update_choices_count = params[:question_choices].present? ? params[:question_choices].count : choices_count #传入的选项个数
@ -662,12 +640,12 @@ class ExerciseQuestionsController < ApplicationController
elsif update_choices_count != choices_count #选项个数有修改
normal_status(-1,"已发布/已截止,不允许增删答案!")
elsif standard_answer.present?
if @exercise_question.question_type == 3
if @exercise_question.question_type == Exercise::COMPLETION
exercise_answers_text = standard_answer.map{|a| a[:answer_text]}.sum.uniq
unless (standard_answer.count == exercise_choice_ids.count) && (standard_answers_text.count == exercise_answers_text.count)
normal_status(-1,"已发布/已截止,不允许增删标准答案!")
end
elsif @exercise_question.question_type == 4
elsif @exercise_question.question_type == Exercise::SUBJECTIVE
unless standard_answers_text.count == standard_answer.count
normal_status(-1,"已发布/已截止,不允许增删标准答案!")
end
@ -677,20 +655,20 @@ class ExerciseQuestionsController < ApplicationController
end
def check_adjust_score
@c_score = params[:score].to_f.round(1) #调分后的分数
@c_score = params[:score].to_f #调分后的分数
@user_id = params[:user_id]
@exercise_current_user = @exercise.exercise_users.exercise_commit_users(@user_id).first #当前试卷用户的答案内容
if @exercise_current_user.blank?
normal_status(-1,"用户不存在!")
elsif @c_score.blank?
normal_status(-1,"分数不能为空!")
elsif @exercise_question.question_type <= 1 || @exercise_question.question_type == 2
elsif @exercise_question.question_type <= Exercise::JUDGMENT
normal_status(-1,"选择题/判断题不能调分!")
elsif params[:comment].present? && params[:comment].length > 100
normal_status(-1,"评语不能超过100个字符!")
else
@shixun_a_id = params[:shixun_challenge_id]
if @exercise_question.question_type == 5 #当为实训题时,为关卡的分数
if @exercise_question.question_type == Exercise::PRACTICAL #当为实训题时,为关卡的分数
@shixun_challenge = @exercise_question.exercise_shixun_challenges.cha_id_find(@shixun_a_id)
if @shixun_challenge.present?
@old_ques_score = @shixun_challenge.first.question_score

File diff suppressed because it is too large Load Diff

@ -1,9 +1,9 @@
class FilesController < ApplicationController
include MessagesHelper
before_action :require_login, except: %i[index]
before_action :require_login, :check_auth, except: %i[index]
before_action :find_course, except: %i[public_with_course_and_project mine_with_course_and_project]
before_action :find_ids, only: %i[bulk_delete bulk_send bulk_move bulk_public]
before_action :find_ids, only: %i[bulk_delete bulk_send bulk_move bulk_public bulk_publish]
before_action :file_validate_sort_type, only: :index
before_action :validate_send_message_to_course_params, only: :bulk_send
before_action :set_pagination, only: %i[index public_with_course_and_project mine_with_course_and_project]
@ -16,29 +16,36 @@ class FilesController < ApplicationController
sort = params[:sort] || 0 # 0: 降序1: 升序
sort_type = params[:sort_type] || 'created_on' # created_on时间排序 downloads下载次数排序; quotes: 引用次数排序
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
@user = current_user || nil
@attachments = @course.attachments.by_keywords(params[:search])
@user = current_user
@attachments = @course.attachments.by_course_second_category_id(course_second_category_id)
.includes(attachment_group_settings: :course_group, author: [:user_extension, :course_members])
.by_course_second_category_id(course_second_category_id)
.ordered(sort: sort.to_i, sort_type: sort_type.strip)
get_category(@course, course_second_category_id)
case @user.course_identity(@course)
when 5
# 课程学生
@attachments = @attachments.published
when 6 || 7
# 非课堂成员
@attachments = @attachments.publiced.published
end
get_category(@course, course_second_category_id)
@total_count = @attachments.size
@public_count = @attachments.publiced.size
@private_count = @total_count - @public_count
@publish_count = @attachments.published.size
@unpublish_count = @total_count - @publish_count
@attachments = @attachments.by_keywords(params[:search])
@attachments =
case @user.course_identity(@course)
when 5
@attachments.published
when 6, 7
@attachments.publiced.published
else
@attachments
end
@attachments = @attachments.page(@page).per(@page_size)
end
def bulk_publish
return normal_status(403, "您没有权限进行操作") if current_user.course_identity(@course) >= 5
@course.attachments.by_ids(@attachment_ids).unpublish.update_all(is_publish: 1, publish_time: Time.now)
render_ok
end
def bulk_delete
ActiveRecord::Base.transaction do
begin
@ -180,6 +187,8 @@ class FilesController < ApplicationController
attach_copied_obj.created_on = Time.now
attach_copied_obj.author = current_user
attach_copied_obj.is_public = 0
attach_copied_obj.is_publish = 1
attach_copied_obj.publish_time = Time.now
attach_copied_obj.course_second_category_id = course_second_category_id
attach_copied_obj.copy_from = ori.copy_from.nil? ? ori.id : ori.copy_from
if attach_copied_obj.attachtype == nil
@ -197,7 +206,7 @@ class FilesController < ApplicationController
# 资源设置
def update
return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_or_admin?(@course) || @file.author == current_user
return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@course) >= 5 && @file.author != current_user
is_unified_setting = params[:is_unified_setting]
publish_time = params[:publish_time]

@ -1,5 +1,5 @@
class GamesController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :find_game
before_action :find_shixun, only: [:show, :answer, :rep_content, :choose_build, :game_build, :game_status]
@ -33,27 +33,24 @@ class GamesController < ApplicationController
is_teacher = @user.is_teacher?
# 实训超时设置
time_limit = @shixun.exec_time
time_limit = game_challenge.exec_time
# 上一关、下一关
prev_game = @game.prev_of_current_game(@shixun.id, @game.myshixun_id, game_challenge.position)
next_game = @game.next_of_current_game(@shixun.id, @game.myshixun_id, game_challenge.position)
# 关卡点赞数, praise_or_tread = 1则表示赞过
praise_count = PraiseTread.where(praise_tread_object_id: game_challenge.id, praise_tread_object_type: "Challenge",
praise_or_tread: 1).count
user_praise = PraiseTread.where(praise_tread_object_id: game_challenge.id, praise_tread_object_type: "Challenge",
user_id: current_user.id, praise_or_tread: 1).present? ? true : false
praise_count = game_challenge.praises_count
user_praise = game_challenge.praise_treads.exists?(user_id:current_user.id, praise_or_tread: 1)
# 实训的最大评测次数,这个值是为了优化查询,每次只取最新的最新一次评测的结果集
max_query_index = @game.query_index.to_i
# 统计评测时间
record_onsume_time = EvaluateRecord.where(game_id: @game.id).first.try(:consume_time)
record_onsume_time = EvaluateRecord.where(game_id: @game.id).first.try(:pod_execute)
# power判断用户是否有权限查看隐藏测试集(TPM管理员平台认证的老师花费金币查看者)
# myshixun_manager
myshixun_manager = current_user.manager_of_shixun?(@shixun) || (current_user.is_teacher? && current_user.pro_certification?)
# myshixun_manager判断用户是否有权限查看隐藏测试集(TPM管理员平台认证的老师花费金币查看者)
myshixun_manager = @identity < User::EDU_GAME_MANAGER
# 选择题和编程题公共部分
@base_date = {st: @st, discusses_count: discusses_count, game_count: game_count, myshixun: @myshixun,
@ -62,10 +59,28 @@ class GamesController < ApplicationController
praise_count: praise_count, user_praise: user_praise, time_limit: time_limit,
tomcat_url: edu_setting('cloud_tomcat_php'), is_teacher: is_teacher,
myshixun_manager: myshixun_manager}
if @shixun.vnc
begin
shixun_tomcat = edu_setting('cloud_bridge')
service_host = edu_setting('vnc_url')
uri = "#{shixun_tomcat}/bridge/vnc/getvnc"
params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}"}
res = uri_post uri, params
if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级99")
end
# 无域名版本
#@vnc_url = "http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
# 有域名版本
@vnc_url = "https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
rescue Exception => e
Rails.logger.error(e.message)
end
end
# 区分选择题和编程题st0编程题
if @st == 0
has_answer = game_challenge.challenge_answers.size == 0 ? false : true
has_answer = game_challenge.challenge_answers.size != 0
game_challenge.answer = nil
mirror_name = @shixun.mirror_name
@ -75,7 +90,7 @@ class GamesController < ApplicationController
rescue
uid_logger("实训平台繁忙繁忙等级81")
end
tpm_cases_modified = (game_challenge.modify_time != @game.modify_time ? true : false) # modify_time 决定TPM测试集是否有更新
tpm_cases_modified = (game_challenge.modify_time != @game.modify_time) # modify_time 决定TPM测试集是否有更新
@task_result = {tpm_modified: tpm_modified, tpm_cases_modified: tpm_cases_modified, mirror_name: mirror_name, has_answer: has_answer}
@ -207,12 +222,12 @@ class GamesController < ApplicationController
@result = challenge.st == 0 ? challenge.try(:answer) : challenge.choose_answer
end
# 获取答案
# 获取实践题答案
# GET: /tasks/:identifier/get_answer_info
# 0 直接查看答案, 1 查看答案弹框, 2 答案详情弹框
def get_answer_info
challenge = @game.challenge
@challenge_answers = challenge.challenge_answers
@challenge = @game.challenge
@challenge_answers = @challenge.challenge_answers
# 平台已认证的老师需要控制
@power = (@identity < User::EDU_GAME_MANAGER)
if !@power
@ -229,16 +244,29 @@ class GamesController < ApplicationController
end
end
end
end
# 获取选择题答案
def get_choose_answer
@challenge = @game.challenge
tip_exception("本接口只能获取选择题答案") if @challenge.st != 1
@power = (@identity < User::EDU_GAME_MANAGER)
# 如果没权限,也没看过答案,则需要解锁
if @game.answer_open == 0 && !@power
tip_exception(1, @challenge.choose_score)
else
@challenge_chooses = @challenge.challenge_chooses
end
end
# 解锁答案
# 解锁实践题答案
# GET: /tasks/:identifier/get_answer_info?answer_id=?
def unlock_answer
@challenge = @game.challenge
@answer = ChallengeAnswer.find(params[:answer_id])
challenge = @answer.challenge
# 解锁需要本层级的答案是否需要扣分
points = challenge.challenge_answers.where(level: @game.answer_open+1..@answer.level).sum(:score)
points = challenge.challenge_answers.where(level: @game.answer_open + 1..@answer.level).sum(:score)
deduct_score = ((points / 100.0) * challenge.score).to_i
uid_logger("############金币数目: #{current_user.grade}")
unless current_user.grade.to_i - deduct_score > 0
@ -249,13 +277,16 @@ class GamesController < ApplicationController
begin
# 积分消耗情况记录
score = challenge.st.zero? ? -deduct_score : -challenge.choose_score.to_i
RewardGradeService.call(current_user, container_id: @answer.id, container_type: 'Answer', score: score)
RewardGradeService.call(current_user, container_id: @game.id, container_type: 'Answer', score: score)
# 通关查看答案 不扣 得分
answer_open = @challenge.st == 1 ? 1 : @answer.level
if @game.status == 2
@game.update_attributes!(:answer_open => @answer.level)
@game.update_attributes!(:answer_open =>answer_open)
else
@game.update_attributes!(:answer_open => @answer.level, :answer_deduction => deduct_score)
# 扣除总分计算
answer_deduction = challenge.challenge_answers.where("level <= #{@answer.level}").sum(:score)
@game.update_attributes!(:answer_open => answer_open, :answer_deduction => answer_deduction)
end
rescue Exception => e
@ -263,7 +294,32 @@ class GamesController < ApplicationController
raise ActiveRecord::Rollback
end
end
end
# 解锁选择题答案
def unlock_choose_answer
@challenge = @game.challenge
score = @challenge.choose_score
unless current_user.grade.to_i - score > 0
tip_exception("您没有足够的金币")
end
ActiveRecord::Base.transaction do
begin
# 积分消耗情况记录
RewardGradeService.call(current_user, container_id: @game.id, container_type: 'Answer', score: -score)
# 通关查看答案 不扣 得分
if @game.status == 2
@game.update_attributes!(:answer_open => 1)
else
# 扣除总分计算
@game.update_attributes!(:answer_open => 1, :answer_deduction => 100)
end
@challenge_chooses = @challenge.challenge_chooses
rescue Exception => e
uid_logger_error("#######金币扣除异常: #{e.message}")
raise ActiveRecord::Rollback
end
end
end
# 查看答案需要扣取金币
@ -327,11 +383,10 @@ class GamesController < ApplicationController
@game.update_attribute(:test_sets_view, true)
# 扣分记录
Grade.create(:user_id => current_user.id, :container_id => @game.id, :score => -@minus_grade, :container_type => "testSet")
@status = 0
@message = "解锁成功!"
max_query_index = @game.query_index.to_i
testset_detail max_query_index, challenge
else
@status = -1
@message = "本操作需要扣除#{ @minus_grade }金币,您的金币不够了"
tip_exception(-1, "本操作需要扣除#{ @minus_grade }金币,您的金币不够了")
end
end
@ -411,12 +466,12 @@ class GamesController < ApplicationController
game_code = GameCode.where(:game_id => @game.try(:id), :path => path).first
if game_code.present?
content = game_code.try(:new_code)
@content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && content.present?
content.gsub(/\t/, ' ')
else
content
end
update_file_content(@content, @myshixun.repo_path, path, current_user.mail, current_user.full_name, "game passed reset")
# @content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && content.present?
# content.gsub(/\t/, ' ')
# else
# content
# end
update_file_content(content, @myshixun.repo_path, path, current_user.mail, current_user.full_name, "game passed reset")
else
tip_exception("代码重置失败,代码为空")
end
@ -425,7 +480,7 @@ class GamesController < ApplicationController
# 获取版本库文件内容
# 注如果本身path传错内容肯定也为空fork成功后可能短时间内也获取不到版本库内容
# params[:status] 1: 目录树点击的请求 0正常自动加载
# 返回参数status -3 需要重试带retry参数-1 给出提示
# 返回参数status -1 系统统一报错提示;-3 需要轮训重试带retry参数-4 立即重试
def rep_content
challenge_path = @game.challenge.try(:path)
if challenge_path.blank?
@ -437,22 +492,19 @@ class GamesController < ApplicationController
path = path.try(:strip)
uid_logger("--rep_content: path is #{path}")
begin
@content = git_fle_content(@myshixun.repo_path, path) || ""
rescue
if params[:retry].present?
begin
begin
# 检测TPM对应的路径代码是否正常
git_fle_content(@myshixun.shixun.repo_path, path)
rescue Exception => e
uid_logger_error("#{e.message}")
if @myshixun.shixun.try(:status) < 2
tip_exception("代码获取异常,请检查实训模板的评测设置是否正确")
else
tip_exception("代码获取异常,请联系系统管理员")
end
end
if @myshixun.repo_name.nil?
g = Gitlab.client
repo_name = g.project(@myshixun.gpid).path_with_namespace
@myshixun.update_column(:repo_name, repo_name)
@content = git_fle_content("#{repo_name}.git", path) || ""
else
@content = git_fle_content(@myshixun.repo_path, path) || ""
end
rescue Exception => e
# 思路: 异常首先应该考虑去恢复
if params[:retry].to_i == 1
begin
# 如果模板没有问题,则通过中间层检测实训仓库是否异常
# 监测版本库HEAD是否存在不存在则取最新的HEAD
gitUrl = repo_url @myshixun.repo_path
@ -462,30 +514,41 @@ class GamesController < ApplicationController
# 监测版本库HEAD是否存在不存在则取最新的HEAD
uri = "#{shixun_tomcat}/bridge/game/check"
res = uri_post uri, rep_params
uid_logger("repo_content to bridge: res is #{res}")
# res值0 表示正常;-1表示有错误-2表示代码版本库没了
if status == 0 && res && (res['code'] == -2 || res['code'] == -1)
# 删除不需要的仓库
begin
GitService.delete_repository(repo_path: @myshixun.repo_path)
rescue Exception => e
uid_logger_error("#{e.message}")
#
if status == 0 && res
# 版本库报错,修复不了
if res['code'] == -1 || res['code'] == -2
begin
# GitService.delete_repository(repo_path: @myshixun.repo_path) if res['code'] == -1
project_fork(@myshixun, @shixun.repo_path, current_user.login)
rescue Exception => e
uid_logger_error("#{e.message}")
tip_exception("#{e.message}")
end
end
# fork一个新的仓库
project_fork(@myshixun, @shixun.repo_path, current_user.login)
end
rescue Exception => e
uid_logger_error(e.message)
# 报错继续retry
tip_exception(-3, "#{e.message}")
if @myshixun.shixun.try(:status) < 2
tip_exception("代码获取异常,请检查实训模板的评测设置是否正确")
else
# 报错继续retry
tip_exception(-3, "#{e.message}")
end
end
end
tip_exception(-3, "#{e.message}")
# 有异常版本库获取不到代码前端轮训30S后调用retry == 1
tip_exception(0, e.message)
end
end
# 编程题评测
def game_build
game_challenge = Challenge.select([:id, :position, :picture_path]).find(@game.challenge_id)
sec_key = params[:sec_key]
game_challenge = Challenge.select([:id, :position, :picture_path, :exec_time]).find(@game.challenge_id)
# 更新评测次数
@game.update_column(:evaluate_count, (@game.evaluate_count.to_i + 1))
@ -531,9 +594,9 @@ class GamesController < ApplicationController
br_params = {:tpiID => "#{@myshixun.id}", :tpiGitURL => "#{gitUrl}", :buildID => "#{@game.id}",
:instanceChallenge => "#{step}", :testCases => "#{testCases}", :resubmit => "#{resubmit}",
:times => params[:first].to_i, :podType => @shixun.webssh, :content_modified => content_modified,
:containers => "#{Base64.urlsafe_encode64(container_limit(@shixun.mirror_repositories))}",
:persistenceName => @shixun.identifier, :tpmScript => "#{tpmScript}",
:timeLimit => "#{@shixun.exec_time}", :isPublished => (@shixun.status < 2 ? 0 : 1) }
:containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}",
:persistenceName => @shixun.identifier, :tpmScript => "#{tpmScript}", :sec_key => sec_key,
:timeLimit => game_challenge.exec_time, :isPublished => (@shixun.status < 2 ? 0 : 1) }
# 评测有文件输出的需要特殊传字段 path表示文件存储的位置
br_params['file'] = Base64.urlsafe_encode64({path: "#{game_challenge.picture_path}"}.to_json) if game_challenge.picture_path.present?
@ -575,7 +638,7 @@ class GamesController < ApplicationController
# user_answer虽然是传的数组,但是可能存在多选择提的情况.
user_answer_tran = user_answer[index].size > 1 ? user_answer[index].split("").sort.join("") : user_answer[index]
standard_answer_tran = choose.standard_answer.size > 1 ? choose.standard_answer.split("").sort.join("") : choose.standard_answer
correct = (user_answer_tran == standard_answer_tran) ? true : false
correct = (user_answer_tran == standard_answer_tran)
if str.present?
str += ","
end
@ -597,13 +660,10 @@ class GamesController < ApplicationController
end
# 批量插入评测结果
uid_logger("choose_build")
uid_logger("#------------chooice score: #{score}")
sql = "INSERT INTO outputs (game_id, test_set_position, actual_output, result, query_index, created_at, updated_at) VALUES" + str
ActiveRecord::Base.connection.execute sql
had_done = @game.had_done
@myshixun.update_attribute(:status, 1) if had_done == 1
# 没通关或者查看了答案通关的时候经验为0
# 通关但是查看了答案评测的时候金币显示0避免用户以为重复扣除但是在关卡列表中金币显示负数
experience = 0
@ -613,7 +673,8 @@ class GamesController < ApplicationController
if had_passed && !@game.had_passed?
@game.update_attributes(:status => 2, :end_time => Time.now)
# TPM实训已发布并且没有查看答案
if @shixun.is_published? && !@game.answer_open
if @shixun.is_published? && @game.answer_open == 0
uid_logger("@@@@@@@@@@@@@@@@@chooice score: #{score}")
# 查看答案的时候处理final_scor和扣分记录
experience = score
reward_attrs = { container_id: @game.id, container_type: 'Game', score: score }
@ -622,6 +683,8 @@ class GamesController < ApplicationController
final_score = score
RewardExperienceService.call(@myshixun.owner, reward_attrs)
end
had_done = @game.had_done
@myshixun.update_attribute(:status, 1) if had_done == 1
end
grade = @myshixun.owner.try(:grade)
@ -660,6 +723,7 @@ class GamesController < ApplicationController
uid_logger("################params[:resubmit]: #{params[:resubmit]}")
uid_logger("################resubmit_identifier: #{resubmit_identifier}")
uid_logger("################time_out: #{params[:time_out]}")
sec_key = params[:sec_key]
if (params[:time_out] == "false") && ((params[:resubmit].blank? && @game.status == 1) || (params[:resubmit].present? &&
(params[:resubmit] != resubmit_identifier)))
# 代码评测的信息
@ -688,14 +752,14 @@ class GamesController < ApplicationController
end
else # 重新评测
# 如果满足前面的条件,进入此处只可能是结果已返回并存入了数据库
if params[:resubmit] == resubmit_identifier # 本次重新评测结果已经返回并存入数据库
if params[:resubmit] == resubmit_identifier # 本次重新评测结果已经返回并存入数据库
game_status = (@game.retry_status == 2 ? 2 : 0) # retry_status是判断重新评测的通关情况。2表示通关
end
end
# 实训的最大评测次数,这个值是为了优化查询,每次只取最新的最新一次评测的结果集
max_query_index = @game.query_index
#max_query_index = @game.outputs.first.try(:query_index)
# max_query_index = @game.outputs.first.try(:query_index)
# 区分评测过未评测过,未评测过按需求取数据
testset_detail max_query_index.to_i, game_challenge
@ -705,9 +769,10 @@ class GamesController < ApplicationController
web_route = game_challenge.try(:web_route)
mirror_name = @shixun.mirror_name
e_record = EvaluateRecord.where(:identifier => sec_key).first
# 轮询结束,更新评测统计耗时
if game_status == 0 || game_status == 2
e_record = EvaluateRecord.where(:game_id => @game.id).first
if e_record
front_js = format("%.3f", (Time.now.to_f - e_record.try(:updated_at).to_f)).to_f
consume_time = format("%.3f", (Time.now - e_record.created_at)).to_f
@ -715,9 +780,10 @@ class GamesController < ApplicationController
end
end
uid_logger("game is is #{@game.id}, record id is #{e_record.try(:id)}, time is**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
uid_logger("game is #{@game.id}, record id is #{e_record.try(:id)}, time is**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
# 记录前端总耗时
record_consume_time = EvaluateRecord.where(:game_id => @game.id).first.try(:consume_time)
record_consume_time = e_record.try(:pod_execute)
max_mem = e_record.try(:max_mem)
# 实训制作者当前拥有的金币
grade = User.where(:id => @game.user_id).pluck(:grade).first
@ -728,7 +794,7 @@ class GamesController < ApplicationController
@base_date = {grade: grade, gold: score, experience: experience, status: game_status, had_done: had_done,
position: game_challenge.position, port: port, record_consume_time: record_consume_time,
mirror_name: mirror_name, picture: picture, web_route: web_route, star: @game.star,
next_game: next_game, prev_game: prev_game}
next_game: next_game, prev_game: prev_game, max_mem: max_mem}
end
# 记录实训花费的时间
@ -796,11 +862,11 @@ class GamesController < ApplicationController
# 评测测试机封装
def testset_detail max_query_index, challenge
# 是否允许查看隐藏的测试集以前的power
@allowed_hidden_testset = @identity < User::EDU_GAME_MANAGER
@allowed_hidden_testset = @identity < User::EDU_GAME_MANAGER || @game.test_sets_view #解锁的用户
if max_query_index > 0
uid_logger("max_query_index is #{max_query_index} game id is #{@game.id}, challenge_id is #{challenge.id}")
@qurey_test_sets = TestSet.find_by_sql("SELECT o.code, o.actual_output, o.out_put, o.result, o.test_set_position,
@qurey_test_sets = TestSet.find_by_sql("SELECT o.code, o.actual_output, o.out_put, o.result, o.test_set_position, o.ts_time, o.ts_mem,
o.query_index, t.is_public, t.input, t.output, o.compile_success FROM outputs o, games g, challenges c,
test_sets t where g.id=#{@game.id} and c.id=#{challenge.id} and o.query_index=#{max_query_index}
and g.id = o.game_id and c.id= g.challenge_id and t.challenge_id = c.id and
@ -814,8 +880,9 @@ class GamesController < ApplicationController
end
@last_compile_output = @qurey_test_sets.first['out_put'].gsub(/\n/, '<br/>').gsub(/\t/, "&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;&nbsp\;") if @qurey_test_sets.first['out_put'].present?
else
# 没有评测过,第一次进来后的呈现方式
@qurey_test_sets = TestSet.find_by_sql("SELECT t.is_public, t.input, t.output, t.position
FROM test_sets t where t.challenge_id = #{challenge.id}")
FROM test_sets t where t.challenge_id = #{challenge.id}")
end
end
@ -849,7 +916,7 @@ class GamesController < ApplicationController
end
# actual_output为空表示暂时没有评测答题不允许查看
actual_output = output.try(:actual_output).try(:strip)
has_answer << choose.answer if choose.answer.present?
#has_answer << choose.answer if choose.answer.present?
# 标准答案处理,错误的不让用户查看,用-1替代
standard_answer = (actual_output.blank? || !output.try(:result)) ? -1 : choose.standard_answer
result = output.try(:result)
@ -860,7 +927,7 @@ class GamesController < ApplicationController
@chooses << sin_choose
test_sets << sin_test_set
end
@has_answer = has_answer.present?
@has_answer = true # 选择题永远都有答案
@choose_test_cases = {:had_submmit => had_submmit, :challenge_chooses_count => challenge_chooses_count,
:choose_correct_num => choose_correct_num, :test_sets => test_sets}
end

@ -1,10 +1,15 @@
class GitsController < ApplicationController
#供git-workhorse反向调用认证
# 说明:
# 以下Git认证只针对新版gitGitlab的Git认证不走该控制器
# 思路:
# 1、用户通过Git客户端推送代码的时候这个时候Git客户端肯定会强制用户输入邮箱的
# 2、通过web端版本库界面更新代码如果用户邮箱不存在则用系统备用邮箱
# 供 git-workhorse反向调用认证
def auth
# HTTP_AUTHORIZATION: "Basic 这里base64编码的的密码(user:passwd)"
logger.info("11111112222223333#{request.env["HTTP_AUTHORIZATION"]}")
#logger.info("#########-----request_env: #{request.env}")
logger.info("11111112222223333 HTTP_AUTHORIZATION: #{request.env["HTTP_AUTHORIZATION"]}")
# logger.info("#########-----request_env: #{request.env}")
# {"service"=>"git-receive-pack", "controller"=>"gits", "action"=>"auth",
# "url"=>"forge01/cermyt39.git/info/refs"}
#
@ -18,15 +23,16 @@ class GitsController < ApplicationController
input_password = username_password.split(":")[1].strip()
uid_logger("git start auth: input_username is #{input_username}")
# Git 超级权限用户
if input_username == gituser && input_password == gitpassword
if input_username.strip == gituser.strip && input_password.strip == gitpassword.strip
result = true
else
# 用户是否对对象拥有权限
system_user = User.find_by_login(input_username) || User.find_by_mail(input_username) || User.find_by_phone(input_username)
# 如果用户名密码错误
if !system_user.check_password?(input_password)
if system_user && !system_user.check_password?(input_password)
uid_logger_error("git start: password is wrong")
result = false
else
@ -43,12 +49,13 @@ class GitsController < ApplicationController
if system_user.present? && system_user.manager_of_shixun?(shixun)
result = true
else
logger.info("git411 start")
uid_logger_error("gituser is not shixun manager")
result = false
end
else
render :json => { :status => 404 }
result = false
uid_logger_error("shixun is not exist")
# result = false
result = true # 为了测试跳出
end
end
end

@ -1,5 +1,5 @@
class GraduationTasksController < ApplicationController
before_action :require_login, except: [:index]
before_action :require_login, :check_auth, except: [:index]
before_action :find_course, except: [:edit, :update, :settings, :update_settings, :tasks_list, :show, :show_comment]
before_action :find_task, only: [:edit, :update, :settings, :update_settings, :tasks_list, :show, :show_comment]
before_action :user_course_identity
@ -37,7 +37,7 @@ class GraduationTasksController < ApplicationController
@all_count = @course.graduation_tasks.size
@published_count = @course.graduation_tasks.where("publish_time <= '#{Time.now}'").size
@task_count = @tasks.size
@tasks = @tasks.reorder("#{default_order}").page(page).per(15).includes(:graduation_works, course: [course_members: :teacher_course_groups])
@tasks = @tasks.reorder("#{default_order}").page(page).per(15).includes(:graduation_works)
end
# 任务问答
@ -55,30 +55,33 @@ class GraduationTasksController < ApplicationController
page = params[:page] || 1
limit = params[:limit] || 20
@work = @task.graduation_works.where(user_id: current_user.id)
@students = @course.students
@assign_power = @user_course_identity < Course::STUDENT && @task.cross_comment && @task.comment_status == 2
#end_time @task.allow_late ? @task.late_time : @task.end_time
# 任务发布的情况下: 是老师身份或者任务已截止的情况下公开任务了作品设置的学生也能查看其他人的作品
if @task.published? && (@user_course_identity < Course::STUDENT ||
(@user_course_identity == Course::STUDENT && @work.present? && @work.take.work_status > 0 &&
@task.status > 1 && @task.open_work))
((!@task.allow_late && @task.status > 1) || (@task.allow_late && @task.late_time && @task.late_time < Time.now)) &&
(@task.open_work || @task.open_score)))
# 如有有分班则看分班内的学生,否则看所有学生的作品
user_ids =
if @user_course_identity < Course::STUDENT
@course.teacher_group_user_ids(current_user.id)
else
course_group_id = @course.course_member(current_user.id).course_group_id
@course.course_members.where(course_group_id: course_group_id).pluck(:user_id)
@course.students.where(course_group_id: course_group_id).pluck(:user_id)
end
@work_list = @task.graduation_works.where(user_id: user_ids).includes(user: [:user_extension])
@all_work_count = @work_list.count
@teachers = @course.teachers
@teachers = @course.teachers.where.not(user_id: current_user.id).includes(:user)
# 教师评阅搜索 0: 未评, 1 已评
unless params[:teacher_comment].blank?
graduation_work_ids = GraduationWorkScore.where(graduation_work_id: @work_list.map(&:id)).pluck(:graduation_work_id)
if params[:teacher_comment] == 0
@work_list = @work_list.where.not(id: graduation_work_ids)
elsif params[:teacher_comment] == 1
@work_list = @work_list.where(id: graduation_work_ids).where.not(work_status: 0)
if params[:teacher_comment].to_i == 0
@work_list = @work_list.where("work_status != 0")
elsif params[:teacher_comment].to_i == 1
@work_list = @work_list.where("work_status != 0").where(id: graduation_work_ids)
end
end
@ -89,7 +92,7 @@ class GraduationTasksController < ApplicationController
# 分班情况
unless params[:course_group].blank?
group_user_ids = @course.course_members.where(course_group_id: params[:course_group]).pluck(:user_id)
group_user_ids = @course.students.where(course_group_id: params[:course_group]).pluck(:user_id)
# 有分组只可能是老师身份查看列表
@work_list = @work_list.where(user_id: group_user_ids)
end
@ -98,7 +101,7 @@ class GraduationTasksController < ApplicationController
unless params[:cross_comment].blank?
graduation_work_id = @task.graduation_work_comment_assignations.where(:user_id =>current_user.id)
.pluck(:graduation_work_id).uniq if @task.graduation_work_comment_assignations
@work_list = @work_list.where(id: graduation_work_id)
@work_list = @task.graduation_works.where(id: graduation_work_id)
end
# 输入姓名和学号搜索
@ -109,57 +112,61 @@ class GraduationTasksController < ApplicationController
end
# 排序
rorder = params[:order] || "updated_at"
b_order = params[:b_order] || "desc"
if rorder == "created_at" || rorder == "work_score"
rorder = params[:order].blank? ? "update_time" : params[:order]
b_order = params[:b_order].blank? ? "desc" : params[:b_order]
if rorder == "update_time" || rorder == "work_score"
@work_list = @work_list.order("graduation_works.#{rorder} #{b_order}")
elsif rorder == "student_id"
@work_list = @work_list.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}")
end
@view_work = @task.open_work || @user_course_identity < Course::STUDENT
@work_count = @work_list.count
@work_excel = @work_list
@work_list = @work_list.page(page).limit(limit)
respond_to do |format|
format.json
format.xlsx{
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
else
graduation_work_to_xlsx(@work_excel,@task,current_user)
exercise_export_name = current_user.real_name + "_" + @course.name + "_" + @task.name + "_" + Time.now.strftime('%Y%m%d_%H%M%S')
render xlsx: "#{exercise_export_name.strip.first(30)}",template: "graduation_tasks/tasks_list.xlsx.axlsx",locals: {table_columns:@head_cells_column, task_users:@task_cells_column}
@work_list = @work_list.page(page).per(limit)
if params[:format] == "xlsx"
complete_works = @work_excel.where("work_status > 0").size
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
elsif complete_works == 0
normal_status(-1,"暂无用户提交")
else
respond_to do |format|
format.xlsx{
graduation_work_to_xlsx(@work_excel,@task,current_user)
task_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@task.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{task_export_name_.strip.first(30)}",template: "graduation_tasks/tasks_list.xlsx.axlsx",locals: {table_columns:@head_cells_column, task_users:@task_cells_column}
}
end
}
format.zip{
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
else
zip_works = @work_excel.where("work_status > 0")
status = checkfileSize(zip_works)
if status == 0
zipfile = zip_homework_common @task, zip_works
file = decode64(zipfile[0][:base64file])
send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
else
tip_exception(status == -1 ? "文件大小超过500M请通过微信或者QQ联系管理员辅助您打包下载" : "无附件可下载")
end
elsif params[:format] == "zip"
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
else
zip_works = @work_excel.where("work_status > 0")
status = checkfileSize(zip_works)
if status == 0
respond_to do |format|
format.zip{
zipfile = zip_homework_common @task, zip_works
file = decode64(zipfile[0][:base64file])
send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
}
end
else
normal_status(status,status == -2 ? "500M" : "无附件可下载")
end
}
end
end
else
@work_list = @work
@view_work = false
@work_count = @work_list.count
@all_work_count = @work_list.count
respond_to do |format|
format.json
format.xlsx{
normal_status(-1,"作业未发布")
}
format.zip{
normal_status(-1,"作业未发布")
}
if params[:format] == "xlsx" || params[:format] == "zip"
normal_status(-1,"毕设任务未发布")
end
end
end

@ -1,9 +1,9 @@
class GraduationTopicsController < ApplicationController
before_action :require_login, except: [:index]
before_action :require_login, :check_auth, except: [:index]
before_action :find_course
before_action :teacher_allowed, only: [:new, :create, :update, :edit, :destroys, :set_public,
:refuse_student_topic, :accept_student_topic, :export]
before_action :find_graduation_topic, except: [:index, :create, :new, :set_public, :destroys, :export]
before_action :find_graduation_topic, except: [:index, :create, :new, :set_public, :destroys, :export, :add_to_bank]
before_action :find_course_teachers, only: [:new, :edit]
before_action :user_course_identity, only: [:index, :show, :show_detail, :show_comment]
@ -24,9 +24,7 @@ class GraduationTopicsController < ApplicationController
end
# 当前用户是否已经选过题
# @user_selected = StudentGraduationTopic.where(graduation_topic_id: @graduation_topic, user_id: current_user.id).count > 0
user_graduation_topics = @course.student_graduation_topics.where(user_id: current_user.id, status: [0, 1], graduation_topic_id: @graduation_topic.pluck(:id)) #6.12 -hs
@user_selected = user_graduation_topics.size > 0
@user_selected = @course.student_graduation_topics.where(user_id: current_user.id, status: [0, 1]).count > 0 #6.12 -hs
## 分页参数
page = params[:page] || 1
limit = params[:limit] || 15
@ -45,16 +43,9 @@ class GraduationTopicsController < ApplicationController
end
## 分页参数
@current_user = current_user
course_group_ids = @course.course_members.where(user_id: current_user.id, role: [1,2,3]).pluck(:course_group_id).uniq
#6.11 -hs
if course_group_ids.present?
if course_group_ids.include?(0)
course_group_ids = @course.course_groups.pluck(:id)
end
end
@group_list = CourseGroup.where(id: course_group_ids)
user_graduation_topics = @course.student_graduation_topics.where(user_id: current_user.id,
status: [0, 1])
@user_selected = user_graduation_topics.size > 0
page = params[:page] || 1
limit = params[:limit] || 50
@users_count = @student_graduation_topics.try(:count).to_i
@ -181,7 +172,7 @@ class GraduationTopicsController < ApplicationController
member = @course.course_members.where(:user_id => @graduation_topic.tea_id).first
tip_exception("分班名称不能为空") if params[:course_group_name].blank?
course_group = CourseGroup.create(:name => params[:course_group_name], :course_id => @course.id)
teacher_group = TeacherCourseGroup.create(:course_id => @course.id, :member_id => member.try(:id),
teacher_group = TeacherCourseGroup.create(:course_id => @course.id, :course_member_id => member.try(:id),
:user_id => @graduation_topic.tea_id,
:course_group_id => course_group.try(:id))
end
@ -202,8 +193,8 @@ class GraduationTopicsController < ApplicationController
def student_select_topic
user_unaccept_topics = @course.student_graduation_topics.where(user_id: current_user.id, status: [0, 1])
if user_unaccept_topics.size == 0
member_id = @course.course_members.find_by_user_id(current_user.id)
StudentGraduationTopic.create(course_id: @course.id, user_id: current_user.id, member_id: member_id,
member = @course.course_members.find_by_user_id(current_user.id)
StudentGraduationTopic.create(course_id: @course.id, user_id: current_user.id, course_member_id: member.try(:id),
graduation_topic_id: @graduation_topic.id)
@graduation_topic.update_attribute(:status, 1)
normal_status("选题成功")
@ -231,7 +222,7 @@ class GraduationTopicsController < ApplicationController
# 已加入的更新,未加入的新建
if topic_bank.present?
topic_bank.update_attributes(name: topic, description: topic.description,
topic_bank.update_attributes(name: topic.name, description: topic.description,
topic_source: topic.topic_source,
topic_property_first: topic.topic_property_first,
topic_property_second: topic.topic_property_second,
@ -242,7 +233,7 @@ class GraduationTopicsController < ApplicationController
course_list_id: @course.course_list_id)
topic_bank.attachments.destroy_all
else
topic_bank = GtopicBank.new(name: topic, description: topic.description,
topic_bank = GtopicBank.new(name: topic.name, description: topic.description,
topic_source: topic.topic_source,
topic_property_first: topic.topic_property_first,
topic_property_second: topic.topic_property_second,
@ -275,11 +266,16 @@ class GraduationTopicsController < ApplicationController
# 导出功能
def export
course = @course
students = course.students.joins(user: :user_extension).order("user_extensions.student_id")
graduation_topic_to_xlsx(students,course)
exercise_export_name = current_user.real_name + "_" + course.name + "_毕设选题" + "_" + Time.now.strftime('%Y%m%d_%H%M%S')
render xlsx: "#{exercise_export_name.strip.first(30)}",template: "graduation_topics/export.xlsx.axlsx",locals: {table_columns:@topic_head_cells,topic_users:@topic_body_cells}
begin
course = @course
students = course.students.joins(user: :user_extension).order("user_extensions.student_id")
graduation_topic_to_xlsx(students,course)
topic_export_name_ = "#{current_user.real_name}_#{course.name}_毕设选题_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{topic_export_name_.strip.first(30)}",template: "graduation_topics/export.xlsx.axlsx",locals: {table_columns:@topic_head_cells,topic_users:@topic_body_cells}
rescue Exception => e
uid_logger(e.message)
missing_template
end
end
private

@ -1,5 +1,5 @@
class GraduationWorksController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :find_task, only: [:new, :create, :search_member_list, :check_project, :relate_project,
:cancel_relate_project]
before_action :find_work, only: [:show, :edit, :update, :revise_attachment, :supply_attachments, :comment_list,
@ -13,6 +13,7 @@ class GraduationWorksController < ApplicationController
before_action :published_task, only: [:new, :create, :edit, :update, :search_member_list, :relate_project,
:cancel_relate_project, :revise_attachment]
before_action :edit_duration, only: [:edit, :update]
before_action :open_work, only: [:show, :supply_attachments, :comment_list]
def new
if @task.task_type == 2 && @task.base_on_project
@ -432,11 +433,11 @@ class GraduationWorksController < ApplicationController
# 交叉评阅分配老师
def assign_teacher
tip_exception(-1, "user_id不能为空") if params[:user_id].nil?
@work_assign_teacher = @work.graduation_work_comment_assignations.first
@work_assign_teacher = @work.graduation_work_comment_assignations.find_by(user_id: params[:user_id])
if @work_assign_teacher
if @work_assign_teacher.present?
# graduation_group_id: 已经是答辩组的需要 将答辩组清空
@work_assign_teacher.update_attributes(user_id: params[:user_id], graduation_group_id: 0)
@work_assign_teacher.update_attributes(graduation_group_id: 0)
else
@work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new(graduation_task_id: @task.id,
user_id: params[:user_id],
@ -489,6 +490,11 @@ class GraduationWorksController < ApplicationController
tip_exception("已过了修改时间") if @task.end_time && @task.end_time < Time.now
end
# 作品是否公开
def open_work
tip_exception(403,"没有操作权限") unless (@user_course_identity < Course::STUDENT || current_user == @work.user || @task.open_work)
end
def update_check work
tip_exception("作品描述不能为空") if params[:description].blank?
if @task.task_type == 2

@ -3,16 +3,17 @@ class HomeworkCommonsController < ApplicationController
include ApplicationHelper
include ExportHelper
before_action :require_login, except: [:index, :choose_category]
before_action :require_login, :check_auth, except: [:index, :choose_category]
before_action :find_course, only: [:index, :create, :new, :shixuns, :subjects, :create_shixun_homework, :publish_homework,
:end_homework, :set_public, :choose_category, :move_to_category, :choose_category,
:create_subject_homework, :multi_destroy, :add_to_homework_bank]
before_action :find_homework, only: [:edit, :show, :update, :group_list, :homework_code_repeat, :code_review_results,
:code_review_detail, :show_comment, :settings, :works_list, :update_settings,
:reference_answer, :publish_groups, :end_groups, :alter_name, :update_explanation]
:reference_answer, :publish_groups, :end_groups, :alter_name, :update_explanation,
:update_score, :update_student_score]
before_action :user_course_identity
before_action :homework_publish, only: [:show, :works_list, :code_review_results, :show_comment, :settings, :reference_answer]
before_action :homework_publish, only: [:show, :works_list, :code_review_results, :show_comment, :settings, :reference_answer, :update_student_score]
before_action :teacher_allowed, only: [:new, :edit, :create, :update, :shixuns, :subjects, :create_shixun_homework,
:publish_homework, :end_homework, :set_public, :choose_category, :move_to_category,
:choose_category, :create_subject_homework, :multi_destroy, :group_list, :homework_code_repeat,
@ -81,23 +82,17 @@ class HomeworkCommonsController < ApplicationController
end
@homework_commons = @homework_commons.joins(:homework_detail_manual).where(sql_str)
end
@homework_commons = @homework_commons.order("IF(ISNULL(homework_commons.publish_time),0,1), homework_commons.publish_time DESC,
homework_commons.created_at DESC")
@task_count = @homework_commons.size
@homework_commons = @homework_commons.page(page).per(15)
@homework_commons = @homework_commons.order("IF(ISNULL(homework_commons.publish_time),0,1), homework_commons.publish_time DESC,
homework_commons.created_at DESC").page(page).per(15)
if @homework_type == 4
if @user_course_identity == Course::STUDENT
@homework_commons = @homework_commons.includes(:homework_detail_manual, :homework_group_settings, :shixuns,
student_works: [myshixun: [:games]])
else
@homework_commons = @homework_commons.includes(:homework_detail_manual, :homework_group_settings, :shixuns, :student_works)
end
@homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings, :shixuns)
elsif @homework_type == 3
@homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings, :homework_detail_group)
else
@homework_commons = @homework_commons.includes(:homework_detail_manual, :homework_group_settings, :homework_detail_group,
:student_works)
@homework_commons = @homework_commons.includes(:homework_detail_manual, :published_settings)
end
end
@ -108,45 +103,43 @@ class HomeworkCommonsController < ApplicationController
@shixun = @homework.shixuns.take if @homework.homework_type == "practice"
student_works = @homework.all_works
@all_member_count = student_works.count
if @homework.publish_time.nil? || @homework.publish_time > Time.now
@all_member_count = student_works.size
if @homework.publish_time.blank? || (@homework.publish_time > Time.now)
@student_works = []
respond_to do |format|
format.json
format.xlsx{
normal_status(-1,"作业未发布")
}
format.zip{
normal_status(-1,"作业未发布")
}
if (params[:format] == "xlsx") || (params[:format] == "zip")
normal_status(-1,"作业未发布")
end
else
if @user_course_identity == Course::STUDENT
@work = @homework.user_work(current_user.id)
# 学生已提交作品且补交(提交)已截止、作品公开、非匿评阶段
if @work.work_status > 0 && @homework.work_public &&
((!@homework.anonymous_comment && @homework.end_or_late) || @homework_detail_manual.comment_status > 4)
@student_works = student_works.where("user_id != #{@work.id}")
if @work&.work_status.to_i > 0 && (@homework.work_public || @homework.score_open) &&
((!@homework.anonymous_comment && @homework.end_or_late) || (@homework_detail_manual.comment_status > 4 && @homework.end_or_late))
@student_works = student_works.where("user_id != #{@work.user_id}")
# 匿评、申诉阶段只能看到分配给自己的匿评作品
elsif @work.work_status > 0 && @homework.anonymous_comment && @homework_detail_manual.comment_status > 2
elsif @work&.work_status.to_i > 0 && @homework.anonymous_comment && @homework_detail_manual.comment_status > 2 && @homework_detail_manual.comment_status <= 4
@is_evaluation = true
@student_works = student_works.joins(:student_works_evaluation_distributions).where(
"student_works_evaluation_distributions.user_id = #{@current_user.id}")
else
@student_works = []
end
@score_open = @homework.score_open && @work&.work_status.to_i > 0
elsif @user_course_identity < Course::STUDENT
@student_works = @homework.teacher_works(@current_user.id)
@all_member_count = @student_works.count
@student_works = @homework.teacher_works(@member)
@all_member_count = @student_works.size
@score_open = true
elsif @user_course_identity > Course::STUDENT && @homework.work_public
@student_works = student_works
@score_open = false
else
@student_works = []
end
unless @student_works.size == 0
if @student_works.size > 0
# 教师评阅搜索 0: 未评, 1 已评
unless params[:teacher_comment].blank?
student_work_ids = StudentWorksScore.where(student_work_id: @student_works.map(&:id)).pluck(:student_work_id)
@ -176,55 +169,121 @@ class HomeworkCommonsController < ApplicationController
or student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
@work_count = @student_works.size
@work_excel = @student_works.where("work_status > 0")
# 排序
rorder = params[:order] || "update_time"
b_order = params[:b_order] || "desc"
rorder = params[:order].blank? ? "update_time" : params[:order]
b_order = params[:b_order].blank? ? "desc" : params[:b_order]
if rorder == "update_time" || rorder == "work_score"
@student_works = @student_works.order("student_works.#{rorder} #{b_order}")
elsif rorder == "student_id"
@student_works = @student_works.joins(user: :user_extension).order("user_extensions.#{rorder} #{b_order}")
end
@work_count = @student_works.size
@work_excel = @student_works
# 分页参数
page = params[:page] || 1
limit = params[:limit] || 20
@student_works = @student_works.page(page).per(limit).includes(:student_works_scores)
@student_works = @student_works.page(page).per(limit)
@students = @course.students.where(user_id: @student_works.pluck(:user_id)).preload(:course_group)
if @homework.homework_type == "practice"
@student_works = @student_works.includes(user: :user_extension, myshixun: :games)
@student_works = @student_works.includes(:student_works_scores, user: :user_extension, myshixun: :games)
else
@student_works = @student_works.includes(:student_works_scores, :project, user: :user_extension)
end
end
respond_to do |format|
format.json
format.xlsx{
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
else
student_work_to_xlsx(@work_excel,@homework)
exercise_export_name = current_user.real_name + "_" + @course.name + "_" + @homework.name + "_" + Time.now.strftime('%Y%m%d_%H%M%S')
render xlsx: "#{exercise_export_name.strip.first(30)}",template: "homework_commons/works_list.xlsx.axlsx",locals:
{table_columns: @work_head_cells,task_users: @work_cells_column}
if params[:format] == "xlsx"
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
elsif @work_excel.blank? || @work_excel.size == 0
normal_status(-1,"暂无用户提交!")
else
respond_to do |format|
format.xlsx{
student_work_to_xlsx(@work_excel,@homework)
exercise_export_name = "#{current_user.real_name}_#{@course.name}_#{@homework.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{exercise_export_name.strip.first(30)}",template: "homework_commons/works_list.xlsx.axlsx",locals:
{table_columns: @work_head_cells,task_users: @work_cells_column}
}
end
}
format.zip{
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
else
zip_works = @work_excel.where("work_status > 0")
end
elsif params[:format] == "zip"
if @user_course_identity >= Course::STUDENT
tip_exception(403, "无权限操作")
else
if @work_excel.present?
zip_works = @work_excel&.where("work_status > 0")
status = checkfileSize(zip_works)
if status == 0
zipfile = zip_homework_common @homework, zip_works
file = decode64(zipfile[0][:base64file])
send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
else
tip_exception(status == -1 ? "文件大小超过500M请通过微信或者QQ联系管理员辅助您打包下载" : "无附件可下载")
else
status = -1
end
if status == 0
respond_to do |format|
format.zip{
zipfile = zip_homework_common @homework, zip_works
file = decode64(zipfile[0][:base64file])
send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
}
end
else
normal_status(status, status == -2 ? "500M" : "无附件可下载")
end
}
end
end
end
end
def update_score
tip_exception("作业还未发布,暂不能计算成绩") if @homework.publish_time.nil? || @homework.publish_time > Time.now
begin
if @homework.unified_setting
student_works = @homework.student_works
user_ids = @course.students.pluck(:user_id)
else
user_ids = @course.students.where(course_group_id: @homework.published_settings.pluck(:course_group_id)).pluck(:user_id)
student_works = @homework.student_works.where(user_id: user_ids)
end
myshixuns = Myshixun.where(shixun_id: @homework.homework_commons_shixun&.shixun_id, user_id: user_ids).
includes(:games).where(games: {challenge_id: @homework.homework_challenge_settings.pluck(:challenge_id)})
challenge_settings = @homework.homework_challenge_settings
myshixuns.find_each(batch_size: 100) do |myshixun|
work = student_works.select{|work| work.user_id == myshixun.user_id}.first
if work && myshixun
games = myshixun.games.where(challenge_id: challenge_settings.pluck(:challenge_id))
HomeworksService.new.update_myshixun_work_score work, myshixun, games, @homework, challenge_settings
end
end
HomeworksService.new.update_student_eff_score @homework if (@homework.allow_late && @homework.late_time < Time.now) ||
(!@homework.allow_late && @homework.end_time < Time.now)
@homework.update_attribute('calculation_time', Time.now)
normal_status("更新成功")
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
def update_student_score
work = @homework.student_works.find_by(user_id: current_user.id)
myshixun = Myshixun.find_by(shixun_id: params[:shixun_id], user_id: current_user.id)
ActiveRecord::Base.transaction do
begin
if work && myshixun
challenge_settings = @homework.homework_challenge_settings
games = myshixun.games.where(challenge_id: challenge_settings.pluck(:challenge_id))
HomeworksService.new.update_myshixun_work_score work, myshixun, games, @homework, challenge_settings
normal_status("更新成功")
else
normal_status("还开启挑战,暂不能更新成绩")
end
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
end
@ -347,10 +406,8 @@ class HomeworkCommonsController < ApplicationController
homework_detail_group = @homework.homework_detail_group
param_min = params[:min_num].to_i
param_max = params[:max_num].to_i
homework_detail_group.min_num = @homework.has_commit_work ? (param_min > homework_detail_group.min_num ? homework_detail_group.min_num :
param_min) : param_min
homework_detail_group.max_num = @homework.has_commit_work ? (param_max < homework_detail_group.max_num ? homework_detail_group.max_num :
param_max) : param_max
homework_detail_group.min_num = @homework.has_commit_work ? [param_min, homework_detail_group.min_num].min : param_min
homework_detail_group.max_num = @homework.has_commit_work ? [param_max, homework_detail_group.max_num].max : param_max
homework_detail_group.base_on_project = params[:base_on_project] unless @homework.has_relate_project
homework_detail_group.save!
end
@ -387,7 +444,7 @@ class HomeworkCommonsController < ApplicationController
tip_exception("发布时间不能早于当前时间") if params[:publish_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= Time.now.strftime("%Y-%m-%d %H:%M:%S")
tip_exception("截止时间不能早于发布时间") if params[:publish_time] > params[:end_time]
tip_exception("截止时间不能于课堂结束时间") if @course.end_date.present? && params[:end_time] > @course.end_date.end_of_day
tip_exception("截止时间不能于课堂结束时间") if @course.end_date.present? && params[:end_time] > @course.end_date.end_of_day
@homework.unified_setting = 1
@homework.homework_group_settings.destroy_all
@ -409,7 +466,7 @@ class HomeworkCommonsController < ApplicationController
tip_exception("发布时间不能早于当前时间") if setting[:publish_time] <= strf_time(Time.now)
tip_exception("截止时间不能早于当前时间") if setting[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能早于发布时间") if setting[:publish_time] > setting[:end_time]
tip_exception("截止时间不能于课堂结束时间") if @course.end_date.present? && setting[:end_time] > @course.end_date.end_of_day
tip_exception("截止时间不能于课堂结束时间") if @course.end_date.present? && setting[:end_time] > @course.end_date.end_of_day
publish_time = setting[:publish_time] == "" ? Time.now : setting[:publish_time]
@ -443,7 +500,7 @@ class HomeworkCommonsController < ApplicationController
if @homework.end_time > Time.now && @homework.unified_setting
tip_exception("截止时间不能为空") if params[:end_time].blank?
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
tip_exception("截止时间不能于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
@homework.end_time = params[:end_time]
@ -457,11 +514,11 @@ class HomeworkCommonsController < ApplicationController
tip_exception("发布时间不能为空") if setting[:publish_time].blank?
tip_exception("截止时间不能为空") if setting[:end_time].blank?
# 如果该发布规则 没有已发布的分班则需判断发布时间
tip_exception("发布时间不能早于当前时间") if setting[:publish_time] <= strf_time(Time.now) && group_settings.group_published.count == 0
tip_exception("发布时间不能早于等于当前时间") if setting[:publish_time] <= strf_time(Time.now) && group_settings.group_published.count == 0
tip_exception("截止时间不能早于当前时间") if setting[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能早于等于当前时间") if setting[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能早于发布时间") if setting[:publish_time] > setting[:end_time]
tip_exception("截止时间不能于课堂结束时间") if setting[:end_time] > strf_time(@course.end_date.end_of_day)
tip_exception("截止时间不能于课堂结束时间") if @course.end_date.present? && setting[:end_time] > strf_time(@course.end_date.end_of_day)
group_settings.none_published.update_all(publish_time: setting[:publish_time])
group_settings.none_end.update_all(end_time: setting[:end_time])
@ -529,7 +586,7 @@ class HomeworkCommonsController < ApplicationController
if setting && setting.score != score
score_change = true
setting.update_attributes(score: score)
else
elsif setting.blank?
score_change = true
HomeworkChallengeSetting.create!(homework_common_id: @homework.id, challenge_id: challenge[:challenge_id],
shixun_id: @homework.homework_commons_shixun.try(:shixun_id), score: score)
@ -547,14 +604,14 @@ class HomeworkCommonsController < ApplicationController
@homework.score_open = params[:score_open]
@homework.save!
if score_change
@homework.student_works.has_committed.each do |student_work|
HomeworksService.new.set_shixun_final_score student_work
end
end
# if score_change
# @homework.student_works.has_committed.each do |student_work|
# HomeworksService.new.set_shixun_final_score student_work
# end
# end
# 更新所有学生的效率分(作业允许补交且补交已截止 或者 作业不允许补交且提交已截止)
if (score_change || update_eff_score) && @homework.end_or_late
if update_eff_score && @homework.end_or_late_none_group
HomeworksService.new.update_student_eff_score HomeworkCommon.find_by(id: @homework.id)
end
@ -584,9 +641,9 @@ class HomeworkCommonsController < ApplicationController
# anonymous_comment :true 是启用false 是不启用
if params[:anonymous_comment]
tip_exception("匿评开启时间不能为空") if params[:evaluation_start].blank?
tip_exception("匿评开启时间不能早于截止时间") if params[:evaluation_start] <= strf_time(@homework.end_time)
tip_exception("匿评开启时间不能早于截止时间") if params[:evaluation_start] < strf_time(@homework.end_time)
tip_exception("匿评结束时间不能为空") if params[:evaluation_end].blank?
tip_exception("匿评截止时间不能早于匿评开启时间") if params[:evaluation_end] <= params[:evaluation_start]
tip_exception("匿评截止时间必须晚于匿评开启时间") if params[:evaluation_end] <= params[:evaluation_start]
tip_exception("匿评截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:evaluation_end] >
strf_time(@course.end_date.end_of_day)
tip_exception("匿评数必须为正整数") if params[:evaluation_num].blank? || params[:evaluation_num].to_i < 1
@ -613,8 +670,8 @@ class HomeworkCommonsController < ApplicationController
# 匿评未截止时可以更新匿评结束时间
if @homework_detail_manual.comment_status < 4
tip_exception("匿评结束时间不能为空") if @homework.anonymous_comment && params[:evaluation_end].blank?
tip_exception("匿评截止时间不能早于匿评开启时间") if @homework.anonymous_comment &&
params[:evaluation_end] <= params[:evaluation_start]
tip_exception("匿评截止时间必须晚于匿评开启时间") if @homework.anonymous_comment &&
params[:evaluation_end] <= strf_time(@homework_detail_manual.evaluation_start)
tip_exception("匿评截止时间不能晚于课堂结束时间") if @homework.anonymous_comment &&
@course.end_date.present? && params[:evaluation_end] > strf_time(@course.end_date.end_of_day)
@ -758,6 +815,9 @@ class HomeworkCommonsController < ApplicationController
# 选用实训
def shixuns
@main_catrgory = @course.course_modules.where(module_type: "shixun_homework")
@homework_category = @main_catrgory.take.course_second_categories
search = params[:search]
type = params[:type]
# 超级管理员用户显示所有未隐藏的实训、非管理员显示所有已发布的实训(对本单位公开且未隐藏未关闭)
@ -774,22 +834,82 @@ class HomeworkCommonsController < ApplicationController
if params[:search] && params[:search].strip != ""
@shixuns = @shixuns.joins(:user).where("shixuns.name like ? or concat(users.lastname, users.firstname) like ?",
"%#{search}%", "%#{search}%").distinct
"%#{search}%", "%#{search}%").distinct
end
unless type.blank? || type == "all"
@shixuns = @shixuns.joins(:shixun_tag_repertoires).where(shixun_tag_repertoires: {tag_repertoire_id: type}).distinct
end
@shixuns = @shixuns.select([:id, :name, :status, :myshixuns_count, :identifier]).reorder("shixuns.created_at desc")
@shixuns_count = @shixuns.size
@shixuns = @shixuns.select([:id, :name, :status, :myshixuns_count, :identifier, :user_id, :trainee])
@total_count = @shixuns.size
## 分页参数
page = params[:page] || 1
@shixuns = @shixuns.page(page).per(10)
@main_catrgory = @course.course_modules.where(module_type: "shixun_homework")
@homework_category = @main_catrgory.take.course_second_categories
@shixuns = @shixuns.reorder("shixuns.created_at desc").includes(:challenges, user: [user_extension: :school]).page(page).per(10)
# 新版用下面的代码
# ## 我的实训
# @shixuns =
# if params[:order_by] == 'mine'
# current_user.my_shixuns.unhidden
# else
# if current_user.admin?
# Shixun.unhidden
# else
# none_shixun_ids = ShixunSchool.where("school_id != #{current_user.school_id}").pluck(:shixun_id)
#
# @shixuns = Shixun.where.not(id: none_shixun_ids).unhidden
# end
# end
#
# ## 方向
# if params[:tag_level].present? && params[:tag_id].present?
# @shixuns = @shixuns.filter_tag(params[:tag_level].to_i, params[:tag_id].to_i)
# case params[:tag_level].to_i
# when 1 #大类
# @search_tags = Repertoire.find(params[:tag_id].to_i).name
# when 2 #子类
# @search_tags = SubRepertoire.find(params[:tag_id].to_i).name
# when 3 #tag
# tag = TagRepertoire.find(params[:tag_id].to_i)
# @search_tags = "#{tag.sub_repertoire.name} / #{tag.name}"
# end
# end
#
# ## 搜索关键字创建者、实训名称、院校名称
# if params[:keyword].present?
# keyword = params[:keyword].strip
# @shixuns = @shixuns.joins(user: [user_extenison: :school]).
# where("schools.name like '%#{keyword}%'
# or concat(lastname, firstname) like '%#{keyword}%'
# or shixuns.name like '%#{keyword.split(" ").join("%")}%'").distinct
# end
#
# ## 筛选 难度
# if params[:diff].present? && params[:diff].to_i != 0
# @shixuns = @shixuns.where(trainee: params[:diff])
# end
#
# ## 排序参数
# bsort = params[:sort] || 'desc'
# case params[:order_by] || 'hot'
# when 'hot'
# @shixuns = @shixuns.order("myshixuns_count #{bsort}")
# when 'mine'
# @shixuns = @shixuns.order("shixuns.created_at #{bsort}")
# else
# @shixuns = @shixuns.order("myshixuns_count #{bsort}")
# end
#
# @total_count = @shixuns.count
#
# ## 分页参数
# page = params[:page] || 1
# limit = params[:limit] || 15
#
# @shixuns = @shixuns.includes(:challenges, user: [user_extension: :school]).page(page).per(limit)
#
end
def create_shixun_homework
@ -815,30 +935,69 @@ class HomeworkCommonsController < ApplicationController
# 选用实训课程
def subjects
@tags = Repertoire.where(nil).order("updated_at desc")
# select = params[:select] # 路径导航类型
select = params[:type] # 路径导航类型
reorder = params[:order] || "myshixun_count"
sort = params[:sort] || "desc"
search = params[:search]
type = params[:type]
# 显示所有未隐藏的、已发布的实训课程
@subjects = Subject.select([:id, :name, :status, :repertoire_id]).visible.unhidden
@tags = Repertoire.select([:id, :name]).where(id: @subjects.pluck(:repertoire_id).uniq).order("updated_at desc")
## 分页参数
page = params[:page] || 1
limit = params[:limit] || 15
offset = (page.to_i-1) * limit
# 最热排序
if reorder == "myshixun_count"
if select && select != "all"
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count #{sort}")
else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
GROUP BY subjects.id ORDER BY myshixun_member_count #{sort}")
end
else
# 我的路径
if reorder == "mine"
mine_subject_id = StageShixun.find_by_sql("select DISTINCT(subject_id) from stage_shixuns where shixun_id in
(select distinct(shixun_id) from myshixuns where user_id=#{current_user.id})").map(&:subject_id)
manage_subject_id = SubjectMember.where(user_id: current_user.id).pluck(:subject_id)
total_subject_id = (mine_subject_id + manage_subject_id).uniq
@subjects = Subject.where(id: total_subject_id)
end
if params[:search] && params[:search].strip != ""
@subjects = @subjects.joins(:user).where("subjects.name like ? or concat(users.lastname, users.firstname) like ?",
"%#{search}%", "%#{search}%")
end
# 类型
if select && select != "all"
@subjects = @subjects.where(repertoire_id: select)
end
unless type.blank? || type == "all"
@subjects = @subjects.where(repertoire_id: type)
end
if search.present?
@subjects = @subjects.where("name like ?", "%#{search}%")
end
@subjects = @subjects.reorder("subjects.created_at desc")
@subjects_count = @subjects.size
# 排序
order_str = "updated_at #{sort}"
@subjects = @subjects.reorder(order_str)
end
## 分页参数
page = params[:page] || 1
@subjects = @subjects.page(page).per(10)
@total_count = @subjects.size
@subjects = @subjects.includes(:shixuns)
if reorder != "myshixun_count"
@subjects = @subjects.page(page).per(limit).includes(:shixuns, user: [user_extension: :school])
else
@subjects = @subjects[offset, limit]
unless @subjects.blank?
subject_ids = @subjects.pluck(:id)
order_ids = subject_ids.size > 0 ? subject_ids.join(',') : -1
@subjects = Subject.where(id: subject_ids).order("field(id,#{order_ids})").includes(:shixuns, user: [user_extension: :school])
end
end
end
def create_subject_homework
@ -889,7 +1048,8 @@ class HomeworkCommonsController < ApplicationController
def publish_homework
tip_exception("请至少选择一个分班") if params[:group_ids].blank? && @course.course_groups.size != 0
tip_exception("缺少截止时间参数") if params[:end_time].blank?
tip_exception("截止时间必须晚于当前时间") if params[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
homeworks = @course.homework_commons.where(id: params[:homework_ids])
homeworks = homeworks.includes(:homework_group_settings, :homework_detail_manual)
@ -908,15 +1068,15 @@ class HomeworkCommonsController < ApplicationController
if @course.course_groups.where(id: publish_groups).size == @course.course_groups.size
homework.homework_group_settings.destroy_all
homework.unified_setting = true
homework.end_time = params[:end_time]
else
homework.unified_setting = false
# 创建作业分班设置homework_group_setting
create_homework_group_settings(homework)
# 选中的分班设置的发布时间改为当前时间,截止时间不为空的保持原状,为空的改为一个月后
homework.homework_group_settings.where(course_group_id: publish_groups).update_all(publish_time: Time.now)
homework.homework_group_settings.where(course_group_id: publish_groups, end_time: nil).
update_all(end_time: params[:end_time])
# 选中的分班设置的发布时间改为当前时间,截止时间改为传的截止时间参数
homework.homework_group_settings.where(course_group_id: publish_groups).update_all(publish_time: Time.now,
end_time: params[:end_time])
# 发消息
tiding_group_ids = publish_groups
end
@ -927,7 +1087,7 @@ class HomeworkCommonsController < ApplicationController
homework.publish_time = Time.now
# 截止时间不为空的保持原状,为空的改为一个月后, 非统一设置的更新为最大分班截止时间
# 截止时间的处理
if homework.end_time.nil?
homework.end_time = params[:end_time]
elsif homework.max_group_end_time
@ -938,14 +1098,13 @@ class HomeworkCommonsController < ApplicationController
if homework.course_acts.size == 0
homework.course_acts << CourseActivity.new(user_id: homework.user_id, course_id: homework.course_id)
end
# 发消息
HomeworkCommonPushNotifyJob.perform_later(homework.id, tiding_group_ids)
else
create_homework_group_settings(homework)
none_publish_settings = homework.homework_group_settings.where(course_group_id: publish_groups).none_published
none_publish_settings.update_all(publish_time: Time.now)
none_publish_settings.where(end_time: nil).update_all(end_time: params[:end_time])
none_publish_settings.update_all(publish_time: Time.now, end_time: params[:end_time])
if homework.max_group_end_time
homework.end_time = homework.max_group_end_time
end
@ -960,7 +1119,8 @@ class HomeworkCommonsController < ApplicationController
homework.save!
HomeworkPublishUpdateWorkStatusJob.perform_later(tiding_group_ids, homework.id)
# 更新学生状态及成绩(手动点击计算)
# HomeworkPublishUpdateWorkStatusJob.perform_later(tiding_group_ids, homework.id)
end
normal_status(0, "发布成功")
rescue Exception => e
@ -1060,7 +1220,7 @@ class HomeworkCommonsController < ApplicationController
=end
# 更新所有学生的效率分(重新取homework确保是更新后的)
HomeworksService.new.update_student_eff_score HomeworkCommon.find_by(id: homework.id) if !homework.allow_late && homework.end_time <= time
HomeworkEndUpdateScoreJob.perform_later(homework.id) if !homework.allow_late && homework.end_time <= time
end
end
homework.save!
@ -1259,7 +1419,7 @@ class HomeworkCommonsController < ApplicationController
.where(:user_id => user_ids).joins(user: :user_extension)
# 按学号和姓名搜索
if params[:search]
@users_reviews = @users_reviews.where("concat(lastname, firstname) like ? or student_id like ?", params[:search], params[:search])
@users_reviews = @users_reviews.where("concat(lastname, firstname) like :keyword or student_id like :keyword", keyword: "%#{params[:search]}%")
end
# 抄袭作品数
@copy_reviews_count = @users_reviews.count
@ -1279,7 +1439,7 @@ class HomeworkCommonsController < ApplicationController
end
# 代码查重详情
# 代码查重代码的详情
def code_review_detail
@student_work = @homework.student_works.find_by(user_id: params[:user_id])
@user = @student_work.user
@ -1292,7 +1452,7 @@ class HomeworkCommonsController < ApplicationController
if results.status == 0
code_info = results.code_info
homework_challenge_settings = @homework.homework_challenge_settings
@challenges = @shixun.challenges.where(id: homework_challenge_settings.pluck(:challenge_id), st: 0).includes(:games)
@challenges = @shixun.challenges.where(id: homework_challenge_settings.pluck(:challenge_id), st: 0)
@challenges =
@challenges.map do |challenge|
code_rate = 0
@ -1306,24 +1466,8 @@ class HomeworkCommonsController < ApplicationController
game = challenge.games.find_by(user_id: @user.id)
end_time = game.end_time
# 用户关卡的得分
all_score = homework_challenge_settings.find_by(challenge_id: challenge.id).try(:score)
final_score =
if @student_work.challenge_work_scores.where(challenge_id: challenge.id).last.present?
@student_work.challenge_work_scores.where(:challenge_id => game.challenge_id).last.score
else
if game.status == 2 && ((game.end_time && game.end_time < @homework.end_time) ||
(@homework.allow_late && (@course.end_date.nil? ||
(game.end_time && game.end_time < @course.end_date.end_of_day))))
answer_open_evaluation = @homework.homework_detail_manual.answer_open_evaluation
# 设置了查看答案也获得满分的话就取总分。否则取关卡的百分比分支
if answer_open_evaluation.present?
all_score
else
# 关卡的百分比 * 作业设置的分数 = 总得分
((game.final_score) / challenge.score) * all_score
end
end
end
all_score = homework_challenge_settings.find_by(challenge_id: challenge.id).try(:score).to_f
final_score = @student_work.work_challenge_score game, all_score
# 抄袭用户
copy_user = User.find_by_id(game_codes[0].target_user_id)
copy_end_time = copy_user.games.find_by(challenge_id: challenge.id).try(:end_time) if copy_user.present?

@ -3,7 +3,7 @@ class MessagesController < ApplicationController
SORT_TYPE = %w[time hot]
before_action :require_login, only: %i[create update sticky_top bulk_delete create destroy bulk_send bulk_move bulk_public]
before_action :require_login, :check_auth, only: %i[create update sticky_top bulk_delete create destroy bulk_send bulk_move bulk_public]
before_action :find_board, only: [:create, :index, :bulk_delete, :bulk_move, :bulk_send, :bulk_public]
before_action :find_message, only: [:update, :destroy, :sticky_top, :reply_list, :destroy, :reply]
before_action :validate_delete_params, only: %i[bulk_delete bulk_public]
@ -17,17 +17,25 @@ class MessagesController < ApplicationController
@page = params[:page] || 1
@page_size = params[:page_size] || 15
sort = params[:sort] || 0
sort = params[:sort].to_i == 1 ? 'asc' : 'desc'
sort_type = params[:sort_type] || 'time'
sort = sort.to_i
sort_type = sort_type.strip
@messages = @board.messages.root_nodes.by_keywords(params[:search]).includes(:praise_treads, :author, :children)
@messages = @messages.ordered(sort: sort, sort_type: sort_type)
@messages = sort_by_all_replies(sort, sort_type, @messages)
messages = @board.messages.root_nodes.by_keywords(params[:search])
@messages = sort_by_sticky(@messages)
@messages = Kaminari.paginate_array(@messages).page(@page).per(@page_size)
messages = messages.reorder('(sticky = 1) DESC') # 置顶
messages =
case sort_type
when 'time' then messages.order("created_on #{sort}")
when 'hot' then messages.order("descendants_count #{sort}")
else messages.order("created_on #{sort}")
end
messages = messages.includes(:author)
@messages = Kaminari.paginate_array(messages).page(@page).per(@page_size)
ids = @messages.map(&:id)
@praises_count_map = Message.where(root_id: ids).group(:root_id).sum(:praises_count)
end
def reply_list
@ -35,41 +43,31 @@ class MessagesController < ApplicationController
@page_size = params[:page_size] || 10
@current_user = current_user || nil
@messages = @message.children.preload_messages
@messages = @message.children.preload_messages.includes(:message_detail, :praise_treads)
@messages = @messages.ordered(sort: 1) unless @message.parent_id.nil?
@user_course_identity = current_user.course_identity(@message.board.course)
case @user_course_identity
when 5, 6, 7
@messages = @messages.visible
end
@messages = @messages.page(@page).per(@page_size)
end
def reply
return normal_status(2, "回复内容不能为空") if params[:content].blank?
begin
@reply = Message.create!(board: @message.board,
author: current_user,
parent: @message,
message_detail_attributes: {
@reply = Message.create!(board: @message.board, root_id: @message.root_id || @message.id,
author: current_user, parent: @message,
message_detail_attributes: {
content: params[:content]
}
)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
})
end
def sticky_top
return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@message.board.course)
ActiveRecord::Base.transaction do
begin
@message.update_attributes(:sticky => @message.sticky == 1 ? 0 : 1)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
@message.update_attributes(:sticky => @message.sticky == 1 ? 0 : 1)
end
def bulk_delete
@ -89,7 +87,10 @@ class MessagesController < ApplicationController
end
def show
@message = Message.includes(:attachments, :message_detail, :children, :author => :user_extension, :board => [{course: :board_course_modules}]).find_by_id params[:id]
@message = Message.includes(:attachments, :message_detail,
:children, :author => :user_extension,
:board => [{course: :board_course_modules}])
.find_by_id params[:id]
return normal_status(-2, "ID为#{params[:id]}的帖子不存在") if @message.nil?
@attachment_size = @message.attachments.size
@ -101,7 +102,9 @@ class MessagesController < ApplicationController
return normal_status(403, "您没有权限进行该操作") if current_user != @message.author && !current_user.teacher_of_course?(@message.board.course)
begin
@message.update_attributes(message_params)
h = {is_md: true}
m_params = message_params.merge(h)
@message.update_attributes(m_params)
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
@message.update_content(params[:content])
rescue Exception => e
@ -130,7 +133,7 @@ class MessagesController < ApplicationController
def destroy
begin
return normal_status(403, "您没有权限进行该操作") unless @message.author == current_user || current_user.teacher_of_course?(@message.board.course)
return normal_status(403, "您没有权限进行该操作") if current_user.course_identity(@message.board.course) >= 5 || @message.author != current_user
@message.destroy!
rescue Exception => e
uid_logger_error(e.message)
@ -170,15 +173,9 @@ class MessagesController < ApplicationController
def bulk_move
# 课堂的目录之间移动,有子栏目的才显示此项
return normal_status(403) unless current_user.teacher_of_course?(@board.course)
return normal_status(403) unless current_user.teacher_of_course?(@board.course)
begin
Message.bulk_move_to_other_board(params[:ids], params[:to_board_id], current_user.id)
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
Message.bulk_move_to_other_board(params[:ids], params[:to_board_id])
end
def bulk_public

@ -1,7 +1,7 @@
class MyshixunsController < ApplicationController
before_action :require_login, :except => [:training_task_status, :code_runinng_message]
before_action :find_myshixun, :except => [:training_task_status]
before_action :find_repo_name, :except => [:training_task_status]
before_action :require_login, :check_auth, :except => [:training_task_status, :code_runinng_message]
before_action :find_myshixun, :except => [:training_task_status, :code_runinng_message]
before_action :find_repo_name, :except => [:training_task_status, :code_runinng_message]
skip_before_action :verify_authenticity_token, :only => [:html_content]
## TPI关卡列表
@ -15,7 +15,6 @@ class MyshixunsController < ApplicationController
# For Admin
# 强制重置实训
# REDO等删除是否可以做成异步
# 前段需要按照操作过程提示
def reset_my_game
unless (current_user.admin? || current_user.id == @myshixun.user_id)
@ -34,8 +33,11 @@ class MyshixunsController < ApplicationController
uid_logger_error("版本库删除异常,详情:#{e.message}")
end
StudentWork.where(:myshixun_id => @myshixun.id).update_all(:myshixun_id => nil, :work_status => 0)
StudentWork.where(:myshixun_id => @myshixun.id).update_all(:myshixun_id => 0, :work_status => 0)
# 实训在申请发布前,是否玩过实训,如果玩过需要更改记录,防止二次重置
shixun_mod = ShixunModify.where(:shixun_id => @shixun.id, :myshixun_id => @myshixun.id, :status => 1).take
shixun_mod.update_column(:status, 0) if shixun_mod
rescue Exception => e
uid_logger_error("myshixun reset failed #{e}")
raise ActiveRecord::Rollback
@ -44,6 +46,7 @@ class MyshixunsController < ApplicationController
end
# 代码运行中的信息接口
# 这个方法是中间层主动调用的点击评测后中间层会发送参数过来告诉目前Pod的启动情况一次评测会调用两次请求
def code_runinng_message
begin
jsonTestDetails = JSON.parse(params[:jsonTestDetails])
@ -86,9 +89,6 @@ class MyshixunsController < ApplicationController
# "createPod":"1.610","evaluateAllTime":2820,"evaluateStart":"2017-11-24 11:04:35","execute":"0.294"}'
# params[:pics] = "a.png,b.png,c.png"
def training_task_status
logger.info("123################{params[:jsonTestDetails]}")
logger.info("456################{params[:timeCost]}")
logger.info("666###############{params}")
ActiveRecord::Base.transaction do
begin
@ -99,13 +99,16 @@ class MyshixunsController < ApplicationController
return_back_time = format("%.3f", ( t1.to_f - brige_end_time.to_f)).to_f
status = jsonTestDetails['status']
game_id = jsonTestDetails['buildID']
sec_key = jsonTestDetails['sec_key']
logger.info("training_task_status start#1**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
resubmit = jsonTestDetails['resubmit']
outPut = tran_base64_decode64(jsonTestDetails['outPut'])
jenkins_testsets = jsonTestDetails['msg']
compile_success = jsonTestDetails['compileSuccess']
# message = Base64.decode64(params[:msg]) unless params[:msg].blank?
logger.info(outPut)
game = Game.find(game_id)
myshixun = game.myshixun
challenge = game.challenge
@ -122,11 +125,16 @@ class MyshixunsController < ApplicationController
jenkins_testsets.each_with_index do |j_test_set, i|
logger.info("j_test_set: ############## #{j_test_set}")
actual_output = tran_base64_decode64(j_test_set['output'])
#ts_time += j_test_set['testSetTime'].to_i
# is_public = test_sets.where(:position => j_test_set['caseId']).first.try(:is_public)
logger.info "actual_output:################################################# #{actual_output}"
ts_time = format("%.2f", j_test_set['testSetTime'].to_f/1000000000).to_f
ts_mem = format("%.2f", j_test_set['testSetMem'].to_f/1024/1024).to_f
Output.create!(:code => status, :game_id => game_id, :out_put => outPut, :test_set_position => j_test_set['caseId'],
:actual_output => actual_output, :result => j_test_set['passed'].to_i, :query_index => max_query_index,
:compile_success => compile_success.to_i)
:compile_success => compile_success.to_i, :sec_key => sec_key, :ts_time => ts_time, :ts_mem => ts_mem)
# 如果设置了按测试集给分,则需要统计测试集的分值
if challenge.test_set_score && j_test_set['passed'].to_i == 1
test_set_score += challenge.test_sets.where(:position => j_test_set['caseId']).pluck(:score).first
@ -134,14 +142,14 @@ class MyshixunsController < ApplicationController
end
end
uid_logger("#############status: #{status}")
uid_logger("#############resubmit: #{resubmit}")
record = EvaluateRecord.where(:game_id => game_id).first
record = EvaluateRecord.where(:identifier => sec_key).first
logger.info("training_task_status start#3**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
answer_deduction_percentage = (100 - game.answer_deduction) / 100.to_f # 查看答案后剩余分数的百分比.
# answer_deduction是查看答案的扣分比例
# status0表示评测成功
if status == "0"
if resubmit.present?
uid_logger("#############resubmitdaiao: #{resubmit}")
game.update_attributes!(:retry_status => 2, :resubmit_identifier => resubmit)
challenge.path.split("").each do |path|
game_passed_code(path.try(:strip), myshixun, game_id)
@ -167,7 +175,7 @@ class MyshixunsController < ApplicationController
end
# 更新实训关联的作品分数 TODO: 更新作品分数
HomeworksService.new.update_myshixun_work_score myshixun
# HomeworksService.new.update_myshixun_work_score myshixun
end
# 如果过关了下一关的状态是3为开启则需要把状态改成1已开启
# next_game = game.next_game
@ -182,14 +190,21 @@ class MyshixunsController < ApplicationController
test_set_percentage = test_set_score / 100.to_f # 测试集得分比
score = (challenge.score * test_set_percentage * answer_deduction_percentage).to_i
# 如果分数比上次多,则更新成绩
game.update_attributes!(:status => 0, :final_score => score) if game.final_score < score
game_update =
if game.final_score < score
{final_score: score, status: 0}
else
{status: 0}
end
game.update_attributes!(game_update)
end
end
test_cases_time = format("%.3f", (Time.now.to_f - t1.to_f)).to_f
if record.present?
consume_time = format("%.3f", (Time.now - record.created_at)).to_f
record.update_attributes!(:consume_time => consume_time, :git_pull => timeCost['pull'] ,
:create_pod => timeCost['createPod'], :pod_execute => timeCost['execute'], :test_cases => test_cases_time,
record.update_attributes!(:consume_time => consume_time, :git_pull => timeCost['pull'] , :create_pod => timeCost['createPod'],
:pod_execute => timeCost['execute'], :test_cases => test_cases_time,
:brige => timeCost['evaluateAllTime'], :return_back => return_back_time)
end
uid_logger("training_task_status start#4**#{game_id}**** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
@ -211,7 +226,7 @@ class MyshixunsController < ApplicationController
shixun_tomcat = edu_setting('tomcat_webssh')
uri = "#{shixun_tomcat}/bridge/webssh/getConnectInfo"
params = {tpiID:@myshixun.id, podType:@myshixun.shixun.try(:webssh),
containers:(Base64.urlsafe_encode64(container_limit @myshixun.shixun.mirror_repositories))}
containers:(Base64.urlsafe_encode64(shixun_container_limit @myshixun.shixun))}
res = uri_post uri, params
if res && res['code'].to_i != 0
tip_exception("实训云平台繁忙繁忙等级92")
@ -237,55 +252,58 @@ class MyshixunsController < ApplicationController
# -----Repository
# TODO: 之类需要一个resubmit参数,但是是关于games.
def update_file
@hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first
tip_exception("技术平台为空!") if @myshixun.mirror_name.blank?
path = params[:path].strip unless params[:path].blank?
game_id = params[:game_id]
game = Game.find(game_id)
@content_modified = 0
# params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
# 自动保存的时候evaluate为0点评测的时候为1
if params[:evaluate] == 1
record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id)
uid_logger("-- game is #{game_id}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
student_work_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f
record.update_attributes!(:student_work => student_work_time)
end
unless @hide_code
# 远程版本库文件内容
last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
content = if @myshixun.mirror_name.select{|a| a.include?("MachineLearning") || a.include?("Python")}.present? && params[:content].present?
params[:content].gsub(/\t/, ' ')
else
params[:content]
end
if content != last_content
@content_modified = 1
author_name = current_user.full_name
author_email = current_user.mail
message = params[:evaluate] == 0 ? "auto commit" : "task commit"
@content = GitService.update_file(repo_path: @repo_path,
file_path: path,
message: message,
content: content,
author_name: author_name,
author_email: author_email)
uid_logger("-- file update #{@content}")
begin
@hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first
tip_exception("技术平台为空!") if @myshixun.mirror_name.blank?
path = params[:path].strip unless params[:path].blank?
game_id = params[:game_id]
game = Game.find(game_id)
@content_modified = 0
# params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
# 自动保存的时候evaluate为0点评测的时候为1
if params[:evaluate] == 1
@sec_key = generate_identifier(EvaluateRecord, 12)
record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id,
:identifier => @sec_key)
uid_logger("-- game build: file update #{@sec_key}, record id is #{record.id}, time is **** #{Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")}")
end
end
unless @hide_code
# 远程版本库文件内容
last_content = GitService.file_content(repo_path: @repo_path, path: path)["content"]
content = params[:content]
Rails.logger.info("###11222333####{content}")
Rails.logger.info("###222333####{last_content}")
if content != last_content
@content_modified = 1
if game.status == 2
@resubmit = Time.now.to_i
end
author_name = current_user.real_name
author_email = current_user.git_mail
message = params[:evaluate] == 0 ? "System automatically submitted" : "User submitted"
uid_logger("112233#{author_name}")
uid_logger("112233#{author_email}")
@content = GitService.update_file(repo_path: @repo_path,
file_path: path,
message: message,
content: content,
author_name: author_name,
author_email: author_email)
end
end
# 评测时间记录
if record.present?
consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f
record.update_attributes!(:file_update => consume_time)
if game.status == 2
@resubmit = Time.now.to_i
end
# 评测时间记录
if record.present?
consume_time = format("%.3f", (Time.now.to_f - record.created_at.to_f)).to_f
record.update_attributes!(:file_update => consume_time)
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("文件内容更新异常,请稍后重试")
end
end

@ -1,5 +1,5 @@
class PollQuestionsController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :get_poll,only:[:new,:create]
before_action :get_poll_question,except: [:new,:create]
before_action :is_course_teacher
@ -156,14 +156,10 @@ class PollQuestionsController < ApplicationController
begin
answer_d_id = params[:answer_no].to_i # 答案的当前位置
poll_answers = @poll_question.poll_answers
delete_answer = poll_answers.find_answer_by_custom("answer_position",answer_d_id).first
left_answer = poll_answers.left_answer_choose("answer_position",answer_d_id)
if left_answer.present?
left_answer.each do |p|
p.answer_position -= 1
p.save
end
end
delete_answer = poll_answers.find_by(answer_position: answer_d_id)
left_answers = poll_answers.where("answer_position > ?",answer_d_id)
left_answers.update_all("answer_position = answer_position - 1") if left_answers
if delete_answer.destroy
normal_status(0, "答案删除成功!")
else
@ -197,22 +193,23 @@ class PollQuestionsController < ApplicationController
begin
opr = params[:opr]
current_q_p = @poll_question.question_number.to_i #问题的当前位置
last_q_p = @poll.poll_questions.last_poll(current_q_p) #当前问题的前一个问题
next_q_p = @poll.poll_questions.next_poll(current_q_p) # 当前问题的后一个问题
if @poll.polls_status.to_i == 1
if opr.present?
if opr.to_s == "up"
last_q_p = @poll.poll_questions.find_by(question_number: (current_q_p-1)) #当前问题的前一个问题
if last_q_p.present?
@poll_question.update_attribute(:question_number, (current_q_p - 1))
last_q_p.update_attribute(:question_number, (@poll_question.question_number.to_i + 1)) # 重新获取当前问题的位置
@poll_question.update_attribute("question_number", (current_q_p - 1))
last_q_p.update_attribute("question_number", current_q_p) # 重新获取当前问题的位置
normal_status(0, "问题上移成功!")
else
normal_status(-1, "移动失败,已经是第一个问题了!")
end
elsif opr.to_s == "down"
next_q_p = @poll.poll_questions.find_by(question_number: (current_q_p+1)) #当前问题的后一个问题
if next_q_p.present?
@poll_question.update_attribute(:question_number, (current_q_p + 1))
next_q_p.update_attribute(:question_number, (@poll_question.question_number.to_i - 1))
@poll_question.update_attribute("question_number", (current_q_p + 1))
next_q_p.update_attribute("question_number", current_q_p)
normal_status(0, "问题下移成功!")
else
normal_status(-1, "移动失败,已经是最后一个问题了!")

@ -1,9 +1,8 @@
class PollVotesController < ApplicationController
#在开始回答和提交问卷的时候,已经做了判断用户的身份权限
before_action :require_login
before_action :require_login, :check_auth
before_action :get_poll_question
before_action :check_answer_in_question,only: [:create]
before_action :check_multi_answers
before_action :check_answer_in_question
def create #每一次答案的点击,请求一次
@ -31,11 +30,13 @@ class PollVotesController < ApplicationController
if question_type == 1
if user_votes.present? #用户曾经回答过的,答案选择不一样,否则新建
current_user_answer = user_votes.first
if current_user_answer.poll_answer_id != question_answer_id #如果说更换了答案,则以前的答案删除,并新建记录
if current_user_answer&.poll_answer_id != question_answer_id #如果说更换了答案,则以前的答案删除,并新建记录
current_user_answer.destroy
PollVote.create(vote_answer_params)
else
if question_answer_text.present?
current_user_answer.update_attribute("vote_text", question_answer_text)
end
end
@ -98,9 +99,10 @@ class PollVotesController < ApplicationController
@current_question_necessary = @poll_question.is_necessary
#问答记录存在,且有值,才会有返回值。
@current_question_status = 0
if user_votes.present?
vote_answer_id = user_votes.pluck(:poll_answer_id).reject(&:blank?).size
vote_text_count = user_votes.pluck(:vote_text).reject(&:blank?).size
new_user_votes = question_votes.where(user_id: current_user.id)
if new_user_votes.present?
vote_answer_id = new_user_votes.pluck(:poll_answer_id).reject(&:blank?).size
vote_text_count = new_user_votes.pluck(:vote_text).reject(&:blank?).size
if vote_text_count > 0 || vote_answer_id > 0
@current_question_status = 1
end
@ -129,29 +131,28 @@ class PollVotesController < ApplicationController
normal_status(-1,"课堂不存在!")
end
end
end
def check_answer_in_question
poll_answer_ids = @poll_question.poll_answers.pluck(:id)
if @poll_question.question_type == 1 #单选题/多选题
unless (params[:poll_answer_id].present? && poll_answer_ids.include?(params[:poll_answer_id].to_i)) || (params[:poll_answer_id].blank? && params[:vote_text].present?)
normal_status(-1, "答案ID错误")
end
end
end
poll_user_status = @poll.get_poll_status(current_user)
poll_user = @poll.poll_users.find_by(user_id: current_user.id) #当前用户
def check_multi_answers
if @poll_question.question_type == 2
question_type = @poll_question&.question_type
if (question_type == 1) && params[:poll_answer_id].blank?
normal_status(-1,"答案ID错误!")
elsif question_type == 2
user_vote_count = params[:poll_answer_id].size
if @poll_question.max_choices.present?
question_max_choices = @poll_question.max_choices
else
question_max_choices = 0
end
if question_max_choices > 0 && user_vote_count > question_max_choices
if question_max_choices > 0 && (user_vote_count > question_max_choices)
normal_status(-1,"多选题答案超过最大限制!")
end
elsif (poll_user.present? && poll_user.commit_status == 1) || poll_user_status == 3
normal_status(-1,"已提交/已结束的问卷不允许修改!")
end
end
end

@ -1,6 +1,6 @@
class PollsController < ApplicationController
# before_action :check_poll_status 问卷的发消息和定时任务没有做
before_action :require_login,except: [:index]
before_action :require_login, :check_auth,except: [:index]
before_action :find_course, except: [:show,:poll_setting,:commit_setting,:edit,:update,:start_answer,:commit_poll,
:commit_result,:poll_lists,:cancel_publish,:cancel_publish_modal,:common_header]
before_action :get_poll_and_course, only: [:show,:poll_setting,:commit_setting,:edit,:update,:start_answer,
@ -18,7 +18,7 @@ class PollsController < ApplicationController
before_action :check_user_id_start_answer,only: [:start_answer]
before_action :check_poll_question_complete,only: [:commit_poll] #问卷提交前来判断问题是否完成
before_action :check_poll_commit_result,only: [:commit_result]
before_action :get_all_polls_commit, only: [:commit_result] #该问卷全部的用户
# before_action :get_all_polls_commit, only: [:commit_result] #该问卷全部的用户
before_action :get_left_banner_id, only:[:common_header,:start_answer,:new,:edit,:index]
include PollsHelper
@ -31,50 +31,48 @@ class PollsController < ApplicationController
@current_user_ = current_user
@course_status = @course.is_end ? 0 : 1 # 课堂是否结束
@course_is_public = @course.is_public
@polls_count = @polls_all.count # 全部页面,需返回
@polls_unpublish_counts = @polls_all.poll_by_status(1).count #未发布的问卷数
@polls_published_counts = @polls_all.poll_by_status([2, 3]).count # 已发布的问卷数
# 课堂的学生人数
@course_all_members = @course.students #当前课堂的全部学生
@course_all_members_count = @course_all_members.count #当前课堂的学生数
@current_student = @course_all_members.find_by(user_id: current_user.id) #当前用户是否为课堂的学生
# polls的不同用户群体的显示
if @user_course_identity < Course::STUDENT # @is_teacher_or 1为老师/管理员/助教
@is_teacher_or = 1
@teacher_groups_ids = @course.teacher_course_groups.get_user_groups(current_user.id).pluck(:course_group_id).reject(&:blank?)
@polls = @polls_all #老师能看到全部的问卷,不管是已发布的/未发布的/已截止的/统一设置的/私有设置的(看到内容不同)
elsif @user_course_identity == Course::STUDENT # 2为课堂成员能看到统一设置的和自己班级的
@is_teacher_or = 2
member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id默认为0
if member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的)
@member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id默认为0
if @member_group_id == 0 #表示是课堂的未分班成员,只能查看统一设置的试卷(已发布的/已截止的)
@polls = member_show_polls.size > 0 ? member_show_polls.public_or_unset : []
else #已分班级的成员,可以查看统一设置和单独设置(试卷是发布在该班级)试卷
# 已发布 当前用户班级分组的 试卷id
poll_settings_ids = @course.poll_group_settings.where(course_group_id: member_group_id).poll_group_published.pluck(:poll_id).uniq # 选择成员的班级id等于课堂问卷设置的班级id
@polls = member_show_polls.present? ? member_show_polls.public_or_unset.or(member_show_polls.where(id: poll_settings_ids)) : []
not_poll_ids = @course.poll_group_settings.poll_group_not_published.where("course_group_id = #{@member_group_id}").pluck(:poll_id)
@polls = member_show_polls.where.not(id: not_poll_ids)
end
else #用户未登陆或不是该课堂成员,仅显示统一设置的(已发布的/已截止的),如有公开,则不显示锁,不公开,则显示锁
@is_teacher_or = 0
@polls = member_show_polls.size > 0 ? member_show_polls.public_or_unset : []
@polls = member_show_polls.public_or_unset
end
if @polls.count > 0
if params[:type].present?
choose_type = params[:type]
member_group_id = @current_student.try(:course_group_id).to_i # 成员的分班id默认为0
if @is_teacher_or == 2 && member_group_id > 0
poll_groups_sets = @course.poll_group_settings.where(course_group_id: member_group_id).poll_group_published
poll_settings_ids = poll_groups_sets.pluck(:poll_id)
poll_ended_ids = poll_groups_sets.poll_group_ended.pluck(:poll_id).uniq
# poll_settings_ids = @course.poll_group_settings.where(course_group_id: member_group_id).poll_group_ended.pluck(:poll_id).uniq
if choose_type.to_i == 2
@polls = @polls_all.present? ? @polls_all.poll_by_status(2).public_or_unset.or(@polls_all.where(id:(poll_settings_ids - poll_ended_ids).uniq)).distinct : []
elsif choose_type.to_i == 3
@polls = @polls_all.present? ? @polls_all.poll_by_status(3).public_or_unset.or(@polls_all.where(id: poll_ended_ids)).distinct : []
end
poll_setting_ids = []
if @is_teacher_or != 2
@polls = @polls.where("polls_status = #{choose_type}")
else
@polls = @polls.poll_by_status(choose_type)
case choose_type
when 1
poll_setting_ids = @course.poll_group_settings.where("course_group_id = #{@member_group_id}").poll_group_not_published.pluck(:poll_id)
when 2
poll_setting_ids = @course.poll_group_settings.where("course_group_id = #{@member_group_id}")
.where("publish_time is not null and publish_time <= ? and end_time > ?",Time.now,Time.now).pluck(:poll_id)
when 3
poll_setting_ids = @course.poll_group_settings.where("course_group_id = #{@member_group_id}").poll_group_ended.pluck(:poll_id)
end
unified_setting_ids = @polls.public_or_unset.where("polls_status = #{choose_type}").pluck(:id)
ex_ids = (poll_setting_ids + unified_setting_ids).uniq
@polls = @polls.where(id: ex_ids)
end
end
@ -90,11 +88,16 @@ class PollsController < ApplicationController
@limit = params[:limit] || 15
@polls = @polls.page(@page).per(@limit)
@polls = @polls.includes(:poll_users,:poll_questions,:poll_group_settings)
@polls = @polls&.includes(:published_settings)
else
@polls = []
end
@polls_count = @polls_all.size # 全部页面,需返回
@polls_unpublish_counts = @polls_all.poll_by_status(1).size #未发布的问卷数
@polls_published_counts = @polls_count - @polls_unpublish_counts # 已发布的问卷数
@course_all_members_count = @course_all_members.size #当前课堂的学生数
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@ -146,7 +149,7 @@ class PollsController < ApplicationController
def edit
ActiveRecord::Base.transaction do
begin
@poll_questions = @poll.poll_questions.order("question_number ASC")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面请求失败!")
@ -183,7 +186,7 @@ class PollsController < ApplicationController
else
@is_teacher_or = 0
end
@poll_questions = @poll.poll_questions.order("question_number ASC")
rescue Exception => e
uid_logger_error(e.message)
tip_exception("没有权限")
@ -202,15 +205,15 @@ class PollsController < ApplicationController
@is_teacher_or = 1
@user_poll_answer = 3 #教师页面
end
poll_status = @poll.get_poll_status(current_user.id)
@poll_status = @poll.get_poll_status(current_user)
poll_id_array = [@poll.id]
@poll_publish_count = get_user_permission_course(poll_id_array,2).count #是否存在已发布的
@poll_unpublish_count = get_user_permission_course(poll_id_array,1).count #是否存在未发布的
if (@poll_publish_count == 0) && (@poll_unpublish_count == 0) #即表示没有分班
if poll_status == 1
if @poll_status == 1
@poll_unpublish_count = 1 #试卷未发布,且课堂没有分班的时候
elsif poll_status == 2
elsif @poll_status == 2
@poll_publish_count = 1 #试卷未发布,且课堂没有分班的时候
end
end
@ -241,10 +244,13 @@ class PollsController < ApplicationController
end
#首页批量或单独 立即发布,应是跳出弹窗,设置开始时间和截止时间。
def publish
tip_exception("缺少截止时间参数") if params[:end_time].blank?
tip_exception("截止时间不能早于当前时间") if params[:end_time] <= strf_time(Time.now)
tip_exception("截止时间不能晚于课堂结束时间") if @course.end_date.present? && params[:end_time] > strf_time(@course.end_date.end_of_day)
ActiveRecord::Base.transaction do
begin
check_ids = Poll.where(id: params[:check_ids])
ex_end_time = params[:end_time] || Time.at(((1.month.since.to_i)/3600.0).ceil * 3600)
ex_end_time = params[:end_time].blank? ? Time.at(((1.month.since.to_i)/3600.0).ceil * 3600) : params[:end_time].to_time
check_ids.each do |poll|
if poll.unified_setting
pl_status = poll.polls_status #则为试卷的状态
@ -254,16 +260,11 @@ class PollsController < ApplicationController
if pl_status == 1 #如果问卷存在已发布的,或者是已截止的,那么则直接跳过
g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数那么poll的统一设置需修改
if g_course
course_groups = @course.teacher_course_groups.get_user_groups(current_user.id)
if course_groups.blank?
user_course_groups = @course.course_groups.present? ? @course.course_groups.pluck(:id) : []
else
user_course_groups = course_groups.pluck(:course_group_id)
end
user_course_groups = @course.charge_group_ids(current_user)
if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则问卷不用分组,且问卷设定为统一设置,否则则分组设置
poll.poll_group_settings.destroy_all
poll_unified = true
notify_student_ids = @course.students.pluck(:user_id)
e_time = ex_end_time
else
poll_unified = false
g_course.each do |i|
@ -282,20 +283,13 @@ class PollsController < ApplicationController
new_poll_group.save
end
end
notify_student_ids = @course.students.where(course_group_id: params[:group_ids]).pluck(:user_id)
e_time = poll.poll_group_settings.end_time_present.map(&:end_time).max
# group_ids = params[:group_ids]
end
else
poll.poll_group_settings.destroy_all
poll_unified = true
notify_student_ids = @course.students.pluck(:user_id)
end
if poll.end_time.blank?
e_time = ex_end_time
elsif poll.poll_group_settings.end_time_present.count > 0 # 该问卷分组有结束时间为空的
e_time = poll.poll_group_settings.end_time_present.map(&:end_time).max
else
e_time = poll.end_time
end
poll_status = set_poll_status(Time.now,e_time)
@ -309,7 +303,7 @@ class PollsController < ApplicationController
if poll.course_acts.size == 0
poll.course_acts << CourseActivity.new(:user_id => poll.user_id,:course_id => poll.course_id)
end
PollPublishNotifyJob.perform_later(poll.id, notify_student_ids)
PollPublishNotifyJob.perform_later(poll.id, g_course)
end
end
normal_status(0, "问卷发布成功!")
@ -347,7 +341,7 @@ class PollsController < ApplicationController
begin
check_ids = Poll.where(id: params[:check_ids])
check_ids.each do |poll|
poll_status = poll.get_poll_status(current_user.id)
poll_status = poll.get_poll_status(current_user)
if poll_status == 2 #跳过已截止的或未发布的
g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数那么poll的统一设置需修改poll_group_settings
if g_course
@ -673,7 +667,7 @@ class PollsController < ApplicationController
@user_published_setting = @poll.poll_group_settings.find_in_poll_group("course_group_id",@being_setting_course_ids)
poll_ids = [@poll.id]
@poll_publish_count = get_user_permission_course(poll_ids,2).count
## 需添加发送消息的接口,稍后添加
rescue Exception => e
uid_logger_error(e.message)
tip_exception("页面调用失败!")
@ -688,10 +682,10 @@ class PollsController < ApplicationController
begin
error_count = 0 # 判断循环里是否有已发布/已截止的,且时间更改了的分班。
course_group_ids = @course.teacher_course_group_ids(current_user.id) #当前老师的班级id数组
course_group_ids = @course.charge_group_ids(current_user) #当前老师的班级id数组
poll_status = @poll.get_poll_status(current_user.id)
if poll_status == 1 && (course_group_ids - [0]).count > 0 # 问卷未发布且老师的分班大于1 才可以修改统一设置否则按poll默认的来处理
poll_status = @poll.get_poll_status(current_user)
if poll_status == 1 && course_group_ids.size > 0 # 问卷未发布且老师的分班大于1 才可以修改统一设置否则按poll默认的来处理
unified_setting = params[:unified_setting]
else
unified_setting = @poll.unified_setting
@ -849,8 +843,8 @@ class PollsController < ApplicationController
def start_answer
ActiveRecord::Base.transaction do
begin
poll_user_current = @poll.poll_users.find_by_group_ids(@poll_current_user_id).first #查找当前用户是否有过答题
@poll_status = @poll.get_poll_status(current_user.id)
poll_user_current = PollUser.where(user_id:@poll_current_user_id,poll_id:@poll.id)&.first #查找当前用户是否有过答题
@poll_status = @poll.get_poll_status(current_user)
if poll_user_current.blank?
if @user_course_identity > Course::ASSISTANT_PROFESSOR #当为老师的时候不创建poll_user表理论上老师是不能进入答题的
poll_user_params = {
@ -871,7 +865,6 @@ class PollsController < ApplicationController
@user_poll_status = 0 #可编辑
end
# @answer_user = User.find_by(id:@poll_current_user_id)
@answer_status = []
question_answered = 0
@ -923,21 +916,26 @@ class PollsController < ApplicationController
def commit_result
ActiveRecord::Base.transaction do
begin
# 分页
@poll_users = @poll.all_poll_users(current_user.id)
@poll_commit_ids = @poll_users.commit_by_status(1).pluck(:user_id) #问卷提交用户的id
@page = params[:page] || 1
@limit = params[:limit] || 10
@poll_export_questions = @poll_questions.order("question_number ASC")
@poll_export_questions = @poll_questions
@poll_questions = @poll_questions.page(@page).per(@limit)
respond_to do |format|
format.json
format.xlsx{
if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作")
else
polls_export_name = current_user.real_name + "_" + @course.name + "_" + @poll.polls_name + "_" + Time.now.strftime('%Y%m%d_%H%M%S')
render xlsx: "#{polls_export_name.strip.first(30)}",template: "polls/commit_result.xlsx.axlsx",locals: {poll_questions:@poll_export_questions}
if params[:format] == "xlsx"
if @user_course_identity > Course::ASSISTANT_PROFESSOR
tip_exception(403,"无权限操作")
elsif (@poll.polls_status == 1) || (@poll_export_questions.size == 0) || (@poll_commit_ids.size == 0)
normal_status(-1,"暂无用户提交")
else
respond_to do |format|
format.xlsx{
polls_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@poll.polls_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
polls_user_commit = poll_commit_result(@poll,@poll_export_questions,@poll_users,@poll_commit_ids)
render xlsx: "#{polls_export_name_.strip.first(30)}",template: "polls/commit_result.xlsx.axlsx",locals: {polls_user_commit:polls_user_commit}
}
end
}
end
end
rescue Exception => e
uid_logger_error(e.message)
@ -951,17 +949,17 @@ class PollsController < ApplicationController
def poll_lists
ActiveRecord::Base.transaction do
begin
logger.info("########___________@course.teacher_course_groups)________________####################{@course.teacher_course_groups.where(user_id:current_user.id).pluck(:course_group_id)}")
poll_ids = [@poll.id]
@poll_list_status = @poll.get_poll_status(current_user.id)
@poll_list_status = @poll.get_poll_status(current_user)
@poll_publish_count = get_user_permission_course(poll_ids,2).count
@poll_unpublish_count = get_user_permission_course(poll_ids,1).count
@course_all_members = @course.students
@poll_group_counts = @course.course_groups_count
if @user_course_identity < Course::STUDENT #当前为老师,而且老师只能查看自己班级的/课堂的问卷
@poll_current_user_status = 0
@poll_users_list = @poll.all_poll_users(current_user.id).distinct #该老师分班的全部学生
get_poll_answers(@poll_users_list)
@poll_users_list = @poll.all_poll_users(current_user.id) #该老师分班的全部学生
get_poll_answers(@poll_users_list, @poll_list_status)
if @poll_list_status == 1
@poll_course_groups =[]
else
@ -973,7 +971,7 @@ class PollsController < ApplicationController
end
elsif @user_course_identity > Course::ASSISTANT_PROFESSOR
@poll_all_users = @poll.get_poll_exercise_users
get_poll_answers(@poll_all_users) # 未答和已答的
get_poll_answers(@poll_all_users, @poll_list_status) # 未答和已答的
@poll_course_groups = [] #当为学生的时候,不显示分班情况
@poll_current_user_status = 1 #当前用户的状态,为学生
poll_current_user = @poll_all_users.find_by_group_ids(current_user.id) #当前用户是否开始做问卷(提交/未提交/没做)
@ -984,7 +982,7 @@ class PollsController < ApplicationController
end
else
@poll_all_users = @poll.get_poll_exercise_users
get_poll_answers(@poll_all_users) # 未答和已答的
get_poll_answers(@poll_all_users, @poll_list_status) # 未答和已答的
@poll_current_user_status = 2 #当前用户非课堂成员
@poll_users_list = []
end
@ -1007,14 +1005,8 @@ class PollsController < ApplicationController
search_content = params[:search]
if @poll_users_list.present? && @poll_users_list.count > 0
if order == "student_id"
@poll_users_list = @poll_users_list.joins(user: [:user_extension]).order("user_extensions.student_id DESC")
else
@poll_users_list = @poll_users_list.order("end_at DESC")
end
#答题状态的选择
#
if choose_type.present?
@poll_users_list = @poll_users_list.commit_by_status(choose_type)
end
@ -1028,20 +1020,23 @@ class PollsController < ApplicationController
#搜索
if search_content.present?
#搜索用户的nickname,如果存在则返回,否则继续查询用户的真实姓名或学生号
nick_name_search = @poll_users_list.where(user_id: User.where('CONCAT(users.lastname, users.firstname) like ?',"%#{search_content}%"))
if nick_name_search.present?
@poll_users_list = nick_name_search
else
@poll_users_list = @poll_users_list.joins(user: [:user_extension]).where('user_extensions.student_id like ? OR user_extensions.student_realname like ?',"%#{search_content}%","%#{search_content}%")
end
@poll_users_list = @poll_users_list.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{search_content}%", "%#{search_content}%")
end
poll_users_joins = @poll_users_list.joins(user: :user_extension)
if order == "student_id"
@poll_users_list = poll_users_joins.order("user_extensions.student_id DESC")
else
@poll_users_list = poll_users_joins.order("end_at DESC")
end
@poll_users_size = @poll_users_list.count
# 分页
@page = params[:page] || 1
@limit = params[:limit] || 20
@poll_users_list = @poll_users_list.page(@page).per(@limit)
page = params[:page] || 1
limit = params[:limit] || 20
@poll_users_list = @poll_users_list.page(page).per(limit)
else
@poll_users_list = []
@poll_users_size = 0
@ -1103,7 +1098,7 @@ class PollsController < ApplicationController
## 判断开始答题页面的用户权限
def check_user_on_answer
poll_status = @poll.get_poll_status(current_user.id)
poll_status = @poll.get_poll_status(current_user)
if @user_course_identity == Course::STUDENT && poll_status == 1 #问卷未发布,且当前用户不为老师/管理员
normal_status(-1, "未发布问卷!")
elsif @user_course_identity > Course::STUDENT && (!@poll.is_public || (@poll.is_public && !@poll.unified_setting)) ##不为课堂成员,且问卷不为公开的,或问卷公开,但是不是统一设置的
@ -1151,15 +1146,16 @@ class PollsController < ApplicationController
def get_questions_count
@poll_questions = @poll.poll_questions.order("question_number ASC")
@poll_questions_count = @poll_questions.count # 全部的题目数
@poll_question_singles = @poll_questions.ques_count(1).all.count # 单选题
@poll_question_doubles = @poll_questions.ques_count(2).all.count # 多选题
@poll_question_mains = @poll_questions.ques_count(3).all.count #主观题
@poll_questions_count = @poll_questions&.size # 全部的题目数
@poll_question_singles = @poll_questions.ques_count(1).size # 单选题
@poll_question_doubles = @poll_questions.ques_count(2).size # 多选题
@poll_question_mains = @poll_questions.ques_count(3).size #主观题
@poll_questions = @poll_questions&.includes(:poll_answers,:poll_votes).distinct
end
def check_poll_question_complete #commit_poll 的权限
poll_user_current = @poll.poll_users.find_by_group_ids(current_user.id).first
poll_status = @poll.get_poll_status(current_user.id)
poll_status = @poll.get_poll_status(current_user)
if @user_course_identity < Course::STUDENT || (poll_status == 3) || (poll_user_current.present? && poll_user_current.commit_status == 1)
normal_status(-1,"用户没有权限!") #老师/管理员在提交时没有权限
else
@ -1181,9 +1177,9 @@ class PollsController < ApplicationController
end
def check_poll_commit_result
poll_status = @poll.get_poll_status(current_user.id)
poll_status = @poll.get_poll_status(current_user)
commit_poll_user = @poll.poll_users.find_by_group_ids(current_user.id).commit_by_status(1) #当前用户已提交问卷的
unless @user_course_identity < Course::STUDENT || (@poll.show_result && poll_status == 3 && commit_poll_user.present?)
unless (@user_course_identity < Course::STUDENT) || ((@poll.show_result == 1) && (poll_status == 3) && commit_poll_user.present?)
normal_status(-1,"没有权限!") #当前为老师/问卷公开统计,且问卷已截止,且用户有过回答的
end
end
@ -1213,17 +1209,12 @@ class PollsController < ApplicationController
def get_user_permission_course(poll_ids,status) #获取用户权限范围内的已发布/未发布
poll_status = status.to_i
unpublish_group = []
g_course_ids = @course.teacher_course_groups.get_user_groups(current_user.id).pluck(:course_group_id).reject(&:blank?).uniq
if g_course_ids.blank? || g_course_ids.include?(0) #当前用户的分班权限为空,即具体全部的分班权限
user_groups_id = @course.course_groups.pluck(:id)
else
user_groups_id = g_course_ids
end
user_groups_id = @course.charge_group_ids(current_user)
all_polls = Poll.where(id:poll_ids)
all_polls.each do |poll|
if poll.present?
if poll.unified_setting
poll_user_status = poll.get_poll_status(current_user.id) #当前用户的能看到的试卷
poll_user_status = poll.get_poll_status(current_user) #当前用户的能看到的试卷
if poll_user_status == poll_status || poll_status == 3 #未发布的情况
unpublish_group = unpublish_group + user_groups_id
else
@ -1282,8 +1273,6 @@ class PollsController < ApplicationController
else
normal_status(-1,"请选择分班!")
end
# elsif (@poll.poll_status != 1) && (params[:publish_time].to_time != @poll.publish_time) && (@user_course_identity > Course::CREATOR)
# normal_status(-1,"已发布/已截止的不能修发布时间!") #课堂管理员和超级管理员才有权限
end
end
@ -1297,4 +1286,99 @@ class PollsController < ApplicationController
end
end
#问卷的统计结果的导出
def poll_commit_result(poll,poll_questions,poll_users,poll_commit_ids)
sub_commit = []
user_commit = []
poll_users_info = %w(序号)
poll_ques_titles = poll_questions.pluck(:question_title).map {|k| ActionController::Base.helpers.strip_tags(k) if k.present?}
poll_un_anony = poll.un_anonymous
if poll_un_anony #是否匿名默认为false
user_info = %w(登陆名 真实姓名 邮箱 学号)
else
user_info = []
end
poll_users_info = poll_users_info + user_info + poll_ques_titles
poll_questions.each do |q|
if q.question_type != 3 #问题不为主观题
question_vote_user = q.poll_votes.find_current_vote("user_id",poll_commit_ids)&.size #该问题的有效填写量
sheet_row = ["#{q.question_number}"] #选择题答案选项的数组
sheet_answer_row = ["小计"] #选择题回答的答案人数,数组
sheet_answer_percent = ["比例"]
sheet_answer_useful = ["本题有效填写人次",question_vote_user]
q.poll_answers.each do |a| #问卷的答案选项
answer_users_count = a.poll_votes.find_current_vote("user_id",poll_commit_ids)&.size
answer_percent = (question_vote_user == 0) ? "0.0%" : "#{((answer_users_count / question_vote_user.to_f)*100).round(1).to_s}%"
sheet_row.push(a.answer_text)
sheet_answer_row.push(answer_users_count)
sheet_answer_percent.push(answer_percent)
end
sheet_sub_commit = {
sub_title: sheet_row,
sub_user_votes:[sheet_answer_row,sheet_answer_percent,sheet_answer_useful]
}
sub_commit.push(sheet_sub_commit)
else #主观题答案
user_votes= []
main_show_row = ["#{q.question_number}", q.question_title ]
q.poll_votes.each_with_index do |v,index| #主观题的答案
q_poll_vote = [(index+1), v.vote_text.present? ? v.vote_text : "--"]
user_votes.push(q_poll_vote)
end
sheet_sub_commit = {
sub_title: main_show_row,
sub_user_votes:user_votes
}
sub_commit.push(sheet_sub_commit)
end
end #each_with_index
poll_users.includes(user: [:user_extension,:poll_votes]).each_with_index do |u,index|
u_user = u.user
user_answer_array = []
poll_questions.each do |q|
user_poll_votes = u_user.poll_votes.find_current_vote("poll_question_id",q.id)
if user_poll_votes.present?
user_poll_answer_ids = user_poll_votes.pluck(:poll_answer_id).reject(&:blank?)
user_poll_vote_texts = user_poll_votes.pluck(:vote_text).reject(&:blank?)
if user_poll_answer_ids.count > 0
answer_content = q.poll_answers.find_answer_by_custom("id",user_poll_answer_ids)
if user_poll_answer_ids.count >1
u_answer = answer_content.pluck(:answer_text).join(";")
else
u_answer = answer_content.first.answer_text
end
elsif user_poll_vote_texts.count > 0
if user_poll_vote_texts.count > 1
u_answer = user_poll_vote_texts.join(";")
else
u_answer = user_poll_vote_texts.first
end
else
u_answer = "--"
end
else
u_answer = "--"
end
user_answer_array.push(u_answer)
end
user_cell = [index+1]
if poll_un_anony
user_login = u_user.login
user_name = u_user.real_name.present? ? u_user.real_name : "--"
user_student_id = u_user.student_id.present? ? u_user.student_id : "--"
user_cell += [user_login,user_name, u_user.mail, user_student_id]
end
all_user_cell = user_cell + user_answer_array
user_commit.push(all_user_cell)
end
{
poll_users_info:poll_users_info,
sub_commit:sub_commit,
user_commit:user_commit
}
end
end

@ -1,6 +1,6 @@
class PraiseTreadController < ApplicationController
include MessagesHelper
before_action :require_login
before_action :require_login, :check_auth
before_action :validate_params, only: [:like, :unlike]
before_action :find_object

@ -0,0 +1,6 @@
class ProjectPackageCategoriesController < ApplicationController
def index
categories = ProjectPackageCategory.cached_data
render_ok(count: categories.size, categories: categories)
end
end

@ -0,0 +1,78 @@
class ProjectPackagesController < ApplicationController
include PaginateHelper
before_action :require_login, :check_auth, only: %i[create update destroy]
helper_method :current_package, :package_manageable?
def index
packages = ProjectPackage.where(status: %w(published bidding_ended bidding_finished))
packages = packages.where(project_package_category_id: params[:category_id]) if params[:category_id].present?
keyword = params[:keyword].to_s.strip
packages = packages.where('title LIKE ?', "%#{keyword}%") if keyword.present?
@count = packages.count
direction = params[:sort_direction] == 'asc' ? 'asc' : 'desc'
sort = params[:sort_by] == 'price' ? 'min_price' : 'published_at'
packages = packages.order("#{sort} #{direction}")
@packages = paginate packages.includes(:creator, :attachments, :project_package_category, bidding_users: :user)
end
def show
return render_forbidden unless current_package.visitable? || package_manageable?
current_package.increment!(:visit_count)
end
def create
package = current_user.project_packages.new
ProjectPackages::SaveService.call(package, save_params)
package.increment!(:visit_count)
render_ok(id: package.id)
rescue ProjectPackages::SaveService::Error => ex
render_error(ex.message)
end
def update
package = current_user.project_packages.find(params[:id])
return render_error('该状态下不能编辑') unless package.editable?
ProjectPackages::SaveService.call(package, save_params)
package.increment!(:visit_count)
render_ok(id: package.id)
rescue ProjectPackages::SaveService::Error => ex
render_error(ex.message)
end
def destroy
package = ProjectPackage.find(params[:id])
return render_forbidden unless package.deletable? && package_manageable?
package.destroy!
Tiding.create!(user_id: package.creator_id, trigger_user_id: 1, container_id: package.id,
container_type: 'ProjectPackage', tiding_type: 'Destroyed', extra: package.title)
render_ok
end
private
def current_package
@_current_package ||= ProjectPackage.find(params[:id])
end
def package_manageable?
current_user&.id == current_package.creator_id || admin_or_business?
end
def save_params
params.permit(*%i[category_id title content attachment_ids deadline_at min_price max_price
contact_name contact_phone code publish])
end
end

@ -1,5 +1,5 @@
class QuestionBanksController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :params_filter
# 题库选用列表
@ -178,6 +178,7 @@ class QuestionBanksController < ApplicationController
:question_type => q.question_type || 1,
:question_number => q.question_number,
:question_score => q.question_score,
:shixun_name => q.shixun_name,
:shixun_id => q.shixun_id
}
exercise_question = new_exercise.exercise_questions.new option
@ -240,8 +241,9 @@ class QuestionBanksController < ApplicationController
ActiveRecord::Base.transaction do
new_task = GraduationTask.new
new_task.attributes = task.attributes.dup.except("id", "course_id", "user_id", "quotes", "graduation_task_id",
"course_list_id")
"course_list_id", "gtask_bank_id", "created_at", "updated_at")
new_task.course_id = course.id
new_task.gtask_bank_id = task.id
new_task.user_id = current_user.id
if new_task.save!
new_task.create_work_list
@ -264,9 +266,12 @@ class QuestionBanksController < ApplicationController
def quote_gtopic_bank topic, course
ActiveRecord::Base.transaction do
new_topic = GraduationTopic.new
new_topic.attributes = topic.attributes.dup.except("id", "course_id", "user_id", "graduation_topic_id", "course_list_id")
new_topic.attributes = topic.attributes.dup.except("id", "course_id", "user_id", "graduation_topic_id", "quotes",
"course_list_id", "gtopic_bank_id", "created_at", "updated_at")
new_topic.course_id = course.id
new_topic.gtopic_bank_id = topic.id
new_topic.user_id = current_user.id
new_topic.tea_id = current_user.id
new_topic.save
topic.attachments.each.try(:each) do |attachment|

@ -0,0 +1,5 @@
class RepertoiresController < ApplicationController
def index
render_ok(repertoires: Repertoire.cache_data)
end
end

@ -1,8 +1,16 @@
class SchoolsController < ApplicationController
def school_list
schools = School.all
search = params[:search].to_s.strip
if search.present?
schools = schools.where('name Like ?', "%#{search}%")
end
def school_list
q = params[:search] ? params[:search].strip : ""
@schools = School.where("name like ?", "%#{q}%").pluck(:name)
render_ok(school_names: schools.pluck(:name))
end
def for_option
render_ok(schools: School.cached_names_data)
end
end

@ -0,0 +1,10 @@
class SearchsController < ApplicationController
def index
@results = SearchService.call(search_params)
end
private
def search_params
params.permit(:keyword, :type, :page, :per_page)
end
end

@ -1,9 +1,13 @@
class ShixunsController < ApplicationController
before_action :require_login, except: [:download_file, :index]
# before_action :check_auth, except: [:download_file, :index]
include ShixunsHelper
include ApplicationHelper
before_action :find_shixun, except: [:index, :new, :create, :menus, :get_recommend_shixuns, :propaedeutics,
:departments, :apply_shixun_mirror, :get_mirror_script, :download_file]
before_action :require_login, :check_auth, except: [:download_file, :index, :menus]
before_action :check_auth, except: [:download_file, :index, :menus]
before_action :find_shixun, :shixun_access_allowed, except: [:index, :new, :create, :menus, :get_recommend_shixuns,
:propaedeutics, :departments, :apply_shixun_mirror,
:get_mirror_script, :download_file]
before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy]
before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish,
@ -13,14 +17,12 @@ class ShixunsController < ApplicationController
before_action :special_allowed, only: [:send_to_course, :search_user_courses]
include ShixunsHelper
include ApplicationHelper
## 获取课程列表
def index
## 我的实训
@shixuns =
if params[:order_by] == 'mine'
tip_exception(401, "..") unless current_user.logged?
current_user.my_shixuns
else
Shixun.unhidden
@ -43,11 +45,12 @@ class ShixunsController < ApplicationController
## 搜索关键字 匹配关卡名, 用户名, 实训名 和 空格多搜索
if params[:keyword].present?
keyword = params[:keyword].strip
@shixuns = @shixuns.joins(:users, challenges: :challenge_tags).
where("challenge_tags.name like '%#{keyword}%'
or challenges.subject like '%#{keyword}%'
or concat(lastname, firstname) like '%#{keyword}%'
or shixuns.name like '%#{keyword.split(" ").join("%")}%'")
@shixuns = @shixuns.joins(:user, challenges: :challenge_tags).
where("challenge_tags.name like :keyword
or challenges.subject like :keyword
or concat(lastname, firstname) like :keyword
or shixuns.name like :name",
keyword: "%#{keyword}%", name: "%#{keyword.split(" ").join("%")}%").distinct
end
## 筛选 状态
@ -57,7 +60,7 @@ class ShixunsController < ApplicationController
end
## 筛选 难度
if params[:diff].present? && params[:diff].to_i != 0
if params[:diff].present? && params[:diff].to_i != 0
@shixuns = @shixuns.where(trainee: params[:diff])
end
@ -67,21 +70,27 @@ class ShixunsController < ApplicationController
when 'new'
@shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.created_at #{bsort}")
when 'hot'
@shixuns = @shixuns.order("shixuns.status = 2 desc, myshixuns_count #{bsort}")
@shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.myshixuns_count #{bsort}")
when 'mine'
@shixuns = @shixuns.order("shixuns.created_at #{bsort}")
else
@shixuns = @shixuns.order("shixuns.status = 2 desc, publish_time #{bsort}")
@shixuns = @shixuns.order("shixuns.status = 2 desc, shixuns.publish_time #{bsort}")
end
@total_count = @shixuns.count
# 用id计数会快10+MS左右,对于搜索的内容随着数据的增加,性能会提升一些。
@total_count = @shixuns.count("shixuns.id")
## 分页参数
page = params[:page] || 1
limit = params[:limit] || 16
@shixuns = @shixuns.includes(:tag_repertoires, :challenges).page(page).per(limit)
@tag_name_map = TagRepertoire.joins(:shixun_tag_repertoires)
.where(shixun_tag_repertoires: { shixun_id: @shixuns.map(&:id) })
.group('shixun_tag_repertoires.shixun_id')
.select('shixun_id, tag_repertoires.name')
.each_with_object({}) { |r, obj| obj[r.shixun_id] = r.name }
end
## 获取顶部菜单
@ -115,8 +124,8 @@ class ShixunsController < ApplicationController
def show_right
owner = @shixun.owner
#@fans_count = owner.followers.count
#@followed_count = owner.followed_users.count
#@fans_count = owner.fan_count
#@followed_count = owner.follow_count
@user_own_shixuns = owner.shixuns.published.count
end
@ -127,7 +136,7 @@ class ShixunsController < ApplicationController
select m.user_id, u.login, u.lastname, m.updated_at,
(select sum(cost_time) from games g where g.myshixun_id = m.id) as time,
(select sum(final_score) from games g where g.myshixun_id = m.id) as score
from (myshixuns m join users u on m.user_id = u.id) where m.shixun_id = #{@shixun.id} and m.status = 1
from (users u left join myshixuns m on m.user_id = u.id) where m.shixun_id = #{@shixun.id} and m.status = 1
order by score desc, time asc limit 10
"
@myshixuns = Myshixun.find_by_sql(sql)
@ -178,6 +187,17 @@ class ShixunsController < ApplicationController
ShixunTagRepertoire.create!(:tag_repertoire_id => str.tag_repertoire_id, :shixun_id => @new_shixun.id)
end
# 同步配置
logger.info("########-shixun_service_configs_count: #{@shixun.shixun_service_configs.pluck(:id, :shixun_id)}")
@shixun.shixun_service_configs.each do |config|
ShixunServiceConfig.create!(:shixun_id => @new_shixun.id,
:cpu_limit => config.cpu_limit,
:lower_cpu_limit => config.lower_cpu_limit,
:memory_limit => config.memory_limit,
:request_limit => config.request_limit,
:mirror_repository_id => config.mirror_repository_id)
end
# fork版本库
logger.info("###########fork_repo_path: ######{@repo_path}")
project_fork(@new_shixun, @repo_path, current_user.login)
@ -192,6 +212,13 @@ class ShixunsController < ApplicationController
new_challenge.user_id = User.current.id
new_challenge.shixun_id = @new_shixun.id
new_challenge.save!
# 同步参考答案
challenge.challenge_answers.each do |answer|
new_answer = ChallengeAnswer.new
new_answer.attributes = answer.attributes.dup.except("id","challenge_id")
new_answer.challenge_id = new_challenge.id
new_answer.save!
end
if challenge.st == 0 # 评测题
# 同步测试集
if challenge.test_sets.present?
@ -269,7 +296,6 @@ class ShixunsController < ApplicationController
@small_type = shixun_small_type
end
# 注意这里传参都应该使用params[:shixun]['name']这种格式
def create
# 评测脚本的一些操作
main_type, sub_type = params[:main_type], params[:small_type]
@ -314,9 +340,13 @@ class ShixunsController < ApplicationController
# 镜像-实训关联表
ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i) if main_type.present?
# 实训主镜像服务配置
ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => main_type.to_i)
if sub_type.present?
sub_type.each do |mirror|
ShixunMirrorRepository.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
# 实训子镜像服务配置
ShixunServiceConfig.create!(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
end
end
@ -362,11 +392,6 @@ class ShixunsController < ApplicationController
end
def update
h = {test_set_permission: params[:test_set_permission], code_hidden: params[:code_hidden],
task_pass: params[:task_pass], hide_code: params[:hide_code], forbid_copy: params[:forbid_copy]}
s_params = shixun_params.merge(h)
ActiveRecord::Base.transaction do
begin
@shixun.shixun_mirror_repositories.destroy_all
@ -378,9 +403,8 @@ class ShixunsController < ApplicationController
ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
end
end
@shixun.update_attributes(s_params)
@shixun.shixun_info.update_attributes(description: params[:description], evaluate_script: params[:evaluate_script])
@shixun.update_attributes(shixun_params)
@shixun.shixun_info.update_attributes(shixun_info_params)
@shixun.shixun_schools.delete_all
if params[:scope_partment].present? && params[:user_scope].to_i == 1
arr = []
@ -394,6 +418,11 @@ class ShixunsController < ApplicationController
use_scope = 0
end
@shixun.update_attributes!(:use_scope => use_scope)
# 超级管理员和运营人员才能保存 中间层服务器pod信息的配置
if current_user.admin? || current_user.business?
@shixun.shixun_service_configs.destroy_all
@shixun.shixun_service_configs.create!(service_config_params[:shixun_service_configs])
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception("实训保存失败")
@ -409,12 +438,12 @@ class ShixunsController < ApplicationController
end
def propaedeutics
@content = Shixun.where(identifier: params[:identifier]).pluck(:propaedeutics)
@content = Shixun.find_by_identifier!(params[:identifier]).propaedeutics
end
# 更新背景知识
def update_propaedeutics
@shixun.update_column(:propaedeutics, params[:content])
@shixun.shixun_info.update_column(:propaedeutics, params[:content])
end
# 获取推荐实训接口 2个热门实训 + 2个最新实训
@ -429,6 +458,7 @@ class ShixunsController < ApplicationController
@choice_small_type = @shixun.small_mirror_id
@main_type = shixun_main_type
@small_type = shixun_small_type
@configs = @shixun.shixun_service_configs
#@mirror_script = MirrorScript.select([:id, :script_type]).find(@shixun.mirror_script_id).attributes if @shixun.mirror_script_id && @shixun.mirror_script_id != 0
# @shixun_main_mirror = @shixun.show_shixun_mirror
# @script_type = @shixun.script_tag.try(:script_type) || "无"
@ -472,8 +502,8 @@ class ShixunsController < ApplicationController
# TODO: 目前实训只做软删除.
def destroy
# apply_records = ApplyAction.where(container_id: @shixun.id, container_type: "ApplyShixun")
# apply_records.delete_all if apply_records
apply_records = ApplyAction.where(container_id: @shixun.id, container_type: "ApplyShixun")
apply_records.delete_all if apply_records
# HomeworkCommonShixuns.where(shixun_id: @shixun).delete_all
# @shixun.destroy
@shixun.update_column(:status, -1)
@ -484,21 +514,46 @@ class ShixunsController < ApplicationController
# 中间需要一个过渡动画
# TODO: 第一次开启实训都会去判断是否是纯选择题类型,感觉做成在创建关卡的时候就判断该实训是否是纯选择题更加合适
def shixun_exec
current_myshixun = @shixun.current_myshixun(current_user.id)
if @shixun.opening_time.present? && @shixun.opening_time > Time.now && current_user.shixun_identity(@shixun) > User::EDU_SHIXUN_MEMBER
if is_shixun_opening?
tip_show_exception(-3, "#{@shixun.opening_time.strftime('%Y-%m-%d %H:%M:%S')}")
end
current_myshixun = @shixun.current_myshixun(current_user.id)
min_challenges = @shixun.challenges.pluck(:id , :st)
if current_myshixun
# 如果TPM和TPI的管卡数不相等或者关卡顺序错了说明实训被极大的改动需要重置
if current_myshixun.games.count != @shixun.challenges_count || current_myshixun.games.map(&:challenge_id).sort != Challenge.where(shixun_id: @shixun.id).pluck(:id).sort
Rails.logger.info("11111111112#{current_myshixun.try(:id)}")
Rails.logger.info("111111111102#{params[:reset] != 1}")
# 因为读写分离有延迟所以如果是重置来的请求可以先跳过重置过来的params[:reset]为1
if current_myshixun && params[:reset] != "1"
games = current_myshixun.games
# 如果TPM和TPI的管卡数不相等或者关卡顺序错了说明实训被极大的改动需要重置,实训发布前打过的实训都需要重置
if is_shixun_reset?(games, min_challenges, current_myshixun)
# 这里页面弹框要收到 当前用户myshixun的identifier.
tip_show_exception("/myshixuns/#{current_myshixun.try(:identifier)}/reset_my_game")
end
if current_myshixun.repo_name.nil?
g = Gitlab.client
repo_name = g.project(current_myshixun.gpid).try(:path_with_namespace)
current_myshixun.update_column(:repo_name, repo_name)
end
# 如果存在实训,则直接进入实训
@current_task = current_myshixun.current_task
# 如果实训允许跳关传参params[:challenge_id]跳入具体的关卡
@current_task =
if params[:challenge_id]
game = games.where(challenge_id: params[:challenge_id]).take
if @shixun.task_pass || game.status != 3
game
else
current_myshixun.current_task(games)
end
else
current_myshixun.current_task(games)
end
else
# 如果未创建关卡一定不能开启实训否则TPI没法找到当前的关卡
if @shixun.challenges_count == 0
@ -506,10 +561,10 @@ class ShixunsController < ApplicationController
end
# 判断实训是否全为选择题
is_choice_type = @shixun.is_choice_type?
is_choice_type = (min_challenges.size == min_challenges.select{|challenge| challenge.last == 1}.count)
if !is_choice_type
commit = GitService.commits(repo_path: @repo_path).try(:first)
Rails.logger.info("First comit########{commit}")
uid_logger("First comit########{commit}")
tip_exception("开启实战前请先在版本库中提交代码") if commit.blank?
commit_id = commit["id"]
end
@ -523,6 +578,21 @@ class ShixunsController < ApplicationController
onclick_time: Time.now, commit_id: commit_id)
uid_logger("myshixun_id is #{myshixun.id}")
# 其它创建关卡等操作
challenges = @shixun.challenges
# 之所以增加user_id是为了方便统计查询性能
game_attrs = %i[challenge_id myshixun_id status user_id open_time identifier modify_time created_at updated_at]
Game.bulk_insert(*game_attrs) do |worker|
base_attr = { myshixun_id: myshixun.id, user_id: myshixun.user_id }
challenges.each_with_index do |challenge, index|
status = (index == 0 ? 0 : 3)
game_identifier = generate_identifier(Game, 12)
worker.add(base_attr.merge(challenge_id: challenge.id, status: status, open_time: Time.now,
identifier: game_identifier, modify_time: challenge.modify_time))
end
end
# 如果实训是纯选择题则不需要去fork仓库以及中间层的相关操作了
unless is_choice_type
# fork仓库
@ -534,22 +604,10 @@ class ShixunsController < ApplicationController
logger.info("end openGameInstance")
params = {tpiID: "#{myshixun.id}", tpmGitURL:rep_url, tpiRepoName: myshixun.repo_name.split("/").last}
uid_logger("openGameInstance params is #{params}")
# res = interface_post uri, params, 83, "实训云平台繁忙繁忙等级83"
end
# 其它创建关卡等操作
challenges = @shixun.challenges
# 之所以增加user_id是为了方便统计查询性能
challenges.each_with_index do |challenge, index|
status = (index == 0 ? 0 : 3)
game_identifier = generate_identifier(Game, 12)
Game.create!(:challenge_id => challenge.id, :myshixun_id => myshixun.id, :status => status, :user_id => myshixun.user_id,
:open_time => Time.now, :identifier => game_identifier, :modify_time => challenge.modify_time)
interface_post uri, params, 83, "实训云平台繁忙繁忙等级83"
end
# REDO:开启实训时更新关联作品的状态
HomeworksService.new.update_myshixun_work_status myshixun
@current_task = myshixun.current_task
@current_task = myshixun.current_task(myshixun.games)
uid_logger("## shixun exec: myshixun id is #{myshixun.id}")
rescue Exception => e
uid_logger_error(e.message)
@ -558,10 +616,8 @@ class ShixunsController < ApplicationController
end
end
end
end
# gameID 及实训ID
# status: 0 , 1 申请过, 2实训关卡路径未填 3 实训标签未填, 4 实训未创建关卡
def publish
@ -611,16 +667,27 @@ class ShixunsController < ApplicationController
def update_file
content = params[:content]
author_name = current_user.full_name
author_email = current_user.mail
author_email = current_user.git_mail
@content = update_file_content content, @repo_path, @path, author_email, author_name, "Edit by browser"
end
def add_collaborators
raise("搜索内容不能为空") unless params[:search]
member_ids = "(" + @shixun.shixun_members.map(&:user_id).join(',') + ")"
condition = "%#{params[:search].strip}%".gsub(" ","")
@users = User.where("id not in #{member_ids} and status = 1 and LOWER(concat(lastname, firstname, login, mail, nickname)) LIKE '#{condition}'")
end
member_ids = "(" + @shixun.shixun_members.map(&:user_id).join(',') + ")"
user_name = "%#{params[:user_name].to_s.strip}%"
school_name = "%#{params[:school_name].to_s.strip}%"
if user_name.present? || school_name.present?
@users = User.joins(user_extension: :school).where("users.id not in #{member_ids} AND users.status = 1 AND
(LOWER(users.lastname) LIKE ? or users.phone like ?) AND LOWER(schools.name) LIKE
?", user_name, user_name, school_name)
else
@users = User.none
end
page = params[:page] || 1
limit = params[:limit] || 20
@user_count = @users.count
@users = @users.page(page).per(limit)
end
def shixun_members_added
raise("user_ids 不能为空!") if params[:user_ids].blank?
@ -661,14 +728,14 @@ class ShixunsController < ApplicationController
limit = params[:limit] || 20
if params[:search]
search = "%#{params[:search].to_s.strip.downcase}%"
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, members m, member_roles mr
WHERE m.course_id = c.id AND m.id=mr.member_id AND mr.role_id in (3,7,9)
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m
WHERE m.course_id = c.id AND m.role in (1,2,3)
AND m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0
AND c.name like '#{search}' ").map(&:id)
else
course_ids = Course.find_by_sql("SELECT c.id, c.name FROM courses c, members m, member_roles mr
WHERE m.course_id = c.id AND m.id=mr.member_id AND mr.role_id in (3,7,9)
course_ids = Course.find_by_sql("SELECT c.id, c.name FROM courses c, course_members m
WHERE m.course_id = c.id AND m.role in (1,2,3)
AND m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0").map(&:id)
end
@ -680,7 +747,7 @@ class ShixunsController < ApplicationController
# 将实训发送到课程
def send_to_course
@course = Course.find(params[:course_id])
homework = HomeworksService.new.create_homework shixun, @course, nil, current_user
homework = HomeworksService.new.create_homework @shixun, @course, nil, current_user
end
# 二维码扫描下载
@ -693,32 +760,40 @@ class ShixunsController < ApplicationController
# 撤销发布
def cancel_publish
tip_exception("实训已经发布,无法撤销") if @shixun.status == 2
apply = ApplyAction.where(:container_type => "ApplyShixun", :container_id => @shixun.id).order("created_at desc").first
if apply && apply.status == 0
apply.update_attribute(:status, 3)
apply.tidings.destroy_all
@shixun.update_column('status', 0)
end
@shixun.update_column(:status, 0)
end
private
def shixun_params
raise("实训名称不能为空") if params[:name].blank?
raise("实训名称不能为空") if params[:shixun][:name].blank?
params.require(:shixun).permit(:name, :trainee, :webssh, :can_copy, :use_scope, :vnc, :test_set_permission,
:task_pass, :repo_name, :multi_webssh, :opening_time, :mirror_script_id)
:task_pass, :multi_webssh, :opening_time, :mirror_script_id, :code_hidden,
:hide_code, :forbid_copy)
end
def shixun_info_params
raise("实训描述不能为空") if params[:shixun_info][:description].blank?
raise("评测脚本不能为空") if params[:shixun_info][:evaluate_script].blank?
params.require(:shixun_info).permit(:description, :evaluate_script)
end
def service_config_params
params.permit(shixun_service_configs: [:cpu_limit, :lower_cpu_limit, :memory_limit, :request_limit, :mirror_repository_id])
end
def find_shixun
@shixun = Shixun.find_by_identifier(params[:identifier])
shixun = Shixun.where(identifier: params[:identifier]).first
if @shixun.blank?
normal_status(404, "...")
return
end
if !current_user.shixun_permission(@shixun) || (@shixun.status == -1 && !current_user.admin?)
tip_exception(403, "..")
end
end
def find_repo_name
@ -743,4 +818,20 @@ private
tip_exception(403, "..")
end
end
# 实训是否需要开启
def is_shixun_opening?
@shixun.opening_time.present? &&
@shixun.opening_time > Time.now &&
current_user.shixun_identity(@shixun) > User::EDU_SHIXUN_MEMBER
end
# 实训是否需要重置
def is_shixun_reset?(games, min_challenges, current_myshixun)
# 用户在申请发布之前,是否玩过实训 TODO: 重置的字段应该迁移到myshixuns表比较合适
modify_shixun = ShixunModify.exists?(:myshixun_id => current_myshixun.id, :shixun_id => @shixun.id, :status => 1)
games.size != min_challenges.size ||
games.map(&:challenge_id) != min_challenges.map{|challenge| challenge.first} ||
modify_shixun
end
end

@ -1,5 +1,5 @@
class StagesController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :find_subject, only: [:create, :index]
before_action :find_stage, only: [:update, :destroy, :edit, :up_position, :down_position]
before_action :allowed, except: [:index]

@ -2,7 +2,7 @@ class StudentWorksController < ApplicationController
include HomeworkCommonsHelper
include StudentWorksHelper
before_action :require_login
before_action :require_login, :check_auth
before_action :find_homework, only: [:new, :create, :search_member_list, :check_project, :relate_project,
:cancel_relate_project]
before_action :find_work, only: [:shixun_work_report, :adjust_review_score, :shixun_work, :commit_des, :update_des,
@ -25,7 +25,7 @@ class StudentWorksController < ApplicationController
before_action :require_score_id, only: [:destroy_score, :add_score_reply, :appeal_anonymous_score, :deal_appeal_score, :cancel_appeal]
before_action :is_evaluation, only: [:show, :supply_attachments]
before_action :is_evaluation, :open_work, only: [:show, :supply_attachments]
def new
uid_logger("#######new current_user : 1111")
@ -41,14 +41,16 @@ class StudentWorksController < ApplicationController
# 搜索课堂学生
def search_member_list
unless params[:search].blank?
@members = @course.students.joins(:user).where("user_id != #{current_user.id} and
concat(users.lastname, users.firstname) like ?", "%#{params[:search]}%")
# 统一设置的作业取所有学生,否则取已发布的分班学生
students = @homework.unified_setting? ? @course.students : @course.students.where(course_group_id: @homework.published_settings.pluck(:course_group_id))
if !params[:search].blank?
@members = students.joins(user: :user_extension).where("course_members.user_id != #{current_user.id} and (concat(users.lastname, users.firstname)
like ? or user_extensions.student_id like ?)", "%#{params[:search]}%", "%#{params[:search]}%")
else
# 没有搜索条件时搜索课堂所有未提交的学生
user_ids = @homework.student_works.where("work_status = 0").pluck(:user_id) - [current_user.id]
@members = @course.students.where(user_id: user_ids)
@members = students.where(user_id: user_ids)
end
page = params[:page] ? params[:page].to_i : 1
@ -332,8 +334,9 @@ class StudentWorksController < ApplicationController
ActiveRecord::Base.transaction do
begin
# 没传score则取上次评分成绩
score = StudentWorksScore.where(user_id: current_user.id, student_work_id: @work.id).last
reviewer_role = @user_course_identity == Course::STUDENT ? 3 : @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1
new_score = StudentWorksScore.new
score = StudentWorksScore.where(user_id: current_user.id, student_work_id: @work.id, reviewer_role: reviewer_role).last
new_score.score = params[:score].blank? ? score.try(:score) : params[:score].to_f
new_score.comment = params[:comment] if params[:comment] && params[:comment].strip != ""
new_score.user_id = current_user.id
@ -346,7 +349,7 @@ class StudentWorksController < ApplicationController
@work.update_attributes(group_id: @homework.max_group_id) if @homework.homework_type == "group"
end
new_score.reviewer_role = @user_course_identity == Course::STUDENT ? 3 : @user_course_identity == Course::ASSISTANT_PROFESSOR ? 2 : 1
new_score.reviewer_role = reviewer_role
if new_score.save!
Attachment.associate_container(params[:attachment_ids], new_score.id, new_score.class)
@ -379,7 +382,7 @@ class StudentWorksController < ApplicationController
when 3 #学生评分 学生评分显示平均分
# 匿评分
@work.student_score = new_score.stu_score(@work.id)
if @homework.homework_type == "group" && params[:same_score] && new_score.score.present?
if @homework.homework_type == "group" && new_score.score.present?
add_score_to_member @work, @homework, new_score
end
@ -427,10 +430,17 @@ class StudentWorksController < ApplicationController
def shixun_work_report
@user = @work.user
@shixun = @homework.shixuns.take
@games = @work.myshixun.games.includes(:challenge, :game_codes,:outputs) if @work.myshixun
# 提示: 这里如果includes outputs表的话 sum(:evaluate_count)会出现错误
@games = @work.myshixun.games.joins(:challenge).reorder("challenges.position asc") if @work.myshixun
# 用户最大评测次数
@user_evaluate_count = @games.inject(0){|sum, g| sum + g.outputs.pluck(:query_index).first.to_i } if @games
if @games
@user_evaluate_count = @games.pluck(:evaluate_count).sum
@games = @games.includes(:challenge, :game_codes, :outputs)
else
@user_evaluate_count = 0
end
# 图形效率图的数据
@echart_data = student_efficiency(@homework, @work)
end
@ -438,17 +448,17 @@ class StudentWorksController < ApplicationController
def export_shixun_work_report
@user = @work.user
@shixun = @homework.shixuns.take
@games = @work.myshixun.games.includes(:challenge, :game_codes,:outputs) if @work.myshixun
@games = @work.myshixun.games.includes(:challenge, :game_codes, :outputs) if @work.myshixun
# 用户最大评测次数
@user_evaluate_count = @games.inject(0){|sum, g| sum + g.outputs.pluck(:query_index).first.to_i } if @games
@user_evaluate_count = @games.pluck(:evaluate_count).sum if @games
# 图形效率图的数据
@echart_data = student_efficiency(@homework, @work)
@myself_eff = @echart_data[:efficiency_list].find { |item| item.last == @user.id }
@myself_consume = @echart_data[:consume_list].find { |item| item.last == @user.id }
# filename = "实训报告_#{@shixun.name}_#{@use.real_name}_#{Time.current.strftime('%Y%m%d%H%M%S')}.pdf" #下载报错 unknown nil name,下面为修改的-hs-0606
filename = "实训报告_#{@shixun&.name}_#{@use&.real_name}_#{Time.current.strftime('%Y%m%d%H%M%S')}.pdf"
filename_ = "实训报告_#{@shixun&.name}_#{@use&.real_name}"
filename = Base64.urlsafe_encode64(filename_.strip.first(30))
stylesheets = %w(shixun_work/shixun_work.css shared/codemirror.css)
render pdf: 'shixun_work/shixun_work', filename: filename, stylesheets: stylesheets
end
@ -580,6 +590,9 @@ class StudentWorksController < ApplicationController
score_appeal.tidings.update_all(status: 1)
if params[:status].to_i == 3
# 申诉成功后该评分失效
score.update_attributes(is_invalid: 1)
# 申诉成功后 扣匿评学生的违规匿评扣分
sw = @homework.student_works.find_by(user_id: score.user_id)
sw.update_attribute("appeal_penalty", @homework.homework_detail_manual.appeal_penalty + sw.appeal_penalty) if sw.present?
@ -618,16 +631,35 @@ class StudentWorksController < ApplicationController
# 查重作品调分
def adjust_review_score
if params[:score].nil? || params[:challenge_id].nil? || params[:code_rate].nil? || params[:copy_user_id].nil?
tip_exception("缺少type参数") if params[:type].blank? || !["review", "report"].include?(params[:type])
if params[:type] == "review" && (params[:score].nil? || params[:challenge_id].nil? || params[:code_rate].nil? || params[:copy_user_id].nil?)
tip_exception("参数错误score和challenge_id和code_rate和copy_user_id不能为空")
elsif params[:type] == "report" && (params[:score].nil? || params[:challenge_id].nil?)
tip_exception("参数错误score和challenge_id")
end
challenge_setting = @homework.homework_challenge_settings.find_by(challenge_id: params[:challenge_id])
challenge = challenge_setting&.challenge
tip_exception("不能小于零") if params[:score] < 0
tip_exception("不能大于关卡分值:#{challenge_setting.score}") if challenge_setting.score < params[:score]
ActiveRecord::Base.transaction do
begin
if params[:type] == "review"
copy_user = User.find params[:copy_user_id]
comment = "代码查重结果显示与#{copy_user.try(:show_real_name)}的代码相似度#{params[:code_rate]}%"
else
comment = "根据实训报告中最终提交的代码调整第#{challenge.position}关分数"
end
challenge_score = @work.challenge_work_scores.create(challenge_id: params[:challenge_id], user_id: current_user.id, score: params[:score],
comment: comment)
challenge_score.create_tiding current_user.id
HomeworksService.new.update_myshixun_work_score @work, @work&.myshixun, @work&.myshixun&.games, @homework, @homework.homework_challenge_settings
rescue Exception => e
uid_logger(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
end
copy_user = User.find params[:copy_user_id]
comment = "代码查重结果显示与#{copy_user.try(:show_real_name)}的代码相似度#{params[:code_rate]}%"
@work.challenge_work_scores.create(challenge_id: params[:challenge_id], user_id: current_user.id, score: params[:score],
comment: comment)
HomeworksService.new.set_shixun_final_score(@work)
@work_score = @homework.student_works.find_by(id: @work.id).try(:work_score)
end
@ -692,6 +724,11 @@ class StudentWorksController < ApplicationController
[3, 4].include?(@homework.homework_detail_manual.comment_status)
end
# 作品是否公开
def open_work
tip_exception(403,"没有操作权限") unless (@user_course_identity < Course::STUDENT || current_user == @work.user || @homework.work_public || @is_evaluation)
end
def allow_add_score
# 老师始终有评阅权限,匿评阶段内,学生对分配给该学生的作品有评阅权限
tip_exception(403, "没有权限") unless allow_score(@homework, @user_course_identity, current_user.id, @work)
@ -713,19 +750,19 @@ class StudentWorksController < ApplicationController
student_works.each do |st_work|
st_score = StudentWorksScore.new(user_id: new_score.user_id, score: new_score.score,
reviewer_role: new_score.reviewer_role, comment: new_score.comment)
st_work.student_works_scores << st_score
score = StudentWorksScore.where(user_id: new_score.user_id, student_work_id: st_work.id).last
score = StudentWorksScore.where(user_id: new_score.user_id, student_work_id: st_work.id, reviewer_role: new_score.reviewer_role).last
# 该用户的历史评阅无效
score.update_column('is_invalid', true) if score.present? && score.score.present?
st_work.student_works_scores << st_score
if new_score.reviewer_role == 1
st_work.teacher_score = new_score.score
st_work.teacher_score = new_score.score if new_score.score.present?
elsif new_score.reviewer_role == 2
if homework.homework_detail_manual.ta_mode == 1
st_work.teaching_asistant_score = new_score.ta_score st_work.id
else
st_work.teaching_asistant_score = new_score.score
st_work.teaching_asistant_score = new_score.score if new_score.score.present?
end
else
st_work.student_score = student_work.student_score

@ -1,5 +1,5 @@
class SubjectsController < ApplicationController
before_action :require_login, except: [:index]
before_action :require_login, :check_auth, except: [:index]
# before_action :check_auth, except: [:index]
before_action :find_subject, except: [:index, :create, :append_to_stage]
before_action :allowed, only: [:update, :edit, :destroy, :publish, :cancel_publish, :cancel_has_publish,
@ -22,21 +22,23 @@ class SubjectsController < ApplicationController
# 最热排序
if reorder == "myshixun_count"
if select
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, COUNT(myshixuns.id) AS myshixun_member_count FROM myshixuns, stage_shixuns, subjects
WHERE myshixuns.shixun_id = stage_shixuns.shixun_id AND stage_shixuns.subject_id = subjects.id
AND `subjects`.`hidden` = 0 AND `subjects`.`status` = 2 AND `subjects`.`name` like '%#{search}%'
AND `subjects`.`repertoire_id` = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, COUNT(myshixuns.id) AS myshixun_member_count FROM myshixuns, stage_shixuns, subjects
WHERE myshixuns.shixun_id = stage_shixuns.shixun_id AND stage_shixuns.subject_id = subjects.id
AND `subjects`.`hidden` = 0 AND `subjects`.`status` = 2 AND `subjects`.`name` like '%#{search}%'
GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
end
else
# 我的路径
if reorder == "mine"
tip_exception(401, "..") unless current_user.logged?
mine_subject_id = StageShixun.find_by_sql("select DISTINCT(subject_id) from stage_shixuns where shixun_id in
(select distinct(shixun_id) from myshixuns where user_id=#{current_user.id})").map(&:subject_id)
manage_subject_id = SubjectMember.where(user_id: current_user.id).pluck(:subject_id)
@ -65,9 +67,12 @@ class SubjectsController < ApplicationController
@total_count = @subjects.size
if reorder != "myshixun_count"
@subjects = @subjects.page(page).per(limit).includes(:shixuns)
@subjects = @subjects.page(page).per(limit).includes(:shixuns, :repertoire)
else
@subjects = @subjects[offset, limit]
subject_ids = @subjects.pluck(:id)
order_ids = subject_ids.size > 0 ? subject_ids.join(',') : -1
@subjects = Subject.where(id: subject_ids).order("field(id,#{order_ids})").includes(:shixuns, :repertoire)
end
end
@ -81,6 +86,9 @@ class SubjectsController < ApplicationController
@tags = ChallengeTag.where(challenge_id: challenge_ids).pluck(:name).uniq
# 用户获取的实训标签
@user_tags = @subject.shixuns.map(&:user_tags_name).flatten.uniq
# 访问数变更
@subject.increment!(:visits)
end
def create
@ -131,7 +139,7 @@ class SubjectsController < ApplicationController
if current_user.admin?
@shixuns = Shixun.select([:id, :name, :status, :myshixuns_count, :identifier]).where(hidden: 0)
else
none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id)}").pluck(:shixun_id)
none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id).to_i}").pluck(:shixun_id)
@shixuns = Shixun.select([:id, :name, :status, :myshixuns_count, :identifier]).where.not(id: none_shixun_ids).where(hidden: 0)
end
@ -164,11 +172,11 @@ class SubjectsController < ApplicationController
end
def choose_course
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, members m, member_roles mr
WHERE m.course_id = c.id AND m.id=mr.member_id AND mr.role_id in (3,7,9)
course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m
WHERE m.course_id = c.id AND m.role in (1,2,3)
AND m.user_id=#{current_user.id} AND c.is_delete = 0 AND c.is_end = 0").map(&:id)
@courses = Course.where(id: course_ids)
@none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id)}").pluck(:shixun_id)
@none_shixun_ids = ShixunSchool.where("school_id != #{current_user.user_extension.try(:school_id).to_i}").pluck(:shixun_id)
end
def send_to_course
@ -183,7 +191,7 @@ class SubjectsController < ApplicationController
stages.each do |stage|
category = CourseSecondCategory.where(name: stage.name, course_id: @course.id, category_type: "shixun_homework").first ||
CourseSecondCategory.create!(name: stage.name, course_id: @course.id, category_type: "shixun_homework",
course_module_id: course_module, position: course_module.course_second_categories.count + 1)
course_module_id: course_module.id, position: course_module.course_second_categories.count + 1)
stage.shixuns.where(id: params[:shixun_ids], status: 2).each do |shixun|
homework = HomeworksService.new.create_homework shixun, @course, category, current_user

@ -1,4 +1,5 @@
class TrialAppliesController < ApplicationController
before_action :require_user_login
def create
Users::ApplyTrailService.call(current_user, create_params)
@ -12,4 +13,10 @@ class TrialAppliesController < ApplicationController
def create_params
params.permit(:phone, :code, :reason).merge(remote_ip: request.remote_ip)
end
def require_user_login
return if User.current.logged?
render_unauthorized
end
end

@ -1,4 +1,4 @@
class Users::AccountsController < Users::BaseController
class Users::AccountsController < Users::BaseAccountController
before_action :private_user_resources!
def show

@ -0,0 +1,39 @@
class Users::AuthAttachmentsController < Users::BaseAccountController
before_action :private_user_resources!
before_action :convert_image!, only: [:create]
def create
image_temp_path = auth_image_path + 'temp' # 上传文件保存至临时文件,提交申请时再移到正常目录
File.delete(image_temp_path) if File.exist?(image_temp_path) # 删除之前的临时文件
Util.write_file(@image, image_temp_path)
render_ok
rescue StandardError => ex
logger_error(ex)
render_error('上传失败')
end
private
def convert_image!
max_size = EduSetting.get('upload_avatar_max_size') || 10 * 1024 * 1024 # 10M
if params[:image].class == ActionDispatch::Http::UploadedFile
@image = params[:image]
render_error('请上传文件') if @image.size.zero?
render_error('文件大小超过限制') if @image.size > max_size
else
image = params[:image].to_s.strip
return render_error('请上传正确的图片') if image.blank?
@image = Util.convert_base64_image(image, max_size: max_size)
end
rescue Base64ImageConverter::Error => ex
render_error(ex.message)
end
def auth_image_path
url_method = params[:type] == 'professional' ? :disk_professional_auth_filename : :disk_real_name_auth_filename
ApplicationController.helpers.send(url_method, observed_user.id)
end
end

@ -0,0 +1,16 @@
class Users::AuthenticationAppliesController < Users::BaseAccountController
before_action :private_user_resources!
def create
Users::ApplyAuthenticationService.call(observed_user, create_params)
render_ok
rescue Users::ApplyAuthenticationService::Error => ex
render_error(ex.message)
end
private
def create_params
params.permit(:name, :id_number, :upload_image)
end
end

@ -28,6 +28,6 @@ class Users::AvatarsController < Users::BaseAccountController
end
def avatar_url
ApplicationController.helpers.url_to_avatar(observed_user)
ApplicationController.helpers.url_to_avatar(observed_user).to_s + "?#{Time.now.to_i}"
end
end

@ -4,4 +4,5 @@ class Users::BaseAccountController < Users::BaseController
def observed_user
@_observed_user ||= (User.find_by_id(params[:account_id]) || User.find_by_login(params[:account_id]))
end
end

@ -0,0 +1,26 @@
class Users::InterestsController < Users::BaseController
skip_before_action :check_observed_user_exists!
before_action :require_login
def create
return render_forbidden if current_user.user_extension&.identity.present?
identity = params[:identity].to_s.strip
extension = current_user.user_extension || current_user.build_user_extension
return render_error('请选择职业') unless %w(teacher student professional).include?(identity)
ActiveRecord::Base.transaction do
extension.update_column(:identity, identity)
# 兴趣
current_user.user_interests.delete_all
UserInterest.bulk_insert(:user_id, :repertoire_id) do |worker|
(Repertoire.pluck(:id) & Array.wrap(params[:interest_ids]).map(&:to_i)).each do |repertoire_id|
worker.add(user_id: current_user.id, repertoire_id: repertoire_id)
end
end
end
render_ok
end
end

@ -0,0 +1,16 @@
class Users::ProfessionalAuthAppliesController < Users::BaseAccountController
before_action :private_user_resources!
def create
Users::ApplyProfessionalAuthService.call(observed_user, create_params)
render_ok
rescue Users::ApplyProfessionalAuthService::Error => ex
render_error(ex.message)
end
private
def create_params
params.permit(:school_id, :department_id, :identity, :extra, :upload_image)
end
end

@ -4,6 +4,10 @@ class Users::ShixunsController < Users::BaseController
@count = shixuns.count
@shixuns = paginate(shixuns.includes(:first_tag_repertoire), special: true)
ids = @shixuns.map(&:id)
@finished_challenges_count_map = Game.joins(:myshixun).where(user_id: observed_user.id, status: 2)
.where(myshixuns: { shixun_id: ids }).group('myshixuns.shixun_id').count
end
private

@ -1,5 +1,5 @@
class Users::WatchesController < Users::BaseController
before_action :require_login
before_action :require_login, :check_auth
def create
if observed_logged_user?

@ -9,10 +9,6 @@ class UsersController < ApplicationController
@user = User.find params[:id]
@user.update!(user_params)
render_ok
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
raise ActiveRecord::Rollback
end
# 贴吧获取用户信接口
@ -41,6 +37,7 @@ class UsersController < ApplicationController
end
@course_identity = current_user.course_identity(@course) if @course
rescue Exception => e
uid_logger_error(e.message)
missing_template
end
@ -54,6 +51,13 @@ class UsersController < ApplicationController
:disposition => 'attachment' #inline can open in browser
end
def html_show
@contents = File.read("#{params[:path]}")
respond_to do |format|
format.html {render :layout => false}
end
end
# Redo: 消息总数缓存
def get_navigation_info
@old_domain = edu_setting('old_edu_host')
@ -61,7 +65,7 @@ class UsersController < ApplicationController
# 新消息数
@new_message = @user.tidings.where("created_at > '#{@user.click_time}'").count > 0 || @user.private_messages.where("created_at > '#{@user.click_time}'").count > 0
@user_url = "#{@old_domain}/users/#{@user.login}"
@user_url = "/users/#{@user.login}"
@career = Career.where(status: true).order("created_at asc").pluck(:id, :name)
ec_user = EcSchoolUser.where(:user_id => current_user.id).first
@auth = ec_user ? "#{@old_domain}/ecs/department?school_id=#{ec_user.school_id}" : nil
@ -69,21 +73,24 @@ class UsersController < ApplicationController
# 用户回复功能
def reply_message
@message = JournalsForMessage.new(reply_message_params)
@message.user_id = current_user.id
@message.save!
#normal_status("回复成功")
message = JournalsForMessage.new(reply_message_params)
message.user_id = current_user.id
message.save!
render_ok(id: message.id)
end
# 搜索用户具有管理员角色的项目
def search_user_projects
condition = '%%'
condition = "%#{params[:search].strip}%".gsub(" ","") if !params[:search].blank?
projects = Project.where.not(status: 9)
project_ids = Project.find_by_sql("SELECT p.id FROM projects p, members m, member_roles mr WHERE m.project_id = p.id
AND m.id=mr.member_id AND mr.role_id = 3 AND m.user_id=#{current_user.id} AND p.status != 9 and
p.name like '#{condition}'")
@projects = Project.where(id: project_ids.pluck(:id))
projects = projects.joins(members: :member_roles).where(member_roles: { role_id: 3 })
projects = projects.where(members: { user_id: current_user.id })
search = params[:search].to_s.strip
projects = projects.where('projects.name LIKE ?', "%#{search}%") if search.present?
@projects = projects.select(:id, :name)
end
# 个人主页信息
@ -91,10 +98,6 @@ class UsersController < ApplicationController
def brief_introduction
content = params[:content].to_s.strip
if content.blank?
render_error('内容不能为空')
return
end
current_user.user_extension.update!(brief_introduction: content)

@ -1,26 +1,24 @@
class ZipsController < ApplicationController
before_action :require_login
before_action :require_login, :check_auth
before_action :load_homework, only: [:shixun_report]
before_action :get_exercise, only: [:export_exercises]
before_action :require_admin_or_teacher
def shixun_report
student_work_ids = Array.wrap(params[:student_work_ids])
service = BatchExportShixunReportService.new(@homework, student_work_ids)
filename = filename_for_content_disposition(service.filename)
send_file service.zip, filename: filename, type: 'application/zip'
service = BatchExportShixunReportService.new(@homework, @all_student_works)
filename_ = filename_for_content_disposition(service.filename)
send_file service.zip, filename: filename_, type: 'application/zip'
rescue BatchExportShixunReportService::Error => ex
normal_status(-1, ex.message)
end
def export_exercises
exercises = ExportExercisesService.new(@exercise,@ex_users)
@request_url = request.base_url
exercises = ExportExercisesService.new(@exercise,@ex_users,@request_url)
file_name = filename_for_content_disposition(exercises.filename)
send_file exercises.ex_zip, filename: file_name, type: 'application/zip'
file_name_ = filename_for_content_disposition(exercises.filename)
send_file exercises.ex_zip, filename: file_name_, type: 'application/zip'
rescue Exception => e
normal_status(-1, e.message)
end
@ -39,27 +37,53 @@ class ZipsController < ApplicationController
def get_exercise
ActiveRecord::Base.transaction do
begin
@exercise = Exercise.find_by(id:params[:exercise_id])
@exercise = Exercise.includes(:exercise_users,:exercise_questions).find_by(id:params[:exercise_id])
@exercise_status = @exercise.present? ? @exercise.get_exercise_status(current_user) : 1
group_id = params[:exercise_group_id]
if @exercise.blank?
normal_status(-1,"试卷不存在")
elsif @exercise_status == 1
normal_status(-1,"试卷未发布")
else
@course = @exercise.course
default_ex_users = @exercise.all_exercise_users(current_user.id).exercise_user_committed
default_ex_users_size = default_ex_users.size
@ex_users = default_ex_users #仅导出已提交的,截止后则是全部为提交的。
#是否评阅
if params[:review].present?
review_type = params[:review].first.to_i #已评则数据为1未评则数据为0,前端传过来的为数组
if review_type == 1
@ex_users = @ex_users.where("subjective_score >= ?",0.0)
else
@ex_users = @ex_users.where("subjective_score < ?",0.0)
end
end
#答题状态的选择
if params[:commit_status].present? && (params[:commit_status].to_i == 1)
@exercise_users_list = @exercise_users_list.where(commit_status:params[:commit_status])
elsif params[:commit_status].present? && (params[:commit_status].to_i == 0)
normal_status(-1,"暂无用户提交!")
end
#可以分班选择
if group_id.present?
exercise_students = @course.students.course_find_by_ids("course_group_id",group_id) # 试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?)
@ex_users = @ex_users.exercise_commit_users(user_ids)
exercise_students = @course.students.where(course_group_id: group_id) # 试卷所分班的全部人数
user_ids = exercise_students.pluck(:user_id).reject(&:blank?).uniq
@ex_users = @ex_users.where(user_id: user_ids)
end
# @ex_users = @ex_users.first(200)
if default_ex_users_size == 0
normal_status(-1,"导出失败,暂时没有已提交的学生")
elsif default_ex_users_size > 200
normal_status(-1,"导出数量超过200,请分班导出或联系网站管理员导出")
#搜索
if params[:search].present?
@ex_users = @ex_users.joins(user: :user_extension).where("CONCAT(lastname, firstname) like ? OR student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
default_ex_users_size = @ex_users&.size
if default_ex_users_size.blank? || default_ex_users_size == 0
normal_status(-1,"暂无用户提交")
elsif default_ex_users_size > 100
normal_status(-2,"100")
end
end
rescue Exception => e
@ -71,6 +95,40 @@ class ZipsController < ApplicationController
def load_homework
@homework = HomeworkCommon.find(params[:homework_common_id])
@course = @homework.course
@homework_status = @homework.present? ? @homework.homework_detail_manual.comment_status : 0
if @homework.blank?
normal_status(-1,"该作业不存在")
elsif @homework_status == 0
normal_status(-1,"该作业未发布")
else
@course = @homework.course
##7。2 -hs新增
@member = @course.course_member(current_user.id)
@all_student_works = @homework.teacher_works(@member).where("work_status > 0")
work_status = params[:work_status]
group_id = params[:course_group]
unless work_status.blank?
@all_student_works = @all_student_works.where(work_status:work_status)
end
unless group_id.blank?
group_user_ids = @course.students.where(course_group_id: params[:course_group]).pluck(:user_id)
@all_student_works = @all_student_works.where(user_id: group_user_ids)
end
unless params[:search].blank?
@all_student_works = @all_student_works.joins(user: :user_extension).where("concat(lastname, firstname) like ?
or student_id like ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
student_work_sizes = @all_student_works&.size
if student_work_sizes.blank? || student_work_sizes == 0
normal_status(-1,"暂无用户提交")
elsif student_work_sizes > 100
normal_status(-2,"100")
end
end
end
end

@ -0,0 +1,9 @@
module ApplicationDecorator
def display_time_method(*columns, format: '%Y-%m-%d %H:%M:%S')
columns.each do |column_name|
define_method "display_#{column_name}" do
public_send(column_name)&.strftime(format)
end
end
end
end

@ -0,0 +1,6 @@
module CompetitionDecorator
extend ApplicationDecorator
display_time_method :start_time, :end_time, :enroll_end_time
end

@ -0,0 +1,5 @@
module CompetitionStageSectionDecorator
extend ApplicationDecorator
display_time_method :start_time, :end_time
end

@ -0,0 +1,5 @@
module ProjectPackageDecorator
extend ApplicationDecorator
display_time_method :updated_at, :deadline_at, :published_at
end

@ -1,8 +1,4 @@
module ShixunDecorator
def finished_challenges_count(user)
Game.joins(:myshixun).where(user_id: user.id, status: 2, myshixuns: { shixun_id: id }).count
end
def human_status
I18n.t("shixun.status.#{status}")
end

@ -12,48 +12,6 @@ module UserDecorator
logged_user? ? real_name : full_name
end
# 关注数
def follow_count
User.watched_by(id).count
end
# 粉丝数
def fan_count
watchers.count
end
# 是否绑定邮箱
def email_binded?
mail.present?
end
# 学院的url标识
def college_identifier
Department.find_by_id(department_members.pluck(:department_id).first)&.identifier
end
# 是否能申请试用
def can_apply_trial?
return false if certification == 1
apply = ApplyAction.order(created_at: :desc).find_by(user_id: id, container_type: 'TrialAuthorization')
apply && !apply.status.zero?
end
# 是否已经签到
def attendance_signed?
attendance = Attendance.find_by(user_id: id)
attendance && Util.days_between(Time.zone.now, attendance.created_at).zero?
end
# 明日签到金币
def tomorrow_attendance_gold
Attendance.find_by(user_id: id)&.next_gold
end
# ----------- 账号管理 -------------
def authentication_status
if authentication?
@ -74,16 +32,4 @@ module UserDecorator
'uncertified'
end
end
def base_info_completed?
user_columns = %i[nickname lastname]
user_extension_columns = %i[gender location location_city identity school_id department]
user_columns.all? { |column| public_send(column).present? } &&
user_extension_columns.all? { |column| user_extension.send(column).present? }
end
def all_certified?
authentication? && professional_certification?
end
end

@ -0,0 +1,10 @@
class AddSchoolApplyForm
include ActiveModel::Model
attr_accessor :name, :province, :city, :address, :remarks
validates :name, presence: true
# validates :province, presence: true
# validates :city, presence: true
# validates :address, presence: true
end

@ -0,0 +1,98 @@
class Competitions::SaveTeamForm
include ActiveModel::Model
attr_accessor :competition, :team, :creator
attr_accessor :name, :teacher_ids, :member_ids
validates :name, presence: true
validate :check_creator_enrollable
def check_creator_enrollable
return unless check_creator_identity_enrollable
check_creator_multiple_enrollable
end
validate :check_teachers_enrollable
def check_teachers_enrollable
if competition.teacher_enroll_forbidden? && teacher_ids.present?
errors.add(:teacher_ids, :enroll_forbidden)
return
end
self.teacher_ids = teacher_ids.map(&:to_i)
all_teachers = creator.is_teacher? ? teacher_ids + [creator.id] : teacher_ids
all_teachers.uniq!
if all_teachers.size < competition.teacher_staff.minimum || all_teachers.size > competition.teacher_staff.maximum
errors.add(:teacher_ids, :invalid_count, minimum: competition.teacher_staff.minimum, maximum: competition.teacher_staff.maximum)
return
end
# 老师可多次报名,不检查
return unless competition.teacher_multiple_limited?
# 存在已报名老师
enrolled_teacher_members = competition.team_members.where(user_id: all_teachers)
.where.not(competition_team_id: team.id).includes(:user)
if enrolled_teacher_members.present?
errors.add(:teacher_ids, :enrolled, names: enrolled_teacher_members.map { |m| m.user.real_name }.join(''))
return
end
end
validate :check_members_enrollable
def check_members_enrollable
if competition.member_enroll_forbidden? && member_ids.present?
errors.add(:member_ids, :enroll_forbidden)
return
end
self.member_ids = member_ids.map(&:to_i)
all_members = creator.is_teacher? ? member_ids : member_ids + [creator.id]
all_members.uniq!
if all_members.size < competition.member_staff.minimum || all_members.size > competition.member_staff.maximum
errors.add(:member_ids, :invalid_count, minimum: competition.member_staff.minimum, maximum: competition.member_staff.maximum)
return
end
# 成员可多次报名,不检查
return unless competition.member_multiple_limited?
# 存在已报名成员
enrolled_members = competition.team_members.where(user_id: all_members)
.where.not(competition_team_id: team.id).includes(:user)
if enrolled_members.present?
errors.add(:member_ids, :enrolled, names: enrolled_members.map { |m| m.user.real_name }.join(''))
return
end
end
private
# 竞赛是否限制了职业
def check_creator_identity_enrollable
if user.is_teacher? && competition.teacher_enroll_forbidden?
errors.add(:creator, :teacher_enroll_forbidden)
return false
elsif !user.is_teacher? && competition.member_enroll_forbidden?
errors.add(:creator, :member_enroll_forbidden)
return false
end
true
end
# 创建者是否能多次报名
def check_creator_multiple_enrollable
return unless competition.enrolled?(user)
if (user.is_teacher? && competition.teacher_multiple_limited?) || (!user.is_teacher? && competition.member_multiple_limited?)
errors.add(:creator, :enrolled)
return false
end
true
end
end

@ -0,0 +1,15 @@
class ProjectPackages::SaveForm
include ActiveModel::Model
attr_accessor :category_id, :title, :content, :attachment_ids, :deadline_at,
:min_price, :max_price, :contact_name, :contact_phone, :code, :publish
validates :category_id, presence: true
validates :title, presence: true, length: { maximum: 60 }
validates :content, presence: true
validates :deadline_at, presence: true
validates :min_price, numericality: { greater_than: 0 }, allow_blank: true
validates :max_price, numericality: { greater_than: ->(obj){ obj.min_price.to_i } }, allow_blank: true
validates :contact_name, presence: true, length: { maximum: 20 }
validates :contact_phone, presence: true, format: { with: /1\d{10}/ }
end

@ -0,0 +1,8 @@
class Users::ApplyAuthenticationForm
include ActiveModel::Model
attr_accessor :name, :id_number, :upload_image
validates :name, presence: true
validates :id_number, presence: true
end

@ -0,0 +1,10 @@
class Users::ApplyProfessionalAuthForm
include ActiveModel::Model
attr_accessor :school_id, :department_id, :identity, :extra, :upload_image
validates :school_id, presence: true, numericality: { only_integer: true, greater_than: 0 }
validates :department_id, numericality: { only_integer: true, greater_than: 0 }, allow_blank: true
validates :identity, presence: true, inclusion: { in: %w(student teacher professional) }
validates :extra, presence: true
end

@ -10,9 +10,9 @@ class Users::UpdateAccountForm
validates :gender, presence: true, numericality: { only_integer: true }, inclusion: { in: [0, 1] }
validates :location, presence: true
validates :location_city, presence: true
validates :identity, presence: true, numericality: { only_integer: true }, inclusion: { in: [0, 1, 2] }
validates :technical_title, presence: true, unless: -> { identity == 1 }
validates :student_id, presence: true, if: -> { identity == 1 }
validates :identity, presence: true, inclusion: { in: %w[teacher student professional ] }
validates :technical_title, presence: true, unless: -> { identity.to_s == 'student' }
validates :student_id, presence: true, if: -> { identity.to_s == 'student' }
validates :school_id, presence: true
validate :check_school_exist

@ -1,6 +1,7 @@
# 所有的方法请按首字母的顺序依次列出
module ApplicationHelper
include Educoder::I18n
include GitHelper
ONE_MINUTE = 60 * 1000
ONE_HOUR = 60 * ONE_MINUTE
@ -11,7 +12,7 @@ module ApplicationHelper
# 全局参数配置
def edu_setting name
EduSetting.find_by_name(name).try(:value)
EduSetting.get(name)
end
def graduation_navigation graduation
@ -29,8 +30,9 @@ module ApplicationHelper
end
# git用户
# git用户命名规则login+"@educoder.net"
def git_username(email)
User.find_by_mail(email)
User.find_by_mail(email) || User.find_by_login(email.split("@").first)
end
# 不同的类型扩展不同的目录
@ -109,7 +111,7 @@ module ApplicationHelper
# 计算到结束还有多长时间 **天**小时**分
def how_much_time(time)
if time.nil?
if time.nil? || time < Time.now #6.21 -hs 增加小于time.now
''
else
result = ((time - Time.now.to_i).to_i / (24*60*60)).to_s + ""
@ -128,7 +130,7 @@ module ApplicationHelper
if source.class.to_s == 'User'
File.join(relative_path, ["#{source.class}", "#{source.id}"])
else
File.join("/images/avatars", ["#{source.class}", "#{source.id}"])
File.join("images/avatars", ["#{source.class}", "#{source.id}"])
end
elsif source.class.to_s == 'User'
str = source.user_extension.try(:gender).to_i == 0 ? "b" : "g"
@ -144,9 +146,21 @@ module ApplicationHelper
File.join(storage_path, "#{source_type}", "#{source_id}")
end
def disk_auth_filename(source_type, source_id, type)
File.join(storage_path, "#{source_type}", "#{source_id}#{type}")
end
def disk_real_name_auth_filename(source_id)
disk_auth_filename('UserAuthentication', source_id, 'ID')
end
def disk_professional_auth_filename(source_id)
disk_auth_filename('UserAuthentication', source_id, 'PRO')
end
def shixun_url_to_avatar(shixun)
if File.exist?(disk_filename(shixun.class, shixun.id))
File.join("/images/#{relative_path}", "#{shixun.class}", "#{shixun.id}")
File.join("images/#{relative_path}", "#{shixun.class}", "#{shixun.id}")
else
File.join("educoder", "index", "shixun", "shixun#{rand(23)}.jpg")
end
@ -332,6 +346,24 @@ module ApplicationHelper
raw arr.join('')
end
# 导出pdf时转化markdown为html
def to_markdown(text,origin_url)
return nil if text.blank?
options = {
:autolink => true,
:no_intra_emphasis => true,
:fenced_code_blocks => true,
:lax_html_blocks => true,
:strikethrough => true,
:superscript => true,
:tables => true
}
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,options)
m_t = markdown.render(text)
m_t&.include?("src=\"") ? m_t&.gsub("src=\"","src=\"#{origin_url}") : m_t
end
end

@ -232,7 +232,7 @@ module CoursesHelper
course.course_groups.includes(:course_members)
end
group_info = []
if course_groups.count > 0
if !course_groups.blank?
course_groups.each do |group|
group_info << {course_group_id: group.id, group_group_name: group.name, count: group.course_members_count}
end
@ -246,15 +246,18 @@ module CoursesHelper
def left_group_info course
group_info = []
course.course_groups.each do |course_group|
group_info << {category_id: course_group.id, category_name: course_group.name, position: course_group.position,
category_count: course_group.course_members_count, category_type: false,
second_category_url: "/courses/#{@course.id}/course_groups/#{course_group.id}"}
if course.course_groups_count > 0
none_group_count = course.students.where(course_group_id: 0).size
group_info << {category_id: 0, category_name: "未分班", position: course.course_groups.pluck(:position).max.to_i + 1,
category_count: none_group_count, category_type: false,
second_category_url: "/courses/#{@course.id}/course_groups/0"}
course.course_groups.each do |course_group|
group_info << {category_id: course_group.id, category_name: course_group.name, position: course_group.position,
category_count: course_group.course_members_count, category_type: false,
second_category_url: "/courses/#{@course.id}/course_groups/#{course_group.id}"}
end
end
none_group_count = course.students.where(course_group_id: 0).size
group_info << {category_id: 0, category_name: "未分班", position: course.course_groups.pluck(:position).max.to_i + 1,
category_count: none_group_count, category_type: false,
second_category_url: "/courses/#{@course.id}/course_groups/0"}
group_info
end
end

@ -32,7 +32,7 @@ module ExerciseQuestionsHelper
def shixun_game_scores(challenge,ex_answerer,shixun_type,question_id)
game_score = challenge.question_score
game_answers = challenge.exercise_shixun_answers.search_shixun_answers("user_id",ex_answerer.id).search_shixun_answers("exercise_question_id",question_id)
game_answers = challenge.exercise_shixun_answers.where(user_id:ex_answerer.id,exercise_question_id:question_id)
if shixun_type == 2 && game_answers.present? #试卷已截止,用户才可以查看答案
s_score = game_answers.first.score
else

@ -1,19 +1,42 @@
module ExercisesHelper
# include GitHelper
#获取每个学生对每个题的答案状态
def get_each_student_exercise(exercise_id,exercise_questions,user_id)
@exercise_user = ExerciseUser.current_exercise_user(user_id,exercise_id).first
@exercise_user = ExerciseUser.current_exercise_user(user_id,exercise_id)&.first
exercise_obj_status = exercise_questions.find_objective_questions
@ex_obj_array = []
exercise_obj_status.each do |q|
if q.question_type == 5
ques_score = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id).pluck(:score).sum
q_type = q.question_type
if q_type == Exercise::PRACTICAL
answers_content = q.exercise_shixun_answers.search_shixun_answers("user_id",user_id)
else
ques_score = q.exercise_answers.search_answer_users("user_id",user_id).score_reviewed.pluck(:score).sum
answers_content = q.exercise_answers.search_answer_users("user_id",user_id)
end
if ques_score == q.question_score #满分作答为正确
if q_type <= Exercise::JUDGMENT
if answers_content.present? #学生有回答时
answer_choice_array = []
answers_content.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
user_answer_content = answer_choice_array.sort
standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
ques_score = q.question_score
else
ques_score = 0.0
end
else
ques_score = 0.0
end
else
ques_score = answers_content.select(:score).pluck(:score).sum
end
if ques_score >= q.question_score #满分作答为正确
ques_score = q.question_score
stand_answer = 1
elsif ques_score > 0.0 #部分作答
stand_answer = 2
@ -30,21 +53,21 @@ module ExercisesHelper
}
@ex_obj_array.push(ques_option)
end
exercise_sub_status = exercise_questions.find_by_custom("question_type",4) #主观题
exercise_sub_status = exercise_questions.find_by_custom("question_type",Exercise::SUBJECTIVE) #主观题
@ex_sub_array = [] #主观题的已答/未答
exercise_sub_status.each do |s|
sub_answer = s.exercise_answers.search_answer_users("user_id",user_id) #主观题只有一个回答
if sub_answer.present? && sub_answer.first.score >= 0.0
if s.question_score == sub_answer.first.score
if s.question_score <= sub_answer.first.score
stand_status = 1
else
stand_status = 2
end
# stand_status = 1
sub_answer_score = sub_answer.first.score
else
stand_status = 0
sub_answer_score = 0.0
sub_answer_score = nil
end
sub_score = {
@ -52,65 +75,87 @@ module ExercisesHelper
"q_type":s.question_type,
"q_position":s.question_number,
"stand_status":stand_status,
"user_score":sub_answer_score.round(1).to_s
"user_score":sub_answer_score.present? ? sub_answer_score.round(1).to_s : nil
}
@ex_sub_array.push(sub_score)
end
@ex_obj_array.sort_by {|k| k[:q_position]}
@ex_sub_array.sort_by {|k| k[:q_position]}
@ex_obj_array = @ex_obj_array.sort_by {|k| k[:q_position]}
@ex_sub_array = @ex_sub_array.sort_by {|k| k[:q_position]}
end
#试卷的统计结果页面计算各题的
def exercise_commit_result(questions,user_ids)
question_infos = []
questions.each do |ex|
ex_total_score = user_ids.count * ex&.question_score #该试卷的已回答的总分
ex_answers = ex.exercise_answers
if ex.question_type != 5
percent = 0.0
questions.includes(:exercise_choices).each do |ex|
ex_total_score = user_ids.count * ex&.question_score.to_f #该试卷的已回答的总分
# ex_answers = ex.exercise_answers
if ex.question_type != Exercise::PRACTICAL
ques_title = ex.question_title
ques_less_title = nil
ex_answers = ex.exercise_answers
effictive_users = ex_answers.search_answer_users("user_id",user_ids)
else
ques_title = ex.shixun.name
ques_less_title = ex.question_title
effictive_users = ex.exercise_shixun_answers.search_shixun_answers("user_id",user_ids)
ex_answers = ex.exercise_shixun_answers
effictive_users = ex_answers.search_shixun_answers("user_id",user_ids)
end
effictive_users_count = effictive_users.count #有效回答数可能有重复的用户id这里仅统计是否回答这个问题的全部人数
ex_answered_scores = effictive_users.score_reviewed.pluck(:score).sum #该问题的全部得分
if ex_total_score == 0.0
percent = 0.0
else
percent = (ex_answered_scores / ex_total_score.to_f).round(3) * 100 #正确率
effictive_users_count = effictive_users.size #有效回答数可能有重复的用户id这里仅统计是否回答这个问题的全部人数
if ex.question_type > Exercise::COMPLETION #当为主观题和实训题时,
ex_answered_scores = effictive_users.score_reviewed.pluck(:score).sum #该问题的全部得分
percent = (ex_total_score == 0.0 ? 0.0 : (ex_answered_scores / ex_total_score.to_f).round(3) * 100) #正确率
end
question_answer_infos = []
if ex.question_type <= 2 #单选题
standard_answer = ex.exercise_standard_answers.pluck(:exercise_choice_id) #标准答案的位置
ex.exercise_choices.each do |c|
if standard_answer.include?(c.choice_position) #选项的标准答案为选项的位置
right_answer = true
else
right_answer = false
end
answer_this_choice = effictive_users.search_exercise_answer("exercise_choice_id",c.id)
answer_users_count = answer_this_choice.count
if effictive_users_count == 0
answer_percent = 0.0
else
answer_percent = (answer_users_count / effictive_users_count.to_f ).round(3)
if ex.question_type <= Exercise::JUDGMENT #选择题和判断题
ex_choices = ex.exercise_choices
standard_answer = ex.exercise_standard_answers.pluck(:exercise_choice_id).sort #标准答案的位置
right_users_count = 0
#该问题的正确率
if ex.question_type == Exercise::MULTIPLE #多选题
right_user_ids = user_ids
standard_answer.each do |choice_position|
standard_answer_choice_id = ex_choices.select{|ec| ec.choice_position == choice_position}.first&.id
right_user_ids = right_user_ids & effictive_users.select{|answer| answer.exercise_choice_id == standard_answer_choice_id}.pluck(:user_id)
end
right_users_count = right_user_ids.size
# user_ids.each do |user_id|
# ex_choice_ids = effictive_users.map{|e| e.exercise_choice_id if e.user_id == user_id}.reject(&:blank?).uniq
# answer_choice_array = ex_choices.map{|a| a.choice_position if ex_choice_ids.include?(a.id)}.reject(&:blank?).uniq
# if answer_choice_array.sort == standard_answer
# right_users_count += 1
# end
# end
else #单选题和判断题
standard_answer_choice_id = ex_choices.select{|ec| ec.choice_position == standard_answer.first}.first&.id
right_users_count = effictive_users.select{|answer| answer.exercise_choice_id == standard_answer_choice_id}.size
end
percent = effictive_users_count > 0 ? (right_users_count / effictive_users_count.to_f).round(3)*100 : 0.0
#每个选项的正确率
ex_choices.each do |c|
right_answer = standard_answer.include?(c.choice_position) #选项的标准答案为选项的位置
answer_users_count = effictive_users.select{|answer| answer.exercise_choice_id == c.id}.size
answer_percent = (effictive_users_count == 0 ? 0.0 : (answer_users_count / effictive_users_count.to_f ).round(3))
answer_option = {
:choice_position => c.choice_position,
:choice_text => c.choice_text,
:choice_users_count => answer_users_count,
:choice_percent => answer_percent.round(1),
:choice_percent => answer_percent.round(1).to_s,
:right_answer => right_answer
}
question_answer_infos.push(answer_option)
end
elsif ex.question_type == 3 #填空题
elsif ex.question_type == Exercise::COMPLETION #填空题
ex_ordered = ex.is_ordered
null_standard_answer = ex.exercise_standard_answers
null_stand_choice = null_standard_answer.pluck(:exercise_choice_id)
null_stand_choice = null_standard_answer.pluck(:exercise_choice_id) #一个exercise_choice_id可能对应多个answer_text
null_stand_text = null_standard_answer.pluck(:answer_text)
standard_answer_count = 0
all_user_count = 0
@ -118,33 +163,24 @@ module ExercisesHelper
user_count = 0
s_choice_text = null_stand_text[index]
if ex_ordered #有序排列
user_ids.each do |u|
user_answers = ex_answers.search_answer_users("user_id",u).search_answer_users("exercise_choice_id",s)
user_answers_choice = user_answers.present? ? user_answers.first.answer_text : ""
if s_choice_text == user_answers_choice
user_count += 1
end
end
user_count = user_count + effictive_users.select{|answer| answer.exercise_choice_id == s && answer.answer_text == s_choice_text}.size
else
user_count = user_count + effictive_users.search_exercise_answer("answer_text",s_choice_text).count #回答了标准答案的用户
end
if effictive_users_count == 0
answer_percent = 0.0
else
answer_percent = (user_count / effictive_users_count.to_f ).round(3)
user_count = user_count + effictive_users.select{|answer| answer.answer_text == s_choice_text }.size #回答了标准答案的用户
end
answer_percent = ((effictive_users_count == 0) ? 0.0 : (user_count / effictive_users_count.to_f ).round(3))
answer_option = {
:choice_position => index+1,
:choice_text => s_choice_text,
:choice_users_count => user_count,
:choice_percent => answer_percent.round(1),
:choice_percent => answer_percent.round(1).to_s,
:right_answer => true
}
question_answer_infos.push(answer_option)
all_user_count += user_count
standard_answer_count += 1
end
percent = effictive_users_count > 0 ? (all_user_count / effictive_users_count.to_f).round(3)*100 : 0.0
user_wrong_count = (effictive_users_count - all_user_count )
if effictive_users_count > 0 && user_wrong_count >= 0
@ -156,25 +192,22 @@ module ExercisesHelper
:choice_position => (standard_answer_count + 1),
:choice_text => "wrong",
:choice_users_count => user_wrong_count,
:choice_percent => wrong_percent.round(1),
:choice_percent => wrong_percent.round(1).to_s,
:right_answer => false
}
question_answer_infos.push(wrong_answer_position)
elsif ex.question_type == 4 #主观题
elsif ex.question_type == Exercise::SUBJECTIVE #主观题
ex_score = ex&.question_score
full_scores = effictive_users.search_exercise_answer("score",ex_score).count #满分人数
no_full_scores = effictive_users.exercise_no_full_scores(ex_score).count #部分分数人数
all_zero_scores = effictive_users.search_exercise_answer("score",0.0).count #包含为0分的及未评阅的
review_scores = ex.exercise_answer_comments.count #主观题的评阅数量
un_review_scores = effictive_users_count - review_scores #未评阅数
zero_scores = all_zero_scores - un_review_scores #已评阅且答案未0分的人数
full_scores = effictive_users.search_exercise_answer("score",ex_score).size #满分人数
no_full_scores = effictive_users.exercise_no_full_scores(ex_score).size #部分分数人数
zero_scores = effictive_users.search_exercise_answer("score",0.0).size #包含为0分的及未评阅的
un_review_scores = effictive_users_count - full_scores - no_full_scores - zero_scores #未评阅数
if un_review_scores < 0
un_review_scores = 0
end
main_scores_array = [full_scores,no_full_scores,zero_scores,un_review_scores]
main_scores_array.each_with_index do |s,index|
if index == 0
right_answer = true
else
right_answer = false
end
right_answer = (index == 0)
if effictive_users_count == 0 || s < 0
s = 0
score_percent = 0.0
@ -185,37 +218,33 @@ module ExercisesHelper
:choice_position => index+1,
:choice_text => index+1,
:choice_users_count => s,
:choice_percent => score_percent.round(1),
:choice_percent => score_percent.round(1).to_s,
:right_answer => right_answer
}
question_answer_infos.push(answer_option)
end
elsif ex.question_type == 5 #实训题
elsif ex.question_type == Exercise::PRACTICAL #实训题
ex.exercise_shixun_challenges.each do |c|
cha_score = c&.question_score
cha_shixun_answer = effictive_users.search_shixun_keys("exercise_shixun_challenge_id",c.id)
effictive_users_count = cha_shixun_answer.count #实训题的每个关卡的有效填写量
full_scores = cha_shixun_answer.search_shixun_keys("score",cha_score).count #满分人数
no_full_scores = cha_shixun_answer.shixun_no_full_scores(cha_score).count #部分分数人数c
all_zero_scores = cha_shixun_answer.search_shixun_keys("score",0.0).count #满分人数
effictive_users_count = cha_shixun_answer.size #实训题的每个关卡的有效填写量
full_scores = cha_shixun_answer.search_shixun_keys("score",cha_score).size #满分人数
no_full_scores = cha_shixun_answer.shixun_no_full_scores(cha_score).size #部分分数人数c
all_zero_scores = cha_shixun_answer.search_shixun_keys("score",0.0).size #零分人数
shixun_scores = user_ids.count * cha_score
shixun_answered_scores = cha_shixun_answer.score_reviewed.pluck(:score).sum #该问题的全部得分
game_percent = (shixun_answered_scores == 0.0 ? 0.0 : (shixun_answered_scores / shixun_scores.to_f).round(3) * 100) #正确率
shixun_score_array = [full_scores,no_full_scores,all_zero_scores]
shixun_chas = []
shixun_score_array.each_with_index do |s,index|
if index == 0
right_answer = true
else
right_answer = false
end
if effictive_users_count == 0
score_percent = 0.0
else
score_percent = (s.to_i / effictive_users_count.to_f ).round(3)
end
right_answer = (index == 0)
score_percent = (effictive_users_count == 0 ? 0.0 : (s.to_i / effictive_users_count.to_f ).round(3))
answer_option = {
:choice_position => index+1,
:choice_text => index+1,
:choice_users_count => s,
:choice_percent => score_percent.round(1),
:choice_percent => score_percent.round(1).to_s,
:right_answer => right_answer
}
shixun_chas.push(answer_option)
@ -224,7 +253,8 @@ module ExercisesHelper
:cha_id => c.challenge_id,
:cha_name => c.challenge.subject,
:cha_position => c.position,
:cha_details => shixun_chas
:cha_details => shixun_chas,
:cha_percent => game_percent.round(1).to_s
}
question_answer_infos.push(shixun_new_chas)
end
@ -244,16 +274,18 @@ module ExercisesHelper
end
#获取试卷的已答/未答人数
def get_exercise_answers(ex_users)
@commit_ex_users = ex_users.commit_exercise_by_status(1) #当前老师的全部学生中已提交的
@exercise_answers = @commit_ex_users.present? ? @commit_ex_users.size : 0 #表示已经提交了的用户
course_all_members_count = ex_users.present? ? ex_users.size : 0
@exercise_unanswers = (course_all_members_count - @exercise_answers)
def get_exercise_answers(ex_users, status)
@exercise_answers = 0
@exercise_unanswers = 0
unless status == Exercise::UNPUBLISHED
@exercise_answers = ex_users.commit_exercise_by_status(1).size #表示已经提交了的用户
course_all_members_count = ex_users.size
@exercise_unanswers = (course_all_members_count - @exercise_answers)
end
end
def exercise_index_show(exercise,course,is_teacher_or,user)
# exercise_all_users = exercise.exercise_users
# lock_icon 0出现锁1不出现锁
ex_show_text = []
if course.is_end #课堂停止后,试卷显示为已结束
@ -261,7 +293,7 @@ module ExercisesHelper
elsif is_teacher_or == 1 #当前为老师的时候,显示的是老师身份的对应试卷的状态,因为该试卷,可能对应老师的多个分班
exercise_status = exercise.exercise_status
else
exercise_status = exercise.get_exercise_status(user.id) #当前用户查看的试卷的发布状态
exercise_status = exercise.get_exercise_status(user) #当前用户查看的试卷的发布状态
end
case exercise_status
@ -274,15 +306,16 @@ module ExercisesHelper
else
ex_show_text
end
if is_teacher_or == 1
exercise_users_list = exercise.all_exercise_users(user.id) #当前老师所在班级的全部学生
unreview_count = exercise_users_list.exercise_unreview.size
get_exercise_answers(exercise_users_list)
unreview_count = exercise_status == 1 ? 0 : exercise_users_list.exercise_unreview.size
get_exercise_answers(exercise_users_list, exercise_status)
ex_pb_time = exercise.get_exercise_times(user.id,true)
exercise_publish_time = ex_pb_time[:publish_time]
exercise_end_time = ex_pb_time[:end_time]
current_status = 3
lock_icon = 1 #不显示锁图标
lock_icon = 0
if exercise_status == 1
ex_show_text.push("未发布")
elsif exercise_status == 3
@ -290,34 +323,38 @@ module ExercisesHelper
end
elsif is_teacher_or == 2
exercise_users_list = exercise.get_stu_exercise_users
get_exercise_answers(exercise_users_list) # 未答和已答的
unreview_count = exercise_users_list.exercise_unreview.size
get_exercise_answers(exercise_users_list, exercise_status) # 未答和已答的
unreview_count = exercise_status == 1 ? 0 : exercise_users_list.exercise_unreview.size
ex_pb_time = exercise.get_exercise_times(user.id,false)
exercise_publish_time = ex_pb_time[:publish_time]
exercise_end_time = ex_pb_time[:end_time]
current_status = exercise.check_user_answer_status(user)
lock_icon = 1 #不显示锁图标
lock_icon = 0
if current_status == 4
ex_show_text.push("未提交")
end
else
exercise_users_list = exercise.get_stu_exercise_users
get_exercise_answers(exercise_users_list) # 未答和已答的
get_exercise_answers(exercise_users_list, exercise_status) # 未答和已答的
exercise_publish_time = exercise.publish_time
exercise_end_time = exercise.end_time
unreview_count = nil
if exercise.is_public
current_status = exercise.check_user_answer_status(user)
lock_icon = 1 #非课堂成员,但是试卷为公开的,不加
lock_icon = 1 #不出现
if current_status == 4
ex_show_text.push("未提交")
end
else
current_status = 4
lock_icon = 0 #显示锁图标
lock_icon = 0
end
end
if (course.is_public == 1) && exercise.is_public
lock_icon = 1
end
if exercise_status > 1
show_unreview_count = unreview_count
else
@ -326,9 +363,7 @@ module ExercisesHelper
if exercise_status == 2 && exercise_end_time.present?
ex_left_time = how_much_time(exercise_end_time)
elsif exercise_status == 3 && course.end_date.present?
ex_left_time = how_much_time(course.end_date.to_time)
else
else #已截止后不显示时间
ex_left_time = nil
end
@ -352,109 +387,144 @@ module ExercisesHelper
score2 = 0.0 #填空题
score5 = 0.0 #实训题
ques_stand = [] #问题是否正确
exercise_questions = exercise.exercise_questions
exercise_questions.each do |q|
if q.question_type != 5
answers_content = q.exercise_answers.search_answer_users("user_id",user.id) #学生的答案
else
answers_content = q.exercise_shixun_answers.search_shixun_answers("user_id",user.id) #学生的答案
end
if q.question_type <= 2 #为选择题或判断题时
answer_choice_array = []
answers_content.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
user_answer_content = answer_choice_array.sort
standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
if standard_answer.count > 0
multi_each_score = (q.question_score / standard_answer.count) #当多选答案正确时每个answer的分数均摊。
else
multi_each_score = 0.0
end
answers_content.update_all(:score => multi_each_score)
score1 = score1 + q.question_score
end
elsif q.question_type == 3 #填空题
null_standard_answer = q.exercise_standard_answers
standard_answer_array = null_standard_answer.select(:exercise_choice_id,:answer_text)
standard_answer_ids = standard_answer_array.pluck(:exercise_choice_id).reject(&:blank?).uniq #标准答案的exercise_choice_id数组
standard_answer_count = standard_answer_ids.count
if standard_answer_count > 0 #存在标准答案时才有分数
each_standard_score = (q.question_score.to_f / standard_answer_count).round(1) #每一空的得分
exercise_questions = exercise.exercise_questions.includes(:exercise_answers,:exercise_shixun_answers,:exercise_standard_answers,:exercise_shixun_challenges)
exercise_questions&.each do |q|
begin
if q.question_type != 5
answers_content = q.exercise_answers.where(user_id: user.id) #学生的答案
else
each_standard_score = 0.0
answers_content = q.exercise_shixun_answers.where(user_id: user.id) #学生的答案
end
if q.is_ordered
answers_content.each do |u|
i_standard_answer = standard_answer_array.where(exercise_choice_id:u.exercise_choice_id).pluck(:answer_text).reject(&:blank?).map!(&:downcase) #该选项的全部标准答案
if i_standard_answer.include?(u.answer_text.downcase) #该空的标准答案包含用户的答案才有分数
u.update_attribute("score",each_standard_score)
score2 = score2 + each_standard_score
if q.question_type <= 2 #为选择题或判断题时
if answers_content.present? #学生有回答时
answer_choice_array = []
answers_content.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
end
else
st_answer_text = standard_answer_array.pluck(:answer_text).reject(&:blank?).map!(&:downcase)
answers_content.each do |u|
u_answer_text = u.answer_text.downcase
if st_answer_text.include?(u_answer_text) #只要标准答案包含用户的答案,就有分数。同时,下一次循环时,就会删除该标准答案。防止用户的相同答案获分
u.update_attribute("score",each_standard_score)
score2 = score2 + each_standard_score
st_answer_text.delete(u_answer_text)
user_answer_content = answer_choice_array.sort
standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
if standard_answer.size > 0
q_score_1 = q.question_score
# q_score_1 = (q.question_score.to_f / standard_answer.count) #当多选答案正确时每个answer的分数均摊。
else
q_score_1 = 0.0
end
answers_content.update_all(:score => q_score_1)
score1 = score1 + q.question_score
else
answers_content.update_all(:score => -1.0)
score1 += 0.0
end
else
score1 += 0.0
end
end
elsif q.question_type == 5 #实训题时,主观题这里不评分
q.exercise_shixun_challenges.each do |exercise_cha|
game = Game.user_games(user.id,exercise_cha.challenge_id).first #当前用户的关卡
if game.present?
exercise_cha_score = 0
answer_status = 0
cha_path = challenge_path exercise_cha.challenge.path
if game.status == 2 && game.final_score >= 0
exercise_cha_score = game.real_score exercise_cha.question_score #每一关卡的得分
answer_status = 1
elsif q.question_type == 3 #填空题
if answers_content.present?
null_standard_answer = q.exercise_standard_answers
standard_answer_array = null_standard_answer.select(:exercise_choice_id,:answer_text)
standard_answer_ids = standard_answer_array.pluck(:exercise_choice_id).reject(&:blank?).uniq #标准答案的exercise_choice_id数组
standard_answer_count = standard_answer_ids.count
if standard_answer_count > 0 #存在标准答案时才有分数
q_score_2 = (q.question_score.to_f / standard_answer_count) #每一空的得分
else
q_score_2 = 0.0
end
if exercise_cha.exercise_shixun_answers.search_shixun_answers("user_id",user.id).blank? #把关卡的答案存入试卷的实训里
game_challenge = game.game_codes.search_challenge_path(cha_path).first
if game_challenge.present?
game_code = game_challenge
code = game_code.try(:new_code)
if q.is_ordered
answers_content.each do |u|
i_standard_answer = standard_answer_array.where(exercise_choice_id:u.exercise_choice_id).pluck(:answer_text).reject(&:blank?).map!(&:downcase) #该选项的全部标准答案
if i_standard_answer.include?(u.answer_text.downcase) #该空的标准答案包含用户的答案才有分数
u.update_column('score',q_score_2)
score2 = score2 + q_score_2
else
u.update_column('score',-1.0)
score2 += 0.0
end
end
else
st_answer_text = standard_answer_array.pluck(:answer_text).reject(&:blank?).map!(&:downcase)
answers_content.each do |u|
u_answer_text = u.answer_text.downcase
if st_answer_text.include?(u_answer_text) #只要标准答案包含用户的答案,就有分数。同时,下一次循环时,就会删除该标准答案。防止用户的相同答案获分
u.update_column("score",q_score_2)
score2 = score2 + q_score_2
st_answer_text.delete(u_answer_text)
else
u.update_column('score',-1.0)
score2 += 0.0
end
end
end
else
score2 += 0.0
end
elsif q.question_type == 5 #实训题时,主观题这里不评分
q.exercise_shixun_challenges&.each do |exercise_cha|
game = Game.user_games(user.id,exercise_cha.challenge_id)&.first #当前用户的关卡
if game.present?
exercise_cha_score = 0.0
answer_status = 0
# if game.status == 2 && game.final_score >= 0
if game.final_score > 0
exercise_cha_score = game.real_score(exercise_cha.question_score)
# exercise_cha_score = exercise_cha.question_score #每一关卡的得分
answer_status = 1
end
ex_shixun_answer_content = answers_content&.where(exercise_shixun_challenge_id: exercise_cha.id)
code = nil
if exercise_cha.challenge&.path.present?
cha_path = challenge_path(exercise_cha.challenge&.path)
game_challenge = game.game_codes.search_challenge_path(cha_path)&.first
if game_challenge.present?
game_code = game_challenge
code = game_code.try(:new_code)
else
code = git_fle_content(game.myshixun.repo_path,cha_path)
end
end
if ex_shixun_answer_content.blank? #把关卡的答案存入试卷的实训里
### Todo 实训题的_shixun_details里的代码是不是直接从这里取出就可以了涉及到code的多个版本库的修改
sx_option = {
:exercise_question_id => q.id,
:exercise_shixun_challenge_id => exercise_cha.id,
:user_id => user.id,
:score => exercise_cha_score.round(1),
:answer_text => code,
:status => answer_status
}
ExerciseShixunAnswer.create(sx_option)
else
code = git_fle_content(exercise_cha.shixun.repo_path,cha_path)
ex_shixun_answer_content.first.update_attributes(score:exercise_cha_score.round(1),answer_text:code)
end
sx_option = {
:exercise_question_id => q.id,
:exercise_shixun_challenge_id => exercise_cha.id,
:user_id => user.id,
:score => exercise_cha_score,
:answer_text => code,
:status => answer_status
}
ExerciseShixunAnswer.create(sx_option)
score5 += exercise_cha_score
else
score5 += 0.0
end
score5 += exercise_cha_score
end
end
user_scores = answers_content.blank? ? 0.0 : answers_content.score_reviewed.pluck(:score).sum
if user_scores > 0.0
stand_answer = 1
else
stand_answer = 0
end
ques_option = {
"q_id":q.id, #该问题的id
"q_type":q.question_type,
"q_position":q.question_number, #该问题的位置
"stand_status":stand_answer, #该问题是否正确,1为正确0为错误
"user_score":user_scores.round(1) #每个问题的总得分
}
ques_stand.push(ques_option)
rescue Exception => e
Rails.logger.info("calcuclate_score_have_error____________________________#{e}")
next
end
user_scores = answers_content.score_reviewed.pluck(:score).sum
if user_scores > 0
stand_answer = 1
else
stand_answer = 0
end
ques_option = {
"q_id":q.id, #该问题的id
"q_type":q.question_type,
"q_position":q.question_number, #该问题的位置
"stand_status":stand_answer, #该问题是否正确,1为正确0为错误
"user_score":user_scores #每个问题的总得分
}
ques_stand.push(ques_option)
end
total_score = score1 + score2 + score5
{
"total_score":total_score,
"total_score":total_score.round(1),
"stand_status":ques_stand
}
end
@ -467,9 +537,9 @@ module ExercisesHelper
ex_user_user = ex_user.user
exercise_user_name = ex_user_user.real_name
exercise_user_id = ex_user_user.id
ex_user_exercise_status = exercise.get_exercise_status(exercise_user_id)
ex_user_exercise_status = exercise.get_exercise_status(ex_user_user)
ex_user_student_id = ex_user_user.student_id
if ex_user.start_at.present? && ex_user.commit_status == 0 #用户已回答,但未提交
if ex_user.start_at.present? && (ex_user.commit_status == 0) #用户已回答,但未提交
commit_status = 2 #继续答题
else
commit_status = ex_user.commit_status
@ -478,18 +548,21 @@ module ExercisesHelper
ex_user_end_at = ex_user.end_at
course_member = course.students.course_find_by_ids("user_id",ex_user.user.id)
current_user_group_id = course_member.first.course_group_id if course_member.present?
course_group = course.course_groups.by_group_ids(current_user_group_id)
current_user_group_name = course_group.first.name if course_group.present?
teacher_review = ex_user.subjective_score < 0.0 ? false : true
if ex_user_exercise_status != 3 || commit_status != 1 #试卷未截止或用户未提交
# if (user_status != 0 && ex_user_exercise_status != 3)|| commit_status == 0 #不为教师,且试卷未截止;当前用户未提交 不显示分数
ex_object_score = nil
ex_subject_score = nil
score = nil
if current_user_group_id == 0
current_user_group_name = "未分班"
else
course_group = course.course_groups.by_group_ids(current_user_group_id)
current_user_group_name = course_group.first.name if course_group.present?
end
teacher_review = ex_user.subjective_score < 0.0 ? false : true
if (user_status == 0 && commit_status == 1) || (user_status == 1 && ex_user_exercise_status == 3 && commit_status == 1) #老师都可以看,学生,需在试卷已提交,且已截止的情况下看
ex_object_score = ex_user.objective_score < 0.0 ? 0.0 : ex_user.objective_score.round(1).to_s
ex_subject_score = ex_user.subjective_score < 0.0 ? nil : ex_user.subjective_score.round(1).to_s
score = ex_user.score.present? ? ex_user.score.round(1).to_s : 0.0.to_s
else
ex_object_score = nil
ex_subject_score = nil
score = nil
end
{
@ -601,21 +674,47 @@ module ExercisesHelper
#学生的分数状态及回答的内容
def user_question_answers(q,ex_answerer_id,student_status,is_teacher_or,ex_status,ques_type,ex_type)
answered_content = []
user_score = 0.0
user_score = nil
shixun_type = 0
question_comment = []
if q.question_type == 5
# user_score_pre = nil
if ques_type == 5
exercise_answers = q.exercise_shixun_answers.search_shixun_answers("user_id",ex_answerer_id)
else
exercise_answers = q.exercise_answers.search_exercise_answer("user_id",ex_answerer_id) #试卷用户的回答
end
if student_status == 2 #当前为老师,或为学生且已提交
user_score = exercise_answers.score_reviewed.pluck(:score).sum
user_score_pre = exercise_answers.score_reviewed
if ques_type == 4 #主观题时且没有大于0的分数时为空
user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : nil
elsif ques_type == 5 || ques_type == 3
user_score = user_score_pre.present? ? user_score_pre.pluck(:score).sum : 0.0
else
if exercise_answers.present? #判断题和选择题时,
answer_choice_array = []
exercise_answers.each do |a|
answer_choice_array.push(a.exercise_choice.choice_position) #学生答案的位置
end
user_answer_content = answer_choice_array.sort
standard_answer = q.exercise_standard_answers.pluck(:exercise_choice_id).sort #该问题的标准答案,可能有多个
if user_answer_content == standard_answer #答案一致,多选或单选才给分,答案不对不给分
user_score = q.question_score
else
user_score = 0.0
end
else
user_score = 0.0
end
end
end
if user_score.present? && (user_score > q.question_score)
user_score = q.question_score
end
if ques_type <= 2
answered_content = exercise_answers.pluck(:exercise_choice_id)
answered_content = exercise_answers&.pluck(:exercise_choice_id)
elsif ques_type == 3
exercise_answers.each do |a|
exercise_answers&.each do |a|
u_answer = {
"choice_id":a.exercise_choice_id,
"answer_text": a.answer_text
@ -623,7 +722,7 @@ module ExercisesHelper
answered_content.push(u_answer)
end
elsif ques_type == 4
answered_content = exercise_answers.pluck(:answer_text)
answered_content = exercise_answers&.pluck(:answer_text)
end
if ques_type == 5 #存在实训题,及已经做了实训题的
if ex_status == 3 || is_teacher_or == 1 #如果试卷已截止,则可以看到分数,否则不能查看分数
@ -638,7 +737,7 @@ module ExercisesHelper
question_comment = q.exercise_answer_comments.search_answer_comments("exercise_answer_id",q_answer_id)
end
{
"user_score": user_score.round(1),
"user_score": (user_score.present? ? user_score.round(1).to_s : nil),
"answered_content":answered_content,
"shixun_type":shixun_type,
"question_comment":question_comment
@ -662,8 +761,35 @@ module ExercisesHelper
result
end
def get_exercise_left_time(exercise,user)
ex_time = exercise.time
user_left_time = nil
time_now_i = Time.now.to_i
if ex_time > 0
exercise_user = exercise.exercise_users.find_by(user_id:user.id)
time_mill = ex_time * 60 #转为秒
exercise_end_time = exercise.end_time.present? ? exercise.end_time.to_i : 0
exercise_user_start = exercise_user&.start_at.present? ? exercise_user.start_at.to_i : 0
#用户未开始答题时即exercise_user_start为0
if exercise_user_start == 0
if (exercise_end_time - time_now_i) > time_mill
user_left_time = time_mill
else
user_left_time = (exercise_end_time < time_now_i) ? nil : (exercise_end_time - time_now_i)
end
else
if (exercise_user_start + time_mill) > exercise_end_time
time_mill = exercise_end_time - exercise_user_start #如果开始答题时间加试卷的限时长大于试卷的截止时间,则以试卷的截止时间到开始答题时间为试卷的限时
end
exercise_user_left_time = time_now_i - exercise_user_start #用户已回答的时间
user_left_time = (time_mill < exercise_user_left_time) ? nil : (time_mill - exercise_user_left_time) #当前用户对试卷的回答剩余时间
end
end
user_left_time
end
#实训题学生代码的行数
def content_line(content)
content.split(/\r?\n/).length
content.split(/\r?\n/).length + 1
end
end

@ -35,16 +35,23 @@ module ExportHelper
else
head_cells_add = []
end
normal_head_b_cells = %w(最终成绩 提交时间 更新时间)
normal_head_b_cells = %w(最终成绩 提交时间 更新时间 评语)
@work_head_cells = (head_cells_format + group_cells + normal_head_cells + head_cells_add + allow_late_cell + normal_head_b_cells).reject(&:blank?)
works.each_with_index do |w, index|
works.includes(user: :user_extension, student_works_scores: :user).each_with_index do |w, index|
w_user = w.user
w_1 = (index + 1)
w_2 = w_user.login
w_3 = w_user.real_name
w_3_1 = w_user.mail
w_4 = w_user.student_id.present? ? w_user.student_id : "--"
course_name = course.course_member(w.user_id).try(:course_group_name)
if w_user.present?
w_2 = w_user&.login.present? ? w_user&.login : "--"
w_3 = w_user&.real_name.present? ? w_user&.real_name : "--"
w_3_1 = w_user&.mail.present? ? w_user.mail : "--"
w_4 = w_user.student_id.present? ? w_user.student_id : "--"
else
w_2 = "--"
w_3 = "--"
w_3_1 = "--"
w_4 = "--"
end
course_name = course.students.find_by(user_id: w.user_id).try(:course_group_name)
w_5 = course_name.present? ? course_name : "--"
#0 未提交, 1 按时提交, 2 延迟提交
if w.work_status == 0
@ -85,8 +92,22 @@ module ExportHelper
w_15 = w.work_score.nil? ? "未评分" : w.work_score.round(1)
w_16 = w.commit_time ? format_time(w.commit_time) : "--"
w_17 = w.update_time ? format_time(w.update_time) : "--"
teacher_comments = w.student_works_scores
if teacher_comments.present?
w_18 = ""
teacher_comments.each do |t|
user_name = t.user&.real_name
user_time = format_time(t.updated_at)
user_score = t&.score
user_comment = t.comment.present? ? t.comment : "--"
comment_title = "#{user_name} #{user_time.to_s} #{user_score.to_s}\n#{user_comment}\n\n"
w_18 = w_18 + comment_title
end
else
w_18 = "--"
end
row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17]
row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17,w_18]
row_cells_column = row_cells_column.reject(&:blank?)
@work_cells_column.push(row_cells_column)
end
@ -102,17 +123,17 @@ module ExportHelper
if allow_late_boolean #允许迟交
eff_score_cell.push("迟交扣分")
end
shixun_time_cells = %w(最终成绩 更新时间 提交耗时)
shixun_time_cells = %w(最终成绩 更新时间 提交耗时 评语)
@work_head_cells = (head_cells_format + shixun_head_cells + eff_score_cell + shixun_time_cells).reject(&:blank?)
works.each_with_index do |w, index|
works.includes(:student_works_scores, user: :user_extension, myshixun: :games).each_with_index do |w, index|
myshixun = w.try(:myshixun)
w_user = w.user
w_1 = (index + 1)
w_2 = w_user.login
w_3 = w_user.real_name
w_3_1 = w_user.mail
w_2 = w_user&.login.present? ? w_user&.login : "--"
w_3 = w_user&.real_name.present? ? w_user&.real_name : "--"
w_3_1 = w_user&.mail.present? ? w_user.mail : "--"
w_4 = w_user.student_id.present? ? w_user.student_id : "--"
course_name = course.course_member(w.user_id).try(:course_group_name)
course_name = course.students.find_by(user_id: w.user_id).try(:course_group_name)
w_5 = course_name.present? ? course_name : "--"
#0 未提交, 1 按时提交, 2 延迟提交
if w.work_status == 0
@ -124,7 +145,7 @@ module ExportHelper
else
w_6 = "--"
end
w_7 = w.work_status == 0 ? '--' : myshixun.try(:passed_count).to_s+"/"+shixun.challenges.count.to_s
w_7 = w.work_status == 0 ? '--' : myshixun.try(:passed_count).to_s+"/"+shixun.challenges_count.to_s
w_8 = myshixun ? myshixun.try(:passed_time) == "--" ? "--" : format_time(myshixun.try(:passed_time)) : "--" # 通关时间
w_9 = myshixun ? (myshixun.try(:passed_count) > 0 ? myshixun.total_spend_time : '--') : "--" #总耗时
w_10 = myshixun ? myshixun.output_times : 0 #评测次数
@ -142,8 +163,22 @@ module ExportHelper
end
w_15 = w.work_score.nil? ? "--" : w.work_score.round(1)
w_16 = w.update_time ? format_time(w.update_time) : "--" "更新时间"
w_17 = w.cost_time
row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17]
w_17 = (game_spend_time w.cost_time)
teacher_comments = w.student_works_scores
if teacher_comments.present?
w_18 = ""
teacher_comments.each do |t|
user_name = t.user&.real_name
user_time = format_time(t.updated_at)
user_score = t&.score
user_comment = t.comment.present? ? t.comment : "--"
comment_title = "#{user_name} #{user_time.to_s} #{user_score.to_s}\n#{user_comment}\n\n"
w_18 = w_18 + comment_title
end
else
w_18 = "--"
end
row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16,w_17,w_18]
row_cells_column = row_cells_column.reject(&:blank?)
@work_cells_column.push(row_cells_column)
end
@ -170,17 +205,17 @@ module ExportHelper
head_cells_format = head_cells_format + ["交叉评分"]
end
head_cells_format = head_cells_format + %w(迟交扣分 最终成绩 提交时间 更新时间)
head_cells_format = head_cells_format + %w(迟交扣分 最终成绩 提交时间 更新时间 评语)
@head_cells_column = head_cells_format
@task_cells_column = []
items.each_with_index do |work,index|
items.includes(user: :user_extension).each_with_index do |work,index|
w_1 = (index+1)
w_user = work.user
w_2 = w_user.login
w_3 = w_user.real_name
w_3_1 = w_user.mail
w_2 = w_user&.login.present? ? w_user&.login : "--"
w_3 = w_user&.real_name.present? ? w_user&.real_name : "--"
w_3_1 = w_user&.mail.present? ? w_user.mail : "--"
w_4 = w_user.student_id.present? ? w_user.student_id : "--"
w_5 = work.class_grouping_name
if task_type_boolean #是否分组
@ -188,7 +223,16 @@ module ExportHelper
else
w_6 = nil
end
w_7 = work.work_status
w_status = work.work_status.to_i
if w_status == 0
w_7 = "未提交"
elsif w_status == 1
w_7 = "按时提交"
elsif w_status == 2
w_7 = "延时提交"
else
w_7 = "--"
end
if task_project_boolean #关联项目
w_project = project_info work, current_user, @user_course_identity #因为课堂引用了export_helper
w_8 = w_project[:name]
@ -212,8 +256,22 @@ module ExportHelper
w_13 = work.work_score.nil? ? "未评分" : work.work_score.round(1)
w_14 = work.commit_time.present? ? format_time(work.commit_time) : "--"
w_15 = work.update_time.present? ? format_time(work.update_time) : "--"
row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15]
teacher_comments = work.graduation_work_scores
if teacher_comments.present?
w_16 = ""
teacher_comments.each do |t|
user_name = t.user&.real_name
user_time = format_time(t.updated_at)
user_score = t&.score
user_comment = t.comment.present? ? t.comment : "--"
comment_title = "#{user_name} #{user_time.to_s} #{user_score.to_s}\n#{user_comment}\n\n"
# ("教师:" + user_name + "\n" + "时间:" + user_time.to_s + "\n" + "分数:" + user_score.to_s + "分" + "\n" + "评语:" + user_comment + "\n\n")
w_16 = w_16 + comment_title
end
else
w_16 = "--"
end
row_cells_column = [w_1,w_2,w_3,w_3_1,w_4,w_5,w_6,w_7,w_8,w_9,w_10,w_11,w_12,w_13,w_14,w_15,w_16]
row_cells_column = row_cells_column.reject(&:blank?)
@task_cells_column.push(row_cells_column)
@ -231,21 +289,11 @@ module ExportHelper
else
@table_columns = @table_columns + %w(最终成绩 开始答题时间 提交时间)
end
export_ex_users.each_with_index do |e_user,index|
export_ex_users.includes(user: :user_extension).each_with_index do |e_user,index|
user_info = e_user.user
user_course_id = user_info.course_members.course_find_by_ids("course_id",course.id).first
if user_course_id.present?
get_course_group_id = user_course_id.course_group_id
if get_course_group_id.present? && get_course_group_id != 0
user_course_info = CourseGroup.by_group_ids(get_course_group_id)
user_course = user_course_info.first.name
else
user_course = "--"
end
else
user_course = "--"
end
user_obj_score = e_user.objective_score < 0.0 ? 0.0 : e_user.subjective_score.round(1).to_s
member = course.students.find_by_user_id(e_user.user_id)
user_course = member.try(:course_group_name)
user_obj_score = e_user.objective_score < 0.0 ? 0.0 : e_user.objective_score.round(1).to_s
user_suj_score = e_user.subjective_score < 0.0 ? 0.0 : e_user.subjective_score.round(1).to_s
user_score = e_user.score.present? ? e_user.score.round(1).to_s : 0.0
if e_user.commit_status.present? && e_user.commit_status == 1
@ -256,8 +304,11 @@ module ExportHelper
user_start_time = e_user.start_at.present? ? e_user.start_at.strftime('%Y-%m-%d %H:%M') : "--"
user_end_time = e_user.end_at.present? ? e_user.end_at.strftime('%Y-%m-%d %H:%M') : "--"
user_student_id = user_info.student_id.present? ? user_info.student_id : "--"
user_login = user_info&.login.present? ? user_info.login : "--"
user_real_name = user_info.real_name.present? ? user_info.real_name : "--"
user_mail = user_info&.mail.present? ? user_info.mail : "--"
user_option = [index+1,user_info.login,user_info.real_name, user_info.mail || '--',
user_option = [index+1,user_login,user_real_name, user_mail,
user_student_id,user_course,user_commit_stu]
if ques_type_boolean
other_user_option = [user_obj_score,user_suj_score,user_score,user_start_time,user_end_time]
@ -276,7 +327,7 @@ module ExportHelper
@topic_body_cells = []
if students.count > 0
students.each_with_index do |student, index|
students.includes(user: :user_extension).each_with_index do |student, index|
user = student.user
student_topic = course.student_graduation_topics.user_topics_accept(user.id).first
if student_topic.present?
@ -286,11 +337,11 @@ module ExportHelper
topic = nil
end
w_1 = (index+1)
w_2 = user.login
w_3 = user.real_name
w_3_1 = user.mail
w_4 = user.user_extension.student_id
w_5 = student.course_group_name
w_2 = user&.login.present? ? user&.login : "--"
w_3 = user&.real_name.present? ? user&.real_name : "--"
w_3_1 = user&.mail.present? ? user.mail : "--"
w_4 = user.student_id.present? ? user.student_id : "--"
w_5 = student&.course_group_name.present? ? student.course_group_name : "--"
w_6 = topic.present? ? topic.name : "--"
w_7 = topic.present? ? topic.teacher.full_name : "--"
w_8 = topic.present? ? topic.teacher.identity : "--"
@ -346,11 +397,11 @@ module ExportHelper
end
if file_size > MAX_DOWN_SIZE
status = -1
status = -2
elsif file_count > 0
status = 0
else
status = -2
status = -1
end
status
end
@ -459,6 +510,8 @@ module ExportHelper
zipfile_name = "#{output_path}/#{rename_zipfile}"
# 同名文件重命名时用
index = 1
Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
files_paths.each do |filename|
@ -468,7 +521,11 @@ module ExportHelper
begin
zipfile.add(rename_file, filename)
rescue Exception => e
zipfile.get_output_stream('FILE_NOTICE.txt'){|os| os.write "该作品中有重复命名文件,请通过文件名学号和姓名信息进入该作业详细界面手动下载"}
rename_file = rename_same_file(rename_file, index)
index += 1
zipfile.add(rename_file, filename)
# zipfile.get_output_stream('FILE_NOTICE.txt'){|os| os.write "该作品中有重复命名文件,请通过文件名学号和姓名信息进入该作业详细界面手动下载"}
next
end
end
@ -485,4 +542,14 @@ module ExportHelper
attach.filename
end
def format_sheet_name name
name = name.gsub(":", "-")
end
def rename_same_file(name, index)
basename = File.basename(name, ".*")
new_basename = basename + "_" + index.to_s
extname = File.extname(name)
new_basename + extname
end
end

@ -14,7 +14,7 @@ module GraduationTasksHelper
# 交叉评阅
def cross_comment task, user_id
if task.cross_comment
if task.cross_comment && task.status >= 3
[{id: 1, name: "只看我的交叉评阅", count: task.graduation_work_comment_assignations.myself(user_id).count}]
else
[]
@ -67,7 +67,7 @@ module GraduationTasksHelper
# 作品数统计type 1 已提交 0 未提交
def grduationwork_count task, type
works = task.graduation_works
type == 1 ? works.where("work_status !=?", 0).size : works.where("work_status =?", 0).size
type == 1 ? works.select{|work| work.work_status != 0}.size : works.select{|work| work.work_status == 0}.size
end
# 普通/分组 作业作品状态数组
@ -131,4 +131,20 @@ module GraduationTasksHelper
end
end
end
# 阶段剩余时间
def task_left_time task
if task.publish_time && task.publish_time < Time.now
if task.end_time > Time.now
status = "剩余提交时间"
time = "#{how_much_time(task.end_time)}"
else
if task.allow_late && task.late_time && task.late_time >= Time.now
status = "剩余补交时间"
time = "#{how_much_time(task.late_time)}"
end
end
end
{status: status, time: time}
end
end

@ -15,7 +15,6 @@ module GraduationWorksHelper
end
end
# work_score 最终成绩; late_penalty 迟交扣分; final_score 最终评分
{username: work.user.full_name, login: work.user.login, work_score: work_score, final_score: work.final_score,
late_penalty:work.late_penalty }
{username: work.user.full_name, login: work.user.login, work_score: work_score, final_score: work.final_score}
end
end

@ -65,7 +65,7 @@ module HomeworkCommonsHelper
# 作业统一设置、游客身份、超级管理员、分班权限不限的老师身份
if homework_common.unified_setting || identity > Course::STUDENT || identity == Course::ADMIN ||
(identity < Course::STUDENT && teacher_course_groups.size == 0)
(identity < Course::STUDENT && teacher_course_groups.blank?)
case ho_detail_manual.comment_status
when 0
status << "未发布"
@ -174,9 +174,9 @@ module HomeworkCommonsHelper
end
# 作品数统计type 1 已提交 0 未提交
def studentwork_count homework_common, type, user_id
student_works = homework_common.teacher_works(user_id)
type == 1 ? student_works.select{|work| work.work_status != 0}.size : student_works.select{|work| work.work_status = 0}.size
def studentwork_count homework_common, type, member
student_works = homework_common.teacher_works(member)
type == 1 ? student_works.where("work_status != 0").size : student_works.where(work_status: 0).size
end
# 上次查重的时间
@ -223,10 +223,10 @@ module HomeworkCommonsHelper
end
# 作品状态
def homework_status homework, user_id
[{id: 0, name: "未提交", count: homework.unfinished_count(user_id)},
{id: 1, name: "按时提交", count: homework.finished_count(user_id)},
{id: 2, name: "延时提交", count: homework.delay_finished_count(user_id)}]
def homework_status homework, member
[{id: 0, name: "未提交", count: homework.unfinished_count(member)},
{id: 1, name: "按时提交", count: homework.finished_count(member)},
{id: 2, name: "延时提交", count: homework.delay_finished_count(member)}]
end
# 作品分数的显示

@ -1,11 +1,15 @@
module PollsHelper
#获取试卷的已答/未答人数
def get_poll_answers(poll_users)
@commit_poll_users = poll_users.commit_by_status(1) #当前老师的全部学生中已提交的
@poll_answers = @commit_poll_users.present? ? @commit_poll_users.count : 0 #表示已经提交了的用户
course_all_members_count = poll_users.present? ? poll_users.count : 0
@poll_unanswers = (course_all_members_count - @poll_answers)
def get_poll_answers(poll_users, status)
if status == 1
@poll_answers = 0
@poll_unanswers = 0
else
@poll_answers = poll_users.commit_by_status(1).size #表示已经提交了的用户
course_all_members_count = poll_users.size
@poll_unanswers = (course_all_members_count - @poll_answers)
end
end
def poll_votes_count(votes,user_ids)
@ -55,29 +59,29 @@ module PollsHelper
#当前为老师(非课堂成员、统一设置)的时候,显示的是老师身份的对应试卷的状态,因为该试卷,可能对应老师的多个分班
poll_status = poll.polls_status
else
poll_status = poll.get_poll_status(user.id) #当前用户查看的试卷的发布状态
poll_status = poll.get_poll_status(user) #当前用户查看的试卷的发布状态
end
if is_teacher_or == 1
poll_users_list = poll.all_poll_users(user.id) #当前老师所在班级的全部学生
get_poll_answers(poll_users_list)
get_poll_answers(poll_users_list, poll_status)
ex_pb_time = poll.get_poll_times(user.id,true)
poll_publish_time = ex_pb_time[:publish_time]
poll_end_time = ex_pb_time[:end_time]
current_status = 3
lock_icon = 1 #不显示锁图标
lock_icon = 0 #不显示锁图标
elsif is_teacher_or == 2
poll_users_list = poll.get_poll_exercise_users
get_poll_answers(poll_users_list) # 未答和已答的
get_poll_answers(poll_users_list, poll_status) # 未答和已答的
# get_poll_answers(poll_all_users)
ex_pb_time = poll.get_poll_times(user.id,false)
poll_publish_time = ex_pb_time[:publish_time]
poll_end_time = ex_pb_time[:end_time]
current_status = poll.check_user_votes_status(user)
lock_icon = 1 #不显示锁图标
lock_icon = 0 #不显示锁图标
else
poll_users_list = poll.get_poll_exercise_users
get_poll_answers(poll_users_list) # 未答和已答的
get_poll_answers(poll_users_list, poll_status) # 未答和已答的
poll_publish_time = poll.publish_time
poll_end_time = poll.end_time
current_status = 4
@ -87,6 +91,9 @@ module PollsHelper
lock_icon = 0 #显示锁图标
end
end
if (course.is_public == 1) && poll.is_public
lock_icon = 1
end
{
"publish_time":poll_publish_time,
"end_time":poll_end_time,
@ -110,15 +117,22 @@ module PollsHelper
poll_user_name = user.nickname
end
course_member = course_members.find_by(user_id:user.id)
current_user_group_id = course_members.present? ? course_member.course_group_id : nil
course_group = course.course_groups.find_by_id(current_user_group_id)
course_group_id = course_member.present? ? course_member.course_group_id : nil
if course_group_id == 0
course_group_name = "未分班"
else
course_group = course.course_groups.find_by_id(course_group_id)
course_group_id = course_group&.id
course_group_name = course_group&.name
end
{
"user_name":poll_user_name,
"user_id": user.id,
"student_id":user_student_id,
"group_name":course_group.try(:name),
"group_id":course_group.try(:id),
"group_name":course_group_name,
"group_id":course_group_id,
"login":user.login
}
end
end

@ -41,7 +41,7 @@ module StudentWorksHelper
def student_efficiency(homework_common, work)
myshixun_ids = homework_common.student_works.pluck(:myshixun_id)
myshixuns = Myshixun.where(id: myshixun_ids).includes(games: [:outputs])
myshixuns = Myshixun.where(id: myshixun_ids).includes(:games)
#student_works_user_id = homework_common.student_works.pluck(:user_id).uniq
#shixun = homework_common.shixuns.first
#logger.info("#########shixun_id: ###{shixun.id}")
@ -54,11 +54,11 @@ module StudentWorksHelper
objects =
myshixuns.map do |myshixun|
# 评测次数
evaluate_count = myshixun.games.inject(0) {|sum, g| sum + g.outputs.pluck(:query_index).first.to_i}
evaluate_count = myshixun.games.pluck(:evaluate_count).sum
# 获取最大评测次数
max_evaluate_count = (evaluate_count > max_evaluate_count ? evaluate_count : max_evaluate_count)
# 通关耗时
pass_consume_time = (myshixun.games.where(status: 2).pluck(:cost_time).sum / 60.0)
pass_consume_time = (myshixun.total_cost_time / 60.0)
# 总耗时
all_time = (myshixun.games.pluck(:cost_time).sum / 60.0)
# 通关得分
@ -145,7 +145,7 @@ module StudentWorksHelper
else
user_name = message_user.real_name
user_login = message_user.login
image_url = url_to_avatar(score.user)
image_url = url_to_avatar(message_user)
end
{user_name: user_name, user_login: user_login, user_image_url: image_url}
end

@ -0,0 +1,67 @@
# 学生加入课堂时创建相关任务作品
class CourseAddStudentCreateWorksJob < ApplicationJob
queue_as :default
def perform(course_id, student_ids)
course = Course.find_by(id: course_id)
return if course.blank?
# 如果之前存在相关作品则更新is_delete字段
student_works = StudentWork.joins(:homework_common).where(user_id: student_ids, homework_commons: {course_id: course.id})
student_works.update_all(is_delete: 0)
exercise_users = ExerciseUser.joins(:exercise).where(user_id: student_ids, exercises: {course_id: course.id})
exercise_users.update_all(is_delete: 0)
poll_users = PollUser.joins(:poll).where(user_id: student_ids, polls: {course_id: course.id})
poll_users.update_all(is_delete: 0)
graduation_works = course.graduation_works.where(user_id: student_ids)
graduation_works.update_all(is_delete: 0)
attrs = %i[homework_common_id user_id created_at updated_at]
StudentWork.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
same_attrs = {user_id: user_id}
course.homework_commons.where(homework_type: %i[normal group practice]).each do |homework|
next if homework.student_works.where(user_id: user_id).any?
worker.add same_attrs.merge(homework_common_id: homework.id)
end
end
end
attrs = %i[exercise_id user_id created_at updated_at]
ExerciseUser.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
same_attrs = {user_id: user_id}
course.exercises.each do |exercise|
next if exercise.exercise_users.where(user_id: user_id).any?
worker.add same_attrs.merge(exercise_id: exercise.id)
end
end
end
attrs = %i[poll_id user_id created_at updated_at]
PollUser.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
same_attrs = {user_id: user_id}
course.polls.each do |poll|
next if poll.poll_users.where(user_id: user_id).any?
worker.add same_attrs.merge(poll_id: poll.id)
end
end
end
attrs = %i[graduation_task_id user_id course_id created_at updated_at]
GraduationWork.bulk_insert(*attrs) do |worker|
student_ids.each do |user_id|
same_attrs = {user_id: user_id, course_id: course.id}
course.graduation_tasks.each do |task|
next if task.graduation_works.where(user_id: user_id).any?
worker.add same_attrs.merge(graduation_task_id: task.id)
end
end
end
end
end

@ -0,0 +1,19 @@
class CourseDeleteStudentDeleteWorksJob < ApplicationJob
queue_as :default
def perform(course_id, student_ids)
course = Course.find_by(id: course_id)
return if course.blank?
student_works = StudentWork.joins(:homework_common).where(user_id: student_ids, homework_commons: {course_id: course.id})
student_works.update_all(is_delete: 1)
exercise_users = ExerciseUser.joins(:exercise).where(user_id: student_ids, exercises: {course_id: course.id})
exercise_users.update_all(is_delete: 1)
poll_users = PollUser.joins(:poll).where(user_id: student_ids, polls: {course_id: course.id})
poll_users.update_all(is_delete: 1)
course.graduation_works.where(user_id: student_ids).update_all(is_delete: 1)
end
end

@ -2,10 +2,20 @@
class ExercisePublishNotifyJob < ApplicationJob
queue_as :notify
def perform(exercise_id, receiver_ids)
def perform(exercise_id, group_ids)
exercise = Exercise.find_by(id: exercise_id)
return if exercise.blank?
user = exercise.user
course = exercise.course
if group_ids.present?
students = course.students.where(course_group_id: group_ids)
subquery = course.teacher_course_groups.where(course_group_id: group_ids).select(:course_member_id)
teachers = course.teachers.where(id: subquery)
else
students = course.students
teachers = course.teachers
end
attrs = %i[
user_id trigger_user_id container_id container_type parent_container_id parent_container_type
@ -19,14 +29,14 @@ class ExercisePublishNotifyJob < ApplicationJob
viewed: 0, tiding_type: 'Exercise'
}
Tiding.bulk_insert(*attrs) do |worker|
teacher_ids = exercise.course.teachers.pluck(:user_id)
teacher_ids = teachers.pluck(:user_id)
unless exercise.tidings.exists?(parent_container_type: 'ExercisePublish', user_id: teacher_ids)
exercise.course.teachers.find_each do |teacher|
worker.add same_attrs.merge(user_id: teacher.user_id)
teacher_ids.each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
end
end
receiver_ids.each do |user_id|
students.pluck(:user_id).each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
end
end

@ -0,0 +1,39 @@
# 毕设任务的交叉评阅分配
class GraduationTaskCrossCommentJob < ApplicationJob
queue_as :default
def perform(graduation_task_id)
task = GraduationTask.find_by(id: graduation_task_id)
return if task.blank?
course = task.course
task.graduation_task_group_assignations.each do |assignation|
graduation_group = assignation.graduation_group
assign_group = assignation.assign_group
if graduation_group.present? && assign_group.present?
course_group_ids = course.teacher_course_groups.where(course_member_id: graduation_group.course_members.pluck(:id)).pluck(:course_group_id)
graduation_works = task.graduation_works.where(user_id: course.course_members.where(:course_group_id => course_group_ids).map(&:user_id),
work_status: [1, 2])
if assign_group.course_members.count <= task.comment_num
graduation_works.each do |work|
assign_group.course_members.each do |member|
work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new(
graduation_group_id: assign_group.id, user_id: member.user_id, graduation_task_id: task.id)
end
end
else
member_user_ids = assign_group.course_members.pluck(:user_id)
count = 0
graduation_works.each do |work|
for i in 1 .. task.comment_num
assign_user_id = member_user_ids[count % member_user_ids.size]
work.graduation_work_comment_assignations << GraduationWorkCommentAssignation.new(
graduation_group_id: assign_group.id, user_id: assign_user_id, graduation_task_id: task.id)
count += 1
end
end
end
end
end
end
end

@ -5,6 +5,8 @@ class GraduationTaskPublishNotifyJob < ApplicationJob
def perform(graduation_task_id)
task = GraduationTask.find_by(id: graduation_task_id)
return if task.blank?
course = task.course
return if course.blank?
attrs = %i[
user_id trigger_user_id container_id container_type parent_container_id parent_container_type
@ -18,8 +20,8 @@ class GraduationTaskPublishNotifyJob < ApplicationJob
viewed: 0, tiding_type: 'GraduationTask'
}
Tiding.bulk_insert(*attrs) do |worker|
task.course.students.find_each do |student|
worker.add same_attrs.merge(user_id: student.user_id)
course.course_members.pluck(:user_id).uniq.each do |user_id|
worker.add same_attrs.merge(user_id: user_id)
end
end
end

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save