Description:
update errors.add_to_base("x") to Rails 3 errors.add(:base,"x")
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r347:6d2339b98fac - - 6 files changed: 12 inserted, 12 deleted

@@ -1,381 +1,381
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 before_filter :authenticate, :except => [:index, :login]
3 before_filter :authenticate, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
5
5
6 append_before_filter :confirm_and_update_start_time,
6 append_before_filter :confirm_and_update_start_time,
7 :except => [:index,
7 :except => [:index,
8 :login,
8 :login,
9 :confirm_contest_start]
9 :confirm_contest_start]
10
10
11 # to prevent log in box to be shown when user logged out of the
11 # to prevent log in box to be shown when user logged out of the
12 # system only in some tab
12 # system only in some tab
13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
14 :only => [:announcements]
14 :only => [:announcements]
15
15
16 # COMMENTED OUT: filter in each action instead
16 # COMMENTED OUT: filter in each action instead
17 # before_filter :verify_time_limit, :only => [:submit]
17 # before_filter :verify_time_limit, :only => [:submit]
18
18
19 verify :method => :post, :only => [:submit],
19 verify :method => :post, :only => [:submit],
20 :redirect_to => { :action => :index }
20 :redirect_to => { :action => :index }
21
21
22 # COMMENT OUT: only need when having high load
22 # COMMENT OUT: only need when having high load
23 # caches_action :index, :login
23 # caches_action :index, :login
24
24
25 # NOTE: This method is not actually needed, 'config/routes.rb' has
25 # NOTE: This method is not actually needed, 'config/routes.rb' has
26 # assigned action login as a default action.
26 # assigned action login as a default action.
27 def index
27 def index
28 redirect_to :action => 'login'
28 redirect_to :action => 'login'
29 end
29 end
30
30
31 def login
31 def login
32 saved_notice = flash[:notice]
32 saved_notice = flash[:notice]
33 reset_session
33 reset_session
34 flash.now[:notice] = saved_notice
34 flash.now[:notice] = saved_notice
35
35
36 # EXPERIMENT:
36 # EXPERIMENT:
37 # Hide login if in single user mode and the url does not
37 # Hide login if in single user mode and the url does not
38 # explicitly specify /login
38 # explicitly specify /login
39 #
39 #
40 # logger.info "PATH: #{request.path}"
40 # logger.info "PATH: #{request.path}"
41 # if GraderConfiguration['system.single_user_mode'] and
41 # if GraderConfiguration['system.single_user_mode'] and
42 # request.path!='/main/login'
42 # request.path!='/main/login'
43 # @hidelogin = true
43 # @hidelogin = true
44 # end
44 # end
45
45
46 @announcements = Announcement.find_for_frontpage
46 @announcements = Announcement.find_for_frontpage
47 render :action => 'login', :layout => 'empty'
47 render :action => 'login', :layout => 'empty'
48 end
48 end
49
49
50 def list
50 def list
51 prepare_list_information
51 prepare_list_information
52 end
52 end
53
53
54 def help
54 def help
55 @user = User.find(session[:user_id])
55 @user = User.find(session[:user_id])
56 end
56 end
57
57
58 def submit
58 def submit
59 user = User.find(session[:user_id])
59 user = User.find(session[:user_id])
60
60
61 @submission = Submission.new
61 @submission = Submission.new
62 @submission.problem_id = params[:submission][:problem_id]
62 @submission.problem_id = params[:submission][:problem_id]
63 @submission.user = user
63 @submission.user = user
64 @submission.language_id = 0
64 @submission.language_id = 0
65 if (params['file']) and (params['file']!='')
65 if (params['file']) and (params['file']!='')
66 @submission.source = params['file'].read
66 @submission.source = params['file'].read
67 @submission.source_filename = params['file'].original_filename
67 @submission.source_filename = params['file'].original_filename
68 end
68 end
69 @submission.submitted_at = Time.new.gmtime
69 @submission.submitted_at = Time.new.gmtime
70
70
71 if GraderConfiguration.time_limit_mode? and user.contest_finished?
71 if GraderConfiguration.time_limit_mode? and user.contest_finished?
72 - @submission.errors.add_to_base "The contest is over."
72 + @submission.errors.add(:base,"The contest is over.")
73 prepare_list_information
73 prepare_list_information
74 render :action => 'list' and return
74 render :action => 'list' and return
75 end
75 end
76
76
77 if @submission.valid?
77 if @submission.valid?
78 if @submission.save == false
78 if @submission.save == false
79 flash[:notice] = 'Error saving your submission'
79 flash[:notice] = 'Error saving your submission'
80 elsif Task.create(:submission_id => @submission.id,
80 elsif Task.create(:submission_id => @submission.id,
81 :status => Task::STATUS_INQUEUE) == false
81 :status => Task::STATUS_INQUEUE) == false
82 flash[:notice] = 'Error adding your submission to task queue'
82 flash[:notice] = 'Error adding your submission to task queue'
83 end
83 end
84 else
84 else
85 prepare_list_information
85 prepare_list_information
86 render :action => 'list' and return
86 render :action => 'list' and return
87 end
87 end
88 redirect_to :action => 'list'
88 redirect_to :action => 'list'
89 end
89 end
90
90
91 def source
91 def source
92 submission = Submission.find(params[:id])
92 submission = Submission.find(params[:id])
93 if ((submission.user_id == session[:user_id]) and
93 if ((submission.user_id == session[:user_id]) and
94 (submission.problem != nil) and
94 (submission.problem != nil) and
95 (submission.problem.available))
95 (submission.problem.available))
96 send_data(submission.source,
96 send_data(submission.source,
97 {:filename => submission.download_filename,
97 {:filename => submission.download_filename,
98 :type => 'text/plain'})
98 :type => 'text/plain'})
99 else
99 else
100 flash[:notice] = 'Error viewing source'
100 flash[:notice] = 'Error viewing source'
101 redirect_to :action => 'list'
101 redirect_to :action => 'list'
102 end
102 end
103 end
103 end
104
104
105 def compiler_msg
105 def compiler_msg
106 @submission = Submission.find(params[:id])
106 @submission = Submission.find(params[:id])
107 if @submission.user_id == session[:user_id]
107 if @submission.user_id == session[:user_id]
108 render :action => 'compiler_msg', :layout => 'empty'
108 render :action => 'compiler_msg', :layout => 'empty'
109 else
109 else
110 flash[:notice] = 'Error viewing source'
110 flash[:notice] = 'Error viewing source'
111 redirect_to :action => 'list'
111 redirect_to :action => 'list'
112 end
112 end
113 end
113 end
114
114
115 def submission
115 def submission
116 @user = User.find(session[:user_id])
116 @user = User.find(session[:user_id])
117 @problems = @user.available_problems
117 @problems = @user.available_problems
118 if params[:id]==nil
118 if params[:id]==nil
119 @problem = nil
119 @problem = nil
120 @submissions = nil
120 @submissions = nil
121 else
121 else
122 @problem = Problem.find_by_name(params[:id])
122 @problem = Problem.find_by_name(params[:id])
123 if not @problem.available
123 if not @problem.available
124 redirect_to :action => 'list'
124 redirect_to :action => 'list'
125 flash[:notice] = 'Error: submissions for that problem are not viewable.'
125 flash[:notice] = 'Error: submissions for that problem are not viewable.'
126 return
126 return
127 end
127 end
128 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
128 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
129 end
129 end
130 end
130 end
131
131
132 def result
132 def result
133 if !GraderConfiguration.show_grading_result
133 if !GraderConfiguration.show_grading_result
134 redirect_to :action => 'list' and return
134 redirect_to :action => 'list' and return
135 end
135 end
136 @user = User.find(session[:user_id])
136 @user = User.find(session[:user_id])
137 @submission = Submission.find(params[:id])
137 @submission = Submission.find(params[:id])
138 if @submission.user!=@user
138 if @submission.user!=@user
139 flash[:notice] = 'You are not allowed to view result of other users.'
139 flash[:notice] = 'You are not allowed to view result of other users.'
140 redirect_to :action => 'list' and return
140 redirect_to :action => 'list' and return
141 end
141 end
142 prepare_grading_result(@submission)
142 prepare_grading_result(@submission)
143 end
143 end
144
144
145 def load_output
145 def load_output
146 if !GraderConfiguration.show_grading_result or params[:num]==nil
146 if !GraderConfiguration.show_grading_result or params[:num]==nil
147 redirect_to :action => 'list' and return
147 redirect_to :action => 'list' and return
148 end
148 end
149 @user = User.find(session[:user_id])
149 @user = User.find(session[:user_id])
150 @submission = Submission.find(params[:id])
150 @submission = Submission.find(params[:id])
151 if @submission.user!=@user
151 if @submission.user!=@user
152 flash[:notice] = 'You are not allowed to view result of other users.'
152 flash[:notice] = 'You are not allowed to view result of other users.'
153 redirect_to :action => 'list' and return
153 redirect_to :action => 'list' and return
154 end
154 end
155 case_num = params[:num].to_i
155 case_num = params[:num].to_i
156 out_filename = output_filename(@user.login,
156 out_filename = output_filename(@user.login,
157 @submission.problem.name,
157 @submission.problem.name,
158 @submission.id,
158 @submission.id,
159 case_num)
159 case_num)
160 if !FileTest.exists?(out_filename)
160 if !FileTest.exists?(out_filename)
161 flash[:notice] = 'Output not found.'
161 flash[:notice] = 'Output not found.'
162 redirect_to :action => 'list' and return
162 redirect_to :action => 'list' and return
163 end
163 end
164
164
165 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
165 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
166 response.headers['Content-Type'] = "application/force-download"
166 response.headers['Content-Type'] = "application/force-download"
167 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
167 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
168 response.headers["X-Sendfile"] = out_filename
168 response.headers["X-Sendfile"] = out_filename
169 response.headers['Content-length'] = File.size(out_filename)
169 response.headers['Content-length'] = File.size(out_filename)
170 render :nothing => true
170 render :nothing => true
171 else
171 else
172 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
172 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
173 end
173 end
174 end
174 end
175
175
176 def error
176 def error
177 @user = User.find(session[:user_id])
177 @user = User.find(session[:user_id])
178 end
178 end
179
179
180 # announcement refreshing and hiding methods
180 # announcement refreshing and hiding methods
181
181
182 def announcements
182 def announcements
183 if params.has_key? 'recent'
183 if params.has_key? 'recent'
184 prepare_announcements(params[:recent])
184 prepare_announcements(params[:recent])
185 else
185 else
186 prepare_announcements
186 prepare_announcements
187 end
187 end
188 render(:partial => 'announcement',
188 render(:partial => 'announcement',
189 :collection => @announcements,
189 :collection => @announcements,
190 :locals => {:announcement_effect => true})
190 :locals => {:announcement_effect => true})
191 end
191 end
192
192
193 def confirm_contest_start
193 def confirm_contest_start
194 user = User.find(session[:user_id])
194 user = User.find(session[:user_id])
195 if request.method == :post
195 if request.method == :post
196 user.update_start_time
196 user.update_start_time
197 redirect_to :action => 'list'
197 redirect_to :action => 'list'
198 else
198 else
199 @contests = user.contests
199 @contests = user.contests
200 @user = user
200 @user = user
201 end
201 end
202 end
202 end
203
203
204 protected
204 protected
205
205
206 def prepare_announcements(recent=nil)
206 def prepare_announcements(recent=nil)
207 if GraderConfiguration.show_tasks_to?(@user)
207 if GraderConfiguration.show_tasks_to?(@user)
208 @announcements = Announcement.find_published(true)
208 @announcements = Announcement.find_published(true)
209 else
209 else
210 @announcements = Announcement.find_published
210 @announcements = Announcement.find_published
211 end
211 end
212 if recent!=nil
212 if recent!=nil
213 recent_id = recent.to_i
213 recent_id = recent.to_i
214 @announcements = @announcements.find_all { |a| a.id > recent_id }
214 @announcements = @announcements.find_all { |a| a.id > recent_id }
215 end
215 end
216 end
216 end
217
217
218 def prepare_list_information
218 def prepare_list_information
219 @user = User.find(session[:user_id])
219 @user = User.find(session[:user_id])
220 if not GraderConfiguration.multicontests?
220 if not GraderConfiguration.multicontests?
221 @problems = @user.available_problems
221 @problems = @user.available_problems
222 else
222 else
223 @contest_problems = @user.available_problems_group_by_contests
223 @contest_problems = @user.available_problems_group_by_contests
224 @problems = @user.available_problems
224 @problems = @user.available_problems
225 end
225 end
226 @prob_submissions = {}
226 @prob_submissions = {}
227 @problems.each do |p|
227 @problems.each do |p|
228 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
228 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
229 if sub!=nil
229 if sub!=nil
230 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
230 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
231 else
231 else
232 @prob_submissions[p.id] = { :count => 0, :submission => nil }
232 @prob_submissions[p.id] = { :count => 0, :submission => nil }
233 end
233 end
234 end
234 end
235 prepare_announcements
235 prepare_announcements
236 end
236 end
237
237
238 def check_viewability
238 def check_viewability
239 @user = User.find(session[:user_id])
239 @user = User.find(session[:user_id])
240 if (!GraderConfiguration.show_tasks_to?(@user)) and
240 if (!GraderConfiguration.show_tasks_to?(@user)) and
241 ((action_name=='submission') or (action_name=='submit'))
241 ((action_name=='submission') or (action_name=='submit'))
242 redirect_to :action => 'list' and return
242 redirect_to :action => 'list' and return
243 end
243 end
244 end
244 end
245
245
246 def prepare_grading_result(submission)
246 def prepare_grading_result(submission)
247 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
247 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
248 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
248 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
249 else
249 else
250 # guess task info from problem.full_score
250 # guess task info from problem.full_score
251 cases = submission.problem.full_score / 10
251 cases = submission.problem.full_score / 10
252 grading_info = {
252 grading_info = {
253 'testruns' => cases,
253 'testruns' => cases,
254 'testcases' => cases
254 'testcases' => cases
255 }
255 }
256 end
256 end
257 @test_runs = []
257 @test_runs = []
258 if grading_info['testruns'].is_a? Integer
258 if grading_info['testruns'].is_a? Integer
259 trun_count = grading_info['testruns']
259 trun_count = grading_info['testruns']
260 trun_count.times do |i|
260 trun_count.times do |i|
261 @test_runs << [ read_grading_result(@user.login,
261 @test_runs << [ read_grading_result(@user.login,
262 submission.problem.name,
262 submission.problem.name,
263 submission.id,
263 submission.id,
264 i+1) ]
264 i+1) ]
265 end
265 end
266 else
266 else
267 grading_info['testruns'].keys.sort.each do |num|
267 grading_info['testruns'].keys.sort.each do |num|
268 run = []
268 run = []
269 testrun = grading_info['testruns'][num]
269 testrun = grading_info['testruns'][num]
270 testrun.each do |c|
270 testrun.each do |c|
271 run << read_grading_result(@user.login,
271 run << read_grading_result(@user.login,
272 submission.problem.name,
272 submission.problem.name,
273 submission.id,
273 submission.id,
274 c)
274 c)
275 end
275 end
276 @test_runs << run
276 @test_runs << run
277 end
277 end
278 end
278 end
279 end
279 end
280
280
281 def grading_result_dir(user_name, problem_name, submission_id, case_num)
281 def grading_result_dir(user_name, problem_name, submission_id, case_num)
282 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
282 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
283 end
283 end
284
284
285 def output_filename(user_name, problem_name, submission_id, case_num)
285 def output_filename(user_name, problem_name, submission_id, case_num)
286 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
286 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
287 return "#{dir}/output.txt"
287 return "#{dir}/output.txt"
288 end
288 end
289
289
290 def read_grading_result(user_name, problem_name, submission_id, case_num)
290 def read_grading_result(user_name, problem_name, submission_id, case_num)
291 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
291 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
292 result_file_name = "#{dir}/result"
292 result_file_name = "#{dir}/result"
293 if !FileTest.exists?(result_file_name)
293 if !FileTest.exists?(result_file_name)
294 return {:num => case_num, :msg => 'program did not run'}
294 return {:num => case_num, :msg => 'program did not run'}
295 else
295 else
296 results = File.open(result_file_name).readlines
296 results = File.open(result_file_name).readlines
297 run_stat = extract_running_stat(results)
297 run_stat = extract_running_stat(results)
298 output_filename = "#{dir}/output.txt"
298 output_filename = "#{dir}/output.txt"
299 if FileTest.exists?(output_filename)
299 if FileTest.exists?(output_filename)
300 output_file = true
300 output_file = true
301 output_size = File.size(output_filename)
301 output_size = File.size(output_filename)
302 else
302 else
303 output_file = false
303 output_file = false
304 output_size = 0
304 output_size = 0
305 end
305 end
306
306
307 return {
307 return {
308 :num => case_num,
308 :num => case_num,
309 :msg => results[0],
309 :msg => results[0],
310 :run_stat => run_stat,
310 :run_stat => run_stat,
311 :output => output_file,
311 :output => output_file,
312 :output_size => output_size
312 :output_size => output_size
313 }
313 }
314 end
314 end
315 end
315 end
316
316
317 # copied from grader/script/lib/test_request_helper.rb
317 # copied from grader/script/lib/test_request_helper.rb
318 def extract_running_stat(results)
318 def extract_running_stat(results)
319 running_stat_line = results[-1]
319 running_stat_line = results[-1]
320
320
321 # extract exit status line
321 # extract exit status line
322 run_stat = ""
322 run_stat = ""
323 if !(/[Cc]orrect/.match(results[0]))
323 if !(/[Cc]orrect/.match(results[0]))
324 run_stat = results[0].chomp
324 run_stat = results[0].chomp
325 else
325 else
326 run_stat = 'Program exited normally'
326 run_stat = 'Program exited normally'
327 end
327 end
328
328
329 logger.info "Stat line: #{running_stat_line}"
329 logger.info "Stat line: #{running_stat_line}"
330
330
331 # extract running time
331 # extract running time
332 if res = /r(.*)u(.*)s/.match(running_stat_line)
332 if res = /r(.*)u(.*)s/.match(running_stat_line)
333 seconds = (res[1].to_f + res[2].to_f)
333 seconds = (res[1].to_f + res[2].to_f)
334 time_stat = "Time used: #{seconds} sec."
334 time_stat = "Time used: #{seconds} sec."
335 else
335 else
336 seconds = nil
336 seconds = nil
337 time_stat = "Time used: n/a sec."
337 time_stat = "Time used: n/a sec."
338 end
338 end
339
339
340 # extract memory usage
340 # extract memory usage
341 if res = /s(.*)m/.match(running_stat_line)
341 if res = /s(.*)m/.match(running_stat_line)
342 memory_used = res[1].to_i
342 memory_used = res[1].to_i
343 else
343 else
344 memory_used = -1
344 memory_used = -1
345 end
345 end
346
346
347 return {
347 return {
348 :msg => "#{run_stat}\n#{time_stat}",
348 :msg => "#{run_stat}\n#{time_stat}",
349 :running_time => seconds,
349 :running_time => seconds,
350 :exit_status => run_stat,
350 :exit_status => run_stat,
351 :memory_usage => memory_used
351 :memory_usage => memory_used
352 }
352 }
353 end
353 end
354
354
355 def confirm_and_update_start_time
355 def confirm_and_update_start_time
356 user = User.find(session[:user_id])
356 user = User.find(session[:user_id])
357 if (GraderConfiguration.indv_contest_mode? and
357 if (GraderConfiguration.indv_contest_mode? and
358 GraderConfiguration['contest.confirm_indv_contest_start'] and
358 GraderConfiguration['contest.confirm_indv_contest_start'] and
359 !user.contest_started?)
359 !user.contest_started?)
360 redirect_to :action => 'confirm_contest_start' and return
360 redirect_to :action => 'confirm_contest_start' and return
361 end
361 end
362 if not GraderConfiguration.analysis_mode?
362 if not GraderConfiguration.analysis_mode?
363 user.update_start_time
363 user.update_start_time
364 end
364 end
365 end
365 end
366
366
367 def reject_announcement_refresh_when_logged_out
367 def reject_announcement_refresh_when_logged_out
368 if not session[:user_id]
368 if not session[:user_id]
369 render :text => 'Access forbidden', :status => 403
369 render :text => 'Access forbidden', :status => 403
370 end
370 end
371
371
372 if GraderConfiguration.multicontests?
372 if GraderConfiguration.multicontests?
373 user = User.find(session[:user_id])
373 user = User.find(session[:user_id])
374 if user.contest_stat.forced_logout
374 if user.contest_stat.forced_logout
375 render :text => 'Access forbidden', :status => 403
375 render :text => 'Access forbidden', :status => 403
376 end
376 end
377 end
377 end
378 end
378 end
379
379
380 end
380 end
381
381
@@ -1,118 +1,118
1 class TestController < ApplicationController
1 class TestController < ApplicationController
2
2
3 before_filter :authenticate, :check_viewability
3 before_filter :authenticate, :check_viewability
4
4
5 #
5 #
6 # COMMENT OUT: filter in each action instead
6 # COMMENT OUT: filter in each action instead
7 #
7 #
8 # before_filter :verify_time_limit, :only => [:submit]
8 # before_filter :verify_time_limit, :only => [:submit]
9
9
10 verify :method => :post, :only => [:submit],
10 verify :method => :post, :only => [:submit],
11 :redirect_to => { :action => :index }
11 :redirect_to => { :action => :index }
12
12
13 def index
13 def index
14 prepare_index_information
14 prepare_index_information
15 end
15 end
16
16
17 def submit
17 def submit
18 @user = User.find(session[:user_id])
18 @user = User.find(session[:user_id])
19
19
20 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
20 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
21
21
22 if ! @submitted_test_request.errors.empty?
22 if ! @submitted_test_request.errors.empty?
23 prepare_index_information
23 prepare_index_information
24 render :action => 'index' and return
24 render :action => 'index' and return
25 end
25 end
26
26
27 if GraderConfiguration.time_limit_mode?
27 if GraderConfiguration.time_limit_mode?
28 if @user.contest_finished?
28 if @user.contest_finished?
29 - @submitted_test_request.errors.add_to_base('Contest is over.')
29 + @submitted_test_request.errors.add(:base,'Contest is over.')
30 prepare_index_information
30 prepare_index_information
31 render :action => 'index' and return
31 render :action => 'index' and return
32 end
32 end
33
33
34 if !GraderConfiguration.allow_test_request(@user)
34 if !GraderConfiguration.allow_test_request(@user)
35 prepare_index_information
35 prepare_index_information
36 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
36 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
37 redirect_to :action => 'index' and return
37 redirect_to :action => 'index' and return
38 end
38 end
39 end
39 end
40
40
41 if @submitted_test_request.save
41 if @submitted_test_request.save
42 redirect_to :action => 'index'
42 redirect_to :action => 'index'
43 else
43 else
44 prepare_index_information
44 prepare_index_information
45 render :action => 'index'
45 render :action => 'index'
46 end
46 end
47 end
47 end
48
48
49 def read
49 def read
50 user = User.find(session[:user_id])
50 user = User.find(session[:user_id])
51 begin
51 begin
52 test_request = TestRequest.find(params[:id])
52 test_request = TestRequest.find(params[:id])
53 rescue
53 rescue
54 test_request = nil
54 test_request = nil
55 end
55 end
56 if test_request==nil or test_request.user_id != user.id
56 if test_request==nil or test_request.user_id != user.id
57 flash[:notice] = 'Invalid output'
57 flash[:notice] = 'Invalid output'
58 redirect_to :action => 'index'
58 redirect_to :action => 'index'
59 return
59 return
60 end
60 end
61 if test_request.output_file_name!=nil
61 if test_request.output_file_name!=nil
62 data = File.open(test_request.output_file_name).read(2048)
62 data = File.open(test_request.output_file_name).read(2048)
63 if data==nil
63 if data==nil
64 data=""
64 data=""
65 end
65 end
66 send_data(data,
66 send_data(data,
67 {:filename => 'output.txt',
67 {:filename => 'output.txt',
68 :type => 'text/plain'})
68 :type => 'text/plain'})
69 return
69 return
70 end
70 end
71 redirect_to :action => 'index'
71 redirect_to :action => 'index'
72 end
72 end
73
73
74 def result
74 def result
75 @user = User.find(session[:user_id])
75 @user = User.find(session[:user_id])
76 begin
76 begin
77 @test_request = TestRequest.find(params[:id])
77 @test_request = TestRequest.find(params[:id])
78 rescue
78 rescue
79 @test_request = nil
79 @test_request = nil
80 end
80 end
81 if @test_request==nil or @test_request.user_id != @user.id
81 if @test_request==nil or @test_request.user_id != @user.id
82 flash[:notice] = 'Invalid request'
82 flash[:notice] = 'Invalid request'
83 redirect_to :action => 'index'
83 redirect_to :action => 'index'
84 return
84 return
85 end
85 end
86 end
86 end
87
87
88 protected
88 protected
89
89
90 def prepare_index_information
90 def prepare_index_information
91 @user = User.find(session[:user_id])
91 @user = User.find(session[:user_id])
92 @submissions = Submission.find_last_for_all_available_problems(@user.id)
92 @submissions = Submission.find_last_for_all_available_problems(@user.id)
93 all_problems = @submissions.collect { |submission| submission.problem }
93 all_problems = @submissions.collect { |submission| submission.problem }
94 @problems = []
94 @problems = []
95 all_problems.each do |problem|
95 all_problems.each do |problem|
96 if problem.test_allowed
96 if problem.test_allowed
97 @problems << problem
97 @problems << problem
98 end
98 end
99 end
99 end
100 @test_requests = []
100 @test_requests = []
101 @user.test_requests.each do |ts|
101 @user.test_requests.each do |ts|
102 if ts.problem and ts.problem.available
102 if ts.problem and ts.problem.available
103 @test_requests << ts
103 @test_requests << ts
104 end
104 end
105 end
105 end
106 end
106 end
107
107
108 def check_viewability
108 def check_viewability
109 user = User.find(session[:user_id])
109 user = User.find(session[:user_id])
110 if !GraderConfiguration.show_tasks_to?(user)
110 if !GraderConfiguration.show_tasks_to?(user)
111 redirect_to :controller => 'main', :action => 'list'
111 redirect_to :controller => 'main', :action => 'list'
112 end
112 end
113 if (!GraderConfiguration.show_submitbox_to?(user)) and (action_name=='submit')
113 if (!GraderConfiguration.show_submitbox_to?(user)) and (action_name=='submit')
114 redirect_to :controller => 'test', :action => 'index'
114 redirect_to :controller => 'test', :action => 'index'
115 end
115 end
116 end
116 end
117
117
118 end
118 end
@@ -1,156 +1,156
1 require 'net/smtp'
1 require 'net/smtp'
2
2
3 class UsersController < ApplicationController
3 class UsersController < ApplicationController
4
4
5 include MailHelperMethods
5 include MailHelperMethods
6
6
7 before_filter :authenticate, :except => [:new,
7 before_filter :authenticate, :except => [:new,
8 :register,
8 :register,
9 :confirm,
9 :confirm,
10 :forget,
10 :forget,
11 :retrieve_password]
11 :retrieve_password]
12
12
13 before_filter :verify_online_registration, :only => [:new,
13 before_filter :verify_online_registration, :only => [:new,
14 :register,
14 :register,
15 :forget,
15 :forget,
16 :retrieve_password]
16 :retrieve_password]
17
17
18 verify :method => :post, :only => [:chg_passwd],
18 verify :method => :post, :only => [:chg_passwd],
19 :redirect_to => { :action => :index }
19 :redirect_to => { :action => :index }
20
20
21 #in_place_edit_for :user, :alias_for_editing
21 #in_place_edit_for :user, :alias_for_editing
22 #in_place_edit_for :user, :email_for_editing
22 #in_place_edit_for :user, :email_for_editing
23
23
24 def index
24 def index
25 if !GraderConfiguration['system.user_setting_enabled']
25 if !GraderConfiguration['system.user_setting_enabled']
26 redirect_to :controller => 'main', :action => 'list'
26 redirect_to :controller => 'main', :action => 'list'
27 else
27 else
28 @user = User.find(session[:user_id])
28 @user = User.find(session[:user_id])
29 end
29 end
30 end
30 end
31
31
32 def chg_passwd
32 def chg_passwd
33 user = User.find(session[:user_id])
33 user = User.find(session[:user_id])
34 user.password = params[:passwd]
34 user.password = params[:passwd]
35 user.password_confirmation = params[:passwd_verify]
35 user.password_confirmation = params[:passwd_verify]
36 if user.save
36 if user.save
37 flash[:notice] = 'password changed'
37 flash[:notice] = 'password changed'
38 else
38 else
39 flash[:notice] = 'Error: password changing failed'
39 flash[:notice] = 'Error: password changing failed'
40 end
40 end
41 redirect_to :action => 'index'
41 redirect_to :action => 'index'
42 end
42 end
43
43
44 def new
44 def new
45 @user = User.new
45 @user = User.new
46 render :action => 'new', :layout => 'empty'
46 render :action => 'new', :layout => 'empty'
47 end
47 end
48
48
49 def register
49 def register
50 if(params[:cancel])
50 if(params[:cancel])
51 redirect_to :controller => 'main', :action => 'login'
51 redirect_to :controller => 'main', :action => 'login'
52 return
52 return
53 end
53 end
54 @user = User.new(params[:user])
54 @user = User.new(params[:user])
55 @user.password_confirmation = @user.password = User.random_password
55 @user.password_confirmation = @user.password = User.random_password
56 @user.activated = false
56 @user.activated = false
57 if (@user.valid?) and (@user.save)
57 if (@user.valid?) and (@user.save)
58 if send_confirmation_email(@user)
58 if send_confirmation_email(@user)
59 render :action => 'new_splash', :layout => 'empty'
59 render :action => 'new_splash', :layout => 'empty'
60 else
60 else
61 @admin_email = GraderConfiguration['system.admin_email']
61 @admin_email = GraderConfiguration['system.admin_email']
62 render :action => 'email_error', :layout => 'empty'
62 render :action => 'email_error', :layout => 'empty'
63 end
63 end
64 else
64 else
65 - @user.errors.add_to_base("Email cannot be blank") if @user.email==''
65 + @user.errors.add(:base,"Email cannot be blank") if @user.email==''
66 render :action => 'new', :layout => 'empty'
66 render :action => 'new', :layout => 'empty'
67 end
67 end
68 end
68 end
69
69
70 def confirm
70 def confirm
71 login = params[:login]
71 login = params[:login]
72 key = params[:activation]
72 key = params[:activation]
73 @user = User.find_by_login(login)
73 @user = User.find_by_login(login)
74 if (@user) and (@user.verify_activation_key(key))
74 if (@user) and (@user.verify_activation_key(key))
75 if @user.valid? # check uniquenss of email
75 if @user.valid? # check uniquenss of email
76 @user.activated = true
76 @user.activated = true
77 @user.save
77 @user.save
78 @result = :successful
78 @result = :successful
79 else
79 else
80 @result = :email_used
80 @result = :email_used
81 end
81 end
82 else
82 else
83 @result = :failed
83 @result = :failed
84 end
84 end
85 render :action => 'confirm', :layout => 'empty'
85 render :action => 'confirm', :layout => 'empty'
86 end
86 end
87
87
88 def forget
88 def forget
89 render :action => 'forget', :layout => 'empty'
89 render :action => 'forget', :layout => 'empty'
90 end
90 end
91
91
92 def retrieve_password
92 def retrieve_password
93 email = params[:email]
93 email = params[:email]
94 user = User.find_by_email(email)
94 user = User.find_by_email(email)
95 if user
95 if user
96 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
96 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
97 if last_updated_time > Time.now.gmtime - 5.minutes
97 if last_updated_time > Time.now.gmtime - 5.minutes
98 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
98 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
99 else
99 else
100 user.password = user.password_confirmation = User.random_password
100 user.password = user.password_confirmation = User.random_password
101 user.save
101 user.save
102 send_new_password_email(user)
102 send_new_password_email(user)
103 flash[:notice] = 'New password has been mailed to you.'
103 flash[:notice] = 'New password has been mailed to you.'
104 end
104 end
105 else
105 else
106 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
106 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
107 end
107 end
108 redirect_to :action => 'forget'
108 redirect_to :action => 'forget'
109 end
109 end
110
110
111 protected
111 protected
112
112
113 def verify_online_registration
113 def verify_online_registration
114 if !GraderConfiguration['system.online_registration']
114 if !GraderConfiguration['system.online_registration']
115 redirect_to :controller => 'main', :action => 'login'
115 redirect_to :controller => 'main', :action => 'login'
116 end
116 end
117 end
117 end
118
118
119 def send_confirmation_email(user)
119 def send_confirmation_email(user)
120 contest_name = GraderConfiguration['contest.name']
120 contest_name = GraderConfiguration['contest.name']
121 activation_url = url_for(:action => 'confirm',
121 activation_url = url_for(:action => 'confirm',
122 :login => user.login,
122 :login => user.login,
123 :activation => user.activation_key)
123 :activation => user.activation_key)
124 home_url = url_for(:controller => 'main', :action => 'index')
124 home_url = url_for(:controller => 'main', :action => 'index')
125 mail_subject = "[#{contest_name}] Confirmation"
125 mail_subject = "[#{contest_name}] Confirmation"
126 mail_body = t('registration.email_body', {
126 mail_body = t('registration.email_body', {
127 :full_name => user.full_name,
127 :full_name => user.full_name,
128 :contest_name => contest_name,
128 :contest_name => contest_name,
129 :login => user.login,
129 :login => user.login,
130 :password => user.password,
130 :password => user.password,
131 :activation_url => activation_url,
131 :activation_url => activation_url,
132 :admin_email => admin_email
132 :admin_email => admin_email
133 })
133 })
134
134
135 logger.info mail_body
135 logger.info mail_body
136
136
137 send_mail(user.email, mail_subject, mail_body)
137 send_mail(user.email, mail_subject, mail_body)
138 end
138 end
139
139
140 def send_new_password_email(user)
140 def send_new_password_email(user)
141 contest_name = GraderConfiguration['contest.name']
141 contest_name = GraderConfiguration['contest.name']
142 mail_subject = "[#{contest_name}] Password recovery"
142 mail_subject = "[#{contest_name}] Password recovery"
143 mail_body = t('registration.password_retrieval.email_body', {
143 mail_body = t('registration.password_retrieval.email_body', {
144 :full_name => user.full_name,
144 :full_name => user.full_name,
145 :contest_name => contest_name,
145 :contest_name => contest_name,
146 :login => user.login,
146 :login => user.login,
147 :password => user.password,
147 :password => user.password,
148 :admin_email => admin_email
148 :admin_email => admin_email
149 })
149 })
150
150
151 logger.info mail_body
151 logger.info mail_body
152
152
153 send_mail(user.email, mail_subject, mail_body)
153 send_mail(user.email, mail_subject, mail_body)
154 end
154 end
155
155
156 end
156 end
@@ -1,114 +1,114
1 class Problem < ActiveRecord::Base
1 class Problem < ActiveRecord::Base
2
2
3 belongs_to :description
3 belongs_to :description
4 has_and_belongs_to_many :contests, :uniq => true
4 has_and_belongs_to_many :contests, :uniq => true
5 has_many :test_pairs, :dependent => :delete_all
5 has_many :test_pairs, :dependent => :delete_all
6
6
7 validates_presence_of :name
7 validates_presence_of :name
8 validates_format_of :name, :with => /^\w+$/
8 validates_format_of :name, :with => /^\w+$/
9 validates_presence_of :full_name
9 validates_presence_of :full_name
10
10
11 scope :available, :conditions => {:available => true}
11 scope :available, :conditions => {:available => true}
12
12
13 DEFAULT_TIME_LIMIT = 1
13 DEFAULT_TIME_LIMIT = 1
14 DEFAULT_MEMORY_LIMIT = 32
14 DEFAULT_MEMORY_LIMIT = 32
15
15
16 def self.find_available_problems
16 def self.find_available_problems
17 Problem.available.all(:order => "date_added DESC")
17 Problem.available.all(:order => "date_added DESC")
18 end
18 end
19
19
20 def self.create_from_import_form_params(params, old_problem=nil)
20 def self.create_from_import_form_params(params, old_problem=nil)
21 org_problem = old_problem || Problem.new
21 org_problem = old_problem || Problem.new
22 import_params, problem = Problem.extract_params_and_check(params,
22 import_params, problem = Problem.extract_params_and_check(params,
23 org_problem)
23 org_problem)
24
24
25 if !problem.errors.empty?
25 if !problem.errors.empty?
26 return problem, 'Error importing'
26 return problem, 'Error importing'
27 end
27 end
28
28
29 problem.full_score = 100
29 problem.full_score = 100
30 problem.date_added = Time.new
30 problem.date_added = Time.new
31 problem.test_allowed = true
31 problem.test_allowed = true
32 problem.output_only = false
32 problem.output_only = false
33 problem.available = false
33 problem.available = false
34
34
35 if not problem.save
35 if not problem.save
36 return problem, 'Error importing'
36 return problem, 'Error importing'
37 end
37 end
38
38
39 import_to_db = params.has_key? :import_to_db
39 import_to_db = params.has_key? :import_to_db
40
40
41 importer = TestdataImporter.new(problem)
41 importer = TestdataImporter.new(problem)
42
42
43 if not importer.import_from_file(import_params[:file],
43 if not importer.import_from_file(import_params[:file],
44 import_params[:time_limit],
44 import_params[:time_limit],
45 import_params[:memory_limit],
45 import_params[:memory_limit],
46 import_to_db)
46 import_to_db)
47 - problem.errors.add_to_base('Import error.')
47 + problem.errors.add(:base,'Import error.')
48 end
48 end
49
49
50 return problem, importer.log_msg
50 return problem, importer.log_msg
51 end
51 end
52
52
53 def self.download_file_basedir
53 def self.download_file_basedir
54 return "#{Rails.root}/data/tasks"
54 return "#{Rails.root}/data/tasks"
55 end
55 end
56
56
57 protected
57 protected
58
58
59 def self.to_i_or_default(st, default)
59 def self.to_i_or_default(st, default)
60 if st!=''
60 if st!=''
61 result = st.to_i
61 result = st.to_i
62 end
62 end
63 result ||= default
63 result ||= default
64 end
64 end
65
65
66 def self.to_f_or_default(st, default)
66 def self.to_f_or_default(st, default)
67 if st!=''
67 if st!=''
68 result = st.to_f
68 result = st.to_f
69 end
69 end
70 result ||= default
70 result ||= default
71 end
71 end
72
72
73 def self.extract_params_and_check(params, problem)
73 def self.extract_params_and_check(params, problem)
74 time_limit = Problem.to_f_or_default(params[:time_limit],
74 time_limit = Problem.to_f_or_default(params[:time_limit],
75 DEFAULT_TIME_LIMIT)
75 DEFAULT_TIME_LIMIT)
76 memory_limit = Problem.to_i_or_default(params[:memory_limit],
76 memory_limit = Problem.to_i_or_default(params[:memory_limit],
77 DEFAULT_MEMORY_LIMIT)
77 DEFAULT_MEMORY_LIMIT)
78
78
79 if time_limit<=0 or time_limit >60
79 if time_limit<=0 or time_limit >60
80 - problem.errors.add_to_base('Time limit out of range.')
80 + problem.errors.add(:base,'Time limit out of range.')
81 end
81 end
82
82
83 if memory_limit==0 and params[:memory_limit]!='0'
83 if memory_limit==0 and params[:memory_limit]!='0'
84 - problem.errors.add_to_base('Memory limit format errors.')
84 + problem.errors.add(:base,'Memory limit format errors.')
85 elsif memory_limit<=0 or memory_limit >512
85 elsif memory_limit<=0 or memory_limit >512
86 - problem.errors.add_to_base('Memory limit out of range.')
86 + problem.errors.add(:base,'Memory limit out of range.')
87 end
87 end
88
88
89 if params[:file]==nil or params[:file]==''
89 if params[:file]==nil or params[:file]==''
90 - problem.errors.add_to_base('No testdata file.')
90 + problem.errors.add(:base,'No testdata file.')
91 end
91 end
92
92
93 file = params[:file]
93 file = params[:file]
94
94
95 if !problem.errors.empty?
95 if !problem.errors.empty?
96 return nil, problem
96 return nil, problem
97 end
97 end
98
98
99 problem.name = params[:name]
99 problem.name = params[:name]
100 if params[:full_name]!=''
100 if params[:full_name]!=''
101 problem.full_name = params[:full_name]
101 problem.full_name = params[:full_name]
102 else
102 else
103 problem.full_name = params[:name]
103 problem.full_name = params[:name]
104 end
104 end
105
105
106 return [{
106 return [{
107 :time_limit => time_limit,
107 :time_limit => time_limit,
108 :memory_limit => memory_limit,
108 :memory_limit => memory_limit,
109 :file => file
109 :file => file
110 },
110 },
111 problem]
111 problem]
112 end
112 end
113
113
114 end
114 end
@@ -1,157 +1,157
1 #
1 #
2 # A TestRequest is a composition of submission with user's testdata.
2 # A TestRequest is a composition of submission with user's testdata.
3 #
3 #
4 # Note about TestRequest#problem: Usually, A TestRequest has to be
4 # Note about TestRequest#problem: Usually, A TestRequest has to be
5 # associated with a problem, so that execution environment can be
5 # associated with a problem, so that execution environment can be
6 # determined. However, to be more flexible, we have to ensure that
6 # determined. However, to be more flexible, we have to ensure that
7 # it works as well with problem=nil. In this case, we shall provide
7 # it works as well with problem=nil. In this case, we shall provide
8 # a "default" execution environment for it. This can be done
8 # a "default" execution environment for it. This can be done
9 # seamlessly by using TestRequest#problem_name or
9 # seamlessly by using TestRequest#problem_name or
10 # TestRequest#name_of(problem) when retrieving the name of the
10 # TestRequest#name_of(problem) when retrieving the name of the
11 # problem: #name_of would return problem.name when problem!=nil and
11 # problem: #name_of would return problem.name when problem!=nil and
12 # it would return "default" when problem=nil, #problem_name just
12 # it would return "default" when problem=nil, #problem_name just
13 # call #name_of.
13 # call #name_of.
14 #
14 #
15
15
16 require 'fileutils'
16 require 'fileutils'
17
17
18 class TestRequest < Task
18 class TestRequest < Task
19
19
20 set_table_name "test_requests"
20 set_table_name "test_requests"
21
21
22 belongs_to :user
22 belongs_to :user
23 belongs_to :problem
23 belongs_to :problem
24 belongs_to :submission
24 belongs_to :submission
25
25
26 validates_presence_of :submission
26 validates_presence_of :submission
27 validate :must_have_valid_problem
27 validate :must_have_valid_problem
28
28
29 def problem_name
29 def problem_name
30 TestRequest.name_of(self.problem)
30 TestRequest.name_of(self.problem)
31 end
31 end
32
32
33 def language
33 def language
34 self.submission.language
34 self.submission.language
35 end
35 end
36
36
37 def self.get_inqueue_and_change_status(status)
37 def self.get_inqueue_and_change_status(status)
38 # since there will be only one grader grading TestRequest
38 # since there will be only one grader grading TestRequest
39 # we do not need locking (hopefully)
39 # we do not need locking (hopefully)
40
40
41 test_request = TestRequest.find(:first,
41 test_request = TestRequest.find(:first,
42 :order => "created_at",
42 :order => "created_at",
43 :conditions => {:status=> Task::STATUS_INQUEUE})
43 :conditions => {:status=> Task::STATUS_INQUEUE})
44 if test_request!=nil
44 if test_request!=nil
45 test_request.status = status
45 test_request.status = status
46 test_request.save!
46 test_request.save!
47 end
47 end
48
48
49 test_request
49 test_request
50 end
50 end
51
51
52 # interfacing with form
52 # interfacing with form
53 def self.new_from_form_params(user,params)
53 def self.new_from_form_params(user,params)
54 test_request = TestRequest.new
54 test_request = TestRequest.new
55 test_request.user = user
55 test_request.user = user
56 begin
56 begin
57 problem = Problem.find(params[:problem_id])
57 problem = Problem.find(params[:problem_id])
58 rescue ActiveRecord::RecordNotFound
58 rescue ActiveRecord::RecordNotFound
59 problem = nil
59 problem = nil
60 end
60 end
61 test_request.problem = problem
61 test_request.problem = problem
62 if problem!=nil
62 if problem!=nil
63 test_request.submission =
63 test_request.submission =
64 Submission.find_by_user_problem_number(user.id,
64 Submission.find_by_user_problem_number(user.id,
65 problem.id,
65 problem.id,
66 params[:submission_number])
66 params[:submission_number])
67 else
67 else
68 test_request.submission = nil
68 test_request.submission = nil
69 end
69 end
70
70
71 # checks if the user submits any input file
71 # checks if the user submits any input file
72 if params[:input_file]==nil or params[:input_file]==""
72 if params[:input_file]==nil or params[:input_file]==""
73 - test_request.errors.add_to_base("No input submitted.")
73 + test_request.errors.add(:base,"No input submitted.")
74 test_request.input_file_name = nil
74 test_request.input_file_name = nil
75 else
75 else
76 test_request.input_file_name = save_input_file(params[:input_file], user, problem)
76 test_request.input_file_name = save_input_file(params[:input_file], user, problem)
77 if test_request.input_file_name == nil
77 if test_request.input_file_name == nil
78 - test_request.errors.add_to_base("No input submitted.")
78 + test_request.errors.adds(:base,"No input submitted.")
79 end
79 end
80 if params[:additional_file]!=nil and params[:additional_file]!=""
80 if params[:additional_file]!=nil and params[:additional_file]!=""
81 save_additional_file(params[:additional_file],
81 save_additional_file(params[:additional_file],
82 "#{test_request.input_file_name}.files")
82 "#{test_request.input_file_name}.files")
83 end
83 end
84 end
84 end
85 test_request.submitted_at = Time.new.gmtime
85 test_request.submitted_at = Time.new.gmtime
86 test_request.status_inqueue
86 test_request.status_inqueue
87 test_request
87 test_request
88 end
88 end
89
89
90 protected
90 protected
91
91
92 def self.name_of(problem)
92 def self.name_of(problem)
93 if problem!=nil
93 if problem!=nil
94 problem.name
94 problem.name
95 else
95 else
96 "default"
96 "default"
97 end
97 end
98 end
98 end
99
99
100 def self.random_input_file_name(user,problem)
100 def self.random_input_file_name(user,problem)
101 problem_name = TestRequest.name_of(problem)
101 problem_name = TestRequest.name_of(problem)
102 begin
102 begin
103 tmpname = TEST_REQUEST_INPUT_FILE_DIR + "/#{user.login}/#{problem_name}/#{rand(10000)}"
103 tmpname = TEST_REQUEST_INPUT_FILE_DIR + "/#{user.login}/#{problem_name}/#{rand(10000)}"
104 end while File.exists?(tmpname)
104 end while File.exists?(tmpname)
105 tmpname
105 tmpname
106 end
106 end
107
107
108 def self.save_input_file(tempfile, user, problem)
108 def self.save_input_file(tempfile, user, problem)
109 new_file_name = random_input_file_name(user,problem)
109 new_file_name = random_input_file_name(user,problem)
110 dirname = File.dirname(new_file_name)
110 dirname = File.dirname(new_file_name)
111 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
111 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
112
112
113 # when the user did not submit any file
113 # when the user did not submit any file
114 return nil if tempfile==""
114 return nil if tempfile==""
115
115
116 if tempfile.instance_of?(Tempfile)
116 if tempfile.instance_of?(Tempfile)
117 tempfile.close
117 tempfile.close
118 FileUtils.move(tempfile.path,new_file_name)
118 FileUtils.move(tempfile.path,new_file_name)
119 else
119 else
120 File.open(new_file_name, "wb") do |f|
120 File.open(new_file_name, "wb") do |f|
121 f.write(tempfile.read)
121 f.write(tempfile.read)
122 end
122 end
123 end
123 end
124 new_file_name
124 new_file_name
125 end
125 end
126
126
127 def self.save_additional_file(tempfile,dir)
127 def self.save_additional_file(tempfile,dir)
128 new_file_name = "#{dir}/#{tempfile.original_filename}"
128 new_file_name = "#{dir}/#{tempfile.original_filename}"
129 dirname = File.dirname(new_file_name)
129 dirname = File.dirname(new_file_name)
130 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
130 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
131
131
132 # when the user did not submit any file
132 # when the user did not submit any file
133 return nil if tempfile==""
133 return nil if tempfile==""
134
134
135 if tempfile.instance_of?(Tempfile)
135 if tempfile.instance_of?(Tempfile)
136 tempfile.close
136 tempfile.close
137 FileUtils.move(tempfile.path,new_file_name)
137 FileUtils.move(tempfile.path,new_file_name)
138 else
138 else
139 File.open(new_file_name, "wb") do |f|
139 File.open(new_file_name, "wb") do |f|
140 f.write(tempfile.read)
140 f.write(tempfile.read)
141 end
141 end
142 end
142 end
143 new_file_name
143 new_file_name
144 end
144 end
145
145
146 #
146 #
147 # validations
147 # validations
148 #
148 #
149 def must_have_valid_problem
149 def must_have_valid_problem
150 if problem==nil
150 if problem==nil
151 errors.add('problem',"must be specified.")
151 errors.add('problem',"must be specified.")
152 elsif (!problem.available) and (self.new_record?)
152 elsif (!problem.available) and (self.new_record?)
153 errors.add('problem',"must be valid.")
153 errors.add('problem',"must be valid.")
154 end
154 end
155 end
155 end
156
156
157 end
157 end
@@ -1,323 +1,323
1 require 'digest/sha1'
1 require 'digest/sha1'
2
2
3 class User < ActiveRecord::Base
3 class User < ActiveRecord::Base
4
4
5 has_and_belongs_to_many :roles
5 has_and_belongs_to_many :roles
6
6
7 has_many :test_requests, :order => "submitted_at DESC"
7 has_many :test_requests, :order => "submitted_at DESC"
8
8
9 has_many :messages,
9 has_many :messages,
10 :class_name => "Message",
10 :class_name => "Message",
11 :foreign_key => "sender_id",
11 :foreign_key => "sender_id",
12 :order => 'created_at DESC'
12 :order => 'created_at DESC'
13
13
14 has_many :replied_messages,
14 has_many :replied_messages,
15 :class_name => "Message",
15 :class_name => "Message",
16 :foreign_key => "receiver_id",
16 :foreign_key => "receiver_id",
17 :order => 'created_at DESC'
17 :order => 'created_at DESC'
18
18
19 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
19 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
20
20
21 belongs_to :site
21 belongs_to :site
22 belongs_to :country
22 belongs_to :country
23
23
24 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
24 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
25
25
26 scope :activated_users, :conditions => {:activated => true}
26 scope :activated_users, :conditions => {:activated => true}
27
27
28 validates_presence_of :login
28 validates_presence_of :login
29 validates_uniqueness_of :login
29 validates_uniqueness_of :login
30 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
30 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
31 validates_length_of :login, :within => 3..30
31 validates_length_of :login, :within => 3..30
32
32
33 validates_presence_of :full_name
33 validates_presence_of :full_name
34 validates_length_of :full_name, :minimum => 1
34 validates_length_of :full_name, :minimum => 1
35
35
36 validates_presence_of :password, :if => :password_required?
36 validates_presence_of :password, :if => :password_required?
37 validates_length_of :password, :within => 4..20, :if => :password_required?
37 validates_length_of :password, :within => 4..20, :if => :password_required?
38 validates_confirmation_of :password, :if => :password_required?
38 validates_confirmation_of :password, :if => :password_required?
39
39
40 validates_format_of :email,
40 validates_format_of :email,
41 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
41 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
42 :if => :email_validation?
42 :if => :email_validation?
43 validate :uniqueness_of_email_from_activated_users,
43 validate :uniqueness_of_email_from_activated_users,
44 :if => :email_validation?
44 :if => :email_validation?
45 validate :enough_time_interval_between_same_email_registrations,
45 validate :enough_time_interval_between_same_email_registrations,
46 :if => :email_validation?
46 :if => :email_validation?
47
47
48 # these are for ytopc
48 # these are for ytopc
49 # disable for now
49 # disable for now
50 #validates_presence_of :province
50 #validates_presence_of :province
51
51
52 attr_accessor :password
52 attr_accessor :password
53
53
54 before_save :encrypt_new_password
54 before_save :encrypt_new_password
55 before_save :assign_default_site
55 before_save :assign_default_site
56 before_save :assign_default_contest
56 before_save :assign_default_contest
57
57
58 # this is for will_paginate
58 # this is for will_paginate
59 cattr_reader :per_page
59 cattr_reader :per_page
60 @@per_page = 50
60 @@per_page = 50
61
61
62 def self.authenticate(login, password)
62 def self.authenticate(login, password)
63 user = find_by_login(login)
63 user = find_by_login(login)
64 return user if user && user.authenticated?(password)
64 return user if user && user.authenticated?(password)
65 end
65 end
66
66
67 def authenticated?(password)
67 def authenticated?(password)
68 if self.activated
68 if self.activated
69 hashed_password == User.encrypt(password,self.salt)
69 hashed_password == User.encrypt(password,self.salt)
70 else
70 else
71 false
71 false
72 end
72 end
73 end
73 end
74
74
75 def admin?
75 def admin?
76 self.roles.detect {|r| r.name == 'admin' }
76 self.roles.detect {|r| r.name == 'admin' }
77 end
77 end
78
78
79 def email_for_editing
79 def email_for_editing
80 if self.email==nil
80 if self.email==nil
81 "(unknown)"
81 "(unknown)"
82 elsif self.email==''
82 elsif self.email==''
83 "(blank)"
83 "(blank)"
84 else
84 else
85 self.email
85 self.email
86 end
86 end
87 end
87 end
88
88
89 def email_for_editing=(e)
89 def email_for_editing=(e)
90 self.email=e
90 self.email=e
91 end
91 end
92
92
93 def alias_for_editing
93 def alias_for_editing
94 if self.alias==nil
94 if self.alias==nil
95 "(unknown)"
95 "(unknown)"
96 elsif self.alias==''
96 elsif self.alias==''
97 "(blank)"
97 "(blank)"
98 else
98 else
99 self.alias
99 self.alias
100 end
100 end
101 end
101 end
102
102
103 def alias_for_editing=(e)
103 def alias_for_editing=(e)
104 self.alias=e
104 self.alias=e
105 end
105 end
106
106
107 def activation_key
107 def activation_key
108 if self.hashed_password==nil
108 if self.hashed_password==nil
109 encrypt_new_password
109 encrypt_new_password
110 end
110 end
111 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
111 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
112 end
112 end
113
113
114 def verify_activation_key(key)
114 def verify_activation_key(key)
115 key == activation_key
115 key == activation_key
116 end
116 end
117
117
118 def self.random_password(length=5)
118 def self.random_password(length=5)
119 chars = 'abcdefghjkmnopqrstuvwxyz'
119 chars = 'abcdefghjkmnopqrstuvwxyz'
120 password = ''
120 password = ''
121 length.times { password << chars[rand(chars.length - 1)] }
121 length.times { password << chars[rand(chars.length - 1)] }
122 password
122 password
123 end
123 end
124
124
125 def self.find_non_admin_with_prefix(prefix='')
125 def self.find_non_admin_with_prefix(prefix='')
126 users = User.find(:all)
126 users = User.find(:all)
127 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
127 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
128 end
128 end
129
129
130 # Contest information
130 # Contest information
131
131
132 def self.find_users_with_no_contest()
132 def self.find_users_with_no_contest()
133 users = User.find(:all)
133 users = User.find(:all)
134 return users.find_all { |u| u.contests.length == 0 }
134 return users.find_all { |u| u.contests.length == 0 }
135 end
135 end
136
136
137
137
138 def contest_time_left
138 def contest_time_left
139 if GraderConfiguration.contest_mode?
139 if GraderConfiguration.contest_mode?
140 return nil if site==nil
140 return nil if site==nil
141 return site.time_left
141 return site.time_left
142 elsif GraderConfiguration.indv_contest_mode?
142 elsif GraderConfiguration.indv_contest_mode?
143 time_limit = GraderConfiguration.contest_time_limit
143 time_limit = GraderConfiguration.contest_time_limit
144 if time_limit == nil
144 if time_limit == nil
145 return nil
145 return nil
146 end
146 end
147 if contest_stat==nil or contest_stat.started_at==nil
147 if contest_stat==nil or contest_stat.started_at==nil
148 return (Time.now.gmtime + time_limit) - Time.now.gmtime
148 return (Time.now.gmtime + time_limit) - Time.now.gmtime
149 else
149 else
150 finish_time = contest_stat.started_at + time_limit
150 finish_time = contest_stat.started_at + time_limit
151 current_time = Time.now.gmtime
151 current_time = Time.now.gmtime
152 if current_time > finish_time
152 if current_time > finish_time
153 return 0
153 return 0
154 else
154 else
155 return finish_time - current_time
155 return finish_time - current_time
156 end
156 end
157 end
157 end
158 else
158 else
159 return nil
159 return nil
160 end
160 end
161 end
161 end
162
162
163 def contest_finished?
163 def contest_finished?
164 if GraderConfiguration.contest_mode?
164 if GraderConfiguration.contest_mode?
165 return false if site==nil
165 return false if site==nil
166 return site.finished?
166 return site.finished?
167 elsif GraderConfiguration.indv_contest_mode?
167 elsif GraderConfiguration.indv_contest_mode?
168 return false if self.contest_stat(true)==nil
168 return false if self.contest_stat(true)==nil
169 return contest_time_left == 0
169 return contest_time_left == 0
170 else
170 else
171 return false
171 return false
172 end
172 end
173 end
173 end
174
174
175 def contest_started?
175 def contest_started?
176 if GraderConfiguration.indv_contest_mode?
176 if GraderConfiguration.indv_contest_mode?
177 stat = self.contest_stat
177 stat = self.contest_stat
178 return ((stat != nil) and (stat.started_at != nil))
178 return ((stat != nil) and (stat.started_at != nil))
179 elsif GraderConfiguration.contest_mode?
179 elsif GraderConfiguration.contest_mode?
180 return true if site==nil
180 return true if site==nil
181 return site.started
181 return site.started
182 else
182 else
183 return true
183 return true
184 end
184 end
185 end
185 end
186
186
187 def update_start_time
187 def update_start_time
188 stat = self.contest_stat
188 stat = self.contest_stat
189 if stat == nil or stat.started_at == nil
189 if stat == nil or stat.started_at == nil
190 stat ||= UserContestStat.new(:user => self)
190 stat ||= UserContestStat.new(:user => self)
191 stat.started_at = Time.now.gmtime
191 stat.started_at = Time.now.gmtime
192 stat.save
192 stat.save
193 end
193 end
194 end
194 end
195
195
196 def problem_in_user_contests?(problem)
196 def problem_in_user_contests?(problem)
197 problem_contests = problem.contests.all
197 problem_contests = problem.contests.all
198
198
199 if problem_contests.length == 0 # this is public contest
199 if problem_contests.length == 0 # this is public contest
200 return true
200 return true
201 end
201 end
202
202
203 contests.each do |contest|
203 contests.each do |contest|
204 if problem_contests.find {|c| c.id == contest.id }
204 if problem_contests.find {|c| c.id == contest.id }
205 return true
205 return true
206 end
206 end
207 end
207 end
208 return false
208 return false
209 end
209 end
210
210
211 def available_problems_group_by_contests
211 def available_problems_group_by_contests
212 contest_problems = []
212 contest_problems = []
213 pin = {}
213 pin = {}
214 contests.enabled.each do |contest|
214 contests.enabled.each do |contest|
215 available_problems = contest.problems.available
215 available_problems = contest.problems.available
216 contest_problems << {
216 contest_problems << {
217 :contest => contest,
217 :contest => contest,
218 :problems => available_problems
218 :problems => available_problems
219 }
219 }
220 available_problems.each {|p| pin[p.id] = true}
220 available_problems.each {|p| pin[p.id] = true}
221 end
221 end
222 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
222 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
223 contest_problems << {
223 contest_problems << {
224 :contest => nil,
224 :contest => nil,
225 :problems => other_avaiable_problems
225 :problems => other_avaiable_problems
226 }
226 }
227 return contest_problems
227 return contest_problems
228 end
228 end
229
229
230 def available_problems
230 def available_problems
231 if not GraderConfiguration.multicontests?
231 if not GraderConfiguration.multicontests?
232 return Problem.find_available_problems
232 return Problem.find_available_problems
233 else
233 else
234 contest_problems = []
234 contest_problems = []
235 pin = {}
235 pin = {}
236 contests.enabled.each do |contest|
236 contests.enabled.each do |contest|
237 contest.problems.available.each do |problem|
237 contest.problems.available.each do |problem|
238 if not pin.has_key? problem.id
238 if not pin.has_key? problem.id
239 contest_problems << problem
239 contest_problems << problem
240 end
240 end
241 pin[problem.id] = true
241 pin[problem.id] = true
242 end
242 end
243 end
243 end
244 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
244 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
245 return contest_problems + other_avaiable_problems
245 return contest_problems + other_avaiable_problems
246 end
246 end
247 end
247 end
248
248
249 def can_view_problem?(problem)
249 def can_view_problem?(problem)
250 if not GraderConfiguration.multicontests?
250 if not GraderConfiguration.multicontests?
251 return problem.available
251 return problem.available
252 else
252 else
253 return problem_in_user_contests? problem
253 return problem_in_user_contests? problem
254 end
254 end
255 end
255 end
256
256
257 protected
257 protected
258 def encrypt_new_password
258 def encrypt_new_password
259 return if password.blank?
259 return if password.blank?
260 self.salt = (10+rand(90)).to_s
260 self.salt = (10+rand(90)).to_s
261 self.hashed_password = User.encrypt(self.password,self.salt)
261 self.hashed_password = User.encrypt(self.password,self.salt)
262 end
262 end
263
263
264 def assign_default_site
264 def assign_default_site
265 # have to catch error when migrating (because self.site is not available).
265 # have to catch error when migrating (because self.site is not available).
266 begin
266 begin
267 if self.site==nil
267 if self.site==nil
268 self.site = Site.find_by_name('default')
268 self.site = Site.find_by_name('default')
269 if self.site==nil
269 if self.site==nil
270 self.site = Site.find(1) # when 'default has be renamed'
270 self.site = Site.find(1) # when 'default has be renamed'
271 end
271 end
272 end
272 end
273 rescue
273 rescue
274 end
274 end
275 end
275 end
276
276
277 def assign_default_contest
277 def assign_default_contest
278 # have to catch error when migrating (because self.site is not available).
278 # have to catch error when migrating (because self.site is not available).
279 begin
279 begin
280 if self.contests.length == 0
280 if self.contests.length == 0
281 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
281 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
282 if default_contest
282 if default_contest
283 self.contests = [default_contest]
283 self.contests = [default_contest]
284 end
284 end
285 end
285 end
286 rescue
286 rescue
287 end
287 end
288 end
288 end
289
289
290 def password_required?
290 def password_required?
291 self.hashed_password.blank? || !self.password.blank?
291 self.hashed_password.blank? || !self.password.blank?
292 end
292 end
293
293
294 def self.encrypt(string,salt)
294 def self.encrypt(string,salt)
295 Digest::SHA1.hexdigest(salt + string)
295 Digest::SHA1.hexdigest(salt + string)
296 end
296 end
297
297
298 def uniqueness_of_email_from_activated_users
298 def uniqueness_of_email_from_activated_users
299 user = User.activated_users.find_by_email(self.email)
299 user = User.activated_users.find_by_email(self.email)
300 if user and (user.login != self.login)
300 if user and (user.login != self.login)
301 - self.errors.add_to_base("Email has already been taken")
301 + self.errors.add(:base,"Email has already been taken")
302 end
302 end
303 end
303 end
304
304
305 def enough_time_interval_between_same_email_registrations
305 def enough_time_interval_between_same_email_registrations
306 return if !self.new_record?
306 return if !self.new_record?
307 return if self.activated
307 return if self.activated
308 open_user = User.find_by_email(self.email,
308 open_user = User.find_by_email(self.email,
309 :order => 'created_at DESC')
309 :order => 'created_at DESC')
310 if open_user and open_user.created_at and
310 if open_user and open_user.created_at and
311 (open_user.created_at > Time.now.gmtime - 5.minutes)
311 (open_user.created_at > Time.now.gmtime - 5.minutes)
312 - self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
312 + self.errors.add(:base,"There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
313 end
313 end
314 end
314 end
315
315
316 def email_validation?
316 def email_validation?
317 begin
317 begin
318 return VALIDATE_USER_EMAILS
318 return VALIDATE_USER_EMAILS
319 rescue
319 rescue
320 return false
320 return false
321 end
321 end
322 end
322 end
323 end
323 end
You need to be logged in to leave comments. Login now