You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pgfqe6ch8/app/controllers/challenges_controller.rb

491 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# encoding: utf-8
class ChallengesController < ApplicationController
layout "base_shixun"
# 如要添加或修改before_filter时请将handle_openi_request这个before_filter放至第一位
before_filter :handle_openi_request, if: -> { user_login_and_from_openi? }, only: [:index]
before_filter :check_authentication, :except => [:index]
before_filter :find_shixun, :only => [:index, :new, :create, :destroy, :challenge_build, :update_evaluation, :add_choose_question, :new_choose_question,
:choose_type_show, :edit_choose_question, :update_choose_question, :destroy_challenge_choose]
before_filter :find_challenge, :only => [:show, :edit, :update, :challenge_build, :index_up, :index_down, :destroy, :update_evaluation, :add_choose_question,
:show_choose_question, :create_choose_question, :create_choice_question, :new_choose_question, :choose_type_show, :edit_choose_question, :update_choose_question, :destroy_challenge_choose]
before_filter :build_challege_from_params, :only => [:new, :create]
before_filter :tpi_manager_allowed, :only => [:challenge_build, :destroy, :edit, :new, :create]
before_filter :allowed_view, :only => [:show]
before_filter :query_challeges, :only => [:show, :edit, :update, :update_evaluation]
skip_before_filter :verify_authenticity_token, :only => [:create_choose_question, :update_choose_question]
#before_filter :find_shixun_language, :only => [:show, :new, :edit]
before_filter :base_index, :only => [:index, :index_down, :index_up, :destroy]
before_filter :view_allow, :only => [:show]
include ApplicationHelper
##{
# @url: 判断新建与编辑提交的url}
def new
# 顶部导航
@challenge = Challenge.new
@st = params[:st].to_i
@challenge.st = @st
@url = shixun_challenges_path(@shixun, :st => @st)
@method = "post"
@project_menu_type = 11
@task_pass_sample = PlatformSample.where(:samples_type => 'taskPass').first.try(:contents)
respond_to do |format|
format.html { render :action => 'new', :layout => 'base_shixun' }
end
end
def create
ActiveRecord::Base.transaction do
begin
challenge_count = @shixun.challenges.count
@challenge = Challenge.new(params[:challenge])
@challenge.position = challenge_count + 1
@challenge.shixun = @shixun
@challenge.user = User.current
@challenge.st = params[:st].to_i
@challenge.modify_time = Time.now
# 实训是否需要重启
# 非实践任务创建第一个阶段时调用 publishGame, 避免不包含实践任务的实训进行模拟实战时报错
shixun_modify_status_without_publish(@shixun, 1) if @challenge.position != 1
@challenge.save!
if params[:challenge_tag].present?
params[:challenge_tag].each do |input|
ChallengeTag.create!(:name => input, :challenge_id => @challenge.id)
end
end
redirect_to shixun_challenge_path(@challenge, :shixun_id => @shixun)
rescue Exception => e
flash[:error] = "#{e.message}"
redirect_to new_shixun_challenge_path(:shixun_id => @shixun)
raise ActiveRecord::Rollback
end
end
end
# 处理新建challenge返回的pipeline片段
def fragment_from_jenkins
end
def index
base_index
respond_to do |format|
format.js
format.html
end
rescue ActiveRecord::RecordNotFound
render_404
end
def show
@tab = params[:tab].nil? ? 1 : params[:tab].to_i
challenge_num = Challenge.where(:shixun_id => @shixun).count
challenge_pos = @challenge.position
if challenge_pos < challenge_num
@next_challenge = Challenge.where(:shixun_id => @shixun, :position => challenge_pos + 1).first
end
@prev_challenge = Challenge.where(:shixun_id => @shixun, :position => challenge_pos - 1).first if challenge_pos - 1 > 0
respond_to do |format|
format.html
format.js
end
end
##{
# @action: 判断新建与编辑提交的url}
def edit
@tab = params[:tab].blank? ? 1 : params[:tab].to_i
@url = shixun_challenge_path(@challenge, :shixun_id => @shixun, :tab => @tab)
@method= "put"
respond_to do |format|
format.html
format.js
end
end
def update
ActiveRecord::Base.transaction do
tab = params[:tab].to_i
@challenge.update_attributes(params[:challenge])
if tab == 1
@challenge.challenge_tags.delete_all
if params[:challenge_tag].present?
params[:challenge_tag].each do |input|
ChallengeTag.create!(:name => input, :challenge_id => @challenge.id)
end
end
elsif tab == 2
path = @challenge.path
exec_path = @challenge.exec_path
sets_output = @test_sets.map(&:output)
sets_input = @test_sets.map(&:input)
sets_open = @test_sets.map(&:is_public)
params_hidden = params[:test_set][:hidden].map{|hidden| hidden.to_i == 0}
# 测试集变化则需要更新(输入、 输出、 是否隐藏)
if sets_output != params[:test_set][:output] || sets_open != params_hidden || sets_input != params[:test_set][:input]
@test_sets.delete_all unless @test_sets.blank?
if params[:test_set][:hidden].length > 0
params[:test_set][:input].each_with_index do |input, index|
unless (input[index] == params[:test_set][:output][index] && input[index].nil?)
TestSet.create(:challenge_id => @challenge.id, :input => "#{input}", :output => "#{params[:test_set][:output][index]}", :is_public => params_hidden[index], :position => (index + 1))
end
end
end
@challenge.update_column(:modify_time, Time.now)
# 测试集的
@shixun.myshixuns.update_all(:system_tip => 0)
end
# 关卡评测执行文件如果被修改,需要修改脚本内容
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script)
if path != params[:challenge][:path]
shixun_modify_status_without_publish(@shixun, 1)
end
Attachment.attach_files(@challenge, params[:attachments])
end
redirect_to shixun_challenge_path(@challenge, :shixun_id => @shixun, :tab => tab)
end
end
def new_choose_question
@challenge_choose = ChallengeChoose.new
@url = "#{create_choose_question_shixun_challenge_path(@challenge, :shixun_id => @shixun)}"
respond_to do |format|
format.js
end
end
def create_choose_question
ActiveRecord::Base.transaction do
begin
@challenge_choose = ChallengeChoose.new
@challenge_choose.challenge_id = @challenge.id
@challenge_choose.subject = params[:choose][:subject]
@challenge_choose.answer = params[:choose][:answer]
@challenge_choose.standard_answer = params[:standard_answer]
@challenge_choose.score = params[:challenge][:score].to_i
@challenge_choose.difficult = params[:challenge][:difficulty].to_i
@challenge_choose.position = @challenge.challenge_chooses.count + 1
@challenge_choose.category = @challenge_choose.standard_answer.length == 1 ? 1 : 2
if @challenge_choose.save!
# 创建选项
params[:question][:cnt].each_with_index do |test, index|
answer = params[:choice][:answer][index] == "0" ? false : true
ChallengeQuestion.create(:option_name => test, :challenge_choose_id => @challenge_choose.id, :position => index, :right_key => answer)
end
# 创建单选多选的技能标签
if params[:challenge_tag].present?
params[:challenge_tag].each do |tag|
ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id)
end
end
end
rescue Exception => e
flash[:error] = "#{e.message}"
raise ActiveRecord::Rollback
end
end
end
def show_choose_question
@challenge_choose = ChallengeChoose.find params[:choose_id]
respond_to do |format|
format.js
end
end
def update_choose_question
@challenge_choose = ChallengeChoose.where(:id => params[:choose_id]).first
ActiveRecord::Base.transaction do
if params[:standard_answer] != @challenge_choose.standard_answer
@challenge.update_column(:modify_time, Time.now)
end
category = params[:standard_answer].length > 1 ? 2 : 1
score = params[:challenge] ? params[:challenge][:score].to_i : @challenge_choose.score
difficult = params[:challenge] ? params[:challenge][:difficulty].to_i : @challenge_choose.difficult
@challenge_choose.update_attributes(:subject => params[:choose][:subject],
:answer => params[:choose][:answer],
:standard_answer => params[:standard_answer],
:score => score,
:difficult => difficult,
:category => category)
begin
@challenge_choose.challenge_questions.delete_all
params[:question][:cnt].each_with_index do |test, index|
answer = params[:choice][:answer][index] == "0" ? false : true
ChallengeQuestion.create(:option_name => test, :challenge_choose_id => @challenge_choose.id, :position => index, :right_key => answer)
end
@challenge_choose.challenge_tags.delete_all unless @challenge_choose.challenge_tags.blank?
if params[:challenge_tag].present?
params[:challenge_tag].each do |tag|
ChallengeTag.create(:name => tag, :challenge_choose_id => @challenge_choose.id, :challenge_id => @challenge.id)
end
end
@challenge_choose = ChallengeChoose.find params[:choose_id]
rescue Exception => e
flash[:error] = "#{e.message}"
raise ActiveRecord::Rollback
end
end
end
def edit_choose_question
@challenge_choose = ChallengeChoose.find params[:choose_id]
@url = "#{update_choose_question_shixun_challenge_path(@challenge, :shixun_id => @shixun, :choose_id => params[:choose_id])}"
respond_to do |format|
format.js
end
end
def choose_type_show
@challenge_choose = ChallengeChoose.where(:id => params[:choose_id]).first
@index = params[:index].to_i
respond_to do |format|
format.js
end
end
def destroy_challenge_choose
ActiveRecord::Base.transaction do
@challenge_choose = ChallengeChoose.where(:id => params[:choose_id]).first
pos = @challenge_choose.position
@challenge.challenge_chooses.where("position > ?", pos).update_all("position = position - 1")
@challenge_choose.destroy
# 发起重置请求
shixun_modify_status_without_publish(@shixun, 1)
redirect_to shixun_challenge_path(@challenge, :shixun_id => @shixun)
end
end
def add_choose_question
@category = params[:category].to_i
@position = params[:position].to_i
#@challenge_choose = @challenge.challenge_chooses
respond_to do |format|
format.js
end
end
def destroy
next_challenges = @shixun.challenges.where("position > #{@challenge.position}")
next_challenges.update_all("position = position - 1")
shixun_modify_status_without_publish(@shixun, 1)
@challenge.destroy
# 关卡位置被删除,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script)
base_index
respond_to do |format|
format.js
format.html{redirect_to shixun_challenges_path(@shixun)}
end
end
def update_evaluation
ActiveRecord::Base.transaction do
path = @challenge.path
exec_path = @challenge.exec_path
@challenge.update_attributes(params[:challenge])
begin
if params[:tab].to_i == 2
sets_output = @test_sets.map(&:output)
sets_input = @test_sets.map(&:input)
sets_open = @test_sets.map(&:is_public)
params_hidden = params[:test_set][:hidden].map{|hidden| hidden.to_i == 0}
# 测试集变化则需要更新(输入、 输出、 是否隐藏)
if sets_output != params[:test_set][:output] || sets_open != params_hidden || sets_input != params[:test_set][:input]
@test_sets.delete_all unless @test_sets.blank?
if params[:test_set][:hidden].length > 0
params[:test_set][:input].each_with_index do |input, index|
unless (input[index] == params[:test_set][:output][index] && input[index].nil?)
TestSet.create(:challenge_id => @challenge.id, :input => input, :output => params[:test_set][:output][index], :is_public => params_hidden[index], :position => (index + 1))
end
end
end
@challenge.update_column(:modify_time, Time.now)
# 测试集的
@shixun.myshixuns.update_all(:system_tip => 0)
end
# 关卡评测执行文件如果被修改,需要修改脚本内容
if exec_path != params[:challenge][:exec_path]
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script)
end
# 学员任务文件路径更新不需要重置
# if path != params[:challenge][:path]
# shixun_modify_status_without_publish(@shixun, 1)
# end
Attachment.attach_files(@challenge, params[:attachments])
elsif params[:tab].to_i == 5
@challenge_tags.delete_all unless @challenge_tags.blank?
unless params[:knowledge].blank?
params[:knowledge][:input].each do |input|
ChallengeTag.create!(:name => input, :challenge_id => @challenge.id)
end
end
end
if params[:tab].to_i == 5
respond_to do |format|
format.js{redirect_to edit_shixun_challenge_path(@challenge, :shixun_id => @shixun, :tab => params[:tab])}
end
else
redirect_to edit_shixun_challenge_path(@challenge, :shixun_id => @shixun, :tab => params[:tab])
end
rescue Exception => e
flash[:error] = "#{e.message}"
redirect_to edit_shixun_challenge_path(@challenge, :shixun_id => @shixun, :tab => params[:tab])
raise ActiveRecord::Rollback
end
end
end
def index_down
next_challenge = @challenge.next_challenge
position = @challenge.position
@challenge.update_attribute(:position, (position + 1))
next_challenge.update_attribute(:position, next_challenge.position - 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script)
base_index
end
def index_up
position = @challenge.position
last_challenge = @challenge.last_challenge
@challenge.update_attribute(:position, (position - 1))
last_challenge.update_attribute(:position, last_challenge.position + 1)
# 关卡位置被修改,需要修改脚本
script = modify_shixun_script @shixun, @shixun.evaluate_script
@shixun.update_column(:evaluate_script, script)
base_index
end
# build job 只负责发送请求
def challenge_build
gitUrl = gitlab_url@shixun
gitUrl = Base64.urlsafe_encode64(gitUrl)
taskId = params[:id]
jobName = @shixun.forked_form
step = @challenge.position
jenkins_shixuns = Redmine::Configuration['jenkins_shixuns']
if @challenge.status == 0
params = {:jobName => "#{jobName}", :taskId => "#{taskId}", :step => "#{step}", :gitUrl => "#{gitUrl}"}
uri = URI("#{jenkins_shixuns}/jenkins-exec/api/buildJob")
res = uri_exec uri, params
# @challenge.update_attribute(:status, 1)
end
respond_to do |format|
format.js
end
end
private
# 过滤掉对指定单位公开的用户(超级管理员和实训管理者除外)
def view_allow
shixun_view_allow @shixun
end
def count_input input, output
if input.length == 0 && output.length == 0
result = 0
else
if input.length > output.length
end
end
end
def tpi_manager_allowed
unless User.current.manager_of_shixun?(@shixun)
render_403
end
end
def allowed_view
unless (allow_to_view_challenge(@challenge, @shixun) || User.current.manager_of_shixun?(@shixun))
render_403
end
end
def build_challege_from_params
if params[:id].blank?
@challenge = Challenge.new
@challenge.shixun = @shixun
if params[:st].to_i == 0
@challenge.st = 1
end
else
@challenge = @shixun.challenges.find(params[:id])
end
@challenge.shixun = @shixun
@challenge.user ||= User.current
end
def query_challeges
@test_sets = @challenge.test_sets
@challenge_tags = @challenge.challenge_tags
end
# index/index_down/index_up/destroy等方法公共部分
def base_index
@manager = User.current.manager_of_shixun?(@shixun)
# 当前用户开启的实训
@current_myshixun = @shixun.myshixuns.where(:user_id => User.current).first
if @current_myshixun.present?
@challenges = Challenge.select([:id, :subject, :user_id, :shixun_id, :position, :st, :score]).where(:shixun_id => @shixun)
@current_modify = ShixunModify.where(:myshixun_id => @current_myshixun.id, :shixun_id => @shixun.try(:id), :status => 1).first
else
@challenges = @shixun.challenges
end
end
def find_challenge
@challenge = Challenge.find(params[:id])
@shixun = @challenge.shixun
rescue ActiveRecord::RecordNotFound
render_404
end
# Find project of id params[:id]
def find_shixun
shixun_id = params[:shixun_id] || (params[:challenge] && params[:challenge][:shixun_id])
@shixun = Shixun.find_by_identifier(shixun_id)
if @shixun.nil?
render_404
return
else
logger.info("operable: ##{@shixun.operable?}")
logger.info("@shixun.status: ##{@shixun.status}")
if (@shixun.status == 0 && !User.current.manager_of_shixun?(@shixun)) || (!@shixun.operable? && !User.current.admin?)
render_403
return
end
end
rescue ActiveRecord::RecordNotFound
render_404
end
def find_shixun_language
language = @shixun.language
@language = language_switch language
end
def default_format_js
response.headers['content--type'] = 'text/javascript'
request.format = 'js'
end
end