Description:
merge
Commit status:
[Not Reviewed]
References:
merge java
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r511:d90a3f1b39d0 - - 8 files changed: 106 inserted, 39 deleted

@@ -0,0 +1,34
1 + :css
2 + .fix-width {
3 + font-family: "Consolas, Monaco, Droid Sans Mono,Mono, Monospace,Courier"
4 + }
5 +
6 + %h1 Problem stat: #{@problem.name}
7 + %h2 Overview
8 +
9 + %h2 Submissions
10 + - if @submissions and @submissions.count > 0
11 + %table.info#main_table
12 + %thead
13 + %tr.info-head
14 + %th ID
15 + %th Login
16 + %th Name
17 + %th Submitted_at
18 + %th Points
19 + %th comment
20 + %tbody
21 + - row_odd,curr = true,''
22 + - @submissions.each do |sub|
23 + - next unless sub.user
24 + - row_odd,curr = !row_odd, sub.user if curr != sub.user
25 + %tr{class: row_odd ? "info-odd" : "info-even"}
26 + %td= link_to sub.id, controller: 'graders', action: 'submission', id: sub.id
27 + %td= link_to sub.user.login, controller: :users, action: :profile, id: sub.user.id
28 + %td= sub.user.full_name
29 + %td= time_ago_in_words(sub.submitted_at) + " ago"
30 + %td= sub.points
31 + %td.fix-width= sub.grader_comment
32 + - else
33 + No submission
34 +
@@ -86,97 +86,97
86 elsif @description!=nil
86 elsif @description!=nil
87 if !@description.update_attributes(params[:description])
87 if !@description.update_attributes(params[:description])
88 flash[:notice] = 'Error saving description'
88 flash[:notice] = 'Error saving description'
89 render :action => 'edit' and return
89 render :action => 'edit' and return
90 end
90 end
91 end
91 end
92 if @problem.update_attributes(params[:problem])
92 if @problem.update_attributes(params[:problem])
93 flash[:notice] = 'Problem was successfully updated.'
93 flash[:notice] = 'Problem was successfully updated.'
94 redirect_to :action => 'show', :id => @problem
94 redirect_to :action => 'show', :id => @problem
95 else
95 else
96 render :action => 'edit'
96 render :action => 'edit'
97 end
97 end
98 end
98 end
99
99
100 def destroy
100 def destroy
101 Problem.find(params[:id]).destroy
101 Problem.find(params[:id]).destroy
102 redirect_to :action => 'list'
102 redirect_to :action => 'list'
103 end
103 end
104
104
105 def toggle
105 def toggle
106 @problem = Problem.find(params[:id])
106 @problem = Problem.find(params[:id])
107 @problem.available = !(@problem.available)
107 @problem.available = !(@problem.available)
108 @problem.save
108 @problem.save
109 end
109 end
110
110
111 def turn_all_off
111 def turn_all_off
112 Problem.find(:all,
112 Problem.find(:all,
113 :conditions => "available = 1").each do |problem|
113 :conditions => "available = 1").each do |problem|
114 problem.available = false
114 problem.available = false
115 problem.save
115 problem.save
116 end
116 end
117 redirect_to :action => 'list'
117 redirect_to :action => 'list'
118 end
118 end
119
119
120 def turn_all_on
120 def turn_all_on
121 Problem.find(:all,
121 Problem.find(:all,
122 :conditions => "available = 0").each do |problem|
122 :conditions => "available = 0").each do |problem|
123 problem.available = true
123 problem.available = true
124 problem.save
124 problem.save
125 end
125 end
126 redirect_to :action => 'list'
126 redirect_to :action => 'list'
127 end
127 end
128
128
129 def stat
129 def stat
130 @problem = Problem.find(params[:id])
130 @problem = Problem.find(params[:id])
131 if !@problem.available
131 if !@problem.available
132 redirect_to :controller => 'main', :action => 'list'
132 redirect_to :controller => 'main', :action => 'list'
133 else
133 else
134 - @submissions = Submission.find_all_last_by_problem(params[:id])
134 + @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
135 end
135 end
136 end
136 end
137
137
138 def manage
138 def manage
139 @problems = Problem.find(:all, :order => 'date_added DESC')
139 @problems = Problem.find(:all, :order => 'date_added DESC')
140 end
140 end
141
141
142 def do_manage
142 def do_manage
143 if params.has_key? 'change_date_added'
143 if params.has_key? 'change_date_added'
144 change_date_added
144 change_date_added
145 else params.has_key? 'add_to_contest'
145 else params.has_key? 'add_to_contest'
146 add_to_contest
146 add_to_contest
147 end
147 end
148 redirect_to :action => 'manage'
148 redirect_to :action => 'manage'
149 end
149 end
150
150
151 def import
151 def import
152 @allow_test_pair_import = allow_test_pair_import?
152 @allow_test_pair_import = allow_test_pair_import?
153 end
153 end
154
154
155 def do_import
155 def do_import
156 old_problem = Problem.find_by_name(params[:name])
156 old_problem = Problem.find_by_name(params[:name])
157 if !allow_test_pair_import? and params.has_key? :import_to_db
157 if !allow_test_pair_import? and params.has_key? :import_to_db
158 params.delete :import_to_db
158 params.delete :import_to_db
159 end
159 end
160 @problem, import_log = Problem.create_from_import_form_params(params,
160 @problem, import_log = Problem.create_from_import_form_params(params,
161 old_problem)
161 old_problem)
162
162
163 if !@problem.errors.empty?
163 if !@problem.errors.empty?
164 render :action => 'import' and return
164 render :action => 'import' and return
165 end
165 end
166
166
167 if old_problem!=nil
167 if old_problem!=nil
168 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
168 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
169 end
169 end
170 @log = import_log
170 @log = import_log
171 end
171 end
172
172
173 def remove_contest
173 def remove_contest
174 problem = Problem.find(params[:id])
174 problem = Problem.find(params[:id])
175 contest = Contest.find(params[:contest_id])
175 contest = Contest.find(params[:contest_id])
176 if problem!=nil and contest!=nil
176 if problem!=nil and contest!=nil
177 problem.contests.delete(contest)
177 problem.contests.delete(contest)
178 end
178 end
179 redirect_to :action => 'manage'
179 redirect_to :action => 'manage'
180 end
180 end
181
181
182 ##################################
182 ##################################
@@ -1,50 +1,53
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
@@ -77,135 +80,155
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
125 - @problems = Problem.find_available_problems
128 + if params[:commit] == 'download csv'
129 + @problems = Problem.all
130 + else
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
144 - @problems = Problem.find_available_problems
158 + if params[:commit] == 'download csv'
159 + @problems = Problem.all
160 + else
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
163 - render template: 'user_admin/user_stat'
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
185 + render template: 'user_admin/user_stat'
186 + end
164 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(', ') +
@@ -430,49 +453,80
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]
524 + end
525 + end
526 + row << total
527 + row << num_passed
528 + csv << row
529 + end
530 + end
531 + end
478 end
532 end
@@ -1,76 +1,76
1 class Submission < ActiveRecord::Base
1 class Submission < ActiveRecord::Base
2
2
3 belongs_to :language
3 belongs_to :language
4 belongs_to :problem
4 belongs_to :problem
5 belongs_to :user
5 belongs_to :user
6
6
7 before_validation :assign_problem
7 before_validation :assign_problem
8 before_validation :assign_language
8 before_validation :assign_language
9
9
10 validates_presence_of :source
10 validates_presence_of :source
11 validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long'
11 validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long'
12 validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short'
12 validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short'
13 validate :must_have_valid_problem
13 validate :must_have_valid_problem
14 validate :must_specify_language
14 validate :must_specify_language
15
15
16 before_save :assign_latest_number_if_new_recond
16 before_save :assign_latest_number_if_new_recond
17
17
18 def self.find_last_by_user_and_problem(user_id, problem_id)
18 def self.find_last_by_user_and_problem(user_id, problem_id)
19 last_sub = find(:first,
19 last_sub = find(:first,
20 :conditions => {:user_id => user_id,
20 :conditions => {:user_id => user_id,
21 :problem_id => problem_id},
21 :problem_id => problem_id},
22 :order => 'number DESC')
22 :order => 'number DESC')
23 return last_sub
23 return last_sub
24 end
24 end
25
25
26 def self.find_all_last_by_problem(problem_id)
26 def self.find_all_last_by_problem(problem_id)
27 # need to put in SQL command, maybe there's a better way
27 # need to put in SQL command, maybe there's a better way
28 - Submission.find_by_sql("SELECT * FROM submissions " +
28 + Submission.includes(:user).find_by_sql("SELECT * FROM submissions " +
29 "WHERE id = " +
29 "WHERE id = " +
30 "(SELECT MAX(id) FROM submissions AS subs " +
30 "(SELECT MAX(id) FROM submissions AS subs " +
31 "WHERE subs.user_id = submissions.user_id AND " +
31 "WHERE subs.user_id = submissions.user_id AND " +
32 "problem_id = " + problem_id.to_s + " " +
32 "problem_id = " + problem_id.to_s + " " +
33 "GROUP BY user_id) " +
33 "GROUP BY user_id) " +
34 "ORDER BY user_id")
34 "ORDER BY user_id")
35 end
35 end
36
36
37 def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id)
37 def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id)
38 records = Submission.where(problem_id: problem_id,user_id: user_id)
38 records = Submission.where(problem_id: problem_id,user_id: user_id)
39 records = records.where('id >= ?',since_id) if since_id > 0
39 records = records.where('id >= ?',since_id) if since_id > 0
40 records = records.where('id <= ?',until_id) if until_id > 0
40 records = records.where('id <= ?',until_id) if until_id > 0
41 records.all
41 records.all
42 end
42 end
43
43
44 def self.find_last_for_all_available_problems(user_id)
44 def self.find_last_for_all_available_problems(user_id)
45 submissions = Array.new
45 submissions = Array.new
46 problems = Problem.find_available_problems
46 problems = Problem.find_available_problems
47 problems.each do |problem|
47 problems.each do |problem|
48 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
48 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
49 submissions << sub if sub!=nil
49 submissions << sub if sub!=nil
50 end
50 end
51 submissions
51 submissions
52 end
52 end
53
53
54 def self.find_by_user_problem_number(user_id, problem_id, number)
54 def self.find_by_user_problem_number(user_id, problem_id, number)
55 Submission.find(:first,
55 Submission.find(:first,
56 :conditions => {
56 :conditions => {
57 :user_id => user_id,
57 :user_id => user_id,
58 :problem_id => problem_id,
58 :problem_id => problem_id,
59 :number => number
59 :number => number
60 })
60 })
61 end
61 end
62
62
63 def self.find_all_by_user_problem(user_id, problem_id)
63 def self.find_all_by_user_problem(user_id, problem_id)
64 Submission.find(:all,
64 Submission.find(:all,
65 :conditions => {
65 :conditions => {
66 :user_id => user_id,
66 :user_id => user_id,
67 :problem_id => problem_id,
67 :problem_id => problem_id,
68 })
68 })
69 end
69 end
70
70
71 def download_filename
71 def download_filename
72 if self.problem.output_only
72 if self.problem.output_only
73 return self.source_filename
73 return self.source_filename
74 else
74 else
75 timestamp = self.submitted_at.localtime.strftime("%H%M%S")
75 timestamp = self.submitted_at.localtime.strftime("%H%M%S")
76 return "#{self.problem.name}-#{timestamp}.#{self.language.ext}"
76 return "#{self.problem.name}-#{timestamp}.#{self.language.ext}"
@@ -1,18 +1,21
1 <tr class="info-<%= (problem_counter%2==0) ? "even" : "odd" %>">
1 <tr class="info-<%= (problem_counter%2==0) ? "even" : "odd" %>">
2 <td>
2 <td>
3 <%= "#{problem_counter+1}" %>
3 <%= "#{problem_counter+1}" %>
4 </td>
4 </td>
5 <td>
5 <td>
6 - <%= "(#{problem.name}) #{problem.full_name}" %>
6 + <%= "#{problem.name}"%>
7 + </td>
8 + <td>
9 + <%= "#{problem.full_name}" %>
7 <%= link_to_description_if_any "[#{t 'main.problem_desc'}]", problem %>
10 <%= link_to_description_if_any "[#{t 'main.problem_desc'}]", problem %>
8 </td>
11 </td>
9 <td align="center">
12 <td align="center">
10 <%= @prob_submissions[problem.id][:count] %>
13 <%= @prob_submissions[problem.id][:count] %>
11 </td>
14 </td>
12 <td>
15 <td>
13 <%= render :partial => 'submission_short',
16 <%= render :partial => 'submission_short',
14 :locals => {
17 :locals => {
15 :submission => @prob_submissions[problem.id][:submission],
18 :submission => @prob_submissions[problem.id][:submission],
16 :problem_name => problem.name }%>
19 :problem_name => problem.name }%>
17 </td>
20 </td>
18 </tr>
21 </tr>
@@ -1,51 +1,53
1 - content_for :head do
1 - content_for :head do
2 = javascript_include_tag "announcement_refresh"
2 = javascript_include_tag "announcement_refresh"
3
3
4 = user_title_bar(@user)
4 = user_title_bar(@user)
5
5
6 .announcementbox{:style => (@announcements.length==0 ? "display:none" : "")}
6 .announcementbox{:style => (@announcements.length==0 ? "display:none" : "")}
7 %span{:class => 'title'}
7 %span{:class => 'title'}
8 Announcements
8 Announcements
9 #announcementbox-body
9 #announcementbox-body
10 = render :partial => 'announcement', :collection => @announcements
10 = render :partial => 'announcement', :collection => @announcements
11
11
12 - if GraderConfiguration.show_submitbox_to?(@user)
12 - if GraderConfiguration.show_submitbox_to?(@user)
13 .submitbox
13 .submitbox
14 = error_messages_for 'submission'
14 = error_messages_for 'submission'
15 = render :partial => 'submission_box'
15 = render :partial => 'submission_box'
16
16
17
17
18 %hr/
18 %hr/
19
19
20 - if (GraderConfiguration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true)
20 - if (GraderConfiguration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true)
21 %p=t 'main.start_soon'
21 %p=t 'main.start_soon'
22
22
23 - if GraderConfiguration.show_tasks_to?(@user)
23 - if GraderConfiguration.show_tasks_to?(@user)
24 - if not GraderConfiguration.multicontests?
24 - if not GraderConfiguration.multicontests?
25 %table.info
25 %table.info
26 %tr.info-head
26 %tr.info-head
27 %th
27 %th
28 - %th Tasks
28 + %th Tasks name
29 + %th Full name
29 %th # of sub(s)
30 %th # of sub(s)
30 %th Results
31 %th Results
31 = render :partial => 'problem', :collection => @problems
32 = render :partial => 'problem', :collection => @problems
32 - else
33 - else
33 - @contest_problems.each do |cp|
34 - @contest_problems.each do |cp|
34 - if cp[:problems].length > 0
35 - if cp[:problems].length > 0
35 %h2{:class =>'contest-title'}
36 %h2{:class =>'contest-title'}
36 = "#{cp[:contest] ? cp[:contest].title : 'Public problems'}"
37 = "#{cp[:contest] ? cp[:contest].title : 'Public problems'}"
37 %table.info
38 %table.info
38 %tr.info-head
39 %tr.info-head
39 %th
40 %th
40 - %th Tasks
41 + %th Tasks name
42 + %th Full name
41 %th # of sub(s)
43 %th # of sub(s)
42 %th Results
44 %th Results
43 = render :partial => 'problem', :collection => cp[:problems]
45 = render :partial => 'problem', :collection => cp[:problems]
44
46
45
47
46 %hr/
48 %hr/
47
49
48 %script{:type => 'text/javascript'}
50 %script{:type => 'text/javascript'}
49 = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';"
51 = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';"
50 Announcement.registerRefreshEventTimer();
52 Announcement.registerRefreshEventTimer();
51
53
@@ -1,56 +1,59
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 %th Section
37 %th Section
35 - @problems.each do |p|
38 - @problems.each do |p|
36 %th= p.name
39 %th= p.name
37 %th Total
40 %th Total
38 %th Passed
41 %th Passed
39 %tbody
42 %tbody
40 - @scorearray.each do |sc|
43 - @scorearray.each do |sc|
41 %tr{class: cycle('info-even','info-odd')}
44 %tr{class: cycle('info-even','info-odd')}
42 - total,num_passed = 0,0
45 - total,num_passed = 0,0
43 - sc.each_index do |i|
46 - sc.each_index do |i|
44 - if i == 0
47 - if i == 0
45 %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
48 %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
46 %td= sc[i].full_name
49 %td= sc[i].full_name
47 %td= sc[i].activated
50 %td= sc[i].activated
48 %td= sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no'
51 %td= sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no'
49 %td= sc[i].contests.collect {|c| c.name}.join(', ')
52 %td= sc[i].contests.collect {|c| c.name}.join(', ')
50 %td= sc[i].section
53 %td= sc[i].section
51 - else
54 - else
52 %td= sc[i][0]
55 %td= sc[i][0]
53 - total += sc[i][0]
56 - total += sc[i][0]
54 - num_passed += 1 if sc[i][1]
57 - num_passed += 1 if sc[i][1]
55 %td= total
58 %td= total
56 %td= num_passed
59 %td= num_passed
deleted file
You need to be logged in to leave comments. Login now