Description:
fixed indv contest timing bug (same as in codejom), added user contest stat reset
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r247:bdb708ab847b - - 4 files changed: 16 inserted, 2 deleted

@@ -1,30 +1,38
1 class ContestsController < ApplicationController
1 class ContestsController < ApplicationController
2
2
3 before_filter :admin_authorization
3 before_filter :admin_authorization
4
4
5 def index
5 def index
6 end
6 end
7
7
8 def user_stat
8 def user_stat
9 if not Configuration.indv_contest_mode?
9 if not Configuration.indv_contest_mode?
10 redirect_to :action => 'index' and return
10 redirect_to :action => 'index' and return
11 end
11 end
12
12
13 @users = User.find(:all)
13 @users = User.find(:all)
14 @start_times = {}
14 @start_times = {}
15 UserContestStat.find(:all).each do |stat|
15 UserContestStat.find(:all).each do |stat|
16 @start_times[stat.user_id] = stat.started_at
16 @start_times[stat.user_id] = stat.started_at
17 end
17 end
18 end
18 end
19
19
20 + def clear_stat
21 + user = User.find(params[:id])
22 + if user.contest_stat!=nil
23 + user.contest_stat.destroy
24 + end
25 + redirect_to :action => 'user_stat'
26 + end
27 +
20 def clear_all_stat
28 def clear_all_stat
21 if not Configuration.indv_contest_mode?
29 if not Configuration.indv_contest_mode?
22 redirect_to :action => 'index' and return
30 redirect_to :action => 'index' and return
23 end
31 end
24
32
25 UserContestStat.delete_all()
33 UserContestStat.delete_all()
26 flash[:notice] = 'All start time statistic cleared.'
34 flash[:notice] = 'All start time statistic cleared.'
27 redirect_to :action => 'index'
35 redirect_to :action => 'index'
28 end
36 end
29
37
30 end
38 end
@@ -1,40 +1,39
1 class LoginController < ApplicationController
1 class LoginController < ApplicationController
2
2
3 def index
3 def index
4 # show login screen
4 # show login screen
5 reset_session
5 reset_session
6 redirect_to :controller => 'main', :action => 'login'
6 redirect_to :controller => 'main', :action => 'login'
7 end
7 end
8
8
9 def login
9 def login
10 if user = User.authenticate(params[:login], params[:password])
10 if user = User.authenticate(params[:login], params[:password])
11 session[:user_id] = user.id
11 session[:user_id] = user.id
12 session[:admin] = user.admin?
12 session[:admin] = user.admin?
13 - UserContestStat.update_user_start_time(user)
14 redirect_to :controller => 'main', :action => 'list'
13 redirect_to :controller => 'main', :action => 'list'
15 else
14 else
16 flash[:notice] = 'Wrong password'
15 flash[:notice] = 'Wrong password'
17 redirect_to :controller => 'main', :action => 'login'
16 redirect_to :controller => 'main', :action => 'login'
18 end
17 end
19 end
18 end
20
19
21 def site_login
20 def site_login
22 begin
21 begin
23 site = Site.find(params[:login][:site_id])
22 site = Site.find(params[:login][:site_id])
24 rescue ActiveRecord::RecordNotFound
23 rescue ActiveRecord::RecordNotFound
25 site = nil
24 site = nil
26 end
25 end
27 if site==nil
26 if site==nil
28 flash[:notice] = 'Wrong site'
27 flash[:notice] = 'Wrong site'
29 redirect_to :controller => 'main', :action => 'login' and return
28 redirect_to :controller => 'main', :action => 'login' and return
30 end
29 end
31 if (site.password) and (site.password == params[:login][:password])
30 if (site.password) and (site.password == params[:login][:password])
32 session[:site_id] = site.id
31 session[:site_id] = site.id
33 redirect_to :controller => 'site', :action => 'index'
32 redirect_to :controller => 'site', :action => 'index'
34 else
33 else
35 flash[:notice] = 'Wrong site password'
34 flash[:notice] = 'Wrong site password'
36 redirect_to :controller => 'site', :action => 'login'
35 redirect_to :controller => 'site', :action => 'login'
37 end
36 end
38 end
37 end
39
38
40 end
39 end
@@ -1,323 +1,330
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 before_filter :authenticate, :except => [:index, :login]
3 before_filter :authenticate, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
5
5
6 + append_before_filter :update_user_start_time, :except => [:index, :login]
7 +
6 # COMMENTED OUT: filter in each action instead
8 # COMMENTED OUT: filter in each action instead
7 # before_filter :verify_time_limit, :only => [:submit]
9 # before_filter :verify_time_limit, :only => [:submit]
8
10
9 verify :method => :post, :only => [:submit],
11 verify :method => :post, :only => [:submit],
10 :redirect_to => { :action => :index }
12 :redirect_to => { :action => :index }
11
13
12 # COMMENT OUT: only need when having high load
14 # COMMENT OUT: only need when having high load
13 # caches_action :index, :login
15 # caches_action :index, :login
14
16
15 # NOTE: This method is not actually needed, 'config/routes.rb' has
17 # NOTE: This method is not actually needed, 'config/routes.rb' has
16 # assigned action login as a default action.
18 # assigned action login as a default action.
17 def index
19 def index
18 redirect_to :action => 'login'
20 redirect_to :action => 'login'
19 end
21 end
20
22
21 def login
23 def login
22 saved_notice = flash[:notice]
24 saved_notice = flash[:notice]
23 reset_session
25 reset_session
24 flash.now[:notice] = saved_notice
26 flash.now[:notice] = saved_notice
25
27
26 # EXPERIMENT:
28 # EXPERIMENT:
27 # 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
28 # explicitly specify /login
30 # explicitly specify /login
29 #
31 #
30 # logger.info "PATH: #{request.path}"
32 # logger.info "PATH: #{request.path}"
31 # if Configuration['system.single_user_mode'] and
33 # if Configuration['system.single_user_mode'] and
32 # request.path!='/main/login'
34 # request.path!='/main/login'
33 # @hidelogin = true
35 # @hidelogin = true
34 # end
36 # end
35
37
36 @announcements = Announcement.find_for_frontpage
38 @announcements = Announcement.find_for_frontpage
37 render :action => 'login', :layout => 'empty'
39 render :action => 'login', :layout => 'empty'
38 end
40 end
39
41
40 def list
42 def list
41 prepare_list_information
43 prepare_list_information
42 end
44 end
43
45
44 def help
46 def help
45 @user = User.find(session[:user_id])
47 @user = User.find(session[:user_id])
46 end
48 end
47
49
48 def submit
50 def submit
49 user = User.find(session[:user_id])
51 user = User.find(session[:user_id])
50
52
51 @submission = Submission.new(params[:submission])
53 @submission = Submission.new(params[:submission])
52 @submission.user = user
54 @submission.user = user
53 @submission.language_id = 0
55 @submission.language_id = 0
54 if (params['file']) and (params['file']!='')
56 if (params['file']) and (params['file']!='')
55 @submission.source = params['file'].read
57 @submission.source = params['file'].read
56 @submission.source_filename = params['file'].original_filename
58 @submission.source_filename = params['file'].original_filename
57 end
59 end
58 @submission.submitted_at = Time.new.gmtime
60 @submission.submitted_at = Time.new.gmtime
59
61
60 if Configuration.time_limit_mode? and user.contest_finished?
62 if Configuration.time_limit_mode? and user.contest_finished?
61 @submission.errors.add_to_base "The contest is over."
63 @submission.errors.add_to_base "The contest is over."
62 prepare_list_information
64 prepare_list_information
63 render :action => 'list' and return
65 render :action => 'list' and return
64 end
66 end
65
67
66 if @submission.valid?
68 if @submission.valid?
67 if @submission.save == false
69 if @submission.save == false
68 flash[:notice] = 'Error saving your submission'
70 flash[:notice] = 'Error saving your submission'
69 elsif Task.create(:submission_id => @submission.id,
71 elsif Task.create(:submission_id => @submission.id,
70 :status => Task::STATUS_INQUEUE) == false
72 :status => Task::STATUS_INQUEUE) == false
71 flash[:notice] = 'Error adding your submission to task queue'
73 flash[:notice] = 'Error adding your submission to task queue'
72 end
74 end
73 else
75 else
74 prepare_list_information
76 prepare_list_information
75 render :action => 'list' and return
77 render :action => 'list' and return
76 end
78 end
77 redirect_to :action => 'list'
79 redirect_to :action => 'list'
78 end
80 end
79
81
80 def source
82 def source
81 submission = Submission.find(params[:id])
83 submission = Submission.find(params[:id])
82 if submission.user_id == session[:user_id]
84 if submission.user_id == session[:user_id]
83 send_data(submission.source,
85 send_data(submission.source,
84 {:filename => submission.download_filename,
86 {:filename => submission.download_filename,
85 :type => 'text/plain'})
87 :type => 'text/plain'})
86 else
88 else
87 flash[:notice] = 'Error viewing source'
89 flash[:notice] = 'Error viewing source'
88 redirect_to :action => 'list'
90 redirect_to :action => 'list'
89 end
91 end
90 end
92 end
91
93
92 def compiler_msg
94 def compiler_msg
93 @submission = Submission.find(params[:id])
95 @submission = Submission.find(params[:id])
94 if @submission.user_id == session[:user_id]
96 if @submission.user_id == session[:user_id]
95 render :action => 'compiler_msg', :layout => 'empty'
97 render :action => 'compiler_msg', :layout => 'empty'
96 else
98 else
97 flash[:notice] = 'Error viewing source'
99 flash[:notice] = 'Error viewing source'
98 redirect_to :action => 'list'
100 redirect_to :action => 'list'
99 end
101 end
100 end
102 end
101
103
102 def submission
104 def submission
103 @user = User.find(session[:user_id])
105 @user = User.find(session[:user_id])
104 @problems = Problem.find_available_problems
106 @problems = Problem.find_available_problems
105 if params[:id]==nil
107 if params[:id]==nil
106 @problem = nil
108 @problem = nil
107 @submissions = nil
109 @submissions = nil
108 else
110 else
109 @problem = Problem.find_by_name(params[:id])
111 @problem = Problem.find_by_name(params[:id])
110 if not @problem.available
112 if not @problem.available
111 redirect_to :action => 'list'
113 redirect_to :action => 'list'
112 flash[:notice] = 'Error: submissions for that problem are not viewable.'
114 flash[:notice] = 'Error: submissions for that problem are not viewable.'
113 return
115 return
114 end
116 end
115 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
117 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
116 end
118 end
117 end
119 end
118
120
119 def result
121 def result
120 if !Configuration.show_grading_result
122 if !Configuration.show_grading_result
121 redirect_to :action => 'list' and return
123 redirect_to :action => 'list' and return
122 end
124 end
123 @user = User.find(session[:user_id])
125 @user = User.find(session[:user_id])
124 @submission = Submission.find(params[:id])
126 @submission = Submission.find(params[:id])
125 if @submission.user!=@user
127 if @submission.user!=@user
126 flash[:notice] = 'You are not allowed to view result of other users.'
128 flash[:notice] = 'You are not allowed to view result of other users.'
127 redirect_to :action => 'list' and return
129 redirect_to :action => 'list' and return
128 end
130 end
129 prepare_grading_result(@submission)
131 prepare_grading_result(@submission)
130 end
132 end
131
133
132 def load_output
134 def load_output
133 if !Configuration.show_grading_result or params[:num]==nil
135 if !Configuration.show_grading_result or params[:num]==nil
134 redirect_to :action => 'list' and return
136 redirect_to :action => 'list' and return
135 end
137 end
136 @user = User.find(session[:user_id])
138 @user = User.find(session[:user_id])
137 @submission = Submission.find(params[:id])
139 @submission = Submission.find(params[:id])
138 if @submission.user!=@user
140 if @submission.user!=@user
139 flash[:notice] = 'You are not allowed to view result of other users.'
141 flash[:notice] = 'You are not allowed to view result of other users.'
140 redirect_to :action => 'list' and return
142 redirect_to :action => 'list' and return
141 end
143 end
142 case_num = params[:num].to_i
144 case_num = params[:num].to_i
143 out_filename = output_filename(@user.login,
145 out_filename = output_filename(@user.login,
144 @submission.problem.name,
146 @submission.problem.name,
145 @submission.id,
147 @submission.id,
146 case_num)
148 case_num)
147 if !FileTest.exists?(out_filename)
149 if !FileTest.exists?(out_filename)
148 flash[:notice] = 'Output not found.'
150 flash[:notice] = 'Output not found.'
149 redirect_to :action => 'list' and return
151 redirect_to :action => 'list' and return
150 end
152 end
151
153
152 response.headers['Content-Type'] = "application/force-download"
154 response.headers['Content-Type'] = "application/force-download"
153 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
155 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
154 response.headers["X-Sendfile"] = out_filename
156 response.headers["X-Sendfile"] = out_filename
155 response.headers['Content-length'] = File.size(out_filename)
157 response.headers['Content-length'] = File.size(out_filename)
156 render :nothing => true
158 render :nothing => true
157 end
159 end
158
160
159 def error
161 def error
160 @user = User.find(session[:user_id])
162 @user = User.find(session[:user_id])
161 end
163 end
162
164
163 # announcement refreshing and hiding methods
165 # announcement refreshing and hiding methods
164
166
165 def announcements
167 def announcements
166 if params.has_key? 'recent'
168 if params.has_key? 'recent'
167 prepare_announcements(params[:recent])
169 prepare_announcements(params[:recent])
168 else
170 else
169 prepare_announcements
171 prepare_announcements
170 end
172 end
171 render(:partial => 'announcement',
173 render(:partial => 'announcement',
172 :collection => @announcements,
174 :collection => @announcements,
173 :locals => {:announcement_effect => true})
175 :locals => {:announcement_effect => true})
174 end
176 end
175
177
176 protected
178 protected
177
179
178 def prepare_announcements(recent=nil)
180 def prepare_announcements(recent=nil)
179 if Configuration.show_tasks_to?(@user)
181 if Configuration.show_tasks_to?(@user)
180 @announcements = Announcement.find_published(true)
182 @announcements = Announcement.find_published(true)
181 else
183 else
182 @announcements = Announcement.find_published
184 @announcements = Announcement.find_published
183 end
185 end
184 if recent!=nil
186 if recent!=nil
185 recent_id = recent.to_i
187 recent_id = recent.to_i
186 @announcements = @announcements.find_all { |a| a.id > recent_id }
188 @announcements = @announcements.find_all { |a| a.id > recent_id }
187 end
189 end
188 end
190 end
189
191
190 def prepare_list_information
192 def prepare_list_information
191 @problems = Problem.find_available_problems
193 @problems = Problem.find_available_problems
192 @prob_submissions = Array.new
194 @prob_submissions = Array.new
193 @user = User.find(session[:user_id])
195 @user = User.find(session[:user_id])
194 @problems.each do |p|
196 @problems.each do |p|
195 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
197 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
196 if sub!=nil
198 if sub!=nil
197 @prob_submissions << { :count => sub.number, :submission => sub }
199 @prob_submissions << { :count => sub.number, :submission => sub }
198 else
200 else
199 @prob_submissions << { :count => 0, :submission => nil }
201 @prob_submissions << { :count => 0, :submission => nil }
200 end
202 end
201 end
203 end
202 prepare_announcements
204 prepare_announcements
203 end
205 end
204
206
205 def check_viewability
207 def check_viewability
206 @user = User.find(session[:user_id])
208 @user = User.find(session[:user_id])
207 if (!Configuration.show_tasks_to?(@user)) and
209 if (!Configuration.show_tasks_to?(@user)) and
208 ((action_name=='submission') or (action_name=='submit'))
210 ((action_name=='submission') or (action_name=='submit'))
209 redirect_to :action => 'list' and return
211 redirect_to :action => 'list' and return
210 end
212 end
211 end
213 end
212
214
213 def prepare_grading_result(submission)
215 def prepare_grading_result(submission)
214 if Configuration.task_grading_info.has_key? submission.problem.name
216 if Configuration.task_grading_info.has_key? submission.problem.name
215 grading_info = Configuration.task_grading_info[submission.problem.name]
217 grading_info = Configuration.task_grading_info[submission.problem.name]
216 else
218 else
217 # guess task info from problem.full_score
219 # guess task info from problem.full_score
218 cases = submission.problem.full_score / 10
220 cases = submission.problem.full_score / 10
219 grading_info = {
221 grading_info = {
220 'testruns' => cases,
222 'testruns' => cases,
221 'testcases' => cases
223 'testcases' => cases
222 }
224 }
223 end
225 end
224 @test_runs = []
226 @test_runs = []
225 if grading_info['testruns'].is_a? Integer
227 if grading_info['testruns'].is_a? Integer
226 trun_count = grading_info['testruns']
228 trun_count = grading_info['testruns']
227 trun_count.times do |i|
229 trun_count.times do |i|
228 @test_runs << [ read_grading_result(@user.login,
230 @test_runs << [ read_grading_result(@user.login,
229 submission.problem.name,
231 submission.problem.name,
230 submission.id,
232 submission.id,
231 i+1) ]
233 i+1) ]
232 end
234 end
233 else
235 else
234 grading_info['testruns'].keys.sort.each do |num|
236 grading_info['testruns'].keys.sort.each do |num|
235 run = []
237 run = []
236 testrun = grading_info['testruns'][num]
238 testrun = grading_info['testruns'][num]
237 testrun.each do |c|
239 testrun.each do |c|
238 run << read_grading_result(@user.login,
240 run << read_grading_result(@user.login,
239 submission.problem.name,
241 submission.problem.name,
240 submission.id,
242 submission.id,
241 c)
243 c)
242 end
244 end
243 @test_runs << run
245 @test_runs << run
244 end
246 end
245 end
247 end
246 end
248 end
247
249
248 def grading_result_dir(user_name, problem_name, submission_id, case_num)
250 def grading_result_dir(user_name, problem_name, submission_id, case_num)
249 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
251 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
250 end
252 end
251
253
252 def output_filename(user_name, problem_name, submission_id, case_num)
254 def output_filename(user_name, problem_name, submission_id, case_num)
253 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
255 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
254 return "#{dir}/output.txt"
256 return "#{dir}/output.txt"
255 end
257 end
256
258
257 def read_grading_result(user_name, problem_name, submission_id, case_num)
259 def read_grading_result(user_name, problem_name, submission_id, case_num)
258 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
260 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
259 result_file_name = "#{dir}/result"
261 result_file_name = "#{dir}/result"
260 if !FileTest.exists?(result_file_name)
262 if !FileTest.exists?(result_file_name)
261 return {:num => case_num, :msg => 'program did not run'}
263 return {:num => case_num, :msg => 'program did not run'}
262 else
264 else
263 results = File.open(result_file_name).readlines
265 results = File.open(result_file_name).readlines
264 run_stat = extract_running_stat(results)
266 run_stat = extract_running_stat(results)
265 output_filename = "#{dir}/output.txt"
267 output_filename = "#{dir}/output.txt"
266 if FileTest.exists?(output_filename)
268 if FileTest.exists?(output_filename)
267 output_file = true
269 output_file = true
268 output_size = File.size(output_filename)
270 output_size = File.size(output_filename)
269 else
271 else
270 output_file = false
272 output_file = false
271 output_size = 0
273 output_size = 0
272 end
274 end
273
275
274 return {
276 return {
275 :num => case_num,
277 :num => case_num,
276 :msg => results[0],
278 :msg => results[0],
277 :run_stat => run_stat,
279 :run_stat => run_stat,
278 :output => output_file,
280 :output => output_file,
279 :output_size => output_size
281 :output_size => output_size
280 }
282 }
281 end
283 end
282 end
284 end
283
285
284 # copied from grader/script/lib/test_request_helper.rb
286 # copied from grader/script/lib/test_request_helper.rb
285 def extract_running_stat(results)
287 def extract_running_stat(results)
286 running_stat_line = results[-1]
288 running_stat_line = results[-1]
287
289
288 # extract exit status line
290 # extract exit status line
289 run_stat = ""
291 run_stat = ""
290 if !(/[Cc]orrect/.match(results[0]))
292 if !(/[Cc]orrect/.match(results[0]))
291 run_stat = results[0].chomp
293 run_stat = results[0].chomp
292 else
294 else
293 run_stat = 'Program exited normally'
295 run_stat = 'Program exited normally'
294 end
296 end
295
297
296 logger.info "Stat line: #{running_stat_line}"
298 logger.info "Stat line: #{running_stat_line}"
297
299
298 # extract running time
300 # extract running time
299 if res = /r(.*)u(.*)s/.match(running_stat_line)
301 if res = /r(.*)u(.*)s/.match(running_stat_line)
300 seconds = (res[1].to_f + res[2].to_f)
302 seconds = (res[1].to_f + res[2].to_f)
301 time_stat = "Time used: #{seconds} sec."
303 time_stat = "Time used: #{seconds} sec."
302 else
304 else
303 seconds = nil
305 seconds = nil
304 time_stat = "Time used: n/a sec."
306 time_stat = "Time used: n/a sec."
305 end
307 end
306
308
307 # extract memory usage
309 # extract memory usage
308 if res = /s(.*)m/.match(running_stat_line)
310 if res = /s(.*)m/.match(running_stat_line)
309 memory_used = res[1].to_i
311 memory_used = res[1].to_i
310 else
312 else
311 memory_used = -1
313 memory_used = -1
312 end
314 end
313
315
314 return {
316 return {
315 :msg => "#{run_stat}\n#{time_stat}",
317 :msg => "#{run_stat}\n#{time_stat}",
316 :running_time => seconds,
318 :running_time => seconds,
317 :exit_status => run_stat,
319 :exit_status => run_stat,
318 :memory_usage => memory_used
320 :memory_usage => memory_used
319 }
321 }
320 end
322 end
321
323
324 + def update_user_start_time
325 + user = User.find(session[:user_id])
326 + UserContestStat.update_user_start_time(user)
327 + end
328 +
322 end
329 end
323
330
@@ -1,211 +1,211
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_one :contest_stat, :class_name => "UserContestStat"
19 + has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
20
20
21 belongs_to :site
21 belongs_to :site
22 belongs_to :country
22 belongs_to :country
23
23
24 named_scope :activated_users, :conditions => {:activated => true}
24 named_scope :activated_users, :conditions => {:activated => true}
25
25
26 validates_presence_of :login
26 validates_presence_of :login
27 validates_uniqueness_of :login
27 validates_uniqueness_of :login
28 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
28 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
29 validates_length_of :login, :within => 3..30
29 validates_length_of :login, :within => 3..30
30
30
31 validates_presence_of :full_name
31 validates_presence_of :full_name
32 validates_length_of :full_name, :minimum => 1
32 validates_length_of :full_name, :minimum => 1
33
33
34 validates_presence_of :password, :if => :password_required?
34 validates_presence_of :password, :if => :password_required?
35 validates_length_of :password, :within => 4..20, :if => :password_required?
35 validates_length_of :password, :within => 4..20, :if => :password_required?
36 validates_confirmation_of :password, :if => :password_required?
36 validates_confirmation_of :password, :if => :password_required?
37
37
38 validates_format_of :email,
38 validates_format_of :email,
39 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
39 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
40 :if => :email_validation?
40 :if => :email_validation?
41 validate :uniqueness_of_email_from_activated_users,
41 validate :uniqueness_of_email_from_activated_users,
42 :if => :email_validation?
42 :if => :email_validation?
43 validate :enough_time_interval_between_same_email_registrations,
43 validate :enough_time_interval_between_same_email_registrations,
44 :if => :email_validation?
44 :if => :email_validation?
45
45
46 # these are for ytopc
46 # these are for ytopc
47 # disable for now
47 # disable for now
48 #validates_presence_of :province
48 #validates_presence_of :province
49
49
50 attr_accessor :password
50 attr_accessor :password
51
51
52 before_save :encrypt_new_password
52 before_save :encrypt_new_password
53 before_save :assign_default_site
53 before_save :assign_default_site
54
54
55 def self.authenticate(login, password)
55 def self.authenticate(login, password)
56 user = find_by_login(login)
56 user = find_by_login(login)
57 return user if user && user.authenticated?(password)
57 return user if user && user.authenticated?(password)
58 end
58 end
59
59
60 def authenticated?(password)
60 def authenticated?(password)
61 if self.activated
61 if self.activated
62 hashed_password == User.encrypt(password,self.salt)
62 hashed_password == User.encrypt(password,self.salt)
63 else
63 else
64 false
64 false
65 end
65 end
66 end
66 end
67
67
68 def admin?
68 def admin?
69 self.roles.detect {|r| r.name == 'admin' }
69 self.roles.detect {|r| r.name == 'admin' }
70 end
70 end
71
71
72 def email_for_editing
72 def email_for_editing
73 if self.email==nil
73 if self.email==nil
74 "(unknown)"
74 "(unknown)"
75 elsif self.email==''
75 elsif self.email==''
76 "(blank)"
76 "(blank)"
77 else
77 else
78 self.email
78 self.email
79 end
79 end
80 end
80 end
81
81
82 def email_for_editing=(e)
82 def email_for_editing=(e)
83 self.email=e
83 self.email=e
84 end
84 end
85
85
86 def alias_for_editing
86 def alias_for_editing
87 if self.alias==nil
87 if self.alias==nil
88 "(unknown)"
88 "(unknown)"
89 elsif self.alias==''
89 elsif self.alias==''
90 "(blank)"
90 "(blank)"
91 else
91 else
92 self.alias
92 self.alias
93 end
93 end
94 end
94 end
95
95
96 def alias_for_editing=(e)
96 def alias_for_editing=(e)
97 self.alias=e
97 self.alias=e
98 end
98 end
99
99
100 def activation_key
100 def activation_key
101 if self.hashed_password==nil
101 if self.hashed_password==nil
102 encrypt_new_password
102 encrypt_new_password
103 end
103 end
104 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
104 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
105 end
105 end
106
106
107 def verify_activation_key(key)
107 def verify_activation_key(key)
108 key == activation_key
108 key == activation_key
109 end
109 end
110
110
111 def self.random_password(length=5)
111 def self.random_password(length=5)
112 chars = 'abcdefghjkmnopqrstuvwxyz'
112 chars = 'abcdefghjkmnopqrstuvwxyz'
113 password = ''
113 password = ''
114 length.times { password << chars[rand(chars.length - 1)] }
114 length.times { password << chars[rand(chars.length - 1)] }
115 password
115 password
116 end
116 end
117
117
118 def self.find_non_admin_with_prefix(prefix='')
118 def self.find_non_admin_with_prefix(prefix='')
119 users = User.find(:all)
119 users = User.find(:all)
120 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
120 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
121 end
121 end
122
122
123 # Contest information
123 # Contest information
124
124
125 def contest_time_left
125 def contest_time_left
126 if Configuration.contest_mode?
126 if Configuration.contest_mode?
127 return nil if site==nil
127 return nil if site==nil
128 return site.time_left
128 return site.time_left
129 elsif Configuration.indv_contest_mode?
129 elsif Configuration.indv_contest_mode?
130 time_limit = Configuration.contest_time_limit
130 time_limit = Configuration.contest_time_limit
131 if contest_stat==nil
131 if contest_stat==nil
132 return (Time.now.gmtime + time_limit) - Time.now.gmtime
132 return (Time.now.gmtime + time_limit) - Time.now.gmtime
133 else
133 else
134 finish_time = contest_stat.started_at + time_limit
134 finish_time = contest_stat.started_at + time_limit
135 current_time = Time.now.gmtime
135 current_time = Time.now.gmtime
136 if current_time > finish_time
136 if current_time > finish_time
137 return 0
137 return 0
138 else
138 else
139 return finish_time - current_time
139 return finish_time - current_time
140 end
140 end
141 end
141 end
142 else
142 else
143 return nil
143 return nil
144 end
144 end
145 end
145 end
146
146
147 def contest_finished?
147 def contest_finished?
148 if Configuration.contest_mode?
148 if Configuration.contest_mode?
149 return false if site==nil
149 return false if site==nil
150 return site.finished?
150 return site.finished?
151 elsif Configuration.indv_contest_mode?
151 elsif Configuration.indv_contest_mode?
152 time_limit = Configuration.contest_time_limit
152 time_limit = Configuration.contest_time_limit
153
153
154 return false if contest_stat==nil
154 return false if contest_stat==nil
155
155
156 return contest_time_left == 0
156 return contest_time_left == 0
157 else
157 else
158 return false
158 return false
159 end
159 end
160 end
160 end
161
161
162 def contest_started?
162 def contest_started?
163 if Configuration.contest_mode?
163 if Configuration.contest_mode?
164 return true if site==nil
164 return true if site==nil
165 return site.started
165 return site.started
166 else
166 else
167 return true
167 return true
168 end
168 end
169 end
169 end
170
170
171 protected
171 protected
172 def encrypt_new_password
172 def encrypt_new_password
173 return if password.blank?
173 return if password.blank?
174 self.salt = (10+rand(90)).to_s
174 self.salt = (10+rand(90)).to_s
175 self.hashed_password = User.encrypt(self.password,self.salt)
175 self.hashed_password = User.encrypt(self.password,self.salt)
176 end
176 end
177
177
178 def assign_default_site
178 def assign_default_site
179 # have to catch error when migrating (because self.site is not available).
179 # have to catch error when migrating (because self.site is not available).
180 begin
180 begin
181 if self.site==nil
181 if self.site==nil
182 self.site = Site.find_by_name('default')
182 self.site = Site.find_by_name('default')
183 if self.site==nil
183 if self.site==nil
184 self.site = Site.find(1) # when 'default has be renamed'
184 self.site = Site.find(1) # when 'default has be renamed'
185 end
185 end
186 end
186 end
187 rescue
187 rescue
188 end
188 end
189 end
189 end
190
190
191 def password_required?
191 def password_required?
192 self.hashed_password.blank? || !self.password.blank?
192 self.hashed_password.blank? || !self.password.blank?
193 end
193 end
194
194
195 def self.encrypt(string,salt)
195 def self.encrypt(string,salt)
196 Digest::SHA1.hexdigest(salt + string)
196 Digest::SHA1.hexdigest(salt + string)
197 end
197 end
198
198
199 def uniqueness_of_email_from_activated_users
199 def uniqueness_of_email_from_activated_users
200 user = User.activated_users.find_by_email(self.email)
200 user = User.activated_users.find_by_email(self.email)
201 if user and (user.login != self.login)
201 if user and (user.login != self.login)
202 self.errors.add_to_base("Email has already been taken")
202 self.errors.add_to_base("Email has already been taken")
203 end
203 end
204 end
204 end
205
205
206 def enough_time_interval_between_same_email_registrations
206 def enough_time_interval_between_same_email_registrations
207 return if !self.new_record?
207 return if !self.new_record?
208 return if self.activated
208 return if self.activated
209 open_user = User.find_by_email(self.email,
209 open_user = User.find_by_email(self.email,
210 :order => 'created_at DESC')
210 :order => 'created_at DESC')
211 if open_user and open_user.created_at and
211 if open_user and open_user.created_at and
You need to be logged in to leave comments. Login now