Description:
added test assignment time out
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r222:2b6293a64dbb - - 8 files changed: 42 inserted, 2 deleted

@@ -110,192 +110,197
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.expired?
207 + flash[:notice] = 'The current input is expired. Please download a new input data.'
208 + redirect_to :action => 'list' and return
209 + end
210 +
206 if recent_assignment.submitted
211 if recent_assignment.submitted
207 flash[:notice] = 'You have already submitted an incorrect solution for this input. Please download a new input data.'
212 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
213 redirect_to :action => 'list' and return
209 end
214 end
210
215
211 if params[:file] == nil
216 if params[:file] == nil
212 flash[:notice] = 'You have not submitted any output.'
217 flash[:notice] = 'You have not submitted any output.'
213 redirect_to :action => 'list' and return
218 redirect_to :action => 'list' and return
214 end
219 end
215
220
216 submitted_solution = params[:file].read
221 submitted_solution = params[:file].read
217 test_pair = recent_assignment.test_pair
222 test_pair = recent_assignment.test_pair
218 passed = test_pair.grade(submitted_solution)
223 passed = test_pair.grade(submitted_solution)
219 points = passed ? 100 : 0
224 points = passed ? 100 : 0
220 submission = Submission.new(:user => user,
225 submission = Submission.new(:user => user,
221 :problem => problem,
226 :problem => problem,
222 :source => submitted_solution,
227 :source => submitted_solution,
223 :source_filename => params['file'].original_filename,
228 :source_filename => params['file'].original_filename,
224 :language_id => 0,
229 :language_id => 0,
225 :submitted_at => Time.new.gmtime,
230 :submitted_at => Time.new.gmtime,
226 :graded_at => Time.new.gmtime,
231 :graded_at => Time.new.gmtime,
227 :points => points)
232 :points => points)
228 submission.save
233 submission.save
229 recent_assignment.submitted = true
234 recent_assignment.submitted = true
230 recent_assignment.save
235 recent_assignment.save
231
236
232 status = user.get_submission_status_for(problem)
237 status = user.get_submission_status_for(problem)
233 if status == nil
238 if status == nil
234 status = SubmissionStatus.new :user => user, :problem => problem, :submission_count => 0
239 status = SubmissionStatus.new :user => user, :problem => problem, :submission_count => 0
235 end
240 end
236
241
237 status.submission_count += 1
242 status.submission_count += 1
238 status.passed = passed
243 status.passed = passed
239 status.save
244 status.save
240
245
241 if passed
246 if passed
242 flash[:notice] = 'Correct solution.'
247 flash[:notice] = 'Correct solution.'
243 user.update_codejom_status
248 user.update_codejom_status
244 else
249 else
245 flash[:notice] = 'Incorrect solution.'
250 flash[:notice] = 'Incorrect solution.'
246 end
251 end
247 redirect_to :action => 'list'
252 redirect_to :action => 'list'
248 end
253 end
249
254
250 protected
255 protected
251
256
252 def prepare_announcements(recent=nil)
257 def prepare_announcements(recent=nil)
253 if Configuration.show_tasks_to?(@user)
258 if Configuration.show_tasks_to?(@user)
254 @announcements = Announcement.find_published(true)
259 @announcements = Announcement.find_published(true)
255 else
260 else
256 @announcements = Announcement.find_published
261 @announcements = Announcement.find_published
257 end
262 end
258 if recent!=nil
263 if recent!=nil
259 recent_id = recent.to_i
264 recent_id = recent.to_i
260 @announcements = @announcements.find_all { |a| a.id > recent_id }
265 @announcements = @announcements.find_all { |a| a.id > recent_id }
261 end
266 end
262 end
267 end
263
268
264 def prepare_list_information
269 def prepare_list_information
265 @user = User.find(session[:user_id])
270 @user = User.find(session[:user_id])
266
271
267 all_problems = Problem.find_available_problems
272 all_problems = Problem.find_available_problems
268
273
269 passed = {}
274 passed = {}
270 sub_count = {}
275 sub_count = {}
271 @user.submission_statuses.each do |status|
276 @user.submission_statuses.each do |status|
272 if status.passed
277 if status.passed
273 passed[status.problem_id] = true
278 passed[status.problem_id] = true
274 end
279 end
275 sub_count[status.problem_id] = status.submission_count
280 sub_count[status.problem_id] = status.submission_count
276 end
281 end
277
282
278 @problems = all_problems.reject { |problem| passed.has_key? problem.id }
283 @problems = all_problems.reject { |problem| passed.has_key? problem.id }
279
284
280 @prob_submissions = Array.new
285 @prob_submissions = Array.new
281 @problems.each do |p|
286 @problems.each do |p|
282 if sub_count.has_key? p.id
287 if sub_count.has_key? p.id
283 @prob_submissions << { :count => sub_count[p.id] }
288 @prob_submissions << { :count => sub_count[p.id] }
284 else
289 else
285 @prob_submissions << { :count => 0 }
290 @prob_submissions << { :count => 0 }
286 end
291 end
287 end
292 end
288 prepare_announcements
293 prepare_announcements
289 end
294 end
290
295
291 def check_viewability
296 def check_viewability
292 @user = User.find(session[:user_id])
297 @user = User.find(session[:user_id])
293 if (!Configuration.show_tasks_to?(@user)) and
298 if (!Configuration.show_tasks_to?(@user)) and
294 ((action_name=='submission') or (action_name=='submit'))
299 ((action_name=='submission') or (action_name=='submit'))
295 redirect_to :action => 'list' and return
300 redirect_to :action => 'list' and return
296 end
301 end
297 end
302 end
298
303
299 def prepare_grading_result(submission)
304 def prepare_grading_result(submission)
300 if Configuration.task_grading_info.has_key? submission.problem.name
305 if Configuration.task_grading_info.has_key? submission.problem.name
301 grading_info = Configuration.task_grading_info[submission.problem.name]
306 grading_info = Configuration.task_grading_info[submission.problem.name]
@@ -1,5 +1,11
1 class TestPairAssignment < ActiveRecord::Base
1 class TestPairAssignment < ActiveRecord::Base
2 +
2 belongs_to :user
3 belongs_to :user
3 belongs_to :test_pair
4 belongs_to :test_pair
4 belongs_to :problem
5 belongs_to :problem
6 +
7 + def expired?
8 + return created_at + TEST_ASSIGNMENT_EXPIRATION_DURATION < Time.new.gmtime
9 + end
10 +
5 end
11 end
@@ -3,193 +3,193
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
27 # For Code Jom
28 has_one :codejom_status
28 has_one :codejom_status
29
29
30 named_scope :activated_users, :conditions => {:activated => true}
30 named_scope :activated_users, :conditions => {:activated => true}
31
31
32 validates_presence_of :login
32 validates_presence_of :login
33 validates_uniqueness_of :login
33 validates_uniqueness_of :login
34 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
34 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
35 validates_length_of :login, :within => 3..30
35 validates_length_of :login, :within => 3..30
36
36
37 validates_presence_of :full_name
37 validates_presence_of :full_name
38 validates_length_of :full_name, :minimum => 1
38 validates_length_of :full_name, :minimum => 1
39
39
40 validates_presence_of :password, :if => :password_required?
40 validates_presence_of :password, :if => :password_required?
41 validates_length_of :password, :within => 4..20, :if => :password_required?
41 validates_length_of :password, :within => 4..20, :if => :password_required?
42 validates_confirmation_of :password, :if => :password_required?
42 validates_confirmation_of :password, :if => :password_required?
43
43
44 validates_format_of :email,
44 validates_format_of :email,
45 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
45 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
46 :if => :email_validation?
46 :if => :email_validation?
47 validate :uniqueness_of_email_from_activated_users,
47 validate :uniqueness_of_email_from_activated_users,
48 :if => :email_validation?
48 :if => :email_validation?
49 validate :enough_time_interval_between_same_email_registrations,
49 validate :enough_time_interval_between_same_email_registrations,
50 :if => :email_validation?
50 :if => :email_validation?
51
51
52 # these are for ytopc
52 # these are for ytopc
53 # disable for now
53 # disable for now
54 #validates_presence_of :province
54 #validates_presence_of :province
55
55
56 attr_accessor :password
56 attr_accessor :password
57
57
58 before_save :encrypt_new_password
58 before_save :encrypt_new_password
59 before_save :assign_default_site
59 before_save :assign_default_site
60
60
61 def self.authenticate(login, password)
61 def self.authenticate(login, password)
62 user = find_by_login(login)
62 user = find_by_login(login)
63 return user if user && user.authenticated?(password)
63 return user if user && user.authenticated?(password)
64 end
64 end
65
65
66 def authenticated?(password)
66 def authenticated?(password)
67 if self.activated
67 if self.activated
68 hashed_password == User.encrypt(password,self.salt)
68 hashed_password == User.encrypt(password,self.salt)
69 else
69 else
70 false
70 false
71 end
71 end
72 end
72 end
73
73
74 def admin?
74 def admin?
75 self.roles.detect {|r| r.name == 'admin' }
75 self.roles.detect {|r| r.name == 'admin' }
76 end
76 end
77
77
78 # These are methods related to test pairs
78 # These are methods related to test pairs
79
79
80 def get_test_pair_assignments_for(problem)
80 def get_test_pair_assignments_for(problem)
81 test_pair_assignments.find_all { |a| a.problem_id == problem.id }
81 test_pair_assignments.find_all { |a| a.problem_id == problem.id }
82 end
82 end
83
83
84 def get_recent_test_pair_assignment_for(problem)
84 def get_recent_test_pair_assignment_for(problem)
85 assignments = get_test_pair_assignments_for problem
85 assignments = get_test_pair_assignments_for problem
86 if assignments.length == 0
86 if assignments.length == 0
87 return nil
87 return nil
88 else
88 else
89 recent = assignments[0]
89 recent = assignments[0]
90 assignments.each do |a|
90 assignments.each do |a|
91 recent = a if a.request_number > recent.request_number
91 recent = a if a.request_number > recent.request_number
92 end
92 end
93 return recent
93 return recent
94 end
94 end
95 end
95 end
96
96
97 def can_request_new_test_pair_for?(problem)
97 def can_request_new_test_pair_for?(problem)
98 recent = get_recent_test_pair_assignment_for problem
98 recent = get_recent_test_pair_assignment_for problem
99 - return (recent == nil or recent.submitted)
99 + return (recent == nil or recent.submitted or recent.expired?)
100 end
100 end
101
101
102 def get_new_test_pair_assignment_for(problem)
102 def get_new_test_pair_assignment_for(problem)
103 previous_assignment_numbers =
103 previous_assignment_numbers =
104 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 }
105 test_pair = problem.random_test_pair(previous_assignment_numbers)
105 test_pair = problem.random_test_pair(previous_assignment_numbers)
106 if test_pair
106 if test_pair
107 assignment = TestPairAssignment.new(:user => self,
107 assignment = TestPairAssignment.new(:user => self,
108 :problem => problem,
108 :problem => problem,
109 :test_pair => test_pair,
109 :test_pair => test_pair,
110 :test_pair_number => test_pair.number,
110 :test_pair_number => test_pair.number,
111 :request_number =>
111 :request_number =>
112 previous_assignment_numbers.length + 1,
112 previous_assignment_numbers.length + 1,
113 :submitted => false)
113 :submitted => false)
114 return assignment
114 return assignment
115 else
115 else
116 return nil
116 return nil
117 end
117 end
118 end
118 end
119
119
120 def get_submission_status_for(problem)
120 def get_submission_status_for(problem)
121 SubmissionStatus.find(:first,
121 SubmissionStatus.find(:first,
122 :conditions => {
122 :conditions => {
123 :user_id => id,
123 :user_id => id,
124 :problem_id => problem.id
124 :problem_id => problem.id
125 })
125 })
126 end
126 end
127
127
128 def email_for_editing
128 def email_for_editing
129 if self.email==nil
129 if self.email==nil
130 "(unknown)"
130 "(unknown)"
131 elsif self.email==''
131 elsif self.email==''
132 "(blank)"
132 "(blank)"
133 else
133 else
134 self.email
134 self.email
135 end
135 end
136 end
136 end
137
137
138 def email_for_editing=(e)
138 def email_for_editing=(e)
139 self.email=e
139 self.email=e
140 end
140 end
141
141
142 def alias_for_editing
142 def alias_for_editing
143 if self.alias==nil
143 if self.alias==nil
144 "(unknown)"
144 "(unknown)"
145 elsif self.alias==''
145 elsif self.alias==''
146 "(blank)"
146 "(blank)"
147 else
147 else
148 self.alias
148 self.alias
149 end
149 end
150 end
150 end
151
151
152 def alias_for_editing=(e)
152 def alias_for_editing=(e)
153 self.alias=e
153 self.alias=e
154 end
154 end
155
155
156 def activation_key
156 def activation_key
157 if self.hashed_password==nil
157 if self.hashed_password==nil
158 encrypt_new_password
158 encrypt_new_password
159 end
159 end
160 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
160 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
161 end
161 end
162
162
163 def verify_activation_key(key)
163 def verify_activation_key(key)
164 key == activation_key
164 key == activation_key
165 end
165 end
166
166
167 def self.random_password(length=5)
167 def self.random_password(length=5)
168 chars = 'abcdefghjkmnopqrstuvwxyz'
168 chars = 'abcdefghjkmnopqrstuvwxyz'
169 password = ''
169 password = ''
170 length.times { password << chars[rand(chars.length - 1)] }
170 length.times { password << chars[rand(chars.length - 1)] }
171 password
171 password
172 end
172 end
173
173
174 def self.find_non_admin_with_prefix(prefix='')
174 def self.find_non_admin_with_prefix(prefix='')
175 users = User.find(:all)
175 users = User.find(:all)
176 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 }
177 end
177 end
178
178
179 # Contest information
179 # Contest information
180
180
181 def contest_time_left
181 def contest_time_left
182 if Configuration.contest_mode?
182 if Configuration.contest_mode?
183 return nil if site==nil
183 return nil if site==nil
184 return site.time_left
184 return site.time_left
185 elsif Configuration.indv_contest_mode?
185 elsif Configuration.indv_contest_mode?
186 time_limit = Configuration.contest_time_limit
186 time_limit = Configuration.contest_time_limit
187 if contest_stat==nil
187 if contest_stat==nil
188 return (Time.now.gmtime + time_limit) - Time.now.gmtime
188 return (Time.now.gmtime + time_limit) - Time.now.gmtime
189 else
189 else
190 finish_time = contest_stat.started_at + time_limit
190 finish_time = contest_stat.started_at + time_limit
191 current_time = Time.now.gmtime
191 current_time = Time.now.gmtime
192 if current_time > finish_time
192 if current_time > finish_time
193 return 0
193 return 0
194 else
194 else
195 return finish_time - current_time
195 return finish_time - current_time
@@ -1,22 +1,22
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
3
4 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5 <head>
5 <head>
6 <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
6 <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
7 <title><%= Configuration['contest.name'] %></title>
7 <title><%= Configuration['contest.name'] %></title>
8 <%= stylesheet_link_tag 'application' %>
8 <%= stylesheet_link_tag 'application' %>
9 <%= yield :head %>
9 <%= yield :head %>
10 </head>
10 </head>
11 <body>
11 <body>
12
12
13 <div class="userbar">
13 <div class="userbar">
14 <%= user_header %>
14 <%= user_header %>
15 </div>
15 </div>
16
16
17 - <%= content_tag(:p,flash[:notice],:style => "color:green") if flash[:notice]!=nil %>
17 + <% if flash[:notice]!=nil %><div class="notice-bar"><span class="notice"><%= flash[:notice] %></span></div><% end %>
18
18
19 <%= yield %>
19 <%= yield %>
20
20
21 </body>
21 </body>
22 </html>
22 </html>
@@ -1,18 +1,19
1 .problem-panel{:id => "problem-panel-#{problem.id}", :style => "display:none"}
1 .problem-panel{:id => "problem-panel-#{problem.id}", :style => "display:none"}
2 .problem-form{:id => "problem-form-#{problem.id}"}
2 .problem-form{:id => "problem-form-#{problem.id}"}
3 - form_tag({ :action => 'download_input', :id => problem.id }, :method => :post) do
3 - form_tag({ :action => 'download_input', :id => problem.id }, :method => :post) do
4 %b Input:
4 %b Input:
5 %input{:type => "submit", :value => "Download input"}
5 %input{:type => "submit", :value => "Download input"}
6 + = "After downloading, you have #{TEST_ASSIGNMENT_EXPIRATION_DURATION/60} minutes to submit."
6 - form_tag({ :action => 'submit_solution', :id => problem.id }, :method => :post, :multipart => true) do
7 - form_tag({ :action => 'submit_solution', :id => problem.id }, :method => :post, :multipart => true) do
7 %b Submit output:
8 %b Submit output:
8 %input{:type => "file", :name => "file"}
9 %input{:type => "file", :name => "file"}
9 %input{:type => "submit", :value => "Submit solution"}
10 %input{:type => "submit", :value => "Submit solution"}
10
11
11 .problem-description
12 .problem-description
12 - if problem.description!=nil
13 - if problem.description!=nil
13 - if problem.description.markdowned
14 - if problem.description.markdowned
14 = markdown(problem.description.body)
15 = markdown(problem.description.body)
15 - else
16 - else
16 = problem.description.body
17 = problem.description.body
17 - else
18 - else
18 (not available)
19 (not available)
@@ -14,96 +14,97
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
106
107 # OPTIONS FOR CODE JOM
107 # OPTIONS FOR CODE JOM
108 # --------------------
108 # --------------------
109 CODEJOM_MAX_ALIVE_LEVEL = 10
109 CODEJOM_MAX_ALIVE_LEVEL = 10
110 + TEST_ASSIGNMENT_EXPIRATION_DURATION = 5.minute
@@ -171,96 +171,109
171 padding: 1px;
171 padding: 1px;
172 padding-left: 10px;
172 padding-left: 10px;
173 padding-right: 10px;
173 padding-right: 10px;
174 padding-top: 5px;
174 padding-top: 5px;
175 padding-bottom: 5px; }
175 padding-bottom: 5px; }
176 .announcementbox .announcement p {
176 .announcementbox .announcement p {
177 font-size: 12px;
177 font-size: 12px;
178 margin: 2px; }
178 margin: 2px; }
179
179
180 .pub-info {
180 .pub-info {
181 text-align: right;
181 text-align: right;
182 font-style: italic;
182 font-style: italic;
183 font-size: 9px; }
183 font-size: 9px; }
184 .pub-info p {
184 .pub-info p {
185 text-align: right;
185 text-align: right;
186 font-style: italic;
186 font-style: italic;
187 font-size: 9px; }
187 font-size: 9px; }
188
188
189 .announcement .toggles {
189 .announcement .toggles {
190 font-weight: normal;
190 font-weight: normal;
191 float: right;
191 float: right;
192 font-size: 80%; }
192 font-size: 80%; }
193 .announcement .announcement-title {
193 .announcement .announcement-title {
194 font-weight: bold; }
194 font-weight: bold; }
195
195
196 .message {
196 .message {
197 margin: 10px 0 0; }
197 margin: 10px 0 0; }
198 .message .message {
198 .message .message {
199 margin: 0 0 0 30px; }
199 margin: 0 0 0 30px; }
200 .message .message .stat {
200 .message .message .stat {
201 font-size: 10px;
201 font-size: 10px;
202 line-height: 1.75em;
202 line-height: 1.75em;
203 padding: 0 5px;
203 padding: 0 5px;
204 color: #444444;
204 color: #444444;
205 background: #bbbbbb;
205 background: #bbbbbb;
206 font-weight: bold; }
206 font-weight: bold; }
207 .message .body {
207 .message .body {
208 border: 2px solid #dddddd;
208 border: 2px solid #dddddd;
209 background: #fff8f8;
209 background: #fff8f8;
210 padding-left: 5px; }
210 padding-left: 5px; }
211 .message .reply-body {
211 .message .reply-body {
212 border: 2px solid #bbbbbb;
212 border: 2px solid #bbbbbb;
213 background: #fffff8;
213 background: #fffff8;
214 padding-left: 5px; }
214 padding-left: 5px; }
215 .message .stat {
215 .message .stat {
216 font-size: 10px;
216 font-size: 10px;
217 line-height: 1.75em;
217 line-height: 1.75em;
218 padding: 0 5px;
218 padding: 0 5px;
219 color: #333333;
219 color: #333333;
220 background: #dddddd;
220 background: #dddddd;
221 font-weight: bold; }
221 font-weight: bold; }
222
222
223 .contest-title {
223 .contest-title {
224 color: white;
224 color: white;
225 text-align: center;
225 text-align: center;
226 line-height: 2em; }
226 line-height: 2em; }
227
227
228 .registration-desc {
228 .registration-desc {
229 border: 1px dotted gray;
229 border: 1px dotted gray;
230 background: #f5f5f5;
230 background: #f5f5f5;
231 padding: 5px;
231 padding: 5px;
232 margin: 10px 0;
232 margin: 10px 0;
233 font-size: 12px;
233 font-size: 12px;
234 line-height: 1.5em; }
234 line-height: 1.5em; }
235
235
236 .test-desc {
236 .test-desc {
237 border: 1px dotted gray;
237 border: 1px dotted gray;
238 background: #f5f5f5;
238 background: #f5f5f5;
239 padding: 5px;
239 padding: 5px;
240 margin: 10px 0;
240 margin: 10px 0;
241 font-size: 12px;
241 font-size: 12px;
242 line-height: 1.5em; }
242 line-height: 1.5em; }
243
243
244 .problem-list {
244 .problem-list {
245 width: 200px;
245 width: 200px;
246 float: left; }
246 float: left; }
247
247
248 .problem-bar {
248 .problem-bar {
249 margin-top: 5px;
249 margin-top: 5px;
250 padding: 5px;
250 padding: 5px;
251 background: #e0e0e0; }
251 background: #e0e0e0; }
252 .problem-bar span.problem-title {
252 .problem-bar span.problem-title {
253 font-weight: bold;
253 font-weight: bold;
254 font-size: 110%; }
254 font-size: 110%; }
255
255
256 .problem-content {
256 .problem-content {
257 float: left;
257 float: left;
258 margin-left: 10px;
258 margin-left: 10px;
259 width: 700px; }
259 width: 700px; }
260
260
261 .problem-panel {
261 .problem-panel {
262 border: 1px black solid;
262 border: 1px black solid;
263 padding: 5px; }
263 padding: 5px; }
264 .problem-panel .problem-form {
264 .problem-panel .problem-form {
265 border: 1px dotted #99aaee;
265 border: 1px dotted #99aaee;
266 background: #eeeeff; }
266 background: #eeeeff; }
267 +
268 + .notice-bar {
269 + margin-top: 3px;
270 + margin-bottom: 3px;
271 + text-align: center; }
272 + .notice-bar span.notice {
273 + color: white;
274 + font-weight: bold;
275 + background: #000070;
276 + padding: 3px 20px 3px 20px;
277 + -moz-border-radius: 2px;
278 + -webkit-border-radius: 5px;
279 + border-radius: 5px; }
@@ -217,96 +217,110
217 font-size: 9px
217 font-size: 9px
218
218
219 p
219 p
220 text-align: right
220 text-align: right
221 font-style: italic
221 font-style: italic
222 font-size: 9px
222 font-size: 9px
223
223
224
224
225 .announcement
225 .announcement
226 .toggles
226 .toggles
227 font-weight: normal
227 font-weight: normal
228 float: right
228 float: right
229 font-size: 80%
229 font-size: 80%
230
230
231 .announcement-title
231 .announcement-title
232 font-weight: bold
232 font-weight: bold
233
233
234
234
235 .message
235 .message
236 margin: 10px 0 0
236 margin: 10px 0 0
237
237
238 .message
238 .message
239 margin: 0 0 0 30px
239 margin: 0 0 0 30px
240
240
241 .stat
241 .stat
242 font-size: 10px
242 font-size: 10px
243 line-height: 1.75em
243 line-height: 1.75em
244 padding: 0 5px
244 padding: 0 5px
245 color: #444444
245 color: #444444
246 background: #bbbbbb
246 background: #bbbbbb
247 font-weight: bold
247 font-weight: bold
248
248
249 .body
249 .body
250 border: 2px solid #dddddd
250 border: 2px solid #dddddd
251 background: #fff8f8
251 background: #fff8f8
252 padding-left: 5px
252 padding-left: 5px
253
253
254 .reply-body
254 .reply-body
255 border: 2px solid #bbbbbb
255 border: 2px solid #bbbbbb
256 background: #fffff8
256 background: #fffff8
257 padding-left: 5px
257 padding-left: 5px
258
258
259 .stat
259 .stat
260 font-size: 10px
260 font-size: 10px
261 line-height: 1.75em
261 line-height: 1.75em
262 padding: 0 5px
262 padding: 0 5px
263 color: #333333
263 color: #333333
264 background: #dddddd
264 background: #dddddd
265 font-weight: bold
265 font-weight: bold
266
266
267 .contest-title
267 .contest-title
268 color: white
268 color: white
269 text-align: center
269 text-align: center
270 line-height: 2em
270 line-height: 2em
271
271
272 .registration-desc
272 .registration-desc
273 border: 1px dotted gray
273 border: 1px dotted gray
274 background: #f5f5f5
274 background: #f5f5f5
275 padding: 5px
275 padding: 5px
276 margin: 10px 0
276 margin: 10px 0
277 font-size: 12px
277 font-size: 12px
278 line-height: 1.5em
278 line-height: 1.5em
279
279
280 .test-desc
280 .test-desc
281 border: 1px dotted gray
281 border: 1px dotted gray
282 background: #f5f5f5
282 background: #f5f5f5
283 padding: 5px
283 padding: 5px
284 margin: 10px 0
284 margin: 10px 0
285 font-size: 12px
285 font-size: 12px
286 line-height: 1.5em
286 line-height: 1.5em
287
287
288 .problem-list
288 .problem-list
289 width: 200px
289 width: 200px
290 float: left
290 float: left
291
291
292 .problem-bar
292 .problem-bar
293 margin-top: 5px
293 margin-top: 5px
294 padding: 5px
294 padding: 5px
295 background: #e0e0e0
295 background: #e0e0e0
296
296
297 span.problem-title
297 span.problem-title
298 font-weight: bold
298 font-weight: bold
299 font-size: 110%
299 font-size: 110%
300
300
301 .problem-content
301 .problem-content
302 float: left
302 float: left
303 margin-left: 10px
303 margin-left: 10px
304 width: 700px
304 width: 700px
305
305
306 .problem-panel
306 .problem-panel
307 border: 1px black solid
307 border: 1px black solid
308 padding: 5px
308 padding: 5px
309
309
310 .problem-form
310 .problem-form
311 border: 1px dotted #99aaee
311 border: 1px dotted #99aaee
312 background: #eeeeff
312 background: #eeeeff
313 +
314 + .notice-bar
315 + margin-top: 3px
316 + margin-bottom: 3px
317 + text-align: center
318 +
319 + span.notice
320 + color: white
321 + font-weight: bold
322 + background: #000070
323 + padding: 3px 20px 3px 20px
324 + -moz-border-radius: 2px
325 + -webkit-border-radius: 5px
326 + border-radius: 5px
You need to be logged in to leave comments. Login now