Description:
added submission_status to store grading results, first page shows only unpassed problems.
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r216:fa11dca6b078 - - 10 files changed: 131 inserted, 56 deleted

@@ -0,0 +1,6
1 + class SubmissionStatus < ActiveRecord::Base
2 +
3 + belongs_to :user
4 + belongs_to :problem
5 +
6 + end
@@ -0,0 +1,18
1 + .problem-panel{:id => "problem-panel-#{problem.id}", :style => "display:none"}
2 + .problem-form{:id => "problem-form-#{problem.id}"}
3 + - form_tag({ :action => 'download_input', :id => problem.id }, :method => :post) do
4 + %b Input:
5 + %input{:type => "submit", :value => "Download input"}
6 + - form_tag({ :action => 'submit_solution', :id => problem.id }, :method => :post, :multipart => true) do
7 + %b Submit output:
8 + %input{:type => "file", :name => "file"}
9 + %input{:type => "submit", :value => "Submit solution"}
10 +
11 + .problem-description
12 + - if problem.description!=nil
13 + - if problem.description.markdowned
14 + = markdown(problem.description.body)
15 + - else
16 + = problem.description.body
17 + - else
18 + (not available)
@@ -0,0 +1,16
1 + class CreateSubmissionStatuses < ActiveRecord::Migration
2 + def self.up
3 + create_table :submission_statuses do |t|
4 + t.integer :user_id
5 + t.integer :problem_id
6 + t.boolean :passed
7 + t.integer :submission_count
8 +
9 + t.timestamps
10 + end
11 + end
12 +
13 + def self.down
14 + drop_table :submission_statuses
15 + end
16 + end
@@ -0,0 +1,13
1 + # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 +
3 + one:
4 + user_id: 1
5 + problem_id: 1
6 + passed: false
7 + submission_count: 1
8 +
9 + two:
10 + user_id: 1
11 + problem_id: 1
12 + passed: false
13 + submission_count: 1
@@ -0,0 +1,8
1 + require 'test_helper'
2 +
3 + class SubmissionStatusTest < ActiveSupport::TestCase
4 + # Replace this with your real tests.
5 + test "the truth" do
6 + assert true
7 + end
8 + end
@@ -1,361 +1,383
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 SYSTEM_MODE_CONF_KEY = 'system.mode'
3 SYSTEM_MODE_CONF_KEY = 'system.mode'
4
4
5 before_filter :authenticate, :except => [:index, :login]
5 before_filter :authenticate, :except => [:index, :login]
6 before_filter :check_viewability, :except => [:index, :login]
6 before_filter :check_viewability, :except => [:index, :login]
7
7
8 # COMMENTED OUT: filter in each action instead
8 # COMMENTED OUT: filter in each action instead
9 # before_filter :verify_time_limit, :only => [:submit]
9 # before_filter :verify_time_limit, :only => [:submit]
10
10
11 - verify :method => :post, :only => [:submit, :new_input, :download_input, :submit_solution],
11 + verify :method => :post, :only => [:submit, :download_input, :submit_solution],
12 :redirect_to => { :action => :index }
12 :redirect_to => { :action => :index }
13
13
14 # COMMENT OUT: only need when having high load
14 # COMMENT OUT: only need when having high load
15 # caches_action :index, :login
15 # caches_action :index, :login
16
16
17 # NOTE: This method is not actually needed, 'config/routes.rb' has
17 # NOTE: This method is not actually needed, 'config/routes.rb' has
18 # assigned action login as a default action.
18 # assigned action login as a default action.
19 def index
19 def index
20 redirect_to :action => 'login'
20 redirect_to :action => 'login'
21 end
21 end
22
22
23 def login
23 def login
24 saved_notice = flash[:notice]
24 saved_notice = flash[:notice]
25 reset_session
25 reset_session
26 flash[:notice] = saved_notice
26 flash[:notice] = saved_notice
27
27
28 # EXPERIMENT:
28 # EXPERIMENT:
29 # Hide login if in single user mode and the url does not
29 # Hide login if in single user mode and the url does not
30 # explicitly specify /login
30 # explicitly specify /login
31 #
31 #
32 # logger.info "PATH: #{request.path}"
32 # logger.info "PATH: #{request.path}"
33 # if Configuration['system.single_user_mode'] and
33 # if Configuration['system.single_user_mode'] and
34 # request.path!='/main/login'
34 # request.path!='/main/login'
35 # @hidelogin = true
35 # @hidelogin = true
36 # end
36 # end
37
37
38 @announcements = Announcement.find_for_frontpage
38 @announcements = Announcement.find_for_frontpage
39 render :action => 'login', :layout => 'empty'
39 render :action => 'login', :layout => 'empty'
40 end
40 end
41
41
42 def list
42 def list
43 prepare_list_information
43 prepare_list_information
44 end
44 end
45
45
46 def help
46 def help
47 @user = User.find(session[:user_id])
47 @user = User.find(session[:user_id])
48 end
48 end
49
49
50 def submit
50 def submit
51 user = User.find(session[:user_id])
51 user = User.find(session[:user_id])
52
52
53 @submission = Submission.new(params[:submission])
53 @submission = Submission.new(params[:submission])
54 @submission.user = user
54 @submission.user = user
55 @submission.language_id = 0
55 @submission.language_id = 0
56 if (params['file']) and (params['file']!='')
56 if (params['file']) and (params['file']!='')
57 @submission.source = params['file'].read
57 @submission.source = params['file'].read
58 @submission.source_filename = params['file'].original_filename
58 @submission.source_filename = params['file'].original_filename
59 end
59 end
60 @submission.submitted_at = Time.new.gmtime
60 @submission.submitted_at = Time.new.gmtime
61
61
62 if Configuration[SYSTEM_MODE_CONF_KEY]=='contest' and
62 if Configuration[SYSTEM_MODE_CONF_KEY]=='contest' and
63 user.site!=nil and user.site.finished?
63 user.site!=nil and user.site.finished?
64 @submission.errors.add_to_base "The contest is over."
64 @submission.errors.add_to_base "The contest is over."
65 prepare_list_information
65 prepare_list_information
66 render :action => 'list' and return
66 render :action => 'list' and return
67 end
67 end
68
68
69 if @submission.valid?
69 if @submission.valid?
70 if @submission.save == false
70 if @submission.save == false
71 flash[:notice] = 'Error saving your submission'
71 flash[:notice] = 'Error saving your submission'
72 elsif Task.create(:submission_id => @submission.id,
72 elsif Task.create(:submission_id => @submission.id,
73 :status => Task::STATUS_INQUEUE) == false
73 :status => Task::STATUS_INQUEUE) == false
74 flash[:notice] = 'Error adding your submission to task queue'
74 flash[:notice] = 'Error adding your submission to task queue'
75 end
75 end
76 else
76 else
77 prepare_list_information
77 prepare_list_information
78 render :action => 'list' and return
78 render :action => 'list' and return
79 end
79 end
80 redirect_to :action => 'list'
80 redirect_to :action => 'list'
81 end
81 end
82
82
83 def source
83 def source
84 submission = Submission.find(params[:id])
84 submission = Submission.find(params[:id])
85 if submission.user_id == session[:user_id]
85 if submission.user_id == session[:user_id]
86 send_data(submission.source,
86 send_data(submission.source,
87 {:filename => submission.download_filename,
87 {:filename => submission.download_filename,
88 :type => 'text/plain'})
88 :type => 'text/plain'})
89 else
89 else
90 flash[:notice] = 'Error viewing source'
90 flash[:notice] = 'Error viewing source'
91 redirect_to :action => 'list'
91 redirect_to :action => 'list'
92 end
92 end
93 end
93 end
94
94
95 def compiler_msg
95 def compiler_msg
96 @submission = Submission.find(params[:id])
96 @submission = Submission.find(params[:id])
97 if @submission.user_id == session[:user_id]
97 if @submission.user_id == session[:user_id]
98 render :action => 'compiler_msg', :layout => 'empty'
98 render :action => 'compiler_msg', :layout => 'empty'
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 submission
105 def submission
106 @user = User.find(session[:user_id])
106 @user = User.find(session[:user_id])
107 @problems = Problem.find_available_problems
107 @problems = Problem.find_available_problems
108 if params[:id]==nil
108 if params[:id]==nil
109 @problem = nil
109 @problem = nil
110 @submissions = nil
110 @submissions = nil
111 else
111 else
112 @problem = Problem.find_by_name(params[:id])
112 @problem = Problem.find_by_name(params[:id])
113 if not @problem.available
113 if not @problem.available
114 redirect_to :action => 'list'
114 redirect_to :action => 'list'
115 flash[:notice] = 'Error: submissions for that problem are not viewable.'
115 flash[:notice] = 'Error: submissions for that problem are not viewable.'
116 return
116 return
117 end
117 end
118 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
118 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
119 end
119 end
120 end
120 end
121
121
122 def result
122 def result
123 if !Configuration.show_grading_result
123 if !Configuration.show_grading_result
124 redirect_to :action => 'list' and return
124 redirect_to :action => 'list' and return
125 end
125 end
126 @user = User.find(session[:user_id])
126 @user = User.find(session[:user_id])
127 @submission = Submission.find(params[:id])
127 @submission = Submission.find(params[:id])
128 if @submission.user!=@user
128 if @submission.user!=@user
129 flash[:notice] = 'You are not allowed to view result of other users.'
129 flash[:notice] = 'You are not allowed to view result of other users.'
130 redirect_to :action => 'list' and return
130 redirect_to :action => 'list' and return
131 end
131 end
132 prepare_grading_result(@submission)
132 prepare_grading_result(@submission)
133 end
133 end
134
134
135 def load_output
135 def load_output
136 if !Configuration.show_grading_result or params[:num]==nil
136 if !Configuration.show_grading_result or params[:num]==nil
137 redirect_to :action => 'list' and return
137 redirect_to :action => 'list' and return
138 end
138 end
139 @user = User.find(session[:user_id])
139 @user = User.find(session[:user_id])
140 @submission = Submission.find(params[:id])
140 @submission = Submission.find(params[:id])
141 if @submission.user!=@user
141 if @submission.user!=@user
142 flash[:notice] = 'You are not allowed to view result of other users.'
142 flash[:notice] = 'You are not allowed to view result of other users.'
143 redirect_to :action => 'list' and return
143 redirect_to :action => 'list' and return
144 end
144 end
145 case_num = params[:num].to_i
145 case_num = params[:num].to_i
146 out_filename = output_filename(@user.login,
146 out_filename = output_filename(@user.login,
147 @submission.problem.name,
147 @submission.problem.name,
148 @submission.id,
148 @submission.id,
149 case_num)
149 case_num)
150 if !FileTest.exists?(out_filename)
150 if !FileTest.exists?(out_filename)
151 flash[:notice] = 'Output not found.'
151 flash[:notice] = 'Output not found.'
152 redirect_to :action => 'list' and return
152 redirect_to :action => 'list' and return
153 end
153 end
154
154
155 response.headers['Content-Type'] = "application/force-download"
155 response.headers['Content-Type'] = "application/force-download"
156 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
156 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
157 response.headers["X-Sendfile"] = out_filename
157 response.headers["X-Sendfile"] = out_filename
158 response.headers['Content-length'] = File.size(out_filename)
158 response.headers['Content-length'] = File.size(out_filename)
159 render :nothing => true
159 render :nothing => true
160 end
160 end
161
161
162 def error
162 def error
163 @user = User.find(session[:user_id])
163 @user = User.find(session[:user_id])
164 end
164 end
165
165
166 # announcement refreshing and hiding methods
166 # announcement refreshing and hiding methods
167
167
168 def announcements
168 def announcements
169 if params.has_key? 'recent'
169 if params.has_key? 'recent'
170 prepare_announcements(params[:recent])
170 prepare_announcements(params[:recent])
171 else
171 else
172 prepare_announcements
172 prepare_announcements
173 end
173 end
174 render(:partial => 'announcement',
174 render(:partial => 'announcement',
175 :collection => @announcements,
175 :collection => @announcements,
176 :locals => {:announcement_effect => true})
176 :locals => {:announcement_effect => true})
177 end
177 end
178
178
179 + #
179 # actions for Code Jom
180 # actions for Code Jom
180 - def new_input
181 + #
182 + def download_input
181 problem = Problem.find(params[:id])
183 problem = Problem.find(params[:id])
182 user = User.find(session[:user_id])
184 user = User.find(session[:user_id])
183 if user.can_request_new_test_pair_for? problem
185 if user.can_request_new_test_pair_for? problem
184 assignment = user.get_new_test_pair_assignment_for problem
186 assignment = user.get_new_test_pair_assignment_for problem
185 assignment.save
187 assignment.save
186
188
187 send_data(assignment.test_pair.input,
189 send_data(assignment.test_pair.input,
188 { :filename => "#{problem.name}-#{assignment.request_number}.in",
190 { :filename => "#{problem.name}-#{assignment.request_number}.in",
189 :type => 'text/plain' })
191 :type => 'text/plain' })
190 else
192 else
191 - flash[:notice] = 'You cannot request new input now.'
192 - redirect_to :action => 'list'
193 - end
194 - end
195 -
196 - def download_input
197 - problem = Problem.find(params[:id])
198 - user = User.find(session[:user_id])
199 recent_assignment = user.get_recent_test_pair_assignment_for problem
193 recent_assignment = user.get_recent_test_pair_assignment_for problem
200 - if recent_assignment != nil
201 send_data(recent_assignment.test_pair.input,
194 send_data(recent_assignment.test_pair.input,
202 { :filename => "#{problem.name}-#{recent_assignment.request_number}.in",
195 { :filename => "#{problem.name}-#{recent_assignment.request_number}.in",
203 :type => 'text/plain' })
196 :type => 'text/plain' })
204 - else
205 - flash[:notice] = 'You have not requested for any input data for this problem.'
206 - redirect_to :action => 'list'
207 end
197 end
208 end
198 end
209
199
210 def submit_solution
200 def submit_solution
211 problem = Problem.find(params[:id])
201 problem = Problem.find(params[:id])
212 user = User.find(session[:user_id])
202 user = User.find(session[:user_id])
213 recent_assignment = user.get_recent_test_pair_assignment_for problem
203 recent_assignment = user.get_recent_test_pair_assignment_for problem
214 - if recent_assignment != nil
204 + if recent_assignment == nil
205 + flash[:notice] = 'You have not requested for any input data for this problem. Please download an input first.'
206 + redirect_to :action => 'list' and return
207 + end
208 +
209 + if recent_assignment.submitted
210 + flash[:notice] = 'You have already submitted an incorrect solution for this input. Please download a new input data.'
211 + redirect_to :action => 'list' and return
212 + end
213 +
214 + if params[:file] == nil
215 + flash[:notice] = 'You have not submitted any output.'
216 + redirect_to :action => 'list' and return
217 + end
218 +
215 submitted_solution = params[:file].read
219 submitted_solution = params[:file].read
216 test_pair = recent_assignment.test_pair
220 test_pair = recent_assignment.test_pair
217 passed = test_pair.grade(submitted_solution)
221 passed = test_pair.grade(submitted_solution)
218 points = passed ? 100 : 0
222 points = passed ? 100 : 0
219 submission = Submission.new(:user => user,
223 submission = Submission.new(:user => user,
220 :problem => problem,
224 :problem => problem,
221 - :source => params[:file].read,
225 + :source => submitted_solution,
222 :source_filename => params['file'].original_filename,
226 :source_filename => params['file'].original_filename,
223 :language_id => 0,
227 :language_id => 0,
224 :submitted_at => Time.new.gmtime,
228 :submitted_at => Time.new.gmtime,
225 :graded_at => Time.new.gmtime,
229 :graded_at => Time.new.gmtime,
226 :points => points)
230 :points => points)
227 submission.save
231 submission.save
228 recent_assignment.submitted = true
232 recent_assignment.submitted = true
229 recent_assignment.save
233 recent_assignment.save
234 +
235 + status = user.get_submission_status_for(problem)
236 + if status == nil
237 + status = SubmissionStatus.new :user => user, :problem => problem, :submission_count => 0
238 + end
239 +
240 + status.submission_count += 1
241 + status.passed = passed
242 + status.save
243 +
230 if passed
244 if passed
231 - flash[:notice] = 'Correct solution'
245 + flash[:notice] = 'Correct solution.'
232 else
246 else
233 - flash[:notice] = 'Incorrect solution'
247 + flash[:notice] = 'Incorrect solution.'
234 end
248 end
235 redirect_to :action => 'list'
249 redirect_to :action => 'list'
236 - else
237 - flash[:notice] = 'You have not requested for any input data for this problem.'
238 - redirect_to :action => 'list'
239 - end
240 end
250 end
241
251
242 protected
252 protected
243
253
244 def prepare_announcements(recent=nil)
254 def prepare_announcements(recent=nil)
245 if Configuration.show_tasks_to?(@user)
255 if Configuration.show_tasks_to?(@user)
246 @announcements = Announcement.find_published(true)
256 @announcements = Announcement.find_published(true)
247 else
257 else
248 @announcements = Announcement.find_published
258 @announcements = Announcement.find_published
249 end
259 end
250 if recent!=nil
260 if recent!=nil
251 recent_id = recent.to_i
261 recent_id = recent.to_i
252 @announcements = @announcements.find_all { |a| a.id > recent_id }
262 @announcements = @announcements.find_all { |a| a.id > recent_id }
253 end
263 end
254 end
264 end
255
265
256 def prepare_list_information
266 def prepare_list_information
257 - @problems = Problem.find_available_problems
267 + @user = User.find(session[:user_id])
268 +
269 + all_problems = Problem.find_available_problems
270 +
271 + passed = {}
272 + sub_count = {}
273 + @user.submission_statuses.each do |status|
274 + if status.passed
275 + passed[status.problem_id] = true
276 + end
277 + sub_count[status.problem_id] = status.submission_count
278 + end
279 +
280 + @problems = all_problems.reject { |problem| passed.has_key? problem.id }
281 +
258 @prob_submissions = Array.new
282 @prob_submissions = Array.new
259 - @user = User.find(session[:user_id])
260 @problems.each do |p|
283 @problems.each do |p|
261 - sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
284 + if sub_count.has_key? p.id
262 - if sub!=nil
285 + @prob_submissions << { :count => sub_count[p.id] }
263 - @prob_submissions << { :count => sub.number, :submission => sub }
264 else
286 else
265 - @prob_submissions << { :count => 0, :submission => nil }
287 + @prob_submissions << { :count => 0 }
266 end
288 end
267 end
289 end
268 prepare_announcements
290 prepare_announcements
269 end
291 end
270
292
271 def check_viewability
293 def check_viewability
272 @user = User.find(session[:user_id])
294 @user = User.find(session[:user_id])
273 if (!Configuration.show_tasks_to?(@user)) and
295 if (!Configuration.show_tasks_to?(@user)) and
274 ((action_name=='submission') or (action_name=='submit'))
296 ((action_name=='submission') or (action_name=='submit'))
275 redirect_to :action => 'list' and return
297 redirect_to :action => 'list' and return
276 end
298 end
277 end
299 end
278
300
279 def prepare_grading_result(submission)
301 def prepare_grading_result(submission)
280 if Configuration.task_grading_info.has_key? submission.problem.name
302 if Configuration.task_grading_info.has_key? submission.problem.name
281 grading_info = Configuration.task_grading_info[submission.problem.name]
303 grading_info = Configuration.task_grading_info[submission.problem.name]
282 else
304 else
283 # guess task info from problem.full_score
305 # guess task info from problem.full_score
284 cases = submission.problem.full_score / 10
306 cases = submission.problem.full_score / 10
285 grading_info = {
307 grading_info = {
286 'testruns' => cases,
308 'testruns' => cases,
287 'testcases' => cases
309 'testcases' => cases
288 }
310 }
289 end
311 end
290 @test_runs = []
312 @test_runs = []
291 if grading_info['testruns'].is_a? Integer
313 if grading_info['testruns'].is_a? Integer
292 trun_count = grading_info['testruns']
314 trun_count = grading_info['testruns']
293 trun_count.times do |i|
315 trun_count.times do |i|
294 @test_runs << [ read_grading_result(@user.login,
316 @test_runs << [ read_grading_result(@user.login,
295 submission.problem.name,
317 submission.problem.name,
296 submission.id,
318 submission.id,
297 i+1) ]
319 i+1) ]
298 end
320 end
299 else
321 else
300 grading_info['testruns'].keys.sort.each do |num|
322 grading_info['testruns'].keys.sort.each do |num|
301 run = []
323 run = []
302 testrun = grading_info['testruns'][num]
324 testrun = grading_info['testruns'][num]
303 testrun.each do |c|
325 testrun.each do |c|
304 run << read_grading_result(@user.login,
326 run << read_grading_result(@user.login,
305 submission.problem.name,
327 submission.problem.name,
306 submission.id,
328 submission.id,
307 c)
329 c)
308 end
330 end
309 @test_runs << run
331 @test_runs << run
310 end
332 end
311 end
333 end
312 end
334 end
313
335
314 def grading_result_dir(user_name, problem_name, submission_id, case_num)
336 def grading_result_dir(user_name, problem_name, submission_id, case_num)
315 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
337 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
316 end
338 end
317
339
318 def output_filename(user_name, problem_name, submission_id, case_num)
340 def output_filename(user_name, problem_name, submission_id, case_num)
319 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
341 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
320 return "#{dir}/output.txt"
342 return "#{dir}/output.txt"
321 end
343 end
322
344
323 def read_grading_result(user_name, problem_name, submission_id, case_num)
345 def read_grading_result(user_name, problem_name, submission_id, case_num)
324 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
346 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
325 result_file_name = "#{dir}/result"
347 result_file_name = "#{dir}/result"
326 if !FileTest.exists?(result_file_name)
348 if !FileTest.exists?(result_file_name)
327 return {:num => case_num, :msg => 'program did not run'}
349 return {:num => case_num, :msg => 'program did not run'}
328 else
350 else
329 results = File.open(result_file_name).readlines
351 results = File.open(result_file_name).readlines
330 run_stat = extract_running_stat(results)
352 run_stat = extract_running_stat(results)
331 output_filename = "#{dir}/output.txt"
353 output_filename = "#{dir}/output.txt"
332 if FileTest.exists?(output_filename)
354 if FileTest.exists?(output_filename)
333 output_file = true
355 output_file = true
334 output_size = File.size(output_filename)
356 output_size = File.size(output_filename)
335 else
357 else
336 output_file = false
358 output_file = false
337 output_size = 0
359 output_size = 0
338 end
360 end
339
361
340 return {
362 return {
341 :num => case_num,
363 :num => case_num,
342 :msg => results[0],
364 :msg => results[0],
343 :run_stat => run_stat,
365 :run_stat => run_stat,
344 :output => output_file,
366 :output => output_file,
345 :output_size => output_size
367 :output_size => output_size
346 }
368 }
347 end
369 end
348 end
370 end
349
371
350 # copied from grader/script/lib/test_request_helper.rb
372 # copied from grader/script/lib/test_request_helper.rb
351 def extract_running_stat(results)
373 def extract_running_stat(results)
352 running_stat_line = results[-1]
374 running_stat_line = results[-1]
353
375
354 # extract exit status line
376 # extract exit status line
355 run_stat = ""
377 run_stat = ""
356 if !(/[Cc]orrect/.match(results[0]))
378 if !(/[Cc]orrect/.match(results[0]))
357 run_stat = results[0].chomp
379 run_stat = results[0].chomp
358 else
380 else
359 run_stat = 'Program exited normally'
381 run_stat = 'Program exited normally'
360 end
382 end
361
383
@@ -1,110 +1,110
1 class Submission < ActiveRecord::Base
1 class Submission < ActiveRecord::Base
2
2
3 belongs_to :language
3 belongs_to :language
4 belongs_to :problem
4 belongs_to :problem
5 belongs_to :user
5 belongs_to :user
6
6
7 before_validation :assign_problem
7 before_validation :assign_problem
8 before_validation :assign_language
8 before_validation :assign_language
9
9
10 validates_presence_of :source
10 validates_presence_of :source
11 validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long'
11 validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long'
12 validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short'
12 validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short'
13 validate :must_have_valid_problem
13 validate :must_have_valid_problem
14 - validate :must_specify_language
14 + #validate :must_specify_language
15
15
16 before_save :assign_latest_number_if_new_recond
16 before_save :assign_latest_number_if_new_recond
17
17
18 def self.find_last_by_user_and_problem(user_id, problem_id)
18 def self.find_last_by_user_and_problem(user_id, problem_id)
19 last_sub = find(:first,
19 last_sub = find(:first,
20 :conditions => {:user_id => user_id,
20 :conditions => {:user_id => user_id,
21 :problem_id => problem_id},
21 :problem_id => problem_id},
22 :order => 'number DESC')
22 :order => 'number DESC')
23 return last_sub
23 return last_sub
24 end
24 end
25
25
26 def self.find_all_last_by_problem(problem_id)
26 def self.find_all_last_by_problem(problem_id)
27 # need to put in SQL command, maybe there's a better way
27 # need to put in SQL command, maybe there's a better way
28 Submission.find_by_sql("SELECT * FROM submissions " +
28 Submission.find_by_sql("SELECT * FROM submissions " +
29 "WHERE id = " +
29 "WHERE id = " +
30 "(SELECT MAX(id) FROM submissions AS subs " +
30 "(SELECT MAX(id) FROM submissions AS subs " +
31 "WHERE subs.user_id = submissions.user_id AND " +
31 "WHERE subs.user_id = submissions.user_id AND " +
32 "problem_id = " + problem_id.to_s + " " +
32 "problem_id = " + problem_id.to_s + " " +
33 "GROUP BY user_id) " +
33 "GROUP BY user_id) " +
34 "ORDER BY user_id")
34 "ORDER BY user_id")
35 end
35 end
36
36
37 def self.find_last_for_all_available_problems(user_id)
37 def self.find_last_for_all_available_problems(user_id)
38 submissions = Array.new
38 submissions = Array.new
39 problems = Problem.find_available_problems
39 problems = Problem.find_available_problems
40 problems.each do |problem|
40 problems.each do |problem|
41 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
41 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
42 submissions << sub if sub!=nil
42 submissions << sub if sub!=nil
43 end
43 end
44 submissions
44 submissions
45 end
45 end
46
46
47 def self.find_by_user_problem_number(user_id, problem_id, number)
47 def self.find_by_user_problem_number(user_id, problem_id, number)
48 Submission.find(:first,
48 Submission.find(:first,
49 :conditions => {
49 :conditions => {
50 :user_id => user_id,
50 :user_id => user_id,
51 :problem_id => problem_id,
51 :problem_id => problem_id,
52 :number => number
52 :number => number
53 })
53 })
54 end
54 end
55
55
56 def self.find_all_by_user_problem(user_id, problem_id)
56 def self.find_all_by_user_problem(user_id, problem_id)
57 Submission.find(:all,
57 Submission.find(:all,
58 :conditions => {
58 :conditions => {
59 :user_id => user_id,
59 :user_id => user_id,
60 :problem_id => problem_id,
60 :problem_id => problem_id,
61 })
61 })
62 end
62 end
63
63
64 def download_filename
64 def download_filename
65 if self.problem.output_only
65 if self.problem.output_only
66 return self.source_filename
66 return self.source_filename
67 else
67 else
68 timestamp = self.submitted_at.localtime.strftime("%H%M%S")
68 timestamp = self.submitted_at.localtime.strftime("%H%M%S")
69 return "#{self.problem.name}-#{timestamp}.#{self.language.ext}"
69 return "#{self.problem.name}-#{timestamp}.#{self.language.ext}"
70 end
70 end
71 end
71 end
72
72
73 protected
73 protected
74
74
75 def self.find_option_in_source(option, source)
75 def self.find_option_in_source(option, source)
76 if source==nil
76 if source==nil
77 return nil
77 return nil
78 end
78 end
79 i = 0
79 i = 0
80 source.each_line do |s|
80 source.each_line do |s|
81 if s =~ option
81 if s =~ option
82 words = s.split
82 words = s.split
83 return words[1]
83 return words[1]
84 end
84 end
85 i = i + 1
85 i = i + 1
86 if i==10
86 if i==10
87 return nil
87 return nil
88 end
88 end
89 end
89 end
90 return nil
90 return nil
91 end
91 end
92
92
93 def self.find_language_in_source(source, source_filename="")
93 def self.find_language_in_source(source, source_filename="")
94 langopt = find_option_in_source(/^LANG:/,source)
94 langopt = find_option_in_source(/^LANG:/,source)
95 if langopt
95 if langopt
96 return (Language.find_by_name(langopt) ||
96 return (Language.find_by_name(langopt) ||
97 Language.find_by_pretty_name(langopt))
97 Language.find_by_pretty_name(langopt))
98 else
98 else
99 if source_filename
99 if source_filename
100 return Language.find_by_extension(source_filename.split('.').last)
100 return Language.find_by_extension(source_filename.split('.').last)
101 else
101 else
102 return nil
102 return nil
103 end
103 end
104 end
104 end
105 end
105 end
106
106
107 def self.find_problem_in_source(source, source_filename="")
107 def self.find_problem_in_source(source, source_filename="")
108 prob_opt = find_option_in_source(/^TASK:/,source)
108 prob_opt = find_option_in_source(/^TASK:/,source)
109 if problem = Problem.find_by_name(prob_opt)
109 if problem = Problem.find_by_name(prob_opt)
110 return problem
110 return problem
@@ -1,209 +1,218
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
21
21 belongs_to :site
22 belongs_to :site
22 belongs_to :country
23 belongs_to :country
23
24
24 named_scope :activated_users, :conditions => {:activated => true}
25 named_scope :activated_users, :conditions => {:activated => true}
25
26
26 validates_presence_of :login
27 validates_presence_of :login
27 validates_uniqueness_of :login
28 validates_uniqueness_of :login
28 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
29 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
29 validates_length_of :login, :within => 3..30
30 validates_length_of :login, :within => 3..30
30
31
31 validates_presence_of :full_name
32 validates_presence_of :full_name
32 validates_length_of :full_name, :minimum => 1
33 validates_length_of :full_name, :minimum => 1
33
34
34 validates_presence_of :password, :if => :password_required?
35 validates_presence_of :password, :if => :password_required?
35 validates_length_of :password, :within => 4..20, :if => :password_required?
36 validates_length_of :password, :within => 4..20, :if => :password_required?
36 validates_confirmation_of :password, :if => :password_required?
37 validates_confirmation_of :password, :if => :password_required?
37
38
38 validates_format_of :email,
39 validates_format_of :email,
39 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
40 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
40 :if => :email_validation?
41 :if => :email_validation?
41 validate :uniqueness_of_email_from_activated_users,
42 validate :uniqueness_of_email_from_activated_users,
42 :if => :email_validation?
43 :if => :email_validation?
43 validate :enough_time_interval_between_same_email_registrations,
44 validate :enough_time_interval_between_same_email_registrations,
44 :if => :email_validation?
45 :if => :email_validation?
45
46
46 # these are for ytopc
47 # these are for ytopc
47 # disable for now
48 # disable for now
48 #validates_presence_of :province
49 #validates_presence_of :province
49
50
50 attr_accessor :password
51 attr_accessor :password
51
52
52 before_save :encrypt_new_password
53 before_save :encrypt_new_password
53 before_save :assign_default_site
54 before_save :assign_default_site
54
55
55 def self.authenticate(login, password)
56 def self.authenticate(login, password)
56 user = find_by_login(login)
57 user = find_by_login(login)
57 return user if user && user.authenticated?(password)
58 return user if user && user.authenticated?(password)
58 end
59 end
59
60
60 def authenticated?(password)
61 def authenticated?(password)
61 if self.activated
62 if self.activated
62 hashed_password == User.encrypt(password,self.salt)
63 hashed_password == User.encrypt(password,self.salt)
63 else
64 else
64 false
65 false
65 end
66 end
66 end
67 end
67
68
68 def admin?
69 def admin?
69 self.roles.detect {|r| r.name == 'admin' }
70 self.roles.detect {|r| r.name == 'admin' }
70 end
71 end
71
72
72 # These are methods related to test pairs
73 # These are methods related to test pairs
73
74
74 def get_test_pair_assignments_for(problem)
75 def get_test_pair_assignments_for(problem)
75 test_pair_assignments.find_all { |a| a.problem_id == problem.id }
76 test_pair_assignments.find_all { |a| a.problem_id == problem.id }
76 end
77 end
77
78
78 def get_recent_test_pair_assignment_for(problem)
79 def get_recent_test_pair_assignment_for(problem)
79 assignments = get_test_pair_assignments_for problem
80 assignments = get_test_pair_assignments_for problem
80 if assignments.length == 0
81 if assignments.length == 0
81 return nil
82 return nil
82 else
83 else
83 recent = assignments[0]
84 recent = assignments[0]
84 assignments.each do |a|
85 assignments.each do |a|
85 recent = a if a.request_number > recent.request_number
86 recent = a if a.request_number > recent.request_number
86 end
87 end
87 return recent
88 return recent
88 end
89 end
89 end
90 end
90
91
91 def can_request_new_test_pair_for?(problem)
92 def can_request_new_test_pair_for?(problem)
92 recent = get_recent_test_pair_assignment_for problem
93 recent = get_recent_test_pair_assignment_for problem
93 return (recent == nil or recent.submitted)
94 return (recent == nil or recent.submitted)
94 end
95 end
95
96
96 def get_new_test_pair_assignment_for(problem)
97 def get_new_test_pair_assignment_for(problem)
97 previous_assignment_numbers =
98 previous_assignment_numbers =
98 get_test_pair_assignments_for(problem).collect {|a| a.test_pair_number }
99 get_test_pair_assignments_for(problem).collect {|a| a.test_pair_number }
99 test_pair = problem.random_test_pair(previous_assignment_numbers)
100 test_pair = problem.random_test_pair(previous_assignment_numbers)
100 if test_pair
101 if test_pair
101 assignment = TestPairAssignment.new(:user => self,
102 assignment = TestPairAssignment.new(:user => self,
102 :problem => problem,
103 :problem => problem,
103 :test_pair => test_pair,
104 :test_pair => test_pair,
104 :test_pair_number => test_pair.number,
105 :test_pair_number => test_pair.number,
105 :request_number =>
106 :request_number =>
106 previous_assignment_numbers.length + 1,
107 previous_assignment_numbers.length + 1,
107 :submitted => false)
108 :submitted => false)
108 return assignment
109 return assignment
109 else
110 else
110 return nil
111 return nil
111 end
112 end
112 end
113 end
113
114
115 + def get_submission_status_for(problem)
116 + SubmissionStatus.find(:first,
117 + :conditions => {
118 + :user_id => id,
119 + :problem_id => problem.id
120 + })
121 + end
122 +
114 def email_for_editing
123 def email_for_editing
115 if self.email==nil
124 if self.email==nil
116 "(unknown)"
125 "(unknown)"
117 elsif self.email==''
126 elsif self.email==''
118 "(blank)"
127 "(blank)"
119 else
128 else
120 self.email
129 self.email
121 end
130 end
122 end
131 end
123
132
124 def email_for_editing=(e)
133 def email_for_editing=(e)
125 self.email=e
134 self.email=e
126 end
135 end
127
136
128 def alias_for_editing
137 def alias_for_editing
129 if self.alias==nil
138 if self.alias==nil
130 "(unknown)"
139 "(unknown)"
131 elsif self.alias==''
140 elsif self.alias==''
132 "(blank)"
141 "(blank)"
133 else
142 else
134 self.alias
143 self.alias
135 end
144 end
136 end
145 end
137
146
138 def alias_for_editing=(e)
147 def alias_for_editing=(e)
139 self.alias=e
148 self.alias=e
140 end
149 end
141
150
142 def activation_key
151 def activation_key
143 if self.hashed_password==nil
152 if self.hashed_password==nil
144 encrypt_new_password
153 encrypt_new_password
145 end
154 end
146 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
155 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
147 end
156 end
148
157
149 def verify_activation_key(key)
158 def verify_activation_key(key)
150 key == activation_key
159 key == activation_key
151 end
160 end
152
161
153 def self.random_password(length=5)
162 def self.random_password(length=5)
154 chars = 'abcdefghjkmnopqrstuvwxyz'
163 chars = 'abcdefghjkmnopqrstuvwxyz'
155 password = ''
164 password = ''
156 length.times { password << chars[rand(chars.length - 1)] }
165 length.times { password << chars[rand(chars.length - 1)] }
157 password
166 password
158 end
167 end
159
168
160 def self.find_non_admin_with_prefix(prefix='')
169 def self.find_non_admin_with_prefix(prefix='')
161 users = User.find(:all)
170 users = User.find(:all)
162 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
171 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
163 end
172 end
164
173
165 protected
174 protected
166 def encrypt_new_password
175 def encrypt_new_password
167 return if password.blank?
176 return if password.blank?
168 self.salt = (10+rand(90)).to_s
177 self.salt = (10+rand(90)).to_s
169 self.hashed_password = User.encrypt(self.password,self.salt)
178 self.hashed_password = User.encrypt(self.password,self.salt)
170 end
179 end
171
180
172 def assign_default_site
181 def assign_default_site
173 # have to catch error when migrating (because self.site is not available).
182 # have to catch error when migrating (because self.site is not available).
174 begin
183 begin
175 if self.site==nil
184 if self.site==nil
176 self.site = Site.find_by_name('default')
185 self.site = Site.find_by_name('default')
177 if self.site==nil
186 if self.site==nil
178 self.site = Site.find(1) # when 'default has be renamed'
187 self.site = Site.find(1) # when 'default has be renamed'
179 end
188 end
180 end
189 end
181 rescue
190 rescue
182 end
191 end
183 end
192 end
184
193
185 def password_required?
194 def password_required?
186 self.hashed_password.blank? || !self.password.blank?
195 self.hashed_password.blank? || !self.password.blank?
187 end
196 end
188
197
189 def self.encrypt(string,salt)
198 def self.encrypt(string,salt)
190 Digest::SHA1.hexdigest(salt + string)
199 Digest::SHA1.hexdigest(salt + string)
191 end
200 end
192
201
193 def uniqueness_of_email_from_activated_users
202 def uniqueness_of_email_from_activated_users
194 user = User.activated_users.find_by_email(self.email)
203 user = User.activated_users.find_by_email(self.email)
195 if user and (user.login != self.login)
204 if user and (user.login != self.login)
196 self.errors.add_to_base("Email has already been taken")
205 self.errors.add_to_base("Email has already been taken")
197 end
206 end
198 end
207 end
199
208
200 def enough_time_interval_between_same_email_registrations
209 def enough_time_interval_between_same_email_registrations
201 return if !self.new_record?
210 return if !self.new_record?
202 return if self.activated
211 return if self.activated
203 open_user = User.find_by_email(self.email,
212 open_user = User.find_by_email(self.email,
204 :order => 'created_at DESC')
213 :order => 'created_at DESC')
205 if open_user and open_user.created_at and
214 if open_user and open_user.created_at and
206 (open_user.created_at > Time.now.gmtime - 5.minutes)
215 (open_user.created_at > Time.now.gmtime - 5.minutes)
207 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
216 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
208 end
217 end
209 end
218 end
@@ -1,216 +1,225
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 => 20100118174404) do
12 + ActiveRecord::Schema.define(:version => 20100123154326) 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 "configurations", :force => true do |t|
25 create_table "configurations", :force => true do |t|
26 t.string "key"
26 t.string "key"
27 t.string "value_type"
27 t.string "value_type"
28 t.string "value"
28 t.string "value"
29 t.datetime "created_at"
29 t.datetime "created_at"
30 t.datetime "updated_at"
30 t.datetime "updated_at"
31 end
31 end
32
32
33 create_table "countries", :force => true do |t|
33 create_table "countries", :force => true do |t|
34 t.string "name"
34 t.string "name"
35 t.datetime "created_at"
35 t.datetime "created_at"
36 t.datetime "updated_at"
36 t.datetime "updated_at"
37 end
37 end
38
38
39 create_table "descriptions", :force => true do |t|
39 create_table "descriptions", :force => true do |t|
40 t.text "body"
40 t.text "body"
41 t.boolean "markdowned"
41 t.boolean "markdowned"
42 t.datetime "created_at"
42 t.datetime "created_at"
43 t.datetime "updated_at"
43 t.datetime "updated_at"
44 end
44 end
45
45
46 create_table "grader_processes", :force => true do |t|
46 create_table "grader_processes", :force => true do |t|
47 t.string "host", :limit => 20
47 t.string "host", :limit => 20
48 t.integer "pid"
48 t.integer "pid"
49 t.string "mode"
49 t.string "mode"
50 t.boolean "active"
50 t.boolean "active"
51 t.datetime "created_at"
51 t.datetime "created_at"
52 t.datetime "updated_at"
52 t.datetime "updated_at"
53 t.integer "task_id"
53 t.integer "task_id"
54 t.string "task_type"
54 t.string "task_type"
55 t.boolean "terminated"
55 t.boolean "terminated"
56 end
56 end
57
57
58 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
58 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
59
59
60 create_table "languages", :force => true do |t|
60 create_table "languages", :force => true do |t|
61 t.string "name", :limit => 10
61 t.string "name", :limit => 10
62 t.string "pretty_name"
62 t.string "pretty_name"
63 t.string "ext", :limit => 10
63 t.string "ext", :limit => 10
64 t.string "common_ext"
64 t.string "common_ext"
65 end
65 end
66
66
67 create_table "messages", :force => true do |t|
67 create_table "messages", :force => true do |t|
68 t.integer "sender_id"
68 t.integer "sender_id"
69 t.integer "receiver_id"
69 t.integer "receiver_id"
70 t.integer "replying_message_id"
70 t.integer "replying_message_id"
71 t.text "body"
71 t.text "body"
72 t.boolean "replied"
72 t.boolean "replied"
73 t.datetime "created_at"
73 t.datetime "created_at"
74 t.datetime "updated_at"
74 t.datetime "updated_at"
75 end
75 end
76
76
77 create_table "problems", :force => true do |t|
77 create_table "problems", :force => true do |t|
78 t.string "name", :limit => 30
78 t.string "name", :limit => 30
79 t.string "full_name"
79 t.string "full_name"
80 t.integer "full_score"
80 t.integer "full_score"
81 t.date "date_added"
81 t.date "date_added"
82 t.boolean "available"
82 t.boolean "available"
83 t.string "url"
83 t.string "url"
84 t.integer "description_id"
84 t.integer "description_id"
85 t.boolean "test_allowed"
85 t.boolean "test_allowed"
86 t.boolean "output_only"
86 t.boolean "output_only"
87 end
87 end
88
88
89 create_table "rights", :force => true do |t|
89 create_table "rights", :force => true do |t|
90 t.string "name"
90 t.string "name"
91 t.string "controller"
91 t.string "controller"
92 t.string "action"
92 t.string "action"
93 end
93 end
94
94
95 create_table "rights_roles", :id => false, :force => true do |t|
95 create_table "rights_roles", :id => false, :force => true do |t|
96 t.integer "right_id"
96 t.integer "right_id"
97 t.integer "role_id"
97 t.integer "role_id"
98 end
98 end
99
99
100 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
100 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
101
101
102 create_table "roles", :force => true do |t|
102 create_table "roles", :force => true do |t|
103 t.string "name"
103 t.string "name"
104 end
104 end
105
105
106 create_table "roles_users", :id => false, :force => true do |t|
106 create_table "roles_users", :id => false, :force => true do |t|
107 t.integer "role_id"
107 t.integer "role_id"
108 t.integer "user_id"
108 t.integer "user_id"
109 end
109 end
110
110
111 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
111 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
112
112
113 create_table "sessions", :force => true do |t|
113 create_table "sessions", :force => true do |t|
114 t.string "session_id"
114 t.string "session_id"
115 t.text "data"
115 t.text "data"
116 t.datetime "updated_at"
116 t.datetime "updated_at"
117 end
117 end
118
118
119 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
119 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
120 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
120 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
121
121
122 create_table "sites", :force => true do |t|
122 create_table "sites", :force => true do |t|
123 t.string "name"
123 t.string "name"
124 t.boolean "started"
124 t.boolean "started"
125 t.datetime "start_time"
125 t.datetime "start_time"
126 t.datetime "created_at"
126 t.datetime "created_at"
127 t.datetime "updated_at"
127 t.datetime "updated_at"
128 t.integer "country_id"
128 t.integer "country_id"
129 t.string "password"
129 t.string "password"
130 end
130 end
131
131
132 + create_table "submission_statuses", :force => true do |t|
133 + t.integer "user_id"
134 + t.integer "problem_id"
135 + t.boolean "passed"
136 + t.integer "submission_count"
137 + t.datetime "created_at"
138 + t.datetime "updated_at"
139 + end
140 +
132 create_table "submissions", :force => true do |t|
141 create_table "submissions", :force => true do |t|
133 t.integer "user_id"
142 t.integer "user_id"
134 t.integer "problem_id"
143 t.integer "problem_id"
135 t.integer "language_id"
144 t.integer "language_id"
136 t.text "source"
145 t.text "source"
137 t.binary "binary"
146 t.binary "binary"
138 t.datetime "submitted_at"
147 t.datetime "submitted_at"
139 t.datetime "compiled_at"
148 t.datetime "compiled_at"
140 t.text "compiler_message"
149 t.text "compiler_message"
141 t.datetime "graded_at"
150 t.datetime "graded_at"
142 t.integer "points"
151 t.integer "points"
143 t.text "grader_comment"
152 t.text "grader_comment"
144 t.integer "number"
153 t.integer "number"
145 t.string "source_filename"
154 t.string "source_filename"
146 end
155 end
147
156
148 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
157 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
149 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
158 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
150
159
151 create_table "tasks", :force => true do |t|
160 create_table "tasks", :force => true do |t|
152 t.integer "submission_id"
161 t.integer "submission_id"
153 t.datetime "created_at"
162 t.datetime "created_at"
154 t.integer "status"
163 t.integer "status"
155 t.datetime "updated_at"
164 t.datetime "updated_at"
156 end
165 end
157
166
158 create_table "test_pair_assignments", :force => true do |t|
167 create_table "test_pair_assignments", :force => true do |t|
159 t.integer "user_id"
168 t.integer "user_id"
160 t.integer "problem_id"
169 t.integer "problem_id"
161 t.integer "test_pair_id"
170 t.integer "test_pair_id"
162 t.integer "test_pair_number"
171 t.integer "test_pair_number"
163 t.integer "request_number"
172 t.integer "request_number"
164 t.datetime "created_at"
173 t.datetime "created_at"
165 t.datetime "updated_at"
174 t.datetime "updated_at"
166 t.boolean "submitted"
175 t.boolean "submitted"
167 end
176 end
168
177
169 create_table "test_pairs", :force => true do |t|
178 create_table "test_pairs", :force => true do |t|
170 t.integer "problem_id"
179 t.integer "problem_id"
171 t.text "input"
180 t.text "input"
172 t.text "solution"
181 t.text "solution"
173 t.datetime "created_at"
182 t.datetime "created_at"
174 t.datetime "updated_at"
183 t.datetime "updated_at"
175 t.integer "number"
184 t.integer "number"
176 end
185 end
177
186
178 create_table "test_requests", :force => true do |t|
187 create_table "test_requests", :force => true do |t|
179 t.integer "user_id"
188 t.integer "user_id"
180 t.integer "problem_id"
189 t.integer "problem_id"
181 t.integer "submission_id"
190 t.integer "submission_id"
182 t.string "input_file_name"
191 t.string "input_file_name"
183 t.string "output_file_name"
192 t.string "output_file_name"
184 t.string "running_stat"
193 t.string "running_stat"
185 t.integer "status"
194 t.integer "status"
186 t.datetime "updated_at"
195 t.datetime "updated_at"
187 t.datetime "submitted_at"
196 t.datetime "submitted_at"
188 t.datetime "compiled_at"
197 t.datetime "compiled_at"
189 t.text "compiler_message"
198 t.text "compiler_message"
190 t.datetime "graded_at"
199 t.datetime "graded_at"
191 t.string "grader_comment"
200 t.string "grader_comment"
192 t.datetime "created_at"
201 t.datetime "created_at"
193 t.float "running_time"
202 t.float "running_time"
194 t.string "exit_status"
203 t.string "exit_status"
195 t.integer "memory_usage"
204 t.integer "memory_usage"
196 end
205 end
197
206
198 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
207 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
199
208
200 create_table "users", :force => true do |t|
209 create_table "users", :force => true do |t|
201 t.string "login", :limit => 50
210 t.string "login", :limit => 50
202 t.string "full_name"
211 t.string "full_name"
203 t.string "hashed_password"
212 t.string "hashed_password"
204 t.string "salt", :limit => 5
213 t.string "salt", :limit => 5
205 t.string "alias"
214 t.string "alias"
206 t.string "email"
215 t.string "email"
207 t.integer "site_id"
216 t.integer "site_id"
208 t.integer "country_id"
217 t.integer "country_id"
209 t.boolean "activated", :default => false
218 t.boolean "activated", :default => false
210 t.datetime "created_at"
219 t.datetime "created_at"
211 t.datetime "updated_at"
220 t.datetime "updated_at"
212 end
221 end
213
222
214 add_index "users", ["login"], :name => "index_users_on_login", :unique => true
223 add_index "users", ["login"], :name => "index_users_on_login", :unique => true
215
224
216 end
225 end
deleted file
You need to be logged in to leave comments. Login now