Description:
Merge branch 'master' into codejom (bug fixed)
Commit status:
[Not Reviewed]
References:
merge default
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r250:6820e08d6a38 - - 1 file changed: 10 inserted, 0 deleted

@@ -1,199 +1,203
1 1 class MainController < ApplicationController
2 2
3 3 before_filter :authenticate, :except => [:index, :login]
4 4 before_filter :check_viewability, :except => [:index, :login]
5 5
6 6 append_before_filter :update_user_start_time, :except => [:index, :login]
7 7
8 + # to prevent log in box to be shown when user logged out of the
9 + # system only in some tab
10 + prepend_before_filter :reject_announcement_refresh_when_logged_out, :only => [:announcements]
11 +
8 12 # COMMENTED OUT: filter in each action instead
9 13 # before_filter :verify_time_limit, :only => [:submit]
10 14
11 15 verify :method => :post, :only => [:submit, :download_input, :submit_solution],
12 16 :redirect_to => { :action => :index }
13 17
14 18 # COMMENT OUT: only need when having high load
15 19 # caches_action :index, :login
16 20
17 21 # NOTE: This method is not actually needed, 'config/routes.rb' has
18 22 # assigned action login as a default action.
19 23 def index
20 24 redirect_to :action => 'login'
21 25 end
22 26
23 27 def login
24 28 saved_notice = flash[:notice]
25 29 reset_session
26 30 flash.now[:notice] = saved_notice
27 31
28 32 # EXPERIMENT:
29 33 # Hide login if in single user mode and the url does not
30 34 # explicitly specify /login
31 35 #
32 36 # logger.info "PATH: #{request.path}"
33 37 # if Configuration['system.single_user_mode'] and
34 38 # request.path!='/main/login'
35 39 # @hidelogin = true
36 40 # end
37 41
38 42 @announcements = Announcement.find_for_frontpage
39 43 render :action => 'login', :layout => 'empty'
40 44 end
41 45
42 46 def list
43 47 prepare_list_information
44 48 end
45 49
46 50 def help
47 51 @user = User.find(session[:user_id])
48 52 end
49 53
50 54 def submit
51 55 user = User.find(session[:user_id])
52 56
53 57 @submission = Submission.new(params[:submission])
54 58 @submission.user = user
55 59 @submission.language_id = 0
56 60 if (params['file']) and (params['file']!='')
57 61 @submission.source = params['file'].read
58 62 @submission.source_filename = params['file'].original_filename
59 63 end
60 64 @submission.submitted_at = Time.new.gmtime
61 65
62 66 if Configuration.time_limit_mode? and user.contest_finished?
63 67 @submission.errors.add_to_base "The contest is over."
64 68 prepare_list_information
65 69 render :action => 'list' and return
66 70 end
67 71
68 72 if @submission.valid?
69 73 if @submission.save == false
70 74 flash[:notice] = 'Error saving your submission'
71 75 elsif Task.create(:submission_id => @submission.id,
72 76 :status => Task::STATUS_INQUEUE) == false
73 77 flash[:notice] = 'Error adding your submission to task queue'
74 78 end
75 79 else
76 80 prepare_list_information
77 81 render :action => 'list' and return
78 82 end
79 83 redirect_to :action => 'list'
80 84 end
81 85
82 86 def source
83 87 submission = Submission.find(params[:id])
84 88 if submission.user_id == session[:user_id]
85 89 send_data(submission.source,
86 90 {:filename => submission.download_filename,
87 91 :type => 'text/plain'})
88 92 else
89 93 flash[:notice] = 'Error viewing source'
90 94 redirect_to :action => 'list'
91 95 end
92 96 end
93 97
94 98 def compiler_msg
95 99 @submission = Submission.find(params[:id])
96 100 if @submission.user_id == session[:user_id]
97 101 render :action => 'compiler_msg', :layout => 'empty'
98 102 else
99 103 flash[:notice] = 'Error viewing source'
100 104 redirect_to :action => 'list'
101 105 end
102 106 end
103 107
104 108 def submission
105 109 # protect the action for Code Jom
106 110 redirect_to :action => 'list'
107 111
108 112 @user = User.find(session[:user_id])
109 113 @problems = Problem.find_available_problems
110 114 if params[:id]==nil
111 115 @problem = nil
112 116 @submissions = nil
113 117 else
114 118 @problem = Problem.find_by_name(params[:id])
115 119 if not @problem.available
116 120 redirect_to :action => 'list'
117 121 flash[:notice] = 'Error: submissions for that problem are not viewable.'
118 122 return
119 123 end
120 124 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
121 125 end
122 126 end
123 127
124 128 def result
125 129 if !Configuration.show_grading_result
126 130 redirect_to :action => 'list' and return
127 131 end
128 132 @user = User.find(session[:user_id])
129 133 @submission = Submission.find(params[:id])
130 134 if @submission.user!=@user
131 135 flash[:notice] = 'You are not allowed to view result of other users.'
132 136 redirect_to :action => 'list' and return
133 137 end
134 138 prepare_grading_result(@submission)
135 139 end
136 140
137 141 def load_output
138 142 if !Configuration.show_grading_result or params[:num]==nil
139 143 redirect_to :action => 'list' and return
140 144 end
141 145 @user = User.find(session[:user_id])
142 146 @submission = Submission.find(params[:id])
143 147 if @submission.user!=@user
144 148 flash[:notice] = 'You are not allowed to view result of other users.'
145 149 redirect_to :action => 'list' and return
146 150 end
147 151 case_num = params[:num].to_i
148 152 out_filename = output_filename(@user.login,
149 153 @submission.problem.name,
150 154 @submission.id,
151 155 case_num)
152 156 if !FileTest.exists?(out_filename)
153 157 flash[:notice] = 'Output not found.'
154 158 redirect_to :action => 'list' and return
155 159 end
156 160
157 161 response.headers['Content-Type'] = "application/force-download"
158 162 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
159 163 response.headers["X-Sendfile"] = out_filename
160 164 response.headers['Content-length'] = File.size(out_filename)
161 165 render :nothing => true
162 166 end
163 167
164 168 def error
165 169 @user = User.find(session[:user_id])
166 170 end
167 171
168 172 # announcement refreshing and hiding methods
169 173
170 174 def announcements
171 175 if params.has_key? 'recent'
172 176 prepare_announcements(params[:recent])
173 177 else
174 178 prepare_announcements
175 179 end
176 180 render(:partial => 'announcement',
177 181 :collection => @announcements,
178 182 :locals => {:announcement_effect => true})
179 183 end
180 184
181 185 #
182 186 # actions for Code Jom
183 187 #
184 188 def download_input
185 189 user = User.find(session[:user_id])
186 190
187 191 if Configuration.time_limit_mode? and user.contest_finished?
188 192 redirect_to :action => 'list' and return
189 193 end
190 194
191 195 problem = Problem.find(params[:id])
192 196 if user.can_request_new_test_pair_for? problem
193 197 assignment = user.get_new_test_pair_assignment_for problem
194 198 assignment.save
195 199
196 200 send_data(assignment.test_pair.input,
197 201 { :filename => "#{problem.name}-#{assignment.request_number}.in",
198 202 :type => 'text/plain' })
199 203 else
@@ -273,194 +277,200
273 277 end
274 278
275 279 protected
276 280
277 281 def prepare_announcements(recent=nil)
278 282 if Configuration.show_tasks_to?(@user)
279 283 @announcements = Announcement.find_published(true)
280 284 else
281 285 @announcements = Announcement.find_published
282 286 end
283 287 if recent!=nil
284 288 recent_id = recent.to_i
285 289 @announcements = @announcements.find_all { |a| a.id > recent_id }
286 290 end
287 291 end
288 292
289 293 def prepare_timeout_information(problems)
290 294 @submission_timeouts = {}
291 295 problems.each do |problem|
292 296 assignment = @user.get_recent_test_pair_assignment_for(problem)
293 297 if assignment == nil
294 298 timeout = nil
295 299 else
296 300 if (assignment.expired?) or (assignment.submitted)
297 301 timeout = 0
298 302 else
299 303 timeout = assignment.created_at + TEST_ASSIGNMENT_EXPIRATION_DURATION - Time.new.gmtime
300 304 end
301 305 end
302 306 @submission_timeouts[problem.id] = timeout
303 307 end
304 308 @submission_timeouts.each_pair {|k,v| puts "#{k} => #{v}"}
305 309 end
306 310
307 311 def prepare_list_information
308 312 @user = User.find(session[:user_id])
309 313
310 314 all_problems = Problem.find_available_problems
311 315
312 316 passed = {}
313 317 sub_count = {}
314 318 @user.submission_statuses.each do |status|
315 319 if status.passed
316 320 passed[status.problem_id] = true
317 321 end
318 322 sub_count[status.problem_id] = status.submission_count
319 323 end
320 324
321 325 if session.has_key? :current_problem_id
322 326 @current_problem_id = session[:current_problem_id]
323 327 session.delete(:current_problem_id)
324 328 else
325 329 @current_problem_id = nil
326 330 end
327 331
328 332 @problems = all_problems.reject { |problem| passed.has_key? problem.id }
329 333
330 334 prepare_timeout_information(@problems)
331 335
332 336 @prob_submissions = Array.new
333 337 @problems.each do |p|
334 338 if sub_count.has_key? p.id
335 339 @prob_submissions << { :count => sub_count[p.id] }
336 340 else
337 341 @prob_submissions << { :count => 0 }
338 342 end
339 343 end
340 344 prepare_announcements
341 345 end
342 346
343 347 def check_viewability
344 348 @user = User.find(session[:user_id])
345 349 if (!Configuration.show_tasks_to?(@user)) and
346 350 ((action_name=='submission') or (action_name=='submit'))
347 351 redirect_to :action => 'list' and return
348 352 end
349 353 end
350 354
351 355 def prepare_grading_result(submission)
352 356 if Configuration.task_grading_info.has_key? submission.problem.name
353 357 grading_info = Configuration.task_grading_info[submission.problem.name]
354 358 else
355 359 # guess task info from problem.full_score
356 360 cases = submission.problem.full_score / 10
357 361 grading_info = {
358 362 'testruns' => cases,
359 363 'testcases' => cases
360 364 }
361 365 end
362 366 @test_runs = []
363 367 if grading_info['testruns'].is_a? Integer
364 368 trun_count = grading_info['testruns']
365 369 trun_count.times do |i|
366 370 @test_runs << [ read_grading_result(@user.login,
367 371 submission.problem.name,
368 372 submission.id,
369 373 i+1) ]
370 374 end
371 375 else
372 376 grading_info['testruns'].keys.sort.each do |num|
373 377 run = []
374 378 testrun = grading_info['testruns'][num]
375 379 testrun.each do |c|
376 380 run << read_grading_result(@user.login,
377 381 submission.problem.name,
378 382 submission.id,
379 383 c)
380 384 end
381 385 @test_runs << run
382 386 end
383 387 end
384 388 end
385 389
386 390 def grading_result_dir(user_name, problem_name, submission_id, case_num)
387 391 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
388 392 end
389 393
390 394 def output_filename(user_name, problem_name, submission_id, case_num)
391 395 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
392 396 return "#{dir}/output.txt"
393 397 end
394 398
395 399 def read_grading_result(user_name, problem_name, submission_id, case_num)
396 400 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
397 401 result_file_name = "#{dir}/result"
398 402 if !FileTest.exists?(result_file_name)
399 403 return {:num => case_num, :msg => 'program did not run'}
400 404 else
401 405 results = File.open(result_file_name).readlines
402 406 run_stat = extract_running_stat(results)
403 407 output_filename = "#{dir}/output.txt"
404 408 if FileTest.exists?(output_filename)
405 409 output_file = true
406 410 output_size = File.size(output_filename)
407 411 else
408 412 output_file = false
409 413 output_size = 0
410 414 end
411 415
412 416 return {
413 417 :num => case_num,
414 418 :msg => results[0],
415 419 :run_stat => run_stat,
416 420 :output => output_file,
417 421 :output_size => output_size
418 422 }
419 423 end
420 424 end
421 425
422 426 # copied from grader/script/lib/test_request_helper.rb
423 427 def extract_running_stat(results)
424 428 running_stat_line = results[-1]
425 429
426 430 # extract exit status line
427 431 run_stat = ""
428 432 if !(/[Cc]orrect/.match(results[0]))
429 433 run_stat = results[0].chomp
430 434 else
431 435 run_stat = 'Program exited normally'
432 436 end
433 437
434 438 logger.info "Stat line: #{running_stat_line}"
435 439
436 440 # extract running time
437 441 if res = /r(.*)u(.*)s/.match(running_stat_line)
438 442 seconds = (res[1].to_f + res[2].to_f)
439 443 time_stat = "Time used: #{seconds} sec."
440 444 else
441 445 seconds = nil
442 446 time_stat = "Time used: n/a sec."
443 447 end
444 448
445 449 # extract memory usage
446 450 if res = /s(.*)m/.match(running_stat_line)
447 451 memory_used = res[1].to_i
448 452 else
449 453 memory_used = -1
450 454 end
451 455
452 456 return {
453 457 :msg => "#{run_stat}\n#{time_stat}",
454 458 :running_time => seconds,
455 459 :exit_status => run_stat,
456 460 :memory_usage => memory_used
457 461 }
458 462 end
459 463
460 464 def update_user_start_time
461 465 user = User.find(session[:user_id])
462 466 UserContestStat.update_user_start_time(user)
463 467 end
464 468
469 + def reject_announcement_refresh_when_logged_out
470 + if not session[:user_id]
471 + render :text => 'Access forbidden', :status => 403
472 + end
473 + end
474 +
465 475 end
466 476
You need to be logged in to leave comments. Login now