Description:
added codejom_status model for computing level with basic user update
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r219:95cc49d72ca8 - - 9 files changed: 79 inserted, 1 deleted

@@ -0,0 +1,5
1 + class CodejomStatus < ActiveRecord::Base
2 +
3 + belongs_to :user
4 +
5 + end
@@ -0,0 +1,15
1 + class CreateCodejomStatuses < ActiveRecord::Migration
2 + def self.up
3 + create_table :codejom_statuses do |t|
4 + t.integer :user_id
5 + t.boolean :alive
6 + t.integer :num_problems_passed
7 +
8 + t.timestamps
9 + end
10 + end
11 +
12 + def self.down
13 + drop_table :codejom_statuses
14 + end
15 + end
@@ -0,0 +1,11
1 + # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 +
3 + one:
4 + user_id: 1
5 + alive: false
6 + num_problems_passed: 1
7 +
8 + two:
9 + user_id: 1
10 + alive: false
11 + num_problems_passed: 1
@@ -0,0 +1,8
1 + require 'test_helper'
2 +
3 + class CodejomStatusTest < ActiveSupport::TestCase
4 + # Replace this with your real tests.
5 + test "the truth" do
6 + assert true
7 + end
8 + end
@@ -51,358 +51,359
51 @submission = Submission.new(params[:submission])
51 @submission = Submission.new(params[:submission])
52 @submission.user = user
52 @submission.user = user
53 @submission.language_id = 0
53 @submission.language_id = 0
54 if (params['file']) and (params['file']!='')
54 if (params['file']) and (params['file']!='')
55 @submission.source = params['file'].read
55 @submission.source = params['file'].read
56 @submission.source_filename = params['file'].original_filename
56 @submission.source_filename = params['file'].original_filename
57 end
57 end
58 @submission.submitted_at = Time.new.gmtime
58 @submission.submitted_at = Time.new.gmtime
59
59
60 if Configuration.time_limit_mode? and user.contest_finished?
60 if Configuration.time_limit_mode? and user.contest_finished?
61 @submission.errors.add_to_base "The contest is over."
61 @submission.errors.add_to_base "The contest is over."
62 prepare_list_information
62 prepare_list_information
63 render :action => 'list' and return
63 render :action => 'list' and return
64 end
64 end
65
65
66 if @submission.valid?
66 if @submission.valid?
67 if @submission.save == false
67 if @submission.save == false
68 flash[:notice] = 'Error saving your submission'
68 flash[:notice] = 'Error saving your submission'
69 elsif Task.create(:submission_id => @submission.id,
69 elsif Task.create(:submission_id => @submission.id,
70 :status => Task::STATUS_INQUEUE) == false
70 :status => Task::STATUS_INQUEUE) == false
71 flash[:notice] = 'Error adding your submission to task queue'
71 flash[:notice] = 'Error adding your submission to task queue'
72 end
72 end
73 else
73 else
74 prepare_list_information
74 prepare_list_information
75 render :action => 'list' and return
75 render :action => 'list' and return
76 end
76 end
77 redirect_to :action => 'list'
77 redirect_to :action => 'list'
78 end
78 end
79
79
80 def source
80 def source
81 submission = Submission.find(params[:id])
81 submission = Submission.find(params[:id])
82 if submission.user_id == session[:user_id]
82 if submission.user_id == session[:user_id]
83 send_data(submission.source,
83 send_data(submission.source,
84 {:filename => submission.download_filename,
84 {:filename => submission.download_filename,
85 :type => 'text/plain'})
85 :type => 'text/plain'})
86 else
86 else
87 flash[:notice] = 'Error viewing source'
87 flash[:notice] = 'Error viewing source'
88 redirect_to :action => 'list'
88 redirect_to :action => 'list'
89 end
89 end
90 end
90 end
91
91
92 def compiler_msg
92 def compiler_msg
93 @submission = Submission.find(params[:id])
93 @submission = Submission.find(params[:id])
94 if @submission.user_id == session[:user_id]
94 if @submission.user_id == session[:user_id]
95 render :action => 'compiler_msg', :layout => 'empty'
95 render :action => 'compiler_msg', :layout => 'empty'
96 else
96 else
97 flash[:notice] = 'Error viewing source'
97 flash[:notice] = 'Error viewing source'
98 redirect_to :action => 'list'
98 redirect_to :action => 'list'
99 end
99 end
100 end
100 end
101
101
102 def submission
102 def submission
103 @user = User.find(session[:user_id])
103 @user = User.find(session[:user_id])
104 @problems = Problem.find_available_problems
104 @problems = Problem.find_available_problems
105 if params[:id]==nil
105 if params[:id]==nil
106 @problem = nil
106 @problem = nil
107 @submissions = nil
107 @submissions = nil
108 else
108 else
109 @problem = Problem.find_by_name(params[:id])
109 @problem = Problem.find_by_name(params[:id])
110 if not @problem.available
110 if not @problem.available
111 redirect_to :action => 'list'
111 redirect_to :action => 'list'
112 flash[:notice] = 'Error: submissions for that problem are not viewable.'
112 flash[:notice] = 'Error: submissions for that problem are not viewable.'
113 return
113 return
114 end
114 end
115 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
115 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
116 end
116 end
117 end
117 end
118
118
119 def result
119 def result
120 if !Configuration.show_grading_result
120 if !Configuration.show_grading_result
121 redirect_to :action => 'list' and return
121 redirect_to :action => 'list' and return
122 end
122 end
123 @user = User.find(session[:user_id])
123 @user = User.find(session[:user_id])
124 @submission = Submission.find(params[:id])
124 @submission = Submission.find(params[:id])
125 if @submission.user!=@user
125 if @submission.user!=@user
126 flash[:notice] = 'You are not allowed to view result of other users.'
126 flash[:notice] = 'You are not allowed to view result of other users.'
127 redirect_to :action => 'list' and return
127 redirect_to :action => 'list' and return
128 end
128 end
129 prepare_grading_result(@submission)
129 prepare_grading_result(@submission)
130 end
130 end
131
131
132 def load_output
132 def load_output
133 if !Configuration.show_grading_result or params[:num]==nil
133 if !Configuration.show_grading_result or params[:num]==nil
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 case_num = params[:num].to_i
142 case_num = params[:num].to_i
143 out_filename = output_filename(@user.login,
143 out_filename = output_filename(@user.login,
144 @submission.problem.name,
144 @submission.problem.name,
145 @submission.id,
145 @submission.id,
146 case_num)
146 case_num)
147 if !FileTest.exists?(out_filename)
147 if !FileTest.exists?(out_filename)
148 flash[:notice] = 'Output not found.'
148 flash[:notice] = 'Output not found.'
149 redirect_to :action => 'list' and return
149 redirect_to :action => 'list' and return
150 end
150 end
151
151
152 response.headers['Content-Type'] = "application/force-download"
152 response.headers['Content-Type'] = "application/force-download"
153 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
153 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
154 response.headers["X-Sendfile"] = out_filename
154 response.headers["X-Sendfile"] = out_filename
155 response.headers['Content-length'] = File.size(out_filename)
155 response.headers['Content-length'] = File.size(out_filename)
156 render :nothing => true
156 render :nothing => true
157 end
157 end
158
158
159 def error
159 def error
160 @user = User.find(session[:user_id])
160 @user = User.find(session[:user_id])
161 end
161 end
162
162
163 # announcement refreshing and hiding methods
163 # announcement refreshing and hiding methods
164
164
165 def announcements
165 def announcements
166 if params.has_key? 'recent'
166 if params.has_key? 'recent'
167 prepare_announcements(params[:recent])
167 prepare_announcements(params[:recent])
168 else
168 else
169 prepare_announcements
169 prepare_announcements
170 end
170 end
171 render(:partial => 'announcement',
171 render(:partial => 'announcement',
172 :collection => @announcements,
172 :collection => @announcements,
173 :locals => {:announcement_effect => true})
173 :locals => {:announcement_effect => true})
174 end
174 end
175
175
176 #
176 #
177 # actions for Code Jom
177 # actions for Code Jom
178 #
178 #
179 def download_input
179 def download_input
180 problem = Problem.find(params[:id])
180 problem = Problem.find(params[:id])
181 user = User.find(session[:user_id])
181 user = User.find(session[:user_id])
182 if user.can_request_new_test_pair_for? problem
182 if user.can_request_new_test_pair_for? problem
183 assignment = user.get_new_test_pair_assignment_for problem
183 assignment = user.get_new_test_pair_assignment_for problem
184 assignment.save
184 assignment.save
185
185
186 send_data(assignment.test_pair.input,
186 send_data(assignment.test_pair.input,
187 { :filename => "#{problem.name}-#{assignment.request_number}.in",
187 { :filename => "#{problem.name}-#{assignment.request_number}.in",
188 :type => 'text/plain' })
188 :type => 'text/plain' })
189 else
189 else
190 recent_assignment = user.get_recent_test_pair_assignment_for problem
190 recent_assignment = user.get_recent_test_pair_assignment_for problem
191 send_data(recent_assignment.test_pair.input,
191 send_data(recent_assignment.test_pair.input,
192 { :filename => "#{problem.name}-#{recent_assignment.request_number}.in",
192 { :filename => "#{problem.name}-#{recent_assignment.request_number}.in",
193 :type => 'text/plain' })
193 :type => 'text/plain' })
194 end
194 end
195 end
195 end
196
196
197 def submit_solution
197 def submit_solution
198 problem = Problem.find(params[:id])
198 problem = Problem.find(params[:id])
199 user = User.find(session[:user_id])
199 user = User.find(session[:user_id])
200 recent_assignment = user.get_recent_test_pair_assignment_for problem
200 recent_assignment = user.get_recent_test_pair_assignment_for problem
201 if recent_assignment == nil
201 if recent_assignment == nil
202 flash[:notice] = 'You have not requested for any input data for this problem. Please download an input first.'
202 flash[:notice] = 'You have not requested for any input data for this problem. Please download an input first.'
203 redirect_to :action => 'list' and return
203 redirect_to :action => 'list' and return
204 end
204 end
205
205
206 if recent_assignment.submitted
206 if recent_assignment.submitted
207 flash[:notice] = 'You have already submitted an incorrect solution for this input. Please download a new input data.'
207 flash[:notice] = 'You have already submitted an incorrect solution for this input. Please download a new input data.'
208 redirect_to :action => 'list' and return
208 redirect_to :action => 'list' and return
209 end
209 end
210
210
211 if params[:file] == nil
211 if params[:file] == nil
212 flash[:notice] = 'You have not submitted any output.'
212 flash[:notice] = 'You have not submitted any output.'
213 redirect_to :action => 'list' and return
213 redirect_to :action => 'list' and return
214 end
214 end
215
215
216 submitted_solution = params[:file].read
216 submitted_solution = params[:file].read
217 test_pair = recent_assignment.test_pair
217 test_pair = recent_assignment.test_pair
218 passed = test_pair.grade(submitted_solution)
218 passed = test_pair.grade(submitted_solution)
219 points = passed ? 100 : 0
219 points = passed ? 100 : 0
220 submission = Submission.new(:user => user,
220 submission = Submission.new(:user => user,
221 :problem => problem,
221 :problem => problem,
222 :source => submitted_solution,
222 :source => submitted_solution,
223 :source_filename => params['file'].original_filename,
223 :source_filename => params['file'].original_filename,
224 :language_id => 0,
224 :language_id => 0,
225 :submitted_at => Time.new.gmtime,
225 :submitted_at => Time.new.gmtime,
226 :graded_at => Time.new.gmtime,
226 :graded_at => Time.new.gmtime,
227 :points => points)
227 :points => points)
228 submission.save
228 submission.save
229 recent_assignment.submitted = true
229 recent_assignment.submitted = true
230 recent_assignment.save
230 recent_assignment.save
231
231
232 status = user.get_submission_status_for(problem)
232 status = user.get_submission_status_for(problem)
233 if status == nil
233 if status == nil
234 status = SubmissionStatus.new :user => user, :problem => problem, :submission_count => 0
234 status = SubmissionStatus.new :user => user, :problem => problem, :submission_count => 0
235 end
235 end
236
236
237 status.submission_count += 1
237 status.submission_count += 1
238 status.passed = passed
238 status.passed = passed
239 status.save
239 status.save
240
240
241 if passed
241 if passed
242 flash[:notice] = 'Correct solution.'
242 flash[:notice] = 'Correct solution.'
243 + user.update_codejom_status
243 else
244 else
244 flash[:notice] = 'Incorrect solution.'
245 flash[:notice] = 'Incorrect solution.'
245 end
246 end
246 redirect_to :action => 'list'
247 redirect_to :action => 'list'
247 end
248 end
248
249
249 protected
250 protected
250
251
251 def prepare_announcements(recent=nil)
252 def prepare_announcements(recent=nil)
252 if Configuration.show_tasks_to?(@user)
253 if Configuration.show_tasks_to?(@user)
253 @announcements = Announcement.find_published(true)
254 @announcements = Announcement.find_published(true)
254 else
255 else
255 @announcements = Announcement.find_published
256 @announcements = Announcement.find_published
256 end
257 end
257 if recent!=nil
258 if recent!=nil
258 recent_id = recent.to_i
259 recent_id = recent.to_i
259 @announcements = @announcements.find_all { |a| a.id > recent_id }
260 @announcements = @announcements.find_all { |a| a.id > recent_id }
260 end
261 end
261 end
262 end
262
263
263 def prepare_list_information
264 def prepare_list_information
264 @user = User.find(session[:user_id])
265 @user = User.find(session[:user_id])
265
266
266 all_problems = Problem.find_available_problems
267 all_problems = Problem.find_available_problems
267
268
268 passed = {}
269 passed = {}
269 sub_count = {}
270 sub_count = {}
270 @user.submission_statuses.each do |status|
271 @user.submission_statuses.each do |status|
271 if status.passed
272 if status.passed
272 passed[status.problem_id] = true
273 passed[status.problem_id] = true
273 end
274 end
274 sub_count[status.problem_id] = status.submission_count
275 sub_count[status.problem_id] = status.submission_count
275 end
276 end
276
277
277 @problems = all_problems.reject { |problem| passed.has_key? problem.id }
278 @problems = all_problems.reject { |problem| passed.has_key? problem.id }
278
279
279 @prob_submissions = Array.new
280 @prob_submissions = Array.new
280 @problems.each do |p|
281 @problems.each do |p|
281 if sub_count.has_key? p.id
282 if sub_count.has_key? p.id
282 @prob_submissions << { :count => sub_count[p.id] }
283 @prob_submissions << { :count => sub_count[p.id] }
283 else
284 else
284 @prob_submissions << { :count => 0 }
285 @prob_submissions << { :count => 0 }
285 end
286 end
286 end
287 end
287 prepare_announcements
288 prepare_announcements
288 end
289 end
289
290
290 def check_viewability
291 def check_viewability
291 @user = User.find(session[:user_id])
292 @user = User.find(session[:user_id])
292 if (!Configuration.show_tasks_to?(@user)) and
293 if (!Configuration.show_tasks_to?(@user)) and
293 ((action_name=='submission') or (action_name=='submit'))
294 ((action_name=='submission') or (action_name=='submit'))
294 redirect_to :action => 'list' and return
295 redirect_to :action => 'list' and return
295 end
296 end
296 end
297 end
297
298
298 def prepare_grading_result(submission)
299 def prepare_grading_result(submission)
299 if Configuration.task_grading_info.has_key? submission.problem.name
300 if Configuration.task_grading_info.has_key? submission.problem.name
300 grading_info = Configuration.task_grading_info[submission.problem.name]
301 grading_info = Configuration.task_grading_info[submission.problem.name]
301 else
302 else
302 # guess task info from problem.full_score
303 # guess task info from problem.full_score
303 cases = submission.problem.full_score / 10
304 cases = submission.problem.full_score / 10
304 grading_info = {
305 grading_info = {
305 'testruns' => cases,
306 'testruns' => cases,
306 'testcases' => cases
307 'testcases' => cases
307 }
308 }
308 end
309 end
309 @test_runs = []
310 @test_runs = []
310 if grading_info['testruns'].is_a? Integer
311 if grading_info['testruns'].is_a? Integer
311 trun_count = grading_info['testruns']
312 trun_count = grading_info['testruns']
312 trun_count.times do |i|
313 trun_count.times do |i|
313 @test_runs << [ read_grading_result(@user.login,
314 @test_runs << [ read_grading_result(@user.login,
314 submission.problem.name,
315 submission.problem.name,
315 submission.id,
316 submission.id,
316 i+1) ]
317 i+1) ]
317 end
318 end
318 else
319 else
319 grading_info['testruns'].keys.sort.each do |num|
320 grading_info['testruns'].keys.sort.each do |num|
320 run = []
321 run = []
321 testrun = grading_info['testruns'][num]
322 testrun = grading_info['testruns'][num]
322 testrun.each do |c|
323 testrun.each do |c|
323 run << read_grading_result(@user.login,
324 run << read_grading_result(@user.login,
324 submission.problem.name,
325 submission.problem.name,
325 submission.id,
326 submission.id,
326 c)
327 c)
327 end
328 end
328 @test_runs << run
329 @test_runs << run
329 end
330 end
330 end
331 end
331 end
332 end
332
333
333 def grading_result_dir(user_name, problem_name, submission_id, case_num)
334 def grading_result_dir(user_name, problem_name, submission_id, case_num)
334 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
335 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
335 end
336 end
336
337
337 def output_filename(user_name, problem_name, submission_id, case_num)
338 def output_filename(user_name, problem_name, submission_id, case_num)
338 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
339 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
339 return "#{dir}/output.txt"
340 return "#{dir}/output.txt"
340 end
341 end
341
342
342 def read_grading_result(user_name, problem_name, submission_id, case_num)
343 def read_grading_result(user_name, problem_name, submission_id, case_num)
343 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
344 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
344 result_file_name = "#{dir}/result"
345 result_file_name = "#{dir}/result"
345 if !FileTest.exists?(result_file_name)
346 if !FileTest.exists?(result_file_name)
346 return {:num => case_num, :msg => 'program did not run'}
347 return {:num => case_num, :msg => 'program did not run'}
347 else
348 else
348 results = File.open(result_file_name).readlines
349 results = File.open(result_file_name).readlines
349 run_stat = extract_running_stat(results)
350 run_stat = extract_running_stat(results)
350 output_filename = "#{dir}/output.txt"
351 output_filename = "#{dir}/output.txt"
351 if FileTest.exists?(output_filename)
352 if FileTest.exists?(output_filename)
352 output_file = true
353 output_file = true
353 output_size = File.size(output_filename)
354 output_size = File.size(output_filename)
354 else
355 else
355 output_file = false
356 output_file = false
356 output_size = 0
357 output_size = 0
357 end
358 end
358
359
359 return {
360 return {
360 :num => case_num,
361 :num => case_num,
361 :msg => results[0],
362 :msg => results[0],
362 :run_stat => run_stat,
363 :run_stat => run_stat,
363 :output => output_file,
364 :output => output_file,
364 :output_size => output_size
365 :output_size => output_size
365 }
366 }
366 end
367 end
367 end
368 end
368
369
369 # copied from grader/script/lib/test_request_helper.rb
370 # copied from grader/script/lib/test_request_helper.rb
370 def extract_running_stat(results)
371 def extract_running_stat(results)
371 running_stat_line = results[-1]
372 running_stat_line = results[-1]
372
373
373 # extract exit status line
374 # extract exit status line
374 run_stat = ""
375 run_stat = ""
375 if !(/[Cc]orrect/.match(results[0]))
376 if !(/[Cc]orrect/.match(results[0]))
376 run_stat = results[0].chomp
377 run_stat = results[0].chomp
377 else
378 else
378 run_stat = 'Program exited normally'
379 run_stat = 'Program exited normally'
379 end
380 end
380
381
381 logger.info "Stat line: #{running_stat_line}"
382 logger.info "Stat line: #{running_stat_line}"
382
383
383 # extract running time
384 # extract running time
384 if res = /r(.*)u(.*)s/.match(running_stat_line)
385 if res = /r(.*)u(.*)s/.match(running_stat_line)
385 seconds = (res[1].to_f + res[2].to_f)
386 seconds = (res[1].to_f + res[2].to_f)
386 time_stat = "Time used: #{seconds} sec."
387 time_stat = "Time used: #{seconds} sec."
387 else
388 else
388 seconds = nil
389 seconds = nil
389 time_stat = "Time used: n/a sec."
390 time_stat = "Time used: n/a sec."
390 end
391 end
391
392
392 # extract memory usage
393 # extract memory usage
393 if res = /s(.*)m/.match(running_stat_line)
394 if res = /s(.*)m/.match(running_stat_line)
394 memory_used = res[1].to_i
395 memory_used = res[1].to_i
395 else
396 else
396 memory_used = -1
397 memory_used = -1
397 end
398 end
398
399
399 return {
400 return {
400 :msg => "#{run_stat}\n#{time_stat}",
401 :msg => "#{run_stat}\n#{time_stat}",
401 :running_time => seconds,
402 :running_time => seconds,
402 :exit_status => run_stat,
403 :exit_status => run_stat,
403 :memory_usage => memory_used
404 :memory_usage => memory_used
404 }
405 }
405 end
406 end
406
407
407 end
408 end
408
409
@@ -1,116 +1,121
1 class Problem < ActiveRecord::Base
1 class Problem < ActiveRecord::Base
2
2
3 belongs_to :description
3 belongs_to :description
4 has_many :test_pairs, :dependent => :delete_all
4 has_many :test_pairs, :dependent => :delete_all
5
5
6 validates_presence_of :name
6 validates_presence_of :name
7 validates_format_of :name, :with => /^\w+$/
7 validates_format_of :name, :with => /^\w+$/
8 validates_presence_of :full_name
8 validates_presence_of :full_name
9
9
10 DEFAULT_TIME_LIMIT = 1
10 DEFAULT_TIME_LIMIT = 1
11 DEFAULT_MEMORY_LIMIT = 32
11 DEFAULT_MEMORY_LIMIT = 32
12
12
13 def test_pair_count
13 def test_pair_count
14 @test_pair_count ||= test_pairs.size
14 @test_pair_count ||= test_pairs.size
15 end
15 end
16
16
17 def uses_random_test_pair?
17 def uses_random_test_pair?
18 test_pair_count != 0
18 test_pair_count != 0
19 end
19 end
20
20
21 def random_test_pair(forbidden_numbers=nil)
21 def random_test_pair(forbidden_numbers=nil)
22 begin
22 begin
23 test_num = 1 + rand(test_pair_count)
23 test_num = 1 + rand(test_pair_count)
24 end while forbidden_numbers!=nil and forbidden_numbers.include? test_num
24 end while forbidden_numbers!=nil and forbidden_numbers.include? test_num
25 test_pairs.find_by_number test_num
25 test_pairs.find_by_number test_num
26 end
26 end
27
27
28 def self.find_available_problems
28 def self.find_available_problems
29 find(:all, :conditions => {:available => true}, :order => "date_added DESC")
29 find(:all, :conditions => {:available => true}, :order => "date_added DESC")
30 end
30 end
31
31
32 + # TODO: may try to optimize this using cache
33 + def self.available_problem_count
34 + return Problem.find_available_problems.length
35 + end
36 +
32 def self.create_from_import_form_params(params, old_problem=nil)
37 def self.create_from_import_form_params(params, old_problem=nil)
33 problem = old_problem || Problem.new
38 problem = old_problem || Problem.new
34 import_params = Problem.extract_params_and_check(params, problem)
39 import_params = Problem.extract_params_and_check(params, problem)
35
40
36 if not problem.valid?
41 if not problem.valid?
37 return problem, 'Error importing'
42 return problem, 'Error importing'
38 end
43 end
39
44
40 problem.full_score = 100
45 problem.full_score = 100
41 problem.date_added = Time.new
46 problem.date_added = Time.new
42 problem.test_allowed = true
47 problem.test_allowed = true
43 problem.output_only = false
48 problem.output_only = false
44 problem.available = false
49 problem.available = false
45
50
46 if not problem.save
51 if not problem.save
47 return problem, 'Error importing'
52 return problem, 'Error importing'
48 end
53 end
49
54
50 import_to_db = params.has_key? :import_to_db
55 import_to_db = params.has_key? :import_to_db
51
56
52 importer = TestdataImporter.new(problem)
57 importer = TestdataImporter.new(problem)
53
58
54 if not importer.import_from_file(import_params[:file],
59 if not importer.import_from_file(import_params[:file],
55 import_params[:time_limit],
60 import_params[:time_limit],
56 import_params[:memory_limit],
61 import_params[:memory_limit],
57 import_to_db)
62 import_to_db)
58 problem.errors.add_to_base('Import error.')
63 problem.errors.add_to_base('Import error.')
59 end
64 end
60
65
61 return problem, importer.log_msg
66 return problem, importer.log_msg
62 end
67 end
63
68
64 protected
69 protected
65
70
66 def self.to_i_or_default(st, default)
71 def self.to_i_or_default(st, default)
67 if st!=''
72 if st!=''
68 st.to_i
73 st.to_i
69 else
74 else
70 default
75 default
71 end
76 end
72 end
77 end
73
78
74 def self.extract_params_and_check(params, problem)
79 def self.extract_params_and_check(params, problem)
75 time_limit = Problem.to_i_or_default(params[:time_limit],
80 time_limit = Problem.to_i_or_default(params[:time_limit],
76 DEFAULT_TIME_LIMIT)
81 DEFAULT_TIME_LIMIT)
77 memory_limit = Problem.to_i_or_default(params[:memory_limit],
82 memory_limit = Problem.to_i_or_default(params[:memory_limit],
78 DEFAULT_MEMORY_LIMIT)
83 DEFAULT_MEMORY_LIMIT)
79
84
80 if time_limit==0 and time_limit_s!='0'
85 if time_limit==0 and time_limit_s!='0'
81 problem.errors.add_to_base('Time limit format errors.')
86 problem.errors.add_to_base('Time limit format errors.')
82 elsif time_limit<=0 or time_limit >60
87 elsif time_limit<=0 or time_limit >60
83 problem.errors.add_to_base('Time limit out of range.')
88 problem.errors.add_to_base('Time limit out of range.')
84 end
89 end
85
90
86 if memory_limit==0 and memory_limit_s!='0'
91 if memory_limit==0 and memory_limit_s!='0'
87 problem.errors.add_to_base('Memory limit format errors.')
92 problem.errors.add_to_base('Memory limit format errors.')
88 elsif memory_limit<=0 or memory_limit >512
93 elsif memory_limit<=0 or memory_limit >512
89 problem.errors.add_to_base('Memory limit out of range.')
94 problem.errors.add_to_base('Memory limit out of range.')
90 end
95 end
91
96
92 if params[:file]==nil or params[:file]==''
97 if params[:file]==nil or params[:file]==''
93 problem.errors.add_to_base('No testdata file.')
98 problem.errors.add_to_base('No testdata file.')
94 end
99 end
95
100
96 file = params[:file]
101 file = params[:file]
97
102
98 if problem.errors.length!=0
103 if problem.errors.length!=0
99 return problem
104 return problem
100 end
105 end
101
106
102 problem.name = params[:name]
107 problem.name = params[:name]
103 if params[:full_name]!=''
108 if params[:full_name]!=''
104 problem.full_name = params[:full_name]
109 problem.full_name = params[:full_name]
105 else
110 else
106 problem.full_name = params[:name]
111 problem.full_name = params[:name]
107 end
112 end
108
113
109 return {
114 return {
110 :time_limit => time_limit,
115 :time_limit => time_limit,
111 :memory_limit => memory_limit,
116 :memory_limit => memory_limit,
112 :file => file
117 :file => file
113 }
118 }
114 end
119 end
115
120
116 end
121 end
@@ -1,277 +1,298
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_many :test_pair_assignments, :dependent => :delete_all
19 has_many :test_pair_assignments, :dependent => :delete_all
20 has_many :submission_statuses
20 has_many :submission_statuses
21
21
22 has_one :contest_stat, :class_name => "UserContestStat"
22 has_one :contest_stat, :class_name => "UserContestStat"
23
23
24 belongs_to :site
24 belongs_to :site
25 belongs_to :country
25 belongs_to :country
26
26
27 + # For Code Jom
28 + has_one :codejom_status
29 +
27 named_scope :activated_users, :conditions => {:activated => true}
30 named_scope :activated_users, :conditions => {:activated => true}
28
31
29 validates_presence_of :login
32 validates_presence_of :login
30 validates_uniqueness_of :login
33 validates_uniqueness_of :login
31 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
34 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
32 validates_length_of :login, :within => 3..30
35 validates_length_of :login, :within => 3..30
33
36
34 validates_presence_of :full_name
37 validates_presence_of :full_name
35 validates_length_of :full_name, :minimum => 1
38 validates_length_of :full_name, :minimum => 1
36
39
37 validates_presence_of :password, :if => :password_required?
40 validates_presence_of :password, :if => :password_required?
38 validates_length_of :password, :within => 4..20, :if => :password_required?
41 validates_length_of :password, :within => 4..20, :if => :password_required?
39 validates_confirmation_of :password, :if => :password_required?
42 validates_confirmation_of :password, :if => :password_required?
40
43
41 validates_format_of :email,
44 validates_format_of :email,
42 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
45 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
43 :if => :email_validation?
46 :if => :email_validation?
44 validate :uniqueness_of_email_from_activated_users,
47 validate :uniqueness_of_email_from_activated_users,
45 :if => :email_validation?
48 :if => :email_validation?
46 validate :enough_time_interval_between_same_email_registrations,
49 validate :enough_time_interval_between_same_email_registrations,
47 :if => :email_validation?
50 :if => :email_validation?
48
51
49 # these are for ytopc
52 # these are for ytopc
50 # disable for now
53 # disable for now
51 #validates_presence_of :province
54 #validates_presence_of :province
52
55
53 attr_accessor :password
56 attr_accessor :password
54
57
55 before_save :encrypt_new_password
58 before_save :encrypt_new_password
56 before_save :assign_default_site
59 before_save :assign_default_site
57
60
58 def self.authenticate(login, password)
61 def self.authenticate(login, password)
59 user = find_by_login(login)
62 user = find_by_login(login)
60 return user if user && user.authenticated?(password)
63 return user if user && user.authenticated?(password)
61 end
64 end
62
65
63 def authenticated?(password)
66 def authenticated?(password)
64 if self.activated
67 if self.activated
65 hashed_password == User.encrypt(password,self.salt)
68 hashed_password == User.encrypt(password,self.salt)
66 else
69 else
67 false
70 false
68 end
71 end
69 end
72 end
70
73
71 def admin?
74 def admin?
72 self.roles.detect {|r| r.name == 'admin' }
75 self.roles.detect {|r| r.name == 'admin' }
73 end
76 end
74
77
75 # These are methods related to test pairs
78 # These are methods related to test pairs
76
79
77 def get_test_pair_assignments_for(problem)
80 def get_test_pair_assignments_for(problem)
78 test_pair_assignments.find_all { |a| a.problem_id == problem.id }
81 test_pair_assignments.find_all { |a| a.problem_id == problem.id }
79 end
82 end
80
83
81 def get_recent_test_pair_assignment_for(problem)
84 def get_recent_test_pair_assignment_for(problem)
82 assignments = get_test_pair_assignments_for problem
85 assignments = get_test_pair_assignments_for problem
83 if assignments.length == 0
86 if assignments.length == 0
84 return nil
87 return nil
85 else
88 else
86 recent = assignments[0]
89 recent = assignments[0]
87 assignments.each do |a|
90 assignments.each do |a|
88 recent = a if a.request_number > recent.request_number
91 recent = a if a.request_number > recent.request_number
89 end
92 end
90 return recent
93 return recent
91 end
94 end
92 end
95 end
93
96
94 def can_request_new_test_pair_for?(problem)
97 def can_request_new_test_pair_for?(problem)
95 recent = get_recent_test_pair_assignment_for problem
98 recent = get_recent_test_pair_assignment_for problem
96 return (recent == nil or recent.submitted)
99 return (recent == nil or recent.submitted)
97 end
100 end
98
101
99 def get_new_test_pair_assignment_for(problem)
102 def get_new_test_pair_assignment_for(problem)
100 previous_assignment_numbers =
103 previous_assignment_numbers =
101 get_test_pair_assignments_for(problem).collect {|a| a.test_pair_number }
104 get_test_pair_assignments_for(problem).collect {|a| a.test_pair_number }
102 test_pair = problem.random_test_pair(previous_assignment_numbers)
105 test_pair = problem.random_test_pair(previous_assignment_numbers)
103 if test_pair
106 if test_pair
104 assignment = TestPairAssignment.new(:user => self,
107 assignment = TestPairAssignment.new(:user => self,
105 :problem => problem,
108 :problem => problem,
106 :test_pair => test_pair,
109 :test_pair => test_pair,
107 :test_pair_number => test_pair.number,
110 :test_pair_number => test_pair.number,
108 :request_number =>
111 :request_number =>
109 previous_assignment_numbers.length + 1,
112 previous_assignment_numbers.length + 1,
110 :submitted => false)
113 :submitted => false)
111 return assignment
114 return assignment
112 else
115 else
113 return nil
116 return nil
114 end
117 end
115 end
118 end
116
119
117 def get_submission_status_for(problem)
120 def get_submission_status_for(problem)
118 SubmissionStatus.find(:first,
121 SubmissionStatus.find(:first,
119 :conditions => {
122 :conditions => {
120 :user_id => id,
123 :user_id => id,
121 :problem_id => problem.id
124 :problem_id => problem.id
122 })
125 })
123 end
126 end
124
127
125 def email_for_editing
128 def email_for_editing
126 if self.email==nil
129 if self.email==nil
127 "(unknown)"
130 "(unknown)"
128 elsif self.email==''
131 elsif self.email==''
129 "(blank)"
132 "(blank)"
130 else
133 else
131 self.email
134 self.email
132 end
135 end
133 end
136 end
134
137
135 def email_for_editing=(e)
138 def email_for_editing=(e)
136 self.email=e
139 self.email=e
137 end
140 end
138
141
139 def alias_for_editing
142 def alias_for_editing
140 if self.alias==nil
143 if self.alias==nil
141 "(unknown)"
144 "(unknown)"
142 elsif self.alias==''
145 elsif self.alias==''
143 "(blank)"
146 "(blank)"
144 else
147 else
145 self.alias
148 self.alias
146 end
149 end
147 end
150 end
148
151
149 def alias_for_editing=(e)
152 def alias_for_editing=(e)
150 self.alias=e
153 self.alias=e
151 end
154 end
152
155
153 def activation_key
156 def activation_key
154 if self.hashed_password==nil
157 if self.hashed_password==nil
155 encrypt_new_password
158 encrypt_new_password
156 end
159 end
157 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
160 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
158 end
161 end
159
162
160 def verify_activation_key(key)
163 def verify_activation_key(key)
161 key == activation_key
164 key == activation_key
162 end
165 end
163
166
164 def self.random_password(length=5)
167 def self.random_password(length=5)
165 chars = 'abcdefghjkmnopqrstuvwxyz'
168 chars = 'abcdefghjkmnopqrstuvwxyz'
166 password = ''
169 password = ''
167 length.times { password << chars[rand(chars.length - 1)] }
170 length.times { password << chars[rand(chars.length - 1)] }
168 password
171 password
169 end
172 end
170
173
171 def self.find_non_admin_with_prefix(prefix='')
174 def self.find_non_admin_with_prefix(prefix='')
172 users = User.find(:all)
175 users = User.find(:all)
173 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
176 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
174 end
177 end
175
178
176 # Contest information
179 # Contest information
177
180
178 def contest_time_left
181 def contest_time_left
179 if Configuration.contest_mode?
182 if Configuration.contest_mode?
180 return nil if site==nil
183 return nil if site==nil
181 return site.time_left
184 return site.time_left
182 elsif Configuration.indv_contest_mode?
185 elsif Configuration.indv_contest_mode?
183 time_limit = Configuration.contest_time_limit
186 time_limit = Configuration.contest_time_limit
184 if contest_stat==nil
187 if contest_stat==nil
185 return (Time.now.gmtime + time_limit) - Time.now.gmtime
188 return (Time.now.gmtime + time_limit) - Time.now.gmtime
186 else
189 else
187 finish_time = contest_stat.started_at + time_limit
190 finish_time = contest_stat.started_at + time_limit
188 current_time = Time.now.gmtime
191 current_time = Time.now.gmtime
189 if current_time > finish_time
192 if current_time > finish_time
190 return 0
193 return 0
191 else
194 else
192 return finish_time - current_time
195 return finish_time - current_time
193 end
196 end
194 end
197 end
195 else
198 else
196 return nil
199 return nil
197 end
200 end
198 end
201 end
199
202
200 def contest_finished?
203 def contest_finished?
201 if Configuration.contest_mode?
204 if Configuration.contest_mode?
202 return false if site==nil
205 return false if site==nil
203 return site.finished?
206 return site.finished?
204 elsif Configuration.indv_contest_mode?
207 elsif Configuration.indv_contest_mode?
205 time_limit = Configuration.contest_time_limit
208 time_limit = Configuration.contest_time_limit
206
209
207 return false if contest_stat==nil
210 return false if contest_stat==nil
208
211
209 return contest_time_left == 0
212 return contest_time_left == 0
210 else
213 else
211 return false
214 return false
212 end
215 end
213 end
216 end
214
217
215 def contest_started?
218 def contest_started?
216 if Configuration.contest_mode?
219 if Configuration.contest_mode?
217 return true if site==nil
220 return true if site==nil
218 return site.started
221 return site.started
219 else
222 else
220 return true
223 return true
221 end
224 end
222 end
225 end
223
226
227 + # For Code Jom
228 + def update_codejom_status
229 + status = codejom_status || CodejomStatus.new(:user => self)
230 + problem_count = Problem.available_problem_count
231 + status.num_problems_passed = (self.submission_statuses.find_all {|s| s.passed}).length
232 + status.alive = (problem_count - (status.num_problems_passed)) <= CODEJOM_MAX_ALIVE_LEVEL
233 + status.save
234 + end
235 +
236 + def codejom_level
237 + problem_count = Problem.available_problem_count
238 + if codejom_status!=nil
239 + return problem_count - codejom_status.num_problems_passed
240 + else
241 + return problem_count
242 + end
243 + end
244 +
224 protected
245 protected
225 def encrypt_new_password
246 def encrypt_new_password
226 return if password.blank?
247 return if password.blank?
227 self.salt = (10+rand(90)).to_s
248 self.salt = (10+rand(90)).to_s
228 self.hashed_password = User.encrypt(self.password,self.salt)
249 self.hashed_password = User.encrypt(self.password,self.salt)
229 end
250 end
230
251
231 def assign_default_site
252 def assign_default_site
232 # have to catch error when migrating (because self.site is not available).
253 # have to catch error when migrating (because self.site is not available).
233 begin
254 begin
234 if self.site==nil
255 if self.site==nil
235 self.site = Site.find_by_name('default')
256 self.site = Site.find_by_name('default')
236 if self.site==nil
257 if self.site==nil
237 self.site = Site.find(1) # when 'default has be renamed'
258 self.site = Site.find(1) # when 'default has be renamed'
238 end
259 end
239 end
260 end
240 rescue
261 rescue
241 end
262 end
242 end
263 end
243
264
244 def password_required?
265 def password_required?
245 self.hashed_password.blank? || !self.password.blank?
266 self.hashed_password.blank? || !self.password.blank?
246 end
267 end
247
268
248 def self.encrypt(string,salt)
269 def self.encrypt(string,salt)
249 Digest::SHA1.hexdigest(salt + string)
270 Digest::SHA1.hexdigest(salt + string)
250 end
271 end
251
272
252 def uniqueness_of_email_from_activated_users
273 def uniqueness_of_email_from_activated_users
253 user = User.activated_users.find_by_email(self.email)
274 user = User.activated_users.find_by_email(self.email)
254 if user and (user.login != self.login)
275 if user and (user.login != self.login)
255 self.errors.add_to_base("Email has already been taken")
276 self.errors.add_to_base("Email has already been taken")
256 end
277 end
257 end
278 end
258
279
259 def enough_time_interval_between_same_email_registrations
280 def enough_time_interval_between_same_email_registrations
260 return if !self.new_record?
281 return if !self.new_record?
261 return if self.activated
282 return if self.activated
262 open_user = User.find_by_email(self.email,
283 open_user = User.find_by_email(self.email,
263 :order => 'created_at DESC')
284 :order => 'created_at DESC')
264 if open_user and open_user.created_at and
285 if open_user and open_user.created_at and
265 (open_user.created_at > Time.now.gmtime - 5.minutes)
286 (open_user.created_at > Time.now.gmtime - 5.minutes)
266 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
287 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
267 end
288 end
268 end
289 end
269
290
270 def email_validation?
291 def email_validation?
271 begin
292 begin
272 return VALIDATE_USER_EMAILS
293 return VALIDATE_USER_EMAILS
273 rescue
294 rescue
274 return false
295 return false
275 end
296 end
276 end
297 end
277 end
298 end
@@ -1,105 +1,109
1 # Be sure to restart your web server when you modify this file.
1 # Be sure to restart your web server when you modify this file.
2
2
3 # Uncomment below to force Rails into production mode when
3 # Uncomment below to force Rails into production mode when
4 # you don't control web/app server and can't set it the proper way
4 # you don't control web/app server and can't set it the proper way
5 # ENV['RAILS_ENV'] ||= 'production'
5 # ENV['RAILS_ENV'] ||= 'production'
6
6
7 # Specifies gem version of Rails to use when vendor/rails is not present
7 # Specifies gem version of Rails to use when vendor/rails is not present
8 RAILS_GEM_VERSION = '2.3.4' unless defined? RAILS_GEM_VERSION
8 RAILS_GEM_VERSION = '2.3.4' unless defined? RAILS_GEM_VERSION
9
9
10 # Bootstrap the Rails environment, frameworks, and default configuration
10 # Bootstrap the Rails environment, frameworks, and default configuration
11 require File.join(File.dirname(__FILE__), 'boot')
11 require File.join(File.dirname(__FILE__), 'boot')
12
12
13 Rails::Initializer.run do |config|
13 Rails::Initializer.run do |config|
14 # Settings in config/environments/* take precedence over those specified here
14 # Settings in config/environments/* take precedence over those specified here
15
15
16 # Skip frameworks you're not going to use (only works if using vendor/rails)
16 # Skip frameworks you're not going to use (only works if using vendor/rails)
17 # config.frameworks -= [ :action_web_service, :action_mailer ]
17 # config.frameworks -= [ :action_web_service, :action_mailer ]
18
18
19 # Only load the plugins named here, by default all plugins in vendor/plugins are loaded
19 # Only load the plugins named here, by default all plugins in vendor/plugins are loaded
20 # config.plugins = %W( exception_notification ssl_requirement )
20 # config.plugins = %W( exception_notification ssl_requirement )
21
21
22 # Add additional load paths for your own custom dirs
22 # Add additional load paths for your own custom dirs
23 # config.load_paths += %W( #{RAILS_ROOT}/extras )
23 # config.load_paths += %W( #{RAILS_ROOT}/extras )
24
24
25 # Force all environments to use the same logger level
25 # Force all environments to use the same logger level
26 # (by default production uses :info, the others :debug)
26 # (by default production uses :info, the others :debug)
27 # config.log_level = :debug
27 # config.log_level = :debug
28
28
29 # Use the database for sessions instead of the file system
29 # Use the database for sessions instead of the file system
30 # (create the session table with 'rake db:sessions:create')
30 # (create the session table with 'rake db:sessions:create')
31 config.action_controller.session_store = :active_record_store
31 config.action_controller.session_store = :active_record_store
32
32
33 # Use SQL instead of Active Record's schema dumper when creating the test database.
33 # Use SQL instead of Active Record's schema dumper when creating the test database.
34 # This is necessary if your schema can't be completely dumped by the schema dumper,
34 # This is necessary if your schema can't be completely dumped by the schema dumper,
35 # like if you have constraints or database-specific column types
35 # like if you have constraints or database-specific column types
36 # config.active_record.schema_format = :sql
36 # config.active_record.schema_format = :sql
37
37
38 # Activate observers that should always be running
38 # Activate observers that should always be running
39 # config.active_record.observers = :cacher, :garbage_collector
39 # config.active_record.observers = :cacher, :garbage_collector
40
40
41 # Make Active Record use UTC-base instead of local time
41 # Make Active Record use UTC-base instead of local time
42 config.time_zone = 'UTC'
42 config.time_zone = 'UTC'
43
43
44 # Setting locales
44 # Setting locales
45 config.i18n.default_locale = 'en'
45 config.i18n.default_locale = 'en'
46
46
47 # See Rails::Configuration for more options
47 # See Rails::Configuration for more options
48
48
49 # -------------
49 # -------------
50 # Required gems
50 # Required gems
51 # -------------
51 # -------------
52 config.gem "haml"
52 config.gem "haml"
53 config.gem "tmail"
53 config.gem "tmail"
54 config.gem "rdiscount", :lib => "rdiscount"
54 config.gem "rdiscount", :lib => "rdiscount"
55
55
56 # NOTES on rspec: if you wan to test with rspec, you have to install
56 # NOTES on rspec: if you wan to test with rspec, you have to install
57 # rspec yourself, just call: [sudo] gem install rspec-rails
57 # rspec yourself, just call: [sudo] gem install rspec-rails
58
58
59 end
59 end
60
60
61 # Add new inflection rules using the following format
61 # Add new inflection rules using the following format
62 # (all these examples are active by default):
62 # (all these examples are active by default):
63 # Inflector.inflections do |inflect|
63 # Inflector.inflections do |inflect|
64 # inflect.plural /^(ox)$/i, '\1en'
64 # inflect.plural /^(ox)$/i, '\1en'
65 # inflect.singular /^(ox)en/i, '\1'
65 # inflect.singular /^(ox)en/i, '\1'
66 # inflect.irregular 'person', 'people'
66 # inflect.irregular 'person', 'people'
67 # inflect.uncountable %w( fish sheep )
67 # inflect.uncountable %w( fish sheep )
68 # end
68 # end
69
69
70 # Add new mime types for use in respond_to blocks:
70 # Add new mime types for use in respond_to blocks:
71 # Mime::Type.register "text/richtext", :rtf
71 # Mime::Type.register "text/richtext", :rtf
72 # Mime::Type.register "application/x-mobile", :mobile
72 # Mime::Type.register "application/x-mobile", :mobile
73
73
74 # Include your application configuration below
74 # Include your application configuration below
75
75
76 # If you want to manage graders through web interface, set the path to
76 # If you want to manage graders through web interface, set the path to
77 # the grader directory below. This dir is where raw, ev, ev-exam,
77 # the grader directory below. This dir is where raw, ev, ev-exam,
78 # scripts reside. All grader scripts will be in
78 # scripts reside. All grader scripts will be in
79 # #{GRADER_ROOT_DIR}/scripts.
79 # #{GRADER_ROOT_DIR}/scripts.
80 GRADER_ROOT_DIR = ''
80 GRADER_ROOT_DIR = ''
81
81
82 # These are where inputs and outputs of test requests are stored
82 # These are where inputs and outputs of test requests are stored
83 TEST_REQUEST_INPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/input'
83 TEST_REQUEST_INPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/input'
84 TEST_REQUEST_OUTPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/output'
84 TEST_REQUEST_OUTPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/output'
85
85
86 # To use ANALYSIS MODE, provide the testcases/testruns breakdown,
86 # To use ANALYSIS MODE, provide the testcases/testruns breakdown,
87 # and the directory of the grading result (usually in judge's dir).
87 # and the directory of the grading result (usually in judge's dir).
88 TASK_GRADING_INFO_FILENAME = RAILS_ROOT + '/config/tasks.yml'
88 TASK_GRADING_INFO_FILENAME = RAILS_ROOT + '/config/tasks.yml'
89
89
90 # TODO: change this to where results are kept.
90 # TODO: change this to where results are kept.
91 GRADING_RESULT_DIR = 'RESULT-DIR'
91 GRADING_RESULT_DIR = 'RESULT-DIR'
92
92
93 # Change this to allow importing testdata into database as test-pairs.
93 # Change this to allow importing testdata into database as test-pairs.
94 # This is mainly for Code Jom contest.
94 # This is mainly for Code Jom contest.
95 ALLOW_TEST_PAIR_IMPORT = false
95 ALLOW_TEST_PAIR_IMPORT = false
96
96
97 # Uncomment so that the system validates user e-mails
97 # Uncomment so that the system validates user e-mails
98 # VALIDATE_USER_EMAILS = true
98 # VALIDATE_USER_EMAILS = true
99
99
100 # Uncomment so that Apache X-Sendfile is used when delivering files
100 # Uncomment so that Apache X-Sendfile is used when delivering files
101 # (e.g., in /tasks/view).
101 # (e.g., in /tasks/view).
102 # USE_APACHE_XSENDFILE = true
102 # USE_APACHE_XSENDFILE = true
103
103
104 # Uncomment so that configuration is read only once when the server is loaded
104 # Uncomment so that configuration is read only once when the server is loaded
105 # Configuration.enable_caching
105 # Configuration.enable_caching
106 +
107 + # OPTIONS FOR CODE JOM
108 + # --------------------
109 + CODEJOM_MAX_ALIVE_LEVEL = 10
@@ -1,216 +1,224
1 # This file is auto-generated from the current state of the database. Instead of editing this file,
1 # This file is auto-generated from the current state of the database. Instead of editing this file,
2 # please use the migrations feature of Active Record to incrementally modify your database, and
2 # please use the migrations feature of Active Record to incrementally modify your database, and
3 # then regenerate this schema definition.
3 # then regenerate this schema definition.
4 #
4 #
5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6 # to create the application database on another system, you should be using db:schema:load, not running
6 # to create the application database on another system, you should be using db:schema:load, not running
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 #
9 #
10 # It's strongly recommended to check this file into your version control system.
10 # It's strongly recommended to check this file into your version control system.
11
11
12 - ActiveRecord::Schema.define(:version => 20100124054458) do
12 + ActiveRecord::Schema.define(:version => 20100124191250) do
13
13
14 create_table "announcements", :force => true do |t|
14 create_table "announcements", :force => true do |t|
15 t.string "author"
15 t.string "author"
16 t.text "body"
16 t.text "body"
17 t.boolean "published"
17 t.boolean "published"
18 t.datetime "created_at"
18 t.datetime "created_at"
19 t.datetime "updated_at"
19 t.datetime "updated_at"
20 t.boolean "frontpage", :default => false
20 t.boolean "frontpage", :default => false
21 t.boolean "contest_only", :default => false
21 t.boolean "contest_only", :default => false
22 t.string "title"
22 t.string "title"
23 end
23 end
24
24
25 + create_table "codejom_statuses", :force => true do |t|
26 + t.integer "user_id"
27 + t.boolean "alive"
28 + t.integer "num_problems_passed"
29 + t.datetime "created_at"
30 + t.datetime "updated_at"
31 + end
32 +
25 create_table "configurations", :force => true do |t|
33 create_table "configurations", :force => true do |t|
26 t.string "key"
34 t.string "key"
27 t.string "value_type"
35 t.string "value_type"
28 t.string "value"
36 t.string "value"
29 t.datetime "created_at"
37 t.datetime "created_at"
30 t.datetime "updated_at"
38 t.datetime "updated_at"
31 t.text "description"
39 t.text "description"
32 end
40 end
33
41
34 create_table "countries", :force => true do |t|
42 create_table "countries", :force => true do |t|
35 t.string "name"
43 t.string "name"
36 t.datetime "created_at"
44 t.datetime "created_at"
37 t.datetime "updated_at"
45 t.datetime "updated_at"
38 end
46 end
39
47
40 create_table "descriptions", :force => true do |t|
48 create_table "descriptions", :force => true do |t|
41 t.text "body"
49 t.text "body"
42 t.boolean "markdowned"
50 t.boolean "markdowned"
43 t.datetime "created_at"
51 t.datetime "created_at"
44 t.datetime "updated_at"
52 t.datetime "updated_at"
45 end
53 end
46
54
47 create_table "grader_processes", :force => true do |t|
55 create_table "grader_processes", :force => true do |t|
48 t.string "host", :limit => 20
56 t.string "host", :limit => 20
49 t.integer "pid"
57 t.integer "pid"
50 t.string "mode"
58 t.string "mode"
51 t.boolean "active"
59 t.boolean "active"
52 t.datetime "created_at"
60 t.datetime "created_at"
53 t.datetime "updated_at"
61 t.datetime "updated_at"
54 t.integer "task_id"
62 t.integer "task_id"
55 t.string "task_type"
63 t.string "task_type"
56 t.boolean "terminated"
64 t.boolean "terminated"
57 end
65 end
58
66
59 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
67 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
60
68
61 create_table "languages", :force => true do |t|
69 create_table "languages", :force => true do |t|
62 t.string "name", :limit => 10
70 t.string "name", :limit => 10
63 t.string "pretty_name"
71 t.string "pretty_name"
64 t.string "ext", :limit => 10
72 t.string "ext", :limit => 10
65 t.string "common_ext"
73 t.string "common_ext"
66 end
74 end
67
75
68 create_table "messages", :force => true do |t|
76 create_table "messages", :force => true do |t|
69 t.integer "sender_id"
77 t.integer "sender_id"
70 t.integer "receiver_id"
78 t.integer "receiver_id"
71 t.integer "replying_message_id"
79 t.integer "replying_message_id"
72 t.text "body"
80 t.text "body"
73 t.boolean "replied"
81 t.boolean "replied"
74 t.datetime "created_at"
82 t.datetime "created_at"
75 t.datetime "updated_at"
83 t.datetime "updated_at"
76 end
84 end
77
85
78 create_table "problems", :force => true do |t|
86 create_table "problems", :force => true do |t|
79 t.string "name", :limit => 30
87 t.string "name", :limit => 30
80 t.string "full_name"
88 t.string "full_name"
81 t.integer "full_score"
89 t.integer "full_score"
82 t.date "date_added"
90 t.date "date_added"
83 t.boolean "available"
91 t.boolean "available"
84 t.string "url"
92 t.string "url"
85 t.integer "description_id"
93 t.integer "description_id"
86 t.boolean "test_allowed"
94 t.boolean "test_allowed"
87 t.boolean "output_only"
95 t.boolean "output_only"
88 end
96 end
89
97
90 create_table "rights", :force => true do |t|
98 create_table "rights", :force => true do |t|
91 t.string "name"
99 t.string "name"
92 t.string "controller"
100 t.string "controller"
93 t.string "action"
101 t.string "action"
94 end
102 end
95
103
96 create_table "rights_roles", :id => false, :force => true do |t|
104 create_table "rights_roles", :id => false, :force => true do |t|
97 t.integer "right_id"
105 t.integer "right_id"
98 t.integer "role_id"
106 t.integer "role_id"
99 end
107 end
100
108
101 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
109 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
102
110
103 create_table "roles", :force => true do |t|
111 create_table "roles", :force => true do |t|
104 t.string "name"
112 t.string "name"
105 end
113 end
106
114
107 create_table "roles_users", :id => false, :force => true do |t|
115 create_table "roles_users", :id => false, :force => true do |t|
108 t.integer "role_id"
116 t.integer "role_id"
109 t.integer "user_id"
117 t.integer "user_id"
110 end
118 end
111
119
112 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
120 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
113
121
114 create_table "sessions", :force => true do |t|
122 create_table "sessions", :force => true do |t|
115 t.string "session_id"
123 t.string "session_id"
116 t.text "data"
124 t.text "data"
117 t.datetime "updated_at"
125 t.datetime "updated_at"
118 end
126 end
119
127
120 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
128 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
121 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
129 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
122
130
123 create_table "sites", :force => true do |t|
131 create_table "sites", :force => true do |t|
124 t.string "name"
132 t.string "name"
125 t.boolean "started"
133 t.boolean "started"
126 t.datetime "start_time"
134 t.datetime "start_time"
127 t.datetime "created_at"
135 t.datetime "created_at"
128 t.datetime "updated_at"
136 t.datetime "updated_at"
129 t.integer "country_id"
137 t.integer "country_id"
130 t.string "password"
138 t.string "password"
131 end
139 end
132
140
133 create_table "submission_statuses", :force => true do |t|
141 create_table "submission_statuses", :force => true do |t|
134 t.integer "user_id"
142 t.integer "user_id"
135 t.integer "problem_id"
143 t.integer "problem_id"
136 t.boolean "passed"
144 t.boolean "passed"
137 t.integer "submission_count"
145 t.integer "submission_count"
138 t.datetime "created_at"
146 t.datetime "created_at"
139 t.datetime "updated_at"
147 t.datetime "updated_at"
140 end
148 end
141
149
142 create_table "submissions", :force => true do |t|
150 create_table "submissions", :force => true do |t|
143 t.integer "user_id"
151 t.integer "user_id"
144 t.integer "problem_id"
152 t.integer "problem_id"
145 t.integer "language_id"
153 t.integer "language_id"
146 t.text "source"
154 t.text "source"
147 t.binary "binary"
155 t.binary "binary"
148 t.datetime "submitted_at"
156 t.datetime "submitted_at"
149 t.datetime "compiled_at"
157 t.datetime "compiled_at"
150 t.text "compiler_message"
158 t.text "compiler_message"
151 t.datetime "graded_at"
159 t.datetime "graded_at"
152 t.integer "points"
160 t.integer "points"
153 t.text "grader_comment"
161 t.text "grader_comment"
154 t.integer "number"
162 t.integer "number"
155 t.string "source_filename"
163 t.string "source_filename"
156 end
164 end
157
165
158 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
166 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
159 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
167 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
160
168
161 create_table "tasks", :force => true do |t|
169 create_table "tasks", :force => true do |t|
162 t.integer "submission_id"
170 t.integer "submission_id"
163 t.datetime "created_at"
171 t.datetime "created_at"
164 t.integer "status"
172 t.integer "status"
165 t.datetime "updated_at"
173 t.datetime "updated_at"
166 end
174 end
167
175
168 create_table "test_pair_assignments", :force => true do |t|
176 create_table "test_pair_assignments", :force => true do |t|
169 t.integer "user_id"
177 t.integer "user_id"
170 t.integer "problem_id"
178 t.integer "problem_id"
171 t.integer "test_pair_id"
179 t.integer "test_pair_id"
172 t.integer "test_pair_number"
180 t.integer "test_pair_number"
173 t.integer "request_number"
181 t.integer "request_number"
174 t.datetime "created_at"
182 t.datetime "created_at"
175 t.datetime "updated_at"
183 t.datetime "updated_at"
176 t.boolean "submitted"
184 t.boolean "submitted"
177 end
185 end
178
186
179 create_table "test_pairs", :force => true do |t|
187 create_table "test_pairs", :force => true do |t|
180 t.integer "problem_id"
188 t.integer "problem_id"
181 t.text "input"
189 t.text "input"
182 t.text "solution"
190 t.text "solution"
183 t.datetime "created_at"
191 t.datetime "created_at"
184 t.datetime "updated_at"
192 t.datetime "updated_at"
185 t.integer "number"
193 t.integer "number"
186 end
194 end
187
195
188 create_table "test_requests", :force => true do |t|
196 create_table "test_requests", :force => true do |t|
189 t.integer "user_id"
197 t.integer "user_id"
190 t.integer "problem_id"
198 t.integer "problem_id"
191 t.integer "submission_id"
199 t.integer "submission_id"
192 t.string "input_file_name"
200 t.string "input_file_name"
193 t.string "output_file_name"
201 t.string "output_file_name"
194 t.string "running_stat"
202 t.string "running_stat"
195 t.integer "status"
203 t.integer "status"
196 t.datetime "updated_at"
204 t.datetime "updated_at"
197 t.datetime "submitted_at"
205 t.datetime "submitted_at"
198 t.datetime "compiled_at"
206 t.datetime "compiled_at"
199 t.text "compiler_message"
207 t.text "compiler_message"
200 t.datetime "graded_at"
208 t.datetime "graded_at"
201 t.string "grader_comment"
209 t.string "grader_comment"
202 t.datetime "created_at"
210 t.datetime "created_at"
203 t.float "running_time"
211 t.float "running_time"
204 t.string "exit_status"
212 t.string "exit_status"
205 t.integer "memory_usage"
213 t.integer "memory_usage"
206 end
214 end
207
215
208 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
216 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
209
217
210 create_table "user_contest_stats", :force => true do |t|
218 create_table "user_contest_stats", :force => true do |t|
211 t.integer "user_id"
219 t.integer "user_id"
212 t.datetime "started_at"
220 t.datetime "started_at"
213 t.datetime "created_at"
221 t.datetime "created_at"
214 t.datetime "updated_at"
222 t.datetime "updated_at"
215 end
223 end
216
224
You need to be logged in to leave comments. Login now