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

484 lines
18 KiB

6 years ago
# encoding: utf-8
class ChallengesController < ApplicationController
layout "base_shixun"
before_filter :check_authentication
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 => [:index, :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
if (@shixun.status == 0 && !User.current.manager_of_shixun?(@shixun))
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