Description:
add show testcase feature
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r625:7645a0f771ce - - 12 files changed: 113 inserted, 2 deleted

@@ -0,0 +1,24
1 + class TestcasesController < ApplicationController
2 + before_action :set_testcase, only: [:download_input,:download_sol]
3 + before_action :testcase_authorization
4 +
5 + def download_input
6 + send_data @testcase.input, type: 'text/plain', filename: "#{@testcase.problem.name}.#{@testcase.num}.in"
7 + end
8 +
9 + def download_sol
10 + send_data @testcase.sol, type: 'text/plain', filename: "#{@testcase.problem.name}.#{@testcase.num}.sol"
11 + end
12 +
13 +
14 + private
15 + # Use callbacks to share common setup or constraints between actions.
16 + def set_testcase
17 + @testcase = Testcase.find(params[:id])
18 + end
19 +
20 + # Only allow a trusted parameter "white list" through.
21 + def testcase_params
22 + params[:testcase]
23 + end
24 + end
@@ -0,0 +1,2
1 + module TestcasesHelper
2 + end
@@ -0,0 +1,25
1 + %h1 Test cases
2 + %h2= @problem.long_name
3 +
4 + /navbar
5 + %ul.nav.nav-pills{role: :tablist}
6 + - @problem.testcases.each.with_index do |tc,id|
7 + %li{role: :presentation, class: ('active' if id == 0)}
8 + %a{href:"#tc#{tc.id}", role: 'tab', data: {toggle: 'tab'}}= tc.num
9 +
10 + /actual data
11 + .tab-content
12 + - @problem.testcases.each.with_index do |tc,id|
13 + .tab-pane{id: "tc#{tc.id}",class: ('active' if id == 0)}
14 + .row
15 + .col-md-6
16 + %h3 Input
17 + = link_to "Download",download_input_problem_testcase_path(@problem,tc),class: 'btn btn-info btn-sm'
18 + .col-md-6
19 + %h3 Output
20 + = link_to "Download",download_sol_problem_testcase_path(@problem,tc),class: 'btn btn-info btn-sm'
21 + .row
22 + .col-md-6
23 + %textarea{ rows: 25,readonly: true,style: "width:100%;resize=none;overflow-y: scroll;"}= tc.input
24 + .col-md-6
25 + %textarea{ rows: 25,readonly: true,style: "width:100%;resize=none;overflow-y: scroll;"}= tc.sol
@@ -0,0 +1,7
1 + require 'test_helper'
2 +
3 + class TestcasesControllerTest < ActionController::TestCase
4 + setup do
5 + @testcase = testcases(:one)
6 + end
7 + end
@@ -28,24 +28,33
28 return true
28 return true
29 end
29 end
30
30
31 def authorization_by_roles(allowed_roles)
31 def authorization_by_roles(allowed_roles)
32 return false unless authenticate
32 return false unless authenticate
33 user = User.find(session[:user_id])
33 user = User.find(session[:user_id])
34 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
34 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
35 unauthorized_redirect
35 unauthorized_redirect
36 return false
36 return false
37 end
37 end
38 end
38 end
39
39
40 + def testcase_authorization
41 + #admin always has privileged
42 + if @current_user.admin?
43 + return true
44 + end
45 +
46 + unauthorized_redirect if GraderConfiguration["right.view_testcase"]
47 + end
48 +
40 protected
49 protected
41
50
42 def authenticate
51 def authenticate
43 unless session[:user_id]
52 unless session[:user_id]
44 flash[:notice] = 'You need to login'
53 flash[:notice] = 'You need to login'
45 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
54 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
46 flash[:notice] = 'You need to login but you cannot log in at this time'
55 flash[:notice] = 'You need to login but you cannot log in at this time'
47 end
56 end
48 redirect_to :controller => 'main', :action => 'login'
57 redirect_to :controller => 'main', :action => 'login'
49 return false
58 return false
50 end
59 end
51
60
@@ -1,15 +1,16
1 class ProblemsController < ApplicationController
1 class ProblemsController < ApplicationController
2
2
3 - before_filter :authenticate, :authorization
3 + before_action :authenticate, :authorization
4 + before_action :testcase_authorization, only: [:show_testcase]
4
5
5 in_place_edit_for :problem, :name
6 in_place_edit_for :problem, :name
6 in_place_edit_for :problem, :full_name
7 in_place_edit_for :problem, :full_name
7 in_place_edit_for :problem, :full_score
8 in_place_edit_for :problem, :full_score
8
9
9 def index
10 def index
10 @problems = Problem.order(date_added: :desc)
11 @problems = Problem.order(date_added: :desc)
11 end
12 end
12
13
13 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
14 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
14 verify :method => :post, :only => [ :create, :quick_create,
15 verify :method => :post, :only => [ :create, :quick_create,
15 :do_manage,
16 :do_manage,
@@ -212,24 +213,28
212 @log = import_log
213 @log = import_log
213 end
214 end
214
215
215 def remove_contest
216 def remove_contest
216 problem = Problem.find(params[:id])
217 problem = Problem.find(params[:id])
217 contest = Contest.find(params[:contest_id])
218 contest = Contest.find(params[:contest_id])
218 if problem!=nil and contest!=nil
219 if problem!=nil and contest!=nil
219 problem.contests.delete(contest)
220 problem.contests.delete(contest)
220 end
221 end
221 redirect_to :action => 'manage'
222 redirect_to :action => 'manage'
222 end
223 end
223
224
225 + def show_testcase
226 + @problem = Problem.includes(:testcases).find(params[:id])
227 + end
228 +
224 ##################################
229 ##################################
225 protected
230 protected
226
231
227 def allow_test_pair_import?
232 def allow_test_pair_import?
228 if defined? ALLOW_TEST_PAIR_IMPORT
233 if defined? ALLOW_TEST_PAIR_IMPORT
229 return ALLOW_TEST_PAIR_IMPORT
234 return ALLOW_TEST_PAIR_IMPORT
230 else
235 else
231 return false
236 return false
232 end
237 end
233 end
238 end
234
239
235 def change_date_added
240 def change_date_added
@@ -1,24 +1,25
1 require 'yaml'
1 require 'yaml'
2
2
3 #
3 #
4 # This class also contains various login of the system.
4 # This class also contains various login of the system.
5 #
5 #
6 class GraderConfiguration < ActiveRecord::Base
6 class GraderConfiguration < ActiveRecord::Base
7
7
8 SYSTEM_MODE_CONF_KEY = 'system.mode'
8 SYSTEM_MODE_CONF_KEY = 'system.mode'
9 TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout'
9 TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout'
10 MULTICONTESTS_KEY = 'system.multicontests'
10 MULTICONTESTS_KEY = 'system.multicontests'
11 CONTEST_TIME_LIMIT_KEY = 'contest.time_limit'
11 CONTEST_TIME_LIMIT_KEY = 'contest.time_limit'
12 MULTIPLE_IP_LOGIN_KEY = 'right.multiple_ip_login'
12 MULTIPLE_IP_LOGIN_KEY = 'right.multiple_ip_login'
13 + VIEW_TESTCASE = 'right.view_testcase'
13
14
14 cattr_accessor :config_cache
15 cattr_accessor :config_cache
15 cattr_accessor :task_grading_info_cache
16 cattr_accessor :task_grading_info_cache
16 cattr_accessor :contest_time_str
17 cattr_accessor :contest_time_str
17 cattr_accessor :contest_time
18 cattr_accessor :contest_time
18
19
19 GraderConfiguration.config_cache = nil
20 GraderConfiguration.config_cache = nil
20 GraderConfiguration.task_grading_info_cache = nil
21 GraderConfiguration.task_grading_info_cache = nil
21
22
22 def self.config_cached?
23 def self.config_cached?
23 (defined? CONFIGURATION_CACHE_ENABLED) and (CONFIGURATION_CACHE_ENABLED)
24 (defined? CONFIGURATION_CACHE_ENABLED) and (CONFIGURATION_CACHE_ENABLED)
24 end
25 end
@@ -61,24 +62,28
61
62
62 def self.show_tasks_to?(user)
63 def self.show_tasks_to?(user)
63 if time_limit_mode?
64 if time_limit_mode?
64 return false if not user.contest_started?
65 return false if not user.contest_started?
65 end
66 end
66 return true
67 return true
67 end
68 end
68
69
69 def self.show_grading_result
70 def self.show_grading_result
70 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
71 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
71 end
72 end
72
73
74 + def self.show_testcase
75 + return get(VIEW_TESTCASE)
76 + end
77 +
73 def self.allow_test_request(user)
78 def self.allow_test_request(user)
74 mode = get(SYSTEM_MODE_CONF_KEY)
79 mode = get(SYSTEM_MODE_CONF_KEY)
75 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
80 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
76 if (mode=='contest')
81 if (mode=='contest')
77 return false if ((user.site!=nil) and
82 return false if ((user.site!=nil) and
78 ((user.site.started!=true) or
83 ((user.site.started!=true) or
79 (early_timeout and (user.site.time_left < 30.minutes))))
84 (early_timeout and (user.site.time_left < 30.minutes))))
80 end
85 end
81 return false if mode=='analysis'
86 return false if mode=='analysis'
82 return true
87 return true
83 end
88 end
84
89
@@ -15,13 +15,15
15 = " ["
15 = " ["
16 %tt
16 %tt
17 = submission.grader_comment
17 = submission.grader_comment
18 = "]"
18 = "]"
19 %br
19 %br
20 %strong View:
20 %strong View:
21 - if GraderConfiguration.show_grading_result
21 - if GraderConfiguration.show_grading_result
22 = link_to '[detailed result]', :action => 'result', :id => submission.id
22 = link_to '[detailed result]', :action => 'result', :id => submission.id
23 /= link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'}
23 /= link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'}
24 = link_to "#{t 'main.cmp_msg'}", compiler_msg_submission_path(submission.id), {popup: true,remote: true,class: 'btn btn-xs btn-info'}
24 = link_to "#{t 'main.cmp_msg'}", compiler_msg_submission_path(submission.id), {popup: true,remote: true,class: 'btn btn-xs btn-info'}
25 = link_to "#{t 'main.src_link'}",{:action => 'source', :id => submission.id}, class: 'btn btn-xs btn-info'
25 = link_to "#{t 'main.src_link'}",{:action => 'source', :id => submission.id}, class: 'btn btn-xs btn-info'
26 = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info'
26 = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info'
27 + - if GraderConfiguration.show_testcase
28 + = link_to "testcases", show_testcase_problem_path(problem_id), class: 'btn btn-xs btn-info'
27
29
@@ -9,31 +9,39
9
9
10 resources :announcements do
10 resources :announcements do
11 member do
11 member do
12 get 'toggle','toggle_front'
12 get 'toggle','toggle_front'
13 end
13 end
14 end
14 end
15
15
16 resources :problems do
16 resources :problems do
17 member do
17 member do
18 get 'toggle'
18 get 'toggle'
19 get 'toggle_test'
19 get 'toggle_test'
20 get 'stat'
20 get 'stat'
21 + get 'show_testcase'
21 end
22 end
22 collection do
23 collection do
23 get 'turn_all_off'
24 get 'turn_all_off'
24 get 'turn_all_on'
25 get 'turn_all_on'
25 get 'import'
26 get 'import'
26 get 'manage'
27 get 'manage'
27 end
28 end
29 +
30 + resources :testcases, only: [] do
31 + member do
32 + get 'download_input'
33 + get 'download_sol'
34 + end
35 + end
28 end
36 end
29
37
30 resources :grader_configuration, controller: 'configurations'
38 resources :grader_configuration, controller: 'configurations'
31
39
32 resources :users do
40 resources :users do
33 member do
41 member do
34 get 'toggle_activate', 'toggle_enable'
42 get 'toggle_activate', 'toggle_enable'
35 get 'stat'
43 get 'stat'
36 end
44 end
37 end
45 end
38
46
39 resources :submissions do
47 resources :submissions do
@@ -80,24 +80,30
80 :value_type => 'boolean',
80 :value_type => 'boolean',
81 :default_value => 'true',
81 :default_value => 'true',
82 :description => 'When false, a user must accept usage agreement before login'
82 :description => 'When false, a user must accept usage agreement before login'
83 },
83 },
84
84
85 {
85 {
86 :key => 'right.heartbeat_response',
86 :key => 'right.heartbeat_response',
87 :value_type => 'string',
87 :value_type => 'string',
88 :default_value => 'OK',
88 :default_value => 'OK',
89 :description => 'Heart beat response text'
89 :description => 'Heart beat response text'
90 },
90 },
91
91
92 + {
93 + :key => 'right.view_testcase',
94 + :value_type => 'boolean',
95 + :default_value => 'false',
96 + :description => 'When true, any user can view/download test data'
97 + },
92 # If Configuration['system.online_registration'] is true, the
98 # If Configuration['system.online_registration'] is true, the
93 # system allows online registration, and will use these
99 # system allows online registration, and will use these
94 # information for sending confirmation emails.
100 # information for sending confirmation emails.
95 {
101 {
96 :key => 'system.online_registration.smtp',
102 :key => 'system.online_registration.smtp',
97 :value_type => 'string',
103 :value_type => 'string',
98 :default_value => 'smtp.somehost.com'
104 :default_value => 'smtp.somehost.com'
99 },
105 },
100
106
101 {
107 {
102 :key => 'system.online_registration.from',
108 :key => 'system.online_registration.from',
103 :value_type => 'string',
109 :value_type => 'string',
@@ -40,19 +40,34
40 checker_name='text')
40 checker_name='text')
41 if GraderScript.grader_control_enabled?
41 if GraderScript.grader_control_enabled?
42 cur_dir = `pwd`.chomp
42 cur_dir = `pwd`.chomp
43 Dir.chdir(GRADER_ROOT_DIR)
43 Dir.chdir(GRADER_ROOT_DIR)
44
44
45 script_name = File.join(GRADER_ROOT_DIR, "scripts/import_problem")
45 script_name = File.join(GRADER_ROOT_DIR, "scripts/import_problem")
46 cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" +
46 cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" +
47 " -t #{time_limit} -m #{memory_limit}"
47 " -t #{time_limit} -m #{memory_limit}"
48
48
49 output = `#{cmd}`
49 output = `#{cmd}`
50
50
51 Dir.chdir(cur_dir)
51 Dir.chdir(cur_dir)
52 -
52 +
53 return "import CMD: #{cmd}\n" + output
53 return "import CMD: #{cmd}\n" + output
54 end
54 end
55 return ''
55 return ''
56 end
56 end
57
57
58 + def self.call_import_testcase(problem_name)
59 + if GraderScript.grader_control_enabled?
60 + cur_dir = `pwd`.chomp
61 + Dir.chdir(GRADER_ROOT_DIR)
62 +
63 + script_name = File.join(GRADER_ROOT_DIR, "scripts/load_testcase")
64 + cmd = "#{script_name} #{problem_name}"
65 +
66 + output = `#{cmd}`
67 +
68 + Dir.chdir(cur_dir)
69 + return "Testcase import result:\n" + output
70 + end
71 + end
72 +
58 end
73 end
@@ -29,24 +29,27
29 if import_test_pairs(dirname)
29 if import_test_pairs(dirname)
30 test_pair_count = TestPair.count :conditions => "problem_id = #{@problem.id}"
30 test_pair_count = TestPair.count :conditions => "problem_id = #{@problem.id}"
31 @log_msg = "Importing test pair successful. (#{test_pair_count} test pairs imported)"
31 @log_msg = "Importing test pair successful. (#{test_pair_count} test pairs imported)"
32 else
32 else
33 @log_msg = "Importing test pair failed. (0 test pairs imported)"
33 @log_msg = "Importing test pair failed. (0 test pairs imported)"
34 end
34 end
35 end
35 end
36
36
37 @log_msg << import_problem_description(dirname)
37 @log_msg << import_problem_description(dirname)
38 @log_msg << import_problem_pdf(dirname)
38 @log_msg << import_problem_pdf(dirname)
39 @log_msg << import_full_score(dirname)
39 @log_msg << import_full_score(dirname)
40
40
41 + #import test data
42 + @log_msg << GraderScript.call_import_testcase(@problem.name)
43 +
41 return true
44 return true
42 end
45 end
43
46
44 protected
47 protected
45
48
46 def self.long_ext(filename)
49 def self.long_ext(filename)
47 i = filename.index('.')
50 i = filename.index('.')
48 len = filename.length
51 len = filename.length
49 return filename.slice(i..len)
52 return filename.slice(i..len)
50 end
53 end
51
54
52 def extract(tempfile)
55 def extract(tempfile)
You need to be logged in to leave comments. Login now