Description:
Merge branch 'master' into codejom (user stat reset) Conflicts: app/models/user.rb
Commit status:
[Not Reviewed]
References:
merge default
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r248:0f32f3dd1054 - - 2 files changed: 9 inserted, 1 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,315 +1,315
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 require 'digest/sha1'
2 require 'digest/sha1'
3
3
4 class User < ActiveRecord::Base
4 class User < ActiveRecord::Base
5
5
6 has_and_belongs_to_many :roles
6 has_and_belongs_to_many :roles
7
7
8 has_many :test_requests, :order => "submitted_at DESC"
8 has_many :test_requests, :order => "submitted_at DESC"
9
9
10 has_many :messages,
10 has_many :messages,
11 :class_name => "Message",
11 :class_name => "Message",
12 :foreign_key => "sender_id",
12 :foreign_key => "sender_id",
13 :order => 'created_at DESC'
13 :order => 'created_at DESC'
14
14
15 has_many :replied_messages,
15 has_many :replied_messages,
16 :class_name => "Message",
16 :class_name => "Message",
17 :foreign_key => "receiver_id",
17 :foreign_key => "receiver_id",
18 :order => 'created_at DESC'
18 :order => 'created_at DESC'
19
19
20 has_many :test_pair_assignments, :dependent => :delete_all
20 has_many :test_pair_assignments, :dependent => :delete_all
21 has_many :submission_statuses
21 has_many :submission_statuses
22
22
23 - has_one :contest_stat, :class_name => "UserContestStat"
23 + has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
24
24
25 belongs_to :site
25 belongs_to :site
26 belongs_to :country
26 belongs_to :country
27
27
28 # For Code Jom
28 # For Code Jom
29 has_one :codejom_status
29 has_one :codejom_status
30
30
31 named_scope :activated_users, :conditions => {:activated => true}
31 named_scope :activated_users, :conditions => {:activated => true}
32
32
33 validates_presence_of :login
33 validates_presence_of :login
34 validates_uniqueness_of :login
34 validates_uniqueness_of :login
35 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
35 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
36 validates_length_of :login, :within => 3..20
36 validates_length_of :login, :within => 3..20
37
37
38 validates_presence_of :full_name
38 validates_presence_of :full_name
39 validates_length_of :full_name, :minimum => 1
39 validates_length_of :full_name, :minimum => 1
40
40
41 validates_presence_of :member1_full_name
41 validates_presence_of :member1_full_name
42 validates_length_of :member1_full_name, :minimum => 1
42 validates_length_of :member1_full_name, :minimum => 1
43
43
44 validates_presence_of :password, :if => :password_required?
44 validates_presence_of :password, :if => :password_required?
45 validates_length_of :password, :within => 4..20, :if => :password_required?
45 validates_length_of :password, :within => 4..20, :if => :password_required?
46 validates_confirmation_of :password, :if => :password_required?
46 validates_confirmation_of :password, :if => :password_required?
47
47
48 validates_format_of :email,
48 validates_format_of :email,
49 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
49 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
50 :if => :email_validation?
50 :if => :email_validation?
51 validate :uniqueness_of_email_from_activated_users,
51 validate :uniqueness_of_email_from_activated_users,
52 :if => :email_validation?
52 :if => :email_validation?
53 validate :enough_time_interval_between_same_email_registrations,
53 validate :enough_time_interval_between_same_email_registrations,
54 :if => :email_validation?
54 :if => :email_validation?
55
55
56 validate :school_names_for_high_school_users
56 validate :school_names_for_high_school_users
57
57
58 # these are for ytopc
58 # these are for ytopc
59 # disable for now
59 # disable for now
60 #validates_presence_of :province
60 #validates_presence_of :province
61
61
62 attr_accessor :password
62 attr_accessor :password
63
63
64 before_save :encrypt_new_password
64 before_save :encrypt_new_password
65 before_save :assign_default_site
65 before_save :assign_default_site
66
66
67 def self.authenticate(login, password)
67 def self.authenticate(login, password)
68 user = find_by_login(login)
68 user = find_by_login(login)
69 return user if user && user.authenticated?(password)
69 return user if user && user.authenticated?(password)
70 end
70 end
71
71
72 def authenticated?(password)
72 def authenticated?(password)
73 if self.activated
73 if self.activated
74 hashed_password == User.encrypt(password,self.salt)
74 hashed_password == User.encrypt(password,self.salt)
75 else
75 else
76 false
76 false
77 end
77 end
78 end
78 end
79
79
80 def admin?
80 def admin?
81 self.roles.detect {|r| r.name == 'admin' }
81 self.roles.detect {|r| r.name == 'admin' }
82 end
82 end
83
83
84 # These are methods related to test pairs
84 # These are methods related to test pairs
85
85
86 def get_test_pair_assignments_for(problem)
86 def get_test_pair_assignments_for(problem)
87 test_pair_assignments.find_all { |a| a.problem_id == problem.id }
87 test_pair_assignments.find_all { |a| a.problem_id == problem.id }
88 end
88 end
89
89
90 def get_recent_test_pair_assignment_for(problem)
90 def get_recent_test_pair_assignment_for(problem)
91 assignments = get_test_pair_assignments_for problem
91 assignments = get_test_pair_assignments_for problem
92 if assignments.length == 0
92 if assignments.length == 0
93 return nil
93 return nil
94 else
94 else
95 recent = assignments[0]
95 recent = assignments[0]
96 assignments.each do |a|
96 assignments.each do |a|
97 recent = a if a.request_number > recent.request_number
97 recent = a if a.request_number > recent.request_number
98 end
98 end
99 return recent
99 return recent
100 end
100 end
101 end
101 end
102
102
103 def can_request_new_test_pair_for?(problem)
103 def can_request_new_test_pair_for?(problem)
104 recent = get_recent_test_pair_assignment_for problem
104 recent = get_recent_test_pair_assignment_for problem
105 return (recent == nil or recent.submitted or recent.expired?)
105 return (recent == nil or recent.submitted or recent.expired?)
106 end
106 end
107
107
108 def get_new_test_pair_assignment_for(problem)
108 def get_new_test_pair_assignment_for(problem)
109 previous_assignment_numbers =
109 previous_assignment_numbers =
110 get_test_pair_assignments_for(problem).collect {|a| a.test_pair_number }
110 get_test_pair_assignments_for(problem).collect {|a| a.test_pair_number }
111 test_pair = problem.random_test_pair(previous_assignment_numbers)
111 test_pair = problem.random_test_pair(previous_assignment_numbers)
112 if test_pair
112 if test_pair
113 assignment = TestPairAssignment.new(:user => self,
113 assignment = TestPairAssignment.new(:user => self,
114 :problem => problem,
114 :problem => problem,
115 :test_pair => test_pair,
115 :test_pair => test_pair,
116 :test_pair_number => test_pair.number,
116 :test_pair_number => test_pair.number,
117 :request_number =>
117 :request_number =>
118 previous_assignment_numbers.length + 1,
118 previous_assignment_numbers.length + 1,
119 :submitted => false)
119 :submitted => false)
120 return assignment
120 return assignment
121 else
121 else
122 return nil
122 return nil
123 end
123 end
124 end
124 end
125
125
126 def get_submission_status_for(problem)
126 def get_submission_status_for(problem)
127 SubmissionStatus.find(:first,
127 SubmissionStatus.find(:first,
128 :conditions => {
128 :conditions => {
129 :user_id => id,
129 :user_id => id,
130 :problem_id => problem.id
130 :problem_id => problem.id
131 })
131 })
132 end
132 end
133
133
134 def email_for_editing
134 def email_for_editing
135 if self.email==nil
135 if self.email==nil
136 "(unknown)"
136 "(unknown)"
137 elsif self.email==''
137 elsif self.email==''
138 "(blank)"
138 "(blank)"
139 else
139 else
140 self.email
140 self.email
141 end
141 end
142 end
142 end
143
143
144 def email_for_editing=(e)
144 def email_for_editing=(e)
145 self.email=e
145 self.email=e
146 end
146 end
147
147
148 def alias_for_editing
148 def alias_for_editing
149 if self.alias==nil
149 if self.alias==nil
150 "(unknown)"
150 "(unknown)"
151 elsif self.alias==''
151 elsif self.alias==''
152 "(blank)"
152 "(blank)"
153 else
153 else
154 self.alias
154 self.alias
155 end
155 end
156 end
156 end
157
157
158 def alias_for_editing=(e)
158 def alias_for_editing=(e)
159 self.alias=e
159 self.alias=e
160 end
160 end
161
161
162 def activation_key
162 def activation_key
163 if self.hashed_password==nil
163 if self.hashed_password==nil
164 encrypt_new_password
164 encrypt_new_password
165 end
165 end
166 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
166 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
167 end
167 end
168
168
169 def verify_activation_key(key)
169 def verify_activation_key(key)
170 key == activation_key
170 key == activation_key
171 end
171 end
172
172
173 def self.random_password(length=5)
173 def self.random_password(length=5)
174 chars = 'abcdefghjkmnopqrstuvwxyz'
174 chars = 'abcdefghjkmnopqrstuvwxyz'
175 password = ''
175 password = ''
176 length.times { password << chars[rand(chars.length - 1)] }
176 length.times { password << chars[rand(chars.length - 1)] }
177 password
177 password
178 end
178 end
179
179
180 def self.find_non_admin_with_prefix(prefix='')
180 def self.find_non_admin_with_prefix(prefix='')
181 users = User.find(:all)
181 users = User.find(:all)
182 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
182 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
183 end
183 end
184
184
185 # Contest information
185 # Contest information
186
186
187 def contest_time_left
187 def contest_time_left
188 if Configuration.contest_mode?
188 if Configuration.contest_mode?
189 return nil if site==nil
189 return nil if site==nil
190 return site.time_left
190 return site.time_left
191 elsif Configuration.indv_contest_mode?
191 elsif Configuration.indv_contest_mode?
192 time_limit = Configuration.contest_time_limit
192 time_limit = Configuration.contest_time_limit
193 if contest_stat==nil
193 if contest_stat==nil
194 return (Time.now.gmtime + time_limit) - Time.now.gmtime
194 return (Time.now.gmtime + time_limit) - Time.now.gmtime
195 else
195 else
196 finish_time = contest_stat.started_at + time_limit
196 finish_time = contest_stat.started_at + time_limit
197 current_time = Time.now.gmtime
197 current_time = Time.now.gmtime
198 if current_time > finish_time
198 if current_time > finish_time
199 return 0
199 return 0
200 else
200 else
201 return finish_time - current_time
201 return finish_time - current_time
202 end
202 end
203 end
203 end
204 else
204 else
205 return nil
205 return nil
206 end
206 end
207 end
207 end
208
208
209 def contest_finished?
209 def contest_finished?
210 if Configuration.contest_mode?
210 if Configuration.contest_mode?
211 return false if site==nil
211 return false if site==nil
212 return site.finished?
212 return site.finished?
213 elsif Configuration.indv_contest_mode?
213 elsif Configuration.indv_contest_mode?
214 time_limit = Configuration.contest_time_limit
214 time_limit = Configuration.contest_time_limit
215
215
216 return false if contest_stat==nil
216 return false if contest_stat==nil
217
217
218 return contest_time_left == 0
218 return contest_time_left == 0
219 else
219 else
220 return false
220 return false
221 end
221 end
222 end
222 end
223
223
224 def contest_started?
224 def contest_started?
225 if Configuration.contest_mode?
225 if Configuration.contest_mode?
226 return true if site==nil
226 return true if site==nil
227 return site.started
227 return site.started
228 else
228 else
229 return true
229 return true
230 end
230 end
231 end
231 end
232
232
233 # For Code Jom
233 # For Code Jom
234 def update_codejom_status
234 def update_codejom_status
235 status = codejom_status || CodejomStatus.new(:user => self)
235 status = codejom_status || CodejomStatus.new(:user => self)
236 problem_count = Problem.available_problem_count
236 problem_count = Problem.available_problem_count
237 status.num_problems_passed = (self.submission_statuses.find_all {|s| s.passed and s.problem.available }).length
237 status.num_problems_passed = (self.submission_statuses.find_all {|s| s.passed and s.problem.available }).length
238 status.alive = (problem_count - (status.num_problems_passed)) <= CODEJOM_MAX_ALIVE_LEVEL
238 status.alive = (problem_count - (status.num_problems_passed)) <= CODEJOM_MAX_ALIVE_LEVEL
239 status.save
239 status.save
240 end
240 end
241
241
242 def codejom_level
242 def codejom_level
243 problem_count = Problem.available_problem_count
243 problem_count = Problem.available_problem_count
244 if codejom_status!=nil
244 if codejom_status!=nil
245 return problem_count - codejom_status.num_problems_passed
245 return problem_count - codejom_status.num_problems_passed
246 else
246 else
247 return problem_count
247 return problem_count
248 end
248 end
249 end
249 end
250
250
251 protected
251 protected
252 def encrypt_new_password
252 def encrypt_new_password
253 return if password.blank?
253 return if password.blank?
254 self.salt = (10+rand(90)).to_s
254 self.salt = (10+rand(90)).to_s
255 self.hashed_password = User.encrypt(self.password,self.salt)
255 self.hashed_password = User.encrypt(self.password,self.salt)
256 end
256 end
257
257
258 def assign_default_site
258 def assign_default_site
259 # have to catch error when migrating (because self.site is not available).
259 # have to catch error when migrating (because self.site is not available).
260 begin
260 begin
261 if self.site==nil
261 if self.site==nil
262 self.site = Site.find_by_name('default')
262 self.site = Site.find_by_name('default')
263 if self.site==nil
263 if self.site==nil
264 self.site = Site.find(1) # when 'default has be renamed'
264 self.site = Site.find(1) # when 'default has be renamed'
265 end
265 end
266 end
266 end
267 rescue
267 rescue
268 end
268 end
269 end
269 end
270
270
271 def password_required?
271 def password_required?
272 self.hashed_password.blank? || !self.password.blank?
272 self.hashed_password.blank? || !self.password.blank?
273 end
273 end
274
274
275 def self.encrypt(string,salt)
275 def self.encrypt(string,salt)
276 Digest::SHA1.hexdigest(salt + string)
276 Digest::SHA1.hexdigest(salt + string)
277 end
277 end
278
278
279 def uniqueness_of_email_from_activated_users
279 def uniqueness_of_email_from_activated_users
280 user = User.activated_users.find_by_email(self.email)
280 user = User.activated_users.find_by_email(self.email)
281 if user and (user.login != self.login)
281 if user and (user.login != self.login)
282 self.errors.add_to_base("Email has already been taken")
282 self.errors.add_to_base("Email has already been taken")
283 end
283 end
284 end
284 end
285
285
286 def enough_time_interval_between_same_email_registrations
286 def enough_time_interval_between_same_email_registrations
287 return if !self.new_record?
287 return if !self.new_record?
288 return if self.activated
288 return if self.activated
289 open_user = User.find_by_email(self.email,
289 open_user = User.find_by_email(self.email,
290 :order => 'created_at DESC')
290 :order => 'created_at DESC')
291 if open_user and open_user.created_at and
291 if open_user and open_user.created_at and
292 (open_user.created_at > Time.now.gmtime - 5.minutes)
292 (open_user.created_at > Time.now.gmtime - 5.minutes)
293 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
293 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
294 end
294 end
295 end
295 end
296
296
297 def email_validation?
297 def email_validation?
298 begin
298 begin
299 return VALIDATE_USER_EMAILS
299 return VALIDATE_USER_EMAILS
300 rescue
300 rescue
301 return false
301 return false
302 end
302 end
303 end
303 end
304
304
305
305
306 def school_names_for_high_school_users
306 def school_names_for_high_school_users
307 if self.high_school
307 if self.high_school
308 if (self.member1_school_name=='' or
308 if (self.member1_school_name=='' or
309 (self.member2_full_name!='' and self.member2_school_name=='') or
309 (self.member2_full_name!='' and self.member2_school_name=='') or
310 (self.member3_full_name!='' and self.member3_school_name==''))
310 (self.member3_full_name!='' and self.member3_school_name==''))
311 self.errors.add_to_base("โปรดระบุชื่อโรงเรียนสำหรับสมาชิกในทีมทุกคน")
311 self.errors.add_to_base("โปรดระบุชื่อโรงเรียนสำหรับสมาชิกในทีมทุกคน")
312 end
312 end
313 end
313 end
314 end
314 end
315 end
315 end
You need to be logged in to leave comments. Login now