|
|
class ProblemsController < ApplicationController
|
|
|
|
|
|
before_action :authenticate, :authorization
|
|
|
before_action :testcase_authorization, only: [:show_testcase]
|
|
|
|
|
|
in_place_edit_for :problem, :name
|
|
|
in_place_edit_for :problem, :full_name
|
|
|
in_place_edit_for :problem, :full_score
|
|
|
|
|
|
def index
|
|
|
@problems = Problem.order(date_added: :desc)
|
|
|
end
|
|
|
|
|
|
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
|
|
|
verify :method => :post, :only => [ :create, :quick_create,
|
|
|
:do_manage,
|
|
|
:do_import,
|
|
|
],
|
|
|
:redirect_to => { :action => :index }
|
|
|
|
|
|
def show
|
|
|
@problem = Problem.find(params[:id])
|
|
|
end
|
|
|
|
|
|
def new
|
|
|
@problem = Problem.new
|
|
|
@description = nil
|
|
|
end
|
|
|
|
|
|
def create
|
|
|
@problem = Problem.new(problem_params)
|
|
|
@description = Description.new(params[:description])
|
|
|
if @description.body!=''
|
|
|
if !@description.save
|
|
|
render :action => new and return
|
|
|
end
|
|
|
else
|
|
|
@description = nil
|
|
|
end
|
|
|
@problem.description = @description
|
|
|
if @problem.save
|
|
|
flash[:notice] = 'Problem was successfully created.'
|
|
|
redirect_to action: :index
|
|
|
else
|
|
|
render :action => 'new'
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def quick_create
|
|
|
@problem = Problem.new(problem_params)
|
|
|
@problem.full_name = @problem.name if @problem.full_name == ''
|
|
|
@problem.full_score = 100
|
|
|
@problem.available = false
|
|
|
@problem.test_allowed = true
|
|
|
@problem.output_only = false
|
|
|
@problem.date_added = Time.new
|
|
|
if @problem.save
|
|
|
flash[:notice] = 'Problem was successfully created.'
|
|
|
redirect_to action: :index
|
|
|
else
|
|
|
flash[:notice] = 'Error saving problem'
|
|
|
redirect_to action: :index
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def edit
|
|
|
@problem = Problem.find(params[:id])
|
|
|
@description = @problem.description
|
|
|
end
|
|
|
|
|
|
def update
|
|
|
@problem = Problem.find(params[:id])
|
|
|
@description = @problem.description
|
|
|
if @description.nil? and params[:description][:body]!=''
|
|
|
@description = Description.new(params[:description])
|
|
|
if !@description.save
|
|
|
flash[:notice] = 'Error saving description'
|
|
|
render :action => 'edit' and return
|
|
|
end
|
|
|
@problem.description = @description
|
|
|
elsif @description
|
|
|
if !@description.update_attributes(params[:description])
|
|
|
flash[:notice] = 'Error saving description'
|
|
|
render :action => 'edit' and return
|
|
|
end
|
|
|
end
|
|
|
if params[:file] and params[:file].content_type != 'application/pdf'
|
|
|
flash[:notice] = 'Error: Uploaded file is not PDF'
|
|
|
render :action => 'edit' and return
|
|
|
end
|
|
|
if @problem.update_attributes(problem_params)
|
|
|
flash[:notice] = 'Problem was successfully updated.'
|
|
|
unless params[:file] == nil or params[:file] == ''
|
|
|
flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
|
|
|
out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
|
|
|
if not FileTest.exists? out_dirname
|
|
|
Dir.mkdir out_dirname
|
|
|
end
|
|
|
|
|
|
out_filename = "#{out_dirname}/#{@problem.name}.pdf"
|
|
|
if FileTest.exists? out_filename
|
|
|
File.delete out_filename
|
|
|
end
|
|
|
|
|
|
File.open(out_filename,"wb") do |file|
|
|
|
file.write(params[:file].read)
|
|
|
end
|
|
|
@problem.description_filename = "#{@problem.name}.pdf"
|
|
|
@problem.save
|
|
|
end
|
|
|
redirect_to :action => 'show', :id => @problem
|
|
|
else
|
|
|
render :action => 'edit'
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def destroy
|
|
|
p = Problem.find(params[:id]).destroy
|
|
|
redirect_to action: :index
|
|
|
end
|
|
|
|
|
|
def toggle
|
|
|
@problem = Problem.find(params[:id])
|
|
|
@problem.update_attributes(available: !(@problem.available) )
|
|
|
respond_to do |format|
|
|
|
format.js { }
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def toggle_test
|
|
|
@problem = Problem.find(params[:id])
|
|
|
@problem.update_attributes(test_allowed: !(@problem.test_allowed?) )
|
|
|
respond_to do |format|
|
|
|
format.js { }
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def toggle_view_testcase
|
|
|
@problem = Problem.find(params[:id])
|
|
|
@problem.update_attributes(view_testcase: !(@problem.view_testcase?) )
|
|
|
respond_to do |format|
|
|
|
format.js { }
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def turn_all_off
|
|
|
Problem.available.all.each do |problem|
|
|
|
problem.available = false
|
|
|
problem.save
|
|
|
end
|
|
|
redirect_to action: :index
|
|
|
end
|
|
|
|
|
|
def turn_all_on
|
|
|
Problem.where.not(available: true).each do |problem|
|
|
|
problem.available = true
|
|
|
problem.save
|
|
|
end
|
|
|
redirect_to action: :index
|
|
|
end
|
|
|
|
|
|
def stat
|
|
|
@problem = Problem.find(params[:id])
|
|
|
unless @problem.available or session[:admin]
|
|
|
redirect_to :controller => 'main', :action => 'list'
|
|
|
return
|
|
|
end
|
|
|
@submissions = Submission.includes(:user).includes(:language).where(problem_id: params[:id]).order(:user_id,:id)
|
|
|
|
|
|
#stat summary
|
|
|
range =65
|
|
|
@histogram = { data: Array.new(range,0), summary: {} }
|
|
|
user = Hash.new(0)
|
|
|
@submissions.find_each do |sub|
|
|
|
d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
|
|
|
@histogram[:data][d.to_i] += 1 if d < range
|
|
|
user[sub.user_id] = [user[sub.user_id], ((sub.try(:points) || 0) >= @problem.full_score) ? 1 : 0].max
|
|
|
end
|
|
|
@histogram[:summary][:max] = [@histogram[:data].max,1].max
|
|
|
|
|
|
@summary = { attempt: user.count, solve: 0 }
|
|
|
user.each_value { |v| @summary[:solve] += 1 if v == 1 }
|
|
|
end
|
|
|
|
|
|
def manage
|
|
|
@problems = Problem.order(date_added: :desc)
|
|
|
end
|
|
|
|
|
|
def do_manage
|
|
|
if params.has_key? 'change_date_added' and params[:date_added].strip.empty? == false
|
|
|
change_date_added
|
|
|
elsif params.has_key? 'add_to_contest'
|
|
|
add_to_contest
|
|
|
elsif params.has_key? 'enable_problem'
|
|
|
set_available(true)
|
|
|
elsif params.has_key? 'disable_problem'
|
|
|
set_available(false)
|
|
|
elsif params.has_key? 'add_group'
|
|
|
group = Group.find(params[:group_id])
|
|
|
ok = []
|
|
|
failed = []
|
|
|
get_problems_from_params.each do |p|
|
|
|
begin
|
|
|
group.problems << p
|
|
|
ok << p.full_name
|
|
|
rescue => e
|
|
|
failed << p.full_name
|
|
|
end
|
|
|
end
|
|
|
flash[:success] = "The following problems are added to the group #{group.name}: " + ok.join(', ') if ok.count > 0
|
|
|
flash[:alert] = "The following problems are already in the group #{group.name}: " + failed.join(', ') if failed.count > 0
|
|
|
elsif params.has_key? 'add_tags'
|
|
|
get_problems_from_params.each do |p|
|
|
|
p.tag_ids += params[:tag_ids]
|
|
|
end
|
|
|
end
|
|
|
|
|
|
redirect_to :action => 'manage'
|
|
|
end
|
|
|
|
|
|
def import
|
|
|
@allow_test_pair_import = allow_test_pair_import?
|
|
|
end
|
|
|
|
|
|
def do_import
|
|
|
old_problem = Problem.find_by_name(params[:name])
|
|
|
if !allow_test_pair_import? and params.has_key? :import_to_db
|
|
|
params.delete :import_to_db
|
|
|
end
|
|
|
@problem, import_log = Problem.create_from_import_form_params(params,
|
|
|
old_problem)
|
|
|
|
|
|
if !@problem.errors.empty?
|
|
|
render :action => 'import' and return
|
|
|
end
|
|
|
|
|
|
if old_problem!=nil
|
|
|
flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
|
|
|
end
|
|
|
@log = import_log
|
|
|
end
|
|
|
|
|
|
def remove_contest
|
|
|
problem = Problem.find(params[:id])
|
|
|
contest = Contest.find(params[:contest_id])
|
|
|
if problem!=nil and contest!=nil
|
|
|
problem.contests.delete(contest)
|
|
|
end
|
|
|
redirect_to :action => 'manage'
|
|
|
end
|
|
|
|
|
|
##################################
|
|
|
protected
|
|
|
|
|
|
def allow_test_pair_import?
|
|
|
if defined? ALLOW_TEST_PAIR_IMPORT
|
|
|
return ALLOW_TEST_PAIR_IMPORT
|
|
|
else
|
|
|
return false
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def change_date_added
|
|
|
problems = get_problems_from_params
|
|
|
date = Date.parse(params[:date_added])
|
|
|
problems.each do |p|
|
|
|
p.date_added = date
|
|
|
p.save
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def add_to_contest
|
|
|
problems = get_problems_from_params
|
|
|
contest = Contest.find(params[:contest][:id])
|
|
|
if contest!=nil and contest.enabled
|
|
|
problems.each do |p|
|
|
|
p.contests << contest
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def set_available(avail)
|
|
|
problems = get_problems_from_params
|
|
|
problems.each do |p|
|
|
|
p.available = avail
|
|
|
p.save
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def get_problems_from_params
|
|
|
problems = []
|
|
|
params.keys.each do |k|
|
|
|
if k.index('prob-')==0
|
|
|
name, id, order = k.split('-')
|
|
|
problems << Problem.find(id)
|
|
|
end
|
|
|
end
|
|
|
problems
|
|
|
end
|
|
|
|
|
|
def get_problems_stat
|
|
|
end
|
|
|
|
|
|
private
|
|
|
|
|
|
def problem_params
|
|
|
params.require(:problem).permit(:name, :full_name, :full_score, :date_added, :available, :test_allowed,:output_only, :url, :description, tag_ids:[])
|
|
|
end
|
|
|
|
|
|
end
|
|
|
|