Description:
fixed timing stat bug when used with single user mode
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r245:4658efe40e96 - - 2 files changed: 7 inserted, 1 deleted

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