Description:
add download score as csv
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r449:c1892413ee46 - - 2 files changed: 58 inserted, 1 deleted

@@ -1,478 +1,532
1 + require 'csv'
2 +
1 class UserAdminController < ApplicationController
3 class UserAdminController < ApplicationController
2
4
5 +
3 include MailHelperMethods
6 include MailHelperMethods
4
7
5 before_filter :admin_authorization
8 before_filter :admin_authorization
6
9
7 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
10 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
8 verify :method => :post, :only => [ :destroy,
11 verify :method => :post, :only => [ :destroy,
9 :create, :create_from_list,
12 :create, :create_from_list,
10 :update,
13 :update,
11 :manage_contest,
14 :manage_contest,
12 :bulk_mail
15 :bulk_mail
13 ],
16 ],
14 :redirect_to => { :action => :list }
17 :redirect_to => { :action => :list }
15
18
16 def index
19 def index
17 list
20 list
18 render :action => 'list'
21 render :action => 'list'
19 end
22 end
20
23
21 def list
24 def list
22 @user_count = User.count
25 @user_count = User.count
23 if params[:page] == 'all'
26 if params[:page] == 'all'
24 @users = User.all
27 @users = User.all
25 @paginated = false
28 @paginated = false
26 else
29 else
27 @users = User.paginate :page => params[:page]
30 @users = User.paginate :page => params[:page]
28 @paginated = true
31 @paginated = true
29 end
32 end
30 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
33 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
31 @contests = Contest.enabled
34 @contests = Contest.enabled
32 end
35 end
33
36
34 def active
37 def active
35 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
38 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
36 @users = []
39 @users = []
37 sessions.each do |session|
40 sessions.each do |session|
38 if session.data[:user_id]
41 if session.data[:user_id]
39 @users << User.find(session.data[:user_id])
42 @users << User.find(session.data[:user_id])
40 end
43 end
41 end
44 end
42 end
45 end
43
46
44 def show
47 def show
45 @user = User.find(params[:id])
48 @user = User.find(params[:id])
46 end
49 end
47
50
48 def new
51 def new
49 @user = User.new
52 @user = User.new
50 end
53 end
51
54
52 def create
55 def create
53 @user = User.new(params[:user])
56 @user = User.new(params[:user])
54 @user.activated = true
57 @user.activated = true
55 if @user.save
58 if @user.save
56 flash[:notice] = 'User was successfully created.'
59 flash[:notice] = 'User was successfully created.'
57 redirect_to :action => 'list'
60 redirect_to :action => 'list'
58 else
61 else
59 render :action => 'new'
62 render :action => 'new'
60 end
63 end
61 end
64 end
62
65
63 def create_from_list
66 def create_from_list
64 lines = params[:user_list]
67 lines = params[:user_list]
65
68
66 note = []
69 note = []
67
70
68 lines.split("\n").each do |line|
71 lines.split("\n").each do |line|
69 items = line.chomp.split(',')
72 items = line.chomp.split(',')
70 if items.length>=2
73 if items.length>=2
71 login = items[0]
74 login = items[0]
72 full_name = items[1]
75 full_name = items[1]
73
76
74 added_random_password = false
77 added_random_password = false
75 if items.length>=3
78 if items.length>=3
76 password = items[2].chomp(" ")
79 password = items[2].chomp(" ")
77 user_alias = (items.length>=4) ? items[3] : login
80 user_alias = (items.length>=4) ? items[3] : login
78 else
81 else
79 password = random_password
82 password = random_password
80 user_alias = (items.length>=4) ? items[3] : login
83 user_alias = (items.length>=4) ? items[3] : login
81 added_random_password = true
84 added_random_password = true
82 end
85 end
83
86
84 user = User.new({:login => login,
87 user = User.new({:login => login,
85 :full_name => full_name,
88 :full_name => full_name,
86 :password => password,
89 :password => password,
87 :password_confirmation => password,
90 :password_confirmation => password,
88 :alias => user_alias})
91 :alias => user_alias})
89 user.activated = true
92 user.activated = true
90 user.save
93 user.save
91
94
92 if added_random_password
95 if added_random_password
93 note << "'#{login}' (+)"
96 note << "'#{login}' (+)"
94 else
97 else
95 note << login
98 note << login
96 end
99 end
97 end
100 end
98 end
101 end
99 flash[:notice] = 'User(s) ' + note.join(', ') +
102 flash[:notice] = 'User(s) ' + note.join(', ') +
100 ' were successfully created. ' +
103 ' were successfully created. ' +
101 '( (+) - created with random passwords.)'
104 '( (+) - created with random passwords.)'
102 redirect_to :action => 'list'
105 redirect_to :action => 'list'
103 end
106 end
104
107
105 def edit
108 def edit
106 @user = User.find(params[:id])
109 @user = User.find(params[:id])
107 end
110 end
108
111
109 def update
112 def update
110 @user = User.find(params[:id])
113 @user = User.find(params[:id])
111 if @user.update_attributes(params[:user])
114 if @user.update_attributes(params[:user])
112 flash[:notice] = 'User was successfully updated.'
115 flash[:notice] = 'User was successfully updated.'
113 redirect_to :action => 'show', :id => @user
116 redirect_to :action => 'show', :id => @user
114 else
117 else
115 render :action => 'edit'
118 render :action => 'edit'
116 end
119 end
117 end
120 end
118
121
119 def destroy
122 def destroy
120 User.find(params[:id]).destroy
123 User.find(params[:id]).destroy
121 redirect_to :action => 'list'
124 redirect_to :action => 'list'
122 end
125 end
123
126
124 def user_stat
127 def user_stat
128 + if params[:commit] == 'download csv'
129 + @problems = Problem.all
130 + else
125 @problems = Problem.find_available_problems
131 @problems = Problem.find_available_problems
132 + end
126 @users = User.find(:all, :include => [:contests, :contest_stat])
133 @users = User.find(:all, :include => [:contests, :contest_stat])
127 @scorearray = Array.new
134 @scorearray = Array.new
128 @users.each do |u|
135 @users.each do |u|
129 ustat = Array.new
136 ustat = Array.new
130 ustat[0] = u
137 ustat[0] = u
131 @problems.each do |p|
138 @problems.each do |p|
132 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
139 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
133 if (sub!=nil) and (sub.points!=nil)
140 if (sub!=nil) and (sub.points!=nil)
134 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
141 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
135 else
142 else
136 ustat << [0,false]
143 ustat << [0,false]
137 end
144 end
138 end
145 end
139 @scorearray << ustat
146 @scorearray << ustat
140 end
147 end
148 +
149 + if params[:commit] == 'download csv' then
150 + csv = gen_csv_from_scorearray(@scorearray,@problems)
151 + send_data csv, filename: 'last_score.csv'
152 + else
153 + render template: 'user_admin/user_stat'
154 + end
141 end
155 end
142
156
143 def user_stat_max
157 def user_stat_max
158 + if params[:commit] == 'download csv'
159 + @problems = Problem.all
160 + else
144 @problems = Problem.find_available_problems
161 @problems = Problem.find_available_problems
162 + end
145 @users = User.find(:all, :include => [:contests, :contest_stat])
163 @users = User.find(:all, :include => [:contests, :contest_stat])
146 @scorearray = Array.new
164 @scorearray = Array.new
147 #set up range from param
165 #set up range from param
148 since_id = params.fetch(:since_id, 0).to_i
166 since_id = params.fetch(:since_id, 0).to_i
149 until_id = params.fetch(:until_id, 0).to_i
167 until_id = params.fetch(:until_id, 0).to_i
150 @users.each do |u|
168 @users.each do |u|
151 ustat = Array.new
169 ustat = Array.new
152 ustat[0] = u
170 ustat[0] = u
153 @problems.each do |p|
171 @problems.each do |p|
154 max_points = 0
172 max_points = 0
155 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
173 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
156 max_points = sub.points if sub and sub.points and (sub.points > max_points)
174 max_points = sub.points if sub and sub.points and (sub.points > max_points)
157 end
175 end
158 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
176 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
159 end
177 end
160 @scorearray << ustat
178 @scorearray << ustat
161 end
179 end
162
180
181 + if params[:commit] == 'download csv' then
182 + csv = gen_csv_from_scorearray(@scorearray,@problems)
183 + send_data csv, filename: 'max_score.csv'
184 + else
163 render template: 'user_admin/user_stat'
185 render template: 'user_admin/user_stat'
164 end
186 end
187 + end
165
188
166 def import
189 def import
167 if params[:file]==''
190 if params[:file]==''
168 flash[:notice] = 'Error importing no file'
191 flash[:notice] = 'Error importing no file'
169 redirect_to :action => 'list' and return
192 redirect_to :action => 'list' and return
170 end
193 end
171 import_from_file(params[:file])
194 import_from_file(params[:file])
172 end
195 end
173
196
174 def random_all_passwords
197 def random_all_passwords
175 users = User.find(:all)
198 users = User.find(:all)
176 @prefix = params[:prefix] || ''
199 @prefix = params[:prefix] || ''
177 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
200 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
178 @changed = false
201 @changed = false
179 if request.request_method == 'POST'
202 if request.request_method == 'POST'
180 @non_admin_users.each do |user|
203 @non_admin_users.each do |user|
181 password = random_password
204 password = random_password
182 user.password = password
205 user.password = password
183 user.password_confirmation = password
206 user.password_confirmation = password
184 user.save
207 user.save
185 end
208 end
186 @changed = true
209 @changed = true
187 end
210 end
188 end
211 end
189
212
190 # contest management
213 # contest management
191
214
192 def contests
215 def contests
193 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
216 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
194 @contests = Contest.enabled
217 @contests = Contest.enabled
195 end
218 end
196
219
197 def assign_from_list
220 def assign_from_list
198 contest_id = params[:users_contest_id]
221 contest_id = params[:users_contest_id]
199 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
222 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
200 contest = Contest.find(params[:new_contest][:id])
223 contest = Contest.find(params[:new_contest][:id])
201 if !contest
224 if !contest
202 flash[:notice] = 'Error: no contest'
225 flash[:notice] = 'Error: no contest'
203 redirect_to :action => 'contests', :id =>contest_id
226 redirect_to :action => 'contests', :id =>contest_id
204 end
227 end
205
228
206 note = []
229 note = []
207 users.each do |u|
230 users.each do |u|
208 u.contests = [contest]
231 u.contests = [contest]
209 note << u.login
232 note << u.login
210 end
233 end
211 flash[:notice] = 'User(s) ' + note.join(', ') +
234 flash[:notice] = 'User(s) ' + note.join(', ') +
212 " were successfully reassigned to #{contest.title}."
235 " were successfully reassigned to #{contest.title}."
213 redirect_to :action => 'contests', :id =>contest.id
236 redirect_to :action => 'contests', :id =>contest.id
214 end
237 end
215
238
216 def add_to_contest
239 def add_to_contest
217 user = User.find(params[:id])
240 user = User.find(params[:id])
218 contest = Contest.find(params[:contest_id])
241 contest = Contest.find(params[:contest_id])
219 if user and contest
242 if user and contest
220 user.contests << contest
243 user.contests << contest
221 end
244 end
222 redirect_to :action => 'list'
245 redirect_to :action => 'list'
223 end
246 end
224
247
225 def remove_from_contest
248 def remove_from_contest
226 user = User.find(params[:id])
249 user = User.find(params[:id])
227 contest = Contest.find(params[:contest_id])
250 contest = Contest.find(params[:contest_id])
228 if user and contest
251 if user and contest
229 user.contests.delete(contest)
252 user.contests.delete(contest)
230 end
253 end
231 redirect_to :action => 'list'
254 redirect_to :action => 'list'
232 end
255 end
233
256
234 def contest_management
257 def contest_management
235 end
258 end
236
259
237 def manage_contest
260 def manage_contest
238 contest = Contest.find(params[:contest][:id])
261 contest = Contest.find(params[:contest][:id])
239 if !contest
262 if !contest
240 flash[:notice] = 'You did not choose the contest.'
263 flash[:notice] = 'You did not choose the contest.'
241 redirect_to :action => 'contest_management' and return
264 redirect_to :action => 'contest_management' and return
242 end
265 end
243
266
244 operation = params[:operation]
267 operation = params[:operation]
245
268
246 if not ['add','remove','assign'].include? operation
269 if not ['add','remove','assign'].include? operation
247 flash[:notice] = 'You did not choose the operation to perform.'
270 flash[:notice] = 'You did not choose the operation to perform.'
248 redirect_to :action => 'contest_management' and return
271 redirect_to :action => 'contest_management' and return
249 end
272 end
250
273
251 lines = params[:login_list]
274 lines = params[:login_list]
252 if !lines or lines.blank?
275 if !lines or lines.blank?
253 flash[:notice] = 'You entered an empty list.'
276 flash[:notice] = 'You entered an empty list.'
254 redirect_to :action => 'contest_management' and return
277 redirect_to :action => 'contest_management' and return
255 end
278 end
256
279
257 note = []
280 note = []
258 users = []
281 users = []
259 lines.split("\n").each do |line|
282 lines.split("\n").each do |line|
260 user = User.find_by_login(line.chomp)
283 user = User.find_by_login(line.chomp)
261 if user
284 if user
262 if operation=='add'
285 if operation=='add'
263 if ! user.contests.include? contest
286 if ! user.contests.include? contest
264 user.contests << contest
287 user.contests << contest
265 end
288 end
266 elsif operation=='remove'
289 elsif operation=='remove'
267 user.contests.delete(contest)
290 user.contests.delete(contest)
268 else
291 else
269 user.contests = [contest]
292 user.contests = [contest]
270 end
293 end
271
294
272 if params[:reset_timer]
295 if params[:reset_timer]
273 user.contest_stat.forced_logout = true
296 user.contest_stat.forced_logout = true
274 user.contest_stat.reset_timer_and_save
297 user.contest_stat.reset_timer_and_save
275 end
298 end
276
299
277 if params[:notification_emails]
300 if params[:notification_emails]
278 send_contest_update_notification_email(user, contest)
301 send_contest_update_notification_email(user, contest)
279 end
302 end
280
303
281 note << user.login
304 note << user.login
282 users << user
305 users << user
283 end
306 end
284 end
307 end
285
308
286 if params[:reset_timer]
309 if params[:reset_timer]
287 logout_users(users)
310 logout_users(users)
288 end
311 end
289
312
290 flash[:notice] = 'User(s) ' + note.join(', ') +
313 flash[:notice] = 'User(s) ' + note.join(', ') +
291 ' were successfully modified. '
314 ' were successfully modified. '
292 redirect_to :action => 'contest_management'
315 redirect_to :action => 'contest_management'
293 end
316 end
294
317
295 # admin management
318 # admin management
296
319
297 def admin
320 def admin
298 @admins = User.find(:all).find_all {|user| user.admin? }
321 @admins = User.find(:all).find_all {|user| user.admin? }
299 end
322 end
300
323
301 def grant_admin
324 def grant_admin
302 login = params[:login]
325 login = params[:login]
303 user = User.find_by_login(login)
326 user = User.find_by_login(login)
304 if user!=nil
327 if user!=nil
305 admin_role = Role.find_by_name('admin')
328 admin_role = Role.find_by_name('admin')
306 user.roles << admin_role
329 user.roles << admin_role
307 else
330 else
308 flash[:notice] = 'Unknown user'
331 flash[:notice] = 'Unknown user'
309 end
332 end
310 flash[:notice] = 'User added as admins'
333 flash[:notice] = 'User added as admins'
311 redirect_to :action => 'admin'
334 redirect_to :action => 'admin'
312 end
335 end
313
336
314 def revoke_admin
337 def revoke_admin
315 user = User.find(params[:id])
338 user = User.find(params[:id])
316 if user==nil
339 if user==nil
317 flash[:notice] = 'Unknown user'
340 flash[:notice] = 'Unknown user'
318 redirect_to :action => 'admin' and return
341 redirect_to :action => 'admin' and return
319 elsif user.login == 'root'
342 elsif user.login == 'root'
320 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
343 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
321 redirect_to :action => 'admin' and return
344 redirect_to :action => 'admin' and return
322 end
345 end
323
346
324 admin_role = Role.find_by_name('admin')
347 admin_role = Role.find_by_name('admin')
325 user.roles.delete(admin_role)
348 user.roles.delete(admin_role)
326 flash[:notice] = 'User permission revoked'
349 flash[:notice] = 'User permission revoked'
327 redirect_to :action => 'admin'
350 redirect_to :action => 'admin'
328 end
351 end
329
352
330 # mass mailing
353 # mass mailing
331
354
332 def mass_mailing
355 def mass_mailing
333 end
356 end
334
357
335 def bulk_mail
358 def bulk_mail
336 lines = params[:login_list]
359 lines = params[:login_list]
337 if !lines or lines.blank?
360 if !lines or lines.blank?
338 flash[:notice] = 'You entered an empty list.'
361 flash[:notice] = 'You entered an empty list.'
339 redirect_to :action => 'mass_mailing' and return
362 redirect_to :action => 'mass_mailing' and return
340 end
363 end
341
364
342 mail_subject = params[:subject]
365 mail_subject = params[:subject]
343 if !mail_subject or mail_subject.blank?
366 if !mail_subject or mail_subject.blank?
344 flash[:notice] = 'You entered an empty mail subject.'
367 flash[:notice] = 'You entered an empty mail subject.'
345 redirect_to :action => 'mass_mailing' and return
368 redirect_to :action => 'mass_mailing' and return
346 end
369 end
347
370
348 mail_body = params[:email_body]
371 mail_body = params[:email_body]
349 if !mail_body or mail_body.blank?
372 if !mail_body or mail_body.blank?
350 flash[:notice] = 'You entered an empty mail body.'
373 flash[:notice] = 'You entered an empty mail body.'
351 redirect_to :action => 'mass_mailing' and return
374 redirect_to :action => 'mass_mailing' and return
352 end
375 end
353
376
354 note = []
377 note = []
355 users = []
378 users = []
356 lines.split("\n").each do |line|
379 lines.split("\n").each do |line|
357 user = User.find_by_login(line.chomp)
380 user = User.find_by_login(line.chomp)
358 if user
381 if user
359 send_mail(user.email, mail_subject, mail_body)
382 send_mail(user.email, mail_subject, mail_body)
360 note << user.login
383 note << user.login
361 end
384 end
362 end
385 end
363
386
364 flash[:notice] = 'User(s) ' + note.join(', ') +
387 flash[:notice] = 'User(s) ' + note.join(', ') +
365 ' were successfully modified. '
388 ' were successfully modified. '
366 redirect_to :action => 'mass_mailing'
389 redirect_to :action => 'mass_mailing'
367 end
390 end
368
391
369 protected
392 protected
370
393
371 def random_password(length=5)
394 def random_password(length=5)
372 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
395 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
373 newpass = ""
396 newpass = ""
374 length.times { newpass << chars[rand(chars.size-1)] }
397 length.times { newpass << chars[rand(chars.size-1)] }
375 return newpass
398 return newpass
376 end
399 end
377
400
378 def import_from_file(f)
401 def import_from_file(f)
379 data_hash = YAML.load(f)
402 data_hash = YAML.load(f)
380 @import_log = ""
403 @import_log = ""
381
404
382 country_data = data_hash[:countries]
405 country_data = data_hash[:countries]
383 site_data = data_hash[:sites]
406 site_data = data_hash[:sites]
384 user_data = data_hash[:users]
407 user_data = data_hash[:users]
385
408
386 # import country
409 # import country
387 countries = {}
410 countries = {}
388 country_data.each_pair do |id,country|
411 country_data.each_pair do |id,country|
389 c = Country.find_by_name(country[:name])
412 c = Country.find_by_name(country[:name])
390 if c!=nil
413 if c!=nil
391 countries[id] = c
414 countries[id] = c
392 @import_log << "Found #{country[:name]}\n"
415 @import_log << "Found #{country[:name]}\n"
393 else
416 else
394 countries[id] = Country.new(:name => country[:name])
417 countries[id] = Country.new(:name => country[:name])
395 countries[id].save
418 countries[id].save
396 @import_log << "Created #{country[:name]}\n"
419 @import_log << "Created #{country[:name]}\n"
397 end
420 end
398 end
421 end
399
422
400 # import sites
423 # import sites
401 sites = {}
424 sites = {}
402 site_data.each_pair do |id,site|
425 site_data.each_pair do |id,site|
403 s = Site.find_by_name(site[:name])
426 s = Site.find_by_name(site[:name])
404 if s!=nil
427 if s!=nil
405 @import_log << "Found #{site[:name]}\n"
428 @import_log << "Found #{site[:name]}\n"
406 else
429 else
407 s = Site.new(:name => site[:name])
430 s = Site.new(:name => site[:name])
408 @import_log << "Created #{site[:name]}\n"
431 @import_log << "Created #{site[:name]}\n"
409 end
432 end
410 s.password = site[:password]
433 s.password = site[:password]
411 s.country = countries[site[:country_id]]
434 s.country = countries[site[:country_id]]
412 s.save
435 s.save
413 sites[id] = s
436 sites[id] = s
414 end
437 end
415
438
416 # import users
439 # import users
417 user_data.each_pair do |id,user|
440 user_data.each_pair do |id,user|
418 u = User.find_by_login(user[:login])
441 u = User.find_by_login(user[:login])
419 if u!=nil
442 if u!=nil
420 @import_log << "Found #{user[:login]}\n"
443 @import_log << "Found #{user[:login]}\n"
421 else
444 else
422 u = User.new(:login => user[:login])
445 u = User.new(:login => user[:login])
423 @import_log << "Created #{user[:login]}\n"
446 @import_log << "Created #{user[:login]}\n"
424 end
447 end
425 u.full_name = user[:name]
448 u.full_name = user[:name]
426 u.password = user[:password]
449 u.password = user[:password]
427 u.country = countries[user[:country_id]]
450 u.country = countries[user[:country_id]]
428 u.site = sites[user[:site_id]]
451 u.site = sites[user[:site_id]]
429 u.activated = true
452 u.activated = true
430 u.email = "empty-#{u.login}@none.com"
453 u.email = "empty-#{u.login}@none.com"
431 if not u.save
454 if not u.save
432 @import_log << "Errors\n"
455 @import_log << "Errors\n"
433 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
456 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
434 end
457 end
435 end
458 end
436
459
437 end
460 end
438
461
439 def logout_users(users)
462 def logout_users(users)
440 users.each do |user|
463 users.each do |user|
441 contest_stat = user.contest_stat(true)
464 contest_stat = user.contest_stat(true)
442 if contest_stat and !contest_stat.forced_logout
465 if contest_stat and !contest_stat.forced_logout
443 contest_stat.forced_logout = true
466 contest_stat.forced_logout = true
444 contest_stat.save
467 contest_stat.save
445 end
468 end
446 end
469 end
447 end
470 end
448
471
449 def send_contest_update_notification_email(user, contest)
472 def send_contest_update_notification_email(user, contest)
450 contest_title_name = GraderConfiguration['contest.name']
473 contest_title_name = GraderConfiguration['contest.name']
451 contest_name = contest.name
474 contest_name = contest.name
452 mail_subject = t('contest.notification.email_subject', {
475 mail_subject = t('contest.notification.email_subject', {
453 :contest_title_name => contest_title_name,
476 :contest_title_name => contest_title_name,
454 :contest_name => contest_name })
477 :contest_name => contest_name })
455 mail_body = t('contest.notification.email_body', {
478 mail_body = t('contest.notification.email_body', {
456 :full_name => user.full_name,
479 :full_name => user.full_name,
457 :contest_title_name => contest_title_name,
480 :contest_title_name => contest_title_name,
458 :contest_name => contest.name,
481 :contest_name => contest.name,
459 })
482 })
460
483
461 logger.info mail_body
484 logger.info mail_body
462 send_mail(user.email, mail_subject, mail_body)
485 send_mail(user.email, mail_subject, mail_body)
463 end
486 end
464
487
465 def find_contest_and_user_from_contest_id(id)
488 def find_contest_and_user_from_contest_id(id)
466 if id!='none'
489 if id!='none'
467 @contest = Contest.find(id)
490 @contest = Contest.find(id)
468 else
491 else
469 @contest = nil
492 @contest = nil
470 end
493 end
471 if @contest
494 if @contest
472 @users = @contest.users
495 @users = @contest.users
473 else
496 else
474 @users = User.find_users_with_no_contest
497 @users = User.find_users_with_no_contest
475 end
498 end
476 return [@contest, @users]
499 return [@contest, @users]
477 end
500 end
501 +
502 + def gen_csv_from_scorearray(scorearray,problem)
503 + CSV.generate do |csv|
504 + #add header
505 + header = ['User','Name', 'Activated?', 'Logged in', 'Contest']
506 + problem.each { |p| header << p.name }
507 + header += ['Total','Passed']
508 + csv << header
509 + #add data
510 + scorearray.each do |sc|
511 + total = num_passed = 0
512 + row = Array.new
513 + sc.each_index do |i|
514 + if i == 0
515 + row << sc[i].login
516 + row << sc[i].full_name
517 + row << sc[i].activated
518 + row << (sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no')
519 + row << sc[i].contests.collect {|c| c.name}.join(', ')
520 + else
521 + row << sc[i][0]
522 + total += sc[i][0]
523 + num_passed += 1 if sc[i][1]
478 end
524 end
525 + end
526 + row << total
527 + row << num_passed
528 + csv << row
529 + end
530 + end
531 + end
532 + end
@@ -1,54 +1,57
1 - content_for :header do
1 - content_for :header do
2 = javascript_include_tag 'new'
2 = javascript_include_tag 'new'
3 = stylesheet_link_tag 'tablesorter-theme.cafe'
3 = stylesheet_link_tag 'tablesorter-theme.cafe'
4
4
5 %script{:type=>"text/javascript"}
5 %script{:type=>"text/javascript"}
6 $(function () {
6 $(function () {
7 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
7 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
9 $('#my_table').tablesorter({widgets: ['zebra']});
9 $('#my_table').tablesorter({widgets: ['zebra']});
10 });
10 });
11
11
12 %h1 User grading results
12 %h1 User grading results
13 %h2= params[:action] == 'user_stat' ? "Show scores from latest submission" : "Show max scores in submission range"
13 %h2= params[:action] == 'user_stat' ? "Show scores from latest submission" : "Show max scores in submission range"
14
14
15
15
16 - if @problem and @problem.errors
16 - if @problem and @problem.errors
17 =error_messages_for 'problem'
17 =error_messages_for 'problem'
18
18
19 = render partial: 'submission_range'
19 = render partial: 'submission_range'
20
20
21 - if params[:action] == 'user_stat'
21 - if params[:action] == 'user_stat'
22 - = "latest score"
22 + %h3 Latest score
23 + = link_to '[download csv with all problems]', controller: :user_admin, action: :user_stat, commit: 'download csv'
23 - else
24 - else
25 + %h3 Max score
24 = link_to '[Show only latest submissions]', controller: :user_admin, action: :user_stat
26 = link_to '[Show only latest submissions]', controller: :user_admin, action: :user_stat
27 + = link_to '[download csv with all problems]', controller: :user_admin, action: :user_stat_max, commit: 'download csv'
25
28
26 %table.tablesorter-cafe#my_table
29 %table.tablesorter-cafe#my_table
27 %thead
30 %thead
28 %tr
31 %tr
29 %th User
32 %th User
30 %th Name
33 %th Name
31 %th Activated?
34 %th Activated?
32 %th Logged in
35 %th Logged in
33 %th Contest(s)
36 %th Contest(s)
34 - @problems.each do |p|
37 - @problems.each do |p|
35 %th= p.name
38 %th= p.name
36 %th Total
39 %th Total
37 %th Passed
40 %th Passed
38 %tbody
41 %tbody
39 - @scorearray.each do |sc|
42 - @scorearray.each do |sc|
40 %tr{class: cycle('info-even','info-odd')}
43 %tr{class: cycle('info-even','info-odd')}
41 - total,num_passed = 0,0
44 - total,num_passed = 0,0
42 - sc.each_index do |i|
45 - sc.each_index do |i|
43 - if i == 0
46 - if i == 0
44 %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
47 %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
45 %td= sc[i].full_name
48 %td= sc[i].full_name
46 %td= sc[i].activated
49 %td= sc[i].activated
47 %td= sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no'
50 %td= sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no'
48 %td= sc[i].contests.collect {|c| c.name}.join(', ')
51 %td= sc[i].contests.collect {|c| c.name}.join(', ')
49 - else
52 - else
50 %td= sc[i][0]
53 %td= sc[i][0]
51 - total += sc[i][0]
54 - total += sc[i][0]
52 - num_passed += 1 if sc[i][1]
55 - num_passed += 1 if sc[i][1]
53 %td= total
56 %td= total
54 %td= num_passed
57 %td= num_passed
You need to be logged in to leave comments. Login now