Description:
import problem replaced old one, fixed small problems problem validates name to have no space, test interface can deal with broken dependecies on problems. git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@436 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r205:9bf8e38c2911 - - 5 files changed: 14 inserted, 2 deleted

@@ -63,127 +63,135
63 flash[:notice] = 'Problem was successfully created.'
63 flash[:notice] = 'Problem was successfully created.'
64 redirect_to :action => 'list'
64 redirect_to :action => 'list'
65 else
65 else
66 flash[:notice] = 'Error saving problem'
66 flash[:notice] = 'Error saving problem'
67 redirect_to :action => 'list'
67 redirect_to :action => 'list'
68 end
68 end
69 end
69 end
70
70
71 def edit
71 def edit
72 @problem = Problem.find(params[:id])
72 @problem = Problem.find(params[:id])
73 @description = @problem.description
73 @description = @problem.description
74 end
74 end
75
75
76 def update
76 def update
77 @problem = Problem.find(params[:id])
77 @problem = Problem.find(params[:id])
78 @description = @problem.description
78 @description = @problem.description
79 if @description == nil and params[:description][:body]!=''
79 if @description == nil and params[:description][:body]!=''
80 @description = Description.new(params[:description])
80 @description = Description.new(params[:description])
81 if !@description.save
81 if !@description.save
82 flash[:notice] = 'Error saving description'
82 flash[:notice] = 'Error saving description'
83 render :action => 'edit' and return
83 render :action => 'edit' and return
84 end
84 end
85 @problem.description = @description
85 @problem.description = @description
86 elsif @description!=nil
86 elsif @description!=nil
87 if !@description.update_attributes(params[:description])
87 if !@description.update_attributes(params[:description])
88 flash[:notice] = 'Error saving description'
88 flash[:notice] = 'Error saving description'
89 render :action => 'edit' and return
89 render :action => 'edit' and return
90 end
90 end
91 end
91 end
92 if @problem.update_attributes(params[:problem])
92 if @problem.update_attributes(params[:problem])
93 flash[:notice] = 'Problem was successfully updated.'
93 flash[:notice] = 'Problem was successfully updated.'
94 redirect_to :action => 'show', :id => @problem
94 redirect_to :action => 'show', :id => @problem
95 else
95 else
96 render :action => 'edit'
96 render :action => 'edit'
97 end
97 end
98 end
98 end
99
99
100 def destroy
100 def destroy
101 Problem.find(params[:id]).destroy
101 Problem.find(params[:id]).destroy
102 redirect_to :action => 'list'
102 redirect_to :action => 'list'
103 end
103 end
104
104
105 def toggle
105 def toggle
106 @problem = Problem.find(params[:id])
106 @problem = Problem.find(params[:id])
107 @problem.available = !(@problem.available)
107 @problem.available = !(@problem.available)
108 @problem.save
108 @problem.save
109 end
109 end
110
110
111 def turn_all_off
111 def turn_all_off
112 Problem.find(:all,
112 Problem.find(:all,
113 :conditions => "available = 1").each do |problem|
113 :conditions => "available = 1").each do |problem|
114 problem.available = false
114 problem.available = false
115 problem.save
115 problem.save
116 end
116 end
117 redirect_to :action => 'list'
117 redirect_to :action => 'list'
118 end
118 end
119
119
120 def turn_all_on
120 def turn_all_on
121 Problem.find(:all,
121 Problem.find(:all,
122 :conditions => "available = 0").each do |problem|
122 :conditions => "available = 0").each do |problem|
123 problem.available = true
123 problem.available = true
124 problem.save
124 problem.save
125 end
125 end
126 redirect_to :action => 'list'
126 redirect_to :action => 'list'
127 end
127 end
128
128
129 def stat
129 def stat
130 @problem = Problem.find(params[:id])
130 @problem = Problem.find(params[:id])
131 if !@problem.available
131 if !@problem.available
132 redirect_to :controller => 'main', :action => 'list'
132 redirect_to :controller => 'main', :action => 'list'
133 else
133 else
134 @submissions = Submission.find_all_last_by_problem(params[:id])
134 @submissions = Submission.find_all_last_by_problem(params[:id])
135 end
135 end
136 end
136 end
137
137
138 def manage
138 def manage
139 @problems = Problem.find(:all, :order => 'date_added DESC')
139 @problems = Problem.find(:all, :order => 'date_added DESC')
140 end
140 end
141
141
142 def do_manage
142 def do_manage
143 if params.has_key? 'change_date_added'
143 if params.has_key? 'change_date_added'
144 change_date_added
144 change_date_added
145 end
145 end
146 redirect_to :action => 'manage'
146 redirect_to :action => 'manage'
147 end
147 end
148
148
149 def import
149 def import
150 end
150 end
151
151
152 def do_import
152 def do_import
153 @problem, import_log = Problem.new_from_import_form_params(params)
153 @problem, import_log = Problem.new_from_import_form_params(params)
154
154
155 if @problem.errors.length != 0
155 if @problem.errors.length != 0
156 render :action => 'import' and return
156 render :action => 'import' and return
157 end
157 end
158
158
159 + old_problem = Problem.find_by_name(@problem.name)
160 + if old_problem!=nil
161 + old_problem.full_name = @problem.full_name
162 + @problem = old_problem
163 +
164 + flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
165 + end
166 +
159 @problem.save
167 @problem.save
160 @log = import_log
168 @log = import_log
161 end
169 end
162
170
163 ##################################
171 ##################################
164 protected
172 protected
165
173
166 def change_date_added
174 def change_date_added
167 problems = get_problems_from_params
175 problems = get_problems_from_params
168 year = params[:date_added][:year].to_i
176 year = params[:date_added][:year].to_i
169 month = params[:date_added][:month].to_i
177 month = params[:date_added][:month].to_i
170 day = params[:date_added][:day].to_i
178 day = params[:date_added][:day].to_i
171 date = Date.new(year,month,day)
179 date = Date.new(year,month,day)
172 problems.each do |p|
180 problems.each do |p|
173 p.date_added = date
181 p.date_added = date
174 p.save
182 p.save
175 end
183 end
176 end
184 end
177
185
178 def get_problems_from_params
186 def get_problems_from_params
179 problems = []
187 problems = []
180 params.keys.each do |k|
188 params.keys.each do |k|
181 if k.index('prob-')==0
189 if k.index('prob-')==0
182 name, id = k.split('-')
190 name, id = k.split('-')
183 problems << Problem.find(id)
191 problems << Problem.find(id)
184 end
192 end
185 end
193 end
186 problems
194 problems
187 end
195 end
188
196
189 end
197 end
@@ -8,113 +8,113
8 # COMMENT OUT: filter in each action instead
8 # COMMENT OUT: filter in each action instead
9 #
9 #
10 # before_filter :verify_time_limit, :only => [:submit]
10 # before_filter :verify_time_limit, :only => [:submit]
11
11
12 verify :method => :post, :only => [:submit],
12 verify :method => :post, :only => [:submit],
13 :redirect_to => { :action => :index }
13 :redirect_to => { :action => :index }
14
14
15 def index
15 def index
16 prepare_index_information
16 prepare_index_information
17 end
17 end
18
18
19 def submit
19 def submit
20 @user = User.find(session[:user_id])
20 @user = User.find(session[:user_id])
21
21
22 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
22 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
23
23
24 if @submitted_test_request.errors.length != 0
24 if @submitted_test_request.errors.length != 0
25 prepare_index_information
25 prepare_index_information
26 render :action => 'index' and return
26 render :action => 'index' and return
27 end
27 end
28
28
29 if Configuration[SYSTEM_MODE_CONF_KEY]=='contest'
29 if Configuration[SYSTEM_MODE_CONF_KEY]=='contest'
30 if @user.site!=nil and @user.site.finished?
30 if @user.site!=nil and @user.site.finished?
31 @submitted_test_request.errors.add_to_base('Contest is over.')
31 @submitted_test_request.errors.add_to_base('Contest is over.')
32 prepare_index_information
32 prepare_index_information
33 render :action => 'index' and return
33 render :action => 'index' and return
34 end
34 end
35
35
36 if !Configuration.allow_test_request(@user)
36 if !Configuration.allow_test_request(@user)
37 prepare_index_information
37 prepare_index_information
38 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
38 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
39 redirect_to :action => 'index' and return
39 redirect_to :action => 'index' and return
40 end
40 end
41 end
41 end
42
42
43 if @submitted_test_request.save
43 if @submitted_test_request.save
44 redirect_to :action => 'index'
44 redirect_to :action => 'index'
45 else
45 else
46 prepare_index_information
46 prepare_index_information
47 render :action => 'index'
47 render :action => 'index'
48 end
48 end
49 end
49 end
50
50
51 def read
51 def read
52 user = User.find(session[:user_id])
52 user = User.find(session[:user_id])
53 begin
53 begin
54 test_request = TestRequest.find(params[:id])
54 test_request = TestRequest.find(params[:id])
55 rescue
55 rescue
56 test_request = nil
56 test_request = nil
57 end
57 end
58 if test_request==nil or test_request.user_id != user.id
58 if test_request==nil or test_request.user_id != user.id
59 flash[:notice] = 'Invalid output'
59 flash[:notice] = 'Invalid output'
60 redirect_to :action => 'index'
60 redirect_to :action => 'index'
61 return
61 return
62 end
62 end
63 if test_request.output_file_name!=nil
63 if test_request.output_file_name!=nil
64 data = File.open(test_request.output_file_name).read(2048)
64 data = File.open(test_request.output_file_name).read(2048)
65 if data==nil
65 if data==nil
66 data=""
66 data=""
67 end
67 end
68 send_data(data,
68 send_data(data,
69 {:filename => 'output.txt',
69 {:filename => 'output.txt',
70 :type => 'text/plain'})
70 :type => 'text/plain'})
71 return
71 return
72 end
72 end
73 redirect_to :action => 'index'
73 redirect_to :action => 'index'
74 end
74 end
75
75
76 def result
76 def result
77 @user = User.find(session[:user_id])
77 @user = User.find(session[:user_id])
78 begin
78 begin
79 @test_request = TestRequest.find(params[:id])
79 @test_request = TestRequest.find(params[:id])
80 rescue
80 rescue
81 @test_request = nil
81 @test_request = nil
82 end
82 end
83 if @test_request==nil or @test_request.user_id != @user.id
83 if @test_request==nil or @test_request.user_id != @user.id
84 flash[:notice] = 'Invalid request'
84 flash[:notice] = 'Invalid request'
85 redirect_to :action => 'index'
85 redirect_to :action => 'index'
86 return
86 return
87 end
87 end
88 end
88 end
89
89
90 protected
90 protected
91
91
92 def prepare_index_information
92 def prepare_index_information
93 @user = User.find(session[:user_id])
93 @user = User.find(session[:user_id])
94 @submissions = Submission.find_last_for_all_available_problems(@user.id)
94 @submissions = Submission.find_last_for_all_available_problems(@user.id)
95 all_problems = @submissions.collect { |submission| submission.problem }
95 all_problems = @submissions.collect { |submission| submission.problem }
96 @problems = []
96 @problems = []
97 all_problems.each do |problem|
97 all_problems.each do |problem|
98 if problem.test_allowed
98 if problem.test_allowed
99 @problems << problem
99 @problems << problem
100 end
100 end
101 end
101 end
102 @test_requests = []
102 @test_requests = []
103 @user.test_requests.each do |ts|
103 @user.test_requests.each do |ts|
104 - if ts.problem.available
104 + if ts.problem and ts.problem.available
105 @test_requests << ts
105 @test_requests << ts
106 end
106 end
107 end
107 end
108 end
108 end
109
109
110 def check_viewability
110 def check_viewability
111 user = User.find(session[:user_id])
111 user = User.find(session[:user_id])
112 if !Configuration.show_tasks_to?(user)
112 if !Configuration.show_tasks_to?(user)
113 redirect_to :controller => 'main', :action => 'list'
113 redirect_to :controller => 'main', :action => 'list'
114 end
114 end
115 if (!Configuration.show_submitbox_to?(user)) and (action_name=='submit')
115 if (!Configuration.show_submitbox_to?(user)) and (action_name=='submit')
116 redirect_to :controller => 'test', :action => 'index'
116 redirect_to :controller => 'test', :action => 'index'
117 end
117 end
118 end
118 end
119
119
120 end
120 end
@@ -1,76 +1,77
1 class Problem < ActiveRecord::Base
1 class Problem < ActiveRecord::Base
2
2
3 belongs_to :description
3 belongs_to :description
4
4
5 validates_presence_of :name
5 validates_presence_of :name
6 + validates_format_of :name, :with => /^\w+$/
6 validates_presence_of :full_name
7 validates_presence_of :full_name
7
8
8 def self.find_available_problems
9 def self.find_available_problems
9 find(:all, :conditions => {:available => true}, :order => "date_added DESC")
10 find(:all, :conditions => {:available => true}, :order => "date_added DESC")
10 end
11 end
11
12
12 def self.new_from_import_form_params(params)
13 def self.new_from_import_form_params(params)
13 problem = Problem.new
14 problem = Problem.new
14
15
15 # form error checking
16 # form error checking
16
17
17 time_limit_s = params[:time_limit]
18 time_limit_s = params[:time_limit]
18 memory_limit_s = params[:memory_limit]
19 memory_limit_s = params[:memory_limit]
19
20
20 time_limit_s = '1' if time_limit_s==''
21 time_limit_s = '1' if time_limit_s==''
21 memory_limit_s = '32' if memory_limit_s==''
22 memory_limit_s = '32' if memory_limit_s==''
22
23
23 time_limit = time_limit_s.to_i
24 time_limit = time_limit_s.to_i
24 memory_limit = memory_limit_s.to_i
25 memory_limit = memory_limit_s.to_i
25
26
26 if time_limit==0 and time_limit_s!='0'
27 if time_limit==0 and time_limit_s!='0'
27 problem.errors.add_to_base('Time limit format errors.')
28 problem.errors.add_to_base('Time limit format errors.')
28 elsif time_limit<=0 or time_limit >60
29 elsif time_limit<=0 or time_limit >60
29 problem.errors.add_to_base('Time limit out of range.')
30 problem.errors.add_to_base('Time limit out of range.')
30 end
31 end
31
32
32 if memory_limit==0 and memory_limit_s!='0'
33 if memory_limit==0 and memory_limit_s!='0'
33 problem.errors.add_to_base('Memory limit format errors.')
34 problem.errors.add_to_base('Memory limit format errors.')
34 elsif memory_limit<=0 or memory_limit >512
35 elsif memory_limit<=0 or memory_limit >512
35 problem.errors.add_to_base('Memory limit out of range.')
36 problem.errors.add_to_base('Memory limit out of range.')
36 end
37 end
37
38
38 if params[:file]==nil or params[:file]==''
39 if params[:file]==nil or params[:file]==''
39 problem.errors.add_to_base('No testdata file.')
40 problem.errors.add_to_base('No testdata file.')
40 end
41 end
41
42
42 file = params[:file]
43 file = params[:file]
43
44
44 if problem.errors.length!=0
45 if problem.errors.length!=0
45 return problem
46 return problem
46 end
47 end
47
48
48 problem.name = params[:name]
49 problem.name = params[:name]
49 if params[:full_name]!=''
50 if params[:full_name]!=''
50 problem.full_name = params[:full_name]
51 problem.full_name = params[:full_name]
51 else
52 else
52 problem.full_name = params[:name]
53 problem.full_name = params[:name]
53 end
54 end
54
55
55 if not problem.valid?
56 if not problem.valid?
56 return problem
57 return problem
57 end
58 end
58
59
59 importer = TestdataImporter.new
60 importer = TestdataImporter.new
60
61
61 if not importer.import_from_file(problem.name,
62 if not importer.import_from_file(problem.name,
62 file,
63 file,
63 time_limit,
64 time_limit,
64 memory_limit)
65 memory_limit)
65 problem.errors.add_to_base('Import error.')
66 problem.errors.add_to_base('Import error.')
66 end
67 end
67
68
68 problem.full_score = 100
69 problem.full_score = 100
69 problem.date_added = Time.new
70 problem.date_added = Time.new
70 problem.test_allowed = true
71 problem.test_allowed = true
71 problem.output_only = false
72 problem.output_only = false
72 problem.available = false
73 problem.available = false
73 return problem, importer.log_msg
74 return problem, importer.log_msg
74 end
75 end
75
76
76 end
77 end
@@ -1,48 +1,51
1 - content_for :head do
1 - content_for :head do
2 = stylesheet_link_tag 'graders'
2 = stylesheet_link_tag 'graders'
3 <meta http-equiv ="refresh" content="60"/>
3 <meta http-equiv ="refresh" content="60"/>
4
4
5 %h1 Grader information
5 %h1 Grader information
6
6
7 + = link_to '[Refresh]', :action => 'list'
8 + %br/
9 +
7 .submitbox
10 .submitbox
8 .item
11 .item
9 Grader control:
12 Grader control:
10 .item
13 .item
11 - form_for :clear, nil, :url => {:action => 'start_grading'} do |f|
14 - form_for :clear, nil, :url => {:action => 'start_grading'} do |f|
12 = submit_tag 'Start graders in grading env'
15 = submit_tag 'Start graders in grading env'
13 .item
16 .item
14 - form_for :clear, nil, :url => {:action => 'start_exam'} do |f|
17 - form_for :clear, nil, :url => {:action => 'start_exam'} do |f|
15 = submit_tag 'Start graders in exam env'
18 = submit_tag 'Start graders in exam env'
16 .item
19 .item
17 - form_for :clear, nil, :url => {:action => 'stop_all'} do |f|
20 - form_for :clear, nil, :url => {:action => 'stop_all'} do |f|
18 = submit_tag 'Stop all running graders'
21 = submit_tag 'Stop all running graders'
19 .item
22 .item
20 - form_for :clear, nil, :url => {:action => 'clear_all'} do |f|
23 - form_for :clear, nil, :url => {:action => 'clear_all'} do |f|
21 = submit_tag 'Clear all data'
24 = submit_tag 'Clear all data'
22 %br{:style => 'clear:both'}/
25 %br{:style => 'clear:both'}/
23
26
24 - if @last_task
27 - if @last_task
25 Last task:
28 Last task:
26 = link_to "#{@last_task.id}", :action => 'view', :id => @last_task.id, :type => 'Task'
29 = link_to "#{@last_task.id}", :action => 'view', :id => @last_task.id, :type => 'Task'
27
30
28 %br/
31 %br/
29
32
30 - if @last_test_request
33 - if @last_test_request
31 Last test_request:
34 Last test_request:
32 = link_to "#{@last_test_request.id}", :action => 'view', :id => @last_test_request.id, :type => 'TestRequest'
35 = link_to "#{@last_test_request.id}", :action => 'view', :id => @last_test_request.id, :type => 'TestRequest'
33
36
34
37
35 %h2 Current graders
38 %h2 Current graders
36
39
37 = render :partial => 'grader_list', :locals => {:grader_list => @grader_processes}
40 = render :partial => 'grader_list', :locals => {:grader_list => @grader_processes}
38
41
39 %h2 Stalled graders
42 %h2 Stalled graders
40
43
41 = render :partial => 'grader_list', :locals => {:grader_list => @stalled_processes}
44 = render :partial => 'grader_list', :locals => {:grader_list => @stalled_processes}
42
45
43 %h2 Terminated graders
46 %h2 Terminated graders
44
47
45 - form_for :clear, nil, :url => {:action => 'clear_terminated'} do |f|
48 - form_for :clear, nil, :url => {:action => 'clear_terminated'} do |f|
46 = submit_tag 'Clear data for terminated graders'
49 = submit_tag 'Clear data for terminated graders'
47
50
48 = render :partial => 'grader_list', :locals => {:grader_list => @terminated_processes}
51 = render :partial => 'grader_list', :locals => {:grader_list => @terminated_processes}
@@ -1,76 +1,76
1 require 'tmpdir'
1 require 'tmpdir'
2
2
3 class TestdataImporter
3 class TestdataImporter
4
4
5 attr :log_msg
5 attr :log_msg
6
6
7 def import_from_file(problem_name,
7 def import_from_file(problem_name,
8 tempfile,
8 tempfile,
9 time_limit,
9 time_limit,
10 memory_limit)
10 memory_limit)
11
11
12 dirname = TestdataImporter.extract(problem_name, tempfile)
12 dirname = TestdataImporter.extract(problem_name, tempfile)
13 return false if not dirname
13 return false if not dirname
14 @log_msg = GraderScript.call_import_problem(problem_name,
14 @log_msg = GraderScript.call_import_problem(problem_name,
15 dirname,
15 dirname,
16 time_limit,
16 time_limit,
17 memory_limit)
17 memory_limit)
18 return true
18 return true
19 end
19 end
20
20
21 protected
21 protected
22
22
23 def self.long_ext(filename)
23 def self.long_ext(filename)
24 i = filename.index('.')
24 i = filename.index('.')
25 len = filename.length
25 len = filename.length
26 return filename.slice(i..len)
26 return filename.slice(i..len)
27 end
27 end
28
28
29 def self.extract(problem_name, tempfile)
29 def self.extract(problem_name, tempfile)
30 testdata_filename = TestdataImporter.save_testdata_file(problem_name,
30 testdata_filename = TestdataImporter.save_testdata_file(problem_name,
31 tempfile)
31 tempfile)
32 ext = TestdataImporter.long_ext(tempfile.original_filename)
32 ext = TestdataImporter.long_ext(tempfile.original_filename)
33
33
34 extract_dir = File.join(GraderScript.raw_dir, problem_name)
34 extract_dir = File.join(GraderScript.raw_dir, problem_name)
35 begin
35 begin
36 Dir.mkdir extract_dir
36 Dir.mkdir extract_dir
37 rescue Errno::EEXIST
37 rescue Errno::EEXIST
38 end
38 end
39
39
40 if ext=='.tar.gz' or ext=='.tgz'
40 if ext=='.tar.gz' or ext=='.tgz'
41 cmd = "tar -zxvf #{testdata_filename} -C #{extract_dir}"
41 cmd = "tar -zxvf #{testdata_filename} -C #{extract_dir}"
42 elsif ext=='.tar'
42 elsif ext=='.tar'
43 cmd = "tar -xvf #{testdata_filename} -C #{extract_dir}"
43 cmd = "tar -xvf #{testdata_filename} -C #{extract_dir}"
44 elsif ext=='.zip'
44 elsif ext=='.zip'
45 - cmd = "unzip #{testdata_filename} -d #{extract_dir}"
45 + cmd = "unzip -o #{testdata_filename} -d #{extract_dir}"
46 else
46 else
47 return nil
47 return nil
48 end
48 end
49
49
50 system(cmd)
50 system(cmd)
51
51
52 files = Dir["#{extract_dir}/**/1*.in"]
52 files = Dir["#{extract_dir}/**/1*.in"]
53 return nil if files.length==0
53 return nil if files.length==0
54
54
55 return File.dirname(files[0])
55 return File.dirname(files[0])
56 end
56 end
57
57
58 def self.save_testdata_file(problem_name, tempfile)
58 def self.save_testdata_file(problem_name, tempfile)
59 ext = TestdataImporter.long_ext(tempfile.original_filename)
59 ext = TestdataImporter.long_ext(tempfile.original_filename)
60 testdata_filename = File.join(Dir.tmpdir,"#{problem_name}#{ext}")
60 testdata_filename = File.join(Dir.tmpdir,"#{problem_name}#{ext}")
61
61
62 return nil if tempfile==""
62 return nil if tempfile==""
63
63
64 if tempfile.instance_of?(Tempfile)
64 if tempfile.instance_of?(Tempfile)
65 tempfile.close
65 tempfile.close
66 FileUtils.move(tempfile.path,testdata_filename)
66 FileUtils.move(tempfile.path,testdata_filename)
67 else
67 else
68 File.open(testdata_filename, "wb") do |f|
68 File.open(testdata_filename, "wb") do |f|
69 f.write(tempfile.read)
69 f.write(tempfile.read)
70 end
70 end
71 end
71 end
72
72
73 return testdata_filename
73 return testdata_filename
74 end
74 end
75
75
76 end
76 end
You need to be logged in to leave comments. Login now