Description:
- DRY score table - add report to check maximum score of selected problem
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r601:ff006e008326 - - 6 files changed: 46 inserted, 41 deleted

@@ -0,0 +1,34
1 + %table.table.sortable.table-striped.table-bordered.table-condensed
2 + %thead
3 + %tr
4 + %th Login
5 + %th Name
6 + %th Activated?
7 + %th Logged_in
8 + %th Contest(s)
9 + %th Remark
10 + - @problems.each do |p|
11 + %th.text-right= p.name
12 + %th.text-right Total
13 + %th.text-right Passed
14 + %tbody
15 + - @scorearray.each do |sc|
16 + %tr
17 + - total,num_passed = 0,0
18 + - sc.each_index do |i|
19 + - if i == 0
20 + %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
21 + %td= sc[i].full_name
22 + %td= sc[i].activated
23 + %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
24 + %td= sc[i].contests.collect {|c| c.name}.join(', ')
25 + %td= sc[i].remark
26 + - else
27 + %td.text-right= sc[i][0]
28 + - total += sc[i][0]
29 + - num_passed += 1 if sc[i][1]
30 + %td.text-right= total
31 + %td.text-right= num_passed
32 +
33 + :javascript
34 + $.bootstrapSortable(true,'reversed')
@@ -0,0 +1,3
1 + %h1 Current Score
2 +
3 + = render "score_table"
@@ -1,438 +1,441
1 class ReportController < ApplicationController
1 class ReportController < ApplicationController
2
2
3 + before_filter :authenticate
4 +
3 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize, :show_max_score]
5 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize, :show_max_score]
4
6
5 before_filter(only: [:problem_hof]) { |c|
7 before_filter(only: [:problem_hof]) { |c|
6 return false unless authenticate
8 return false unless authenticate
7
9
8 if GraderConfiguration["right.user_view_submission"]
10 if GraderConfiguration["right.user_view_submission"]
9 return true;
11 return true;
10 end
12 end
11
13
12 admin_authorization
14 admin_authorization
13 }
15 }
14
16
15 def max_score
17 def max_score
16 end
18 end
17
19
18 def current_score
20 def current_score
19 @problems = Problem.find_available_problems
21 @problems = Problem.find_available_problems
20 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
22 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
21 - @scorearray = calculate_max_score(problems, users,0,0,{max: true})
23 + @scorearray = calculate_max_score(@problems, @users,0,0,true)
22
24
23 #rencer accordingly
25 #rencer accordingly
24 if params[:commit] == 'download csv' then
26 if params[:commit] == 'download csv' then
25 csv = gen_csv_from_scorearray(@scorearray,@problems)
27 csv = gen_csv_from_scorearray(@scorearray,@problems)
26 send_data csv, filename: 'max_score.csv'
28 send_data csv, filename: 'max_score.csv'
27 else
29 else
28 #render template: 'user_admin/user_stat'
30 #render template: 'user_admin/user_stat'
29 render 'current_score'
31 render 'current_score'
30 end
32 end
31 end
33 end
32
34
33 def show_max_score
35 def show_max_score
34 #process parameters
36 #process parameters
35 #problems
37 #problems
36 @problems = []
38 @problems = []
37 params[:problem_id].each do |id|
39 params[:problem_id].each do |id|
38 next unless id.strip != ""
40 next unless id.strip != ""
39 - @problems << Problem.find(id.to_i)
41 + pid = Problem.find_by_id(id.to_i)
42 + @problems << pid if pid
40 end
43 end
41
44
42 #users
45 #users
43 @users = if params[:user] == "all" then
46 @users = if params[:user] == "all" then
44 User.find(:all, :include => [:contests, :contest_stat])
47 User.find(:all, :include => [:contests, :contest_stat])
45 else
48 else
46 User.includes(:contests).includes(:contest_stat).where(enabled: true)
49 User.includes(:contests).includes(:contest_stat).where(enabled: true)
47 end
50 end
48
51
49 #set up range from param
52 #set up range from param
50 since_id = params.fetch(:min_id, 0).to_i
53 since_id = params.fetch(:min_id, 0).to_i
51 until_id = params.fetch(:max_id, 0).to_i
54 until_id = params.fetch(:max_id, 0).to_i
52
55
53 #calculate the routine
56 #calculate the routine
54 - @scorearray = calculate_max_score(problems, users,since_id,until_id)
57 + @scorearray = calculate_max_score(@problems, @users,since_id,until_id)
55
58
56 #rencer accordingly
59 #rencer accordingly
57 if params[:commit] == 'download csv' then
60 if params[:commit] == 'download csv' then
58 csv = gen_csv_from_scorearray(@scorearray,@problems)
61 csv = gen_csv_from_scorearray(@scorearray,@problems)
59 send_data csv, filename: 'max_score.csv'
62 send_data csv, filename: 'max_score.csv'
60 else
63 else
61 #render template: 'user_admin/user_stat'
64 #render template: 'user_admin/user_stat'
62 render 'max_score'
65 render 'max_score'
63 end
66 end
64
67
65 end
68 end
66
69
67 def score
70 def score
68 if params[:commit] == 'download csv'
71 if params[:commit] == 'download csv'
69 @problems = Problem.all
72 @problems = Problem.all
70 else
73 else
71 @problems = Problem.find_available_problems
74 @problems = Problem.find_available_problems
72 end
75 end
73 @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
76 @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
74 @scorearray = Array.new
77 @scorearray = Array.new
75 @users.each do |u|
78 @users.each do |u|
76 ustat = Array.new
79 ustat = Array.new
77 ustat[0] = u
80 ustat[0] = u
78 @problems.each do |p|
81 @problems.each do |p|
79 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
82 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
80 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
83 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
81 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
84 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
82 else
85 else
83 ustat << [0,false]
86 ustat << [0,false]
84 end
87 end
85 end
88 end
86 @scorearray << ustat
89 @scorearray << ustat
87 end
90 end
88 if params[:commit] == 'download csv' then
91 if params[:commit] == 'download csv' then
89 csv = gen_csv_from_scorearray(@scorearray,@problems)
92 csv = gen_csv_from_scorearray(@scorearray,@problems)
90 send_data csv, filename: 'last_score.csv'
93 send_data csv, filename: 'last_score.csv'
91 else
94 else
92 render template: 'user_admin/user_stat'
95 render template: 'user_admin/user_stat'
93 end
96 end
94
97
95 end
98 end
96
99
97 def login_stat
100 def login_stat
98 @logins = Array.new
101 @logins = Array.new
99
102
100 date_and_time = '%Y-%m-%d %H:%M'
103 date_and_time = '%Y-%m-%d %H:%M'
101 begin
104 begin
102 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
105 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
103 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
106 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
104 rescue
107 rescue
105 @since_time = DateTime.new(1000,1,1)
108 @since_time = DateTime.new(1000,1,1)
106 end
109 end
107 begin
110 begin
108 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
111 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
109 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
112 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
110 rescue
113 rescue
111 @until_time = DateTime.new(3000,1,1)
114 @until_time = DateTime.new(3000,1,1)
112 end
115 end
113
116
114 User.all.each do |user|
117 User.all.each do |user|
115 @logins << { id: user.id,
118 @logins << { id: user.id,
116 login: user.login,
119 login: user.login,
117 full_name: user.full_name,
120 full_name: user.full_name,
118 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
121 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
119 user.id,@since_time,@until_time)
122 user.id,@since_time,@until_time)
120 .count(:id),
123 .count(:id),
121 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
124 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
122 user.id,@since_time,@until_time)
125 user.id,@since_time,@until_time)
123 .minimum(:created_at),
126 .minimum(:created_at),
124 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
127 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
125 user.id,@since_time,@until_time)
128 user.id,@since_time,@until_time)
126 .maximum(:created_at),
129 .maximum(:created_at),
127 ip: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
130 ip: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
128 user.id,@since_time,@until_time)
131 user.id,@since_time,@until_time)
129 .select(:ip_address).uniq
132 .select(:ip_address).uniq
130
133
131 }
134 }
132 end
135 end
133 end
136 end
134
137
135 def submission_stat
138 def submission_stat
136
139
137 date_and_time = '%Y-%m-%d %H:%M'
140 date_and_time = '%Y-%m-%d %H:%M'
138 begin
141 begin
139 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
142 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
140 rescue
143 rescue
141 @since_time = DateTime.new(1000,1,1)
144 @since_time = DateTime.new(1000,1,1)
142 end
145 end
143 begin
146 begin
144 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
147 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
145 rescue
148 rescue
146 @until_time = DateTime.new(3000,1,1)
149 @until_time = DateTime.new(3000,1,1)
147 end
150 end
148
151
149 @submissions = {}
152 @submissions = {}
150
153
151 User.find_each do |user|
154 User.find_each do |user|
152 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
155 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
153 end
156 end
154
157
155 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
158 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
156 if @submissions[s.user_id]
159 if @submissions[s.user_id]
157 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
160 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
158 a = Problem.find_by_id(s.problem_id)
161 a = Problem.find_by_id(s.problem_id)
159 @submissions[s.user_id][:sub][s.problem_id] =
162 @submissions[s.user_id][:sub][s.problem_id] =
160 { prob_name: (a ? a.full_name : '(NULL)'),
163 { prob_name: (a ? a.full_name : '(NULL)'),
161 sub_ids: [s.id] }
164 sub_ids: [s.id] }
162 else
165 else
163 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
166 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
164 end
167 end
165 @submissions[s.user_id][:count] += 1
168 @submissions[s.user_id][:count] += 1
166 end
169 end
167 end
170 end
168 end
171 end
169
172
170 def problem_hof
173 def problem_hof
171 # gen problem list
174 # gen problem list
172 @user = User.find(session[:user_id])
175 @user = User.find(session[:user_id])
173 @problems = @user.available_problems
176 @problems = @user.available_problems
174
177
175 # get selected problems or the default
178 # get selected problems or the default
176 if params[:id]
179 if params[:id]
177 begin
180 begin
178 @problem = Problem.available.find(params[:id])
181 @problem = Problem.available.find(params[:id])
179 rescue
182 rescue
180 redirect_to action: :problem_hof
183 redirect_to action: :problem_hof
181 flash[:notice] = 'Error: submissions for that problem are not viewable.'
184 flash[:notice] = 'Error: submissions for that problem are not viewable.'
182 return
185 return
183 end
186 end
184 end
187 end
185
188
186 return unless @problem
189 return unless @problem
187
190
188 @by_lang = {} #aggregrate by language
191 @by_lang = {} #aggregrate by language
189
192
190 range =65
193 range =65
191 @histogram = { data: Array.new(range,0), summary: {} }
194 @histogram = { data: Array.new(range,0), summary: {} }
192 @summary = {count: 0, solve: 0, attempt: 0}
195 @summary = {count: 0, solve: 0, attempt: 0}
193 user = Hash.new(0)
196 user = Hash.new(0)
194 Submission.where(problem_id: @problem.id).find_each do |sub|
197 Submission.where(problem_id: @problem.id).find_each do |sub|
195 #histogram
198 #histogram
196 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
199 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
197 @histogram[:data][d.to_i] += 1 if d < range
200 @histogram[:data][d.to_i] += 1 if d < range
198
201
199 next unless sub.points
202 next unless sub.points
200 @summary[:count] += 1
203 @summary[:count] += 1
201 user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
204 user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
202
205
203 lang = Language.find_by_id(sub.language_id)
206 lang = Language.find_by_id(sub.language_id)
204 next unless lang
207 next unless lang
205 next unless sub.points >= @problem.full_score
208 next unless sub.points >= @problem.full_score
206
209
207 #initialize
210 #initialize
208 unless @by_lang.has_key?(lang.pretty_name)
211 unless @by_lang.has_key?(lang.pretty_name)
209 @by_lang[lang.pretty_name] = {
212 @by_lang[lang.pretty_name] = {
210 runtime: { avail: false, value: 2**30-1 },
213 runtime: { avail: false, value: 2**30-1 },
211 memory: { avail: false, value: 2**30-1 },
214 memory: { avail: false, value: 2**30-1 },
212 length: { avail: false, value: 2**30-1 },
215 length: { avail: false, value: 2**30-1 },
213 first: { avail: false, value: DateTime.new(3000,1,1) }
216 first: { avail: false, value: DateTime.new(3000,1,1) }
214 }
217 }
215 end
218 end
216
219
217 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
220 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
218 @by_lang[lang.pretty_name][:runtime] = { avail: true, user_id: sub.user_id, value: sub.max_runtime, sub_id: sub.id }
221 @by_lang[lang.pretty_name][:runtime] = { avail: true, user_id: sub.user_id, value: sub.max_runtime, sub_id: sub.id }
219 end
222 end
220
223
221 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
224 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
222 @by_lang[lang.pretty_name][:memory] = { avail: true, user_id: sub.user_id, value: sub.peak_memory, sub_id: sub.id }
225 @by_lang[lang.pretty_name][:memory] = { avail: true, user_id: sub.user_id, value: sub.peak_memory, sub_id: sub.id }
223 end
226 end
224
227
225 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
228 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
226 !sub.user.admin?
229 !sub.user.admin?
227 @by_lang[lang.pretty_name][:first] = { avail: true, user_id: sub.user_id, value: sub.submitted_at, sub_id: sub.id }
230 @by_lang[lang.pretty_name][:first] = { avail: true, user_id: sub.user_id, value: sub.submitted_at, sub_id: sub.id }
228 end
231 end
229
232
230 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
233 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
231 @by_lang[lang.pretty_name][:length] = { avail: true, user_id: sub.user_id, value: sub.effective_code_length, sub_id: sub.id }
234 @by_lang[lang.pretty_name][:length] = { avail: true, user_id: sub.user_id, value: sub.effective_code_length, sub_id: sub.id }
232 end
235 end
233 end
236 end
234
237
235 #process user_id
238 #process user_id
236 @by_lang.each do |lang,prop|
239 @by_lang.each do |lang,prop|
237 prop.each do |k,v|
240 prop.each do |k,v|
238 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
241 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
239 end
242 end
240 end
243 end
241
244
242 #sum into best
245 #sum into best
243 if @by_lang and @by_lang.first
246 if @by_lang and @by_lang.first
244 @best = @by_lang.first[1].clone
247 @best = @by_lang.first[1].clone
245 @by_lang.each do |lang,prop|
248 @by_lang.each do |lang,prop|
246 if @best[:runtime][:value] >= prop[:runtime][:value]
249 if @best[:runtime][:value] >= prop[:runtime][:value]
247 @best[:runtime] = prop[:runtime]
250 @best[:runtime] = prop[:runtime]
248 @best[:runtime][:lang] = lang
251 @best[:runtime][:lang] = lang
249 end
252 end
250 if @best[:memory][:value] >= prop[:memory][:value]
253 if @best[:memory][:value] >= prop[:memory][:value]
251 @best[:memory] = prop[:memory]
254 @best[:memory] = prop[:memory]
252 @best[:memory][:lang] = lang
255 @best[:memory][:lang] = lang
253 end
256 end
254 if @best[:length][:value] >= prop[:length][:value]
257 if @best[:length][:value] >= prop[:length][:value]
255 @best[:length] = prop[:length]
258 @best[:length] = prop[:length]
256 @best[:length][:lang] = lang
259 @best[:length][:lang] = lang
257 end
260 end
258 if @best[:first][:value] >= prop[:first][:value]
261 if @best[:first][:value] >= prop[:first][:value]
259 @best[:first] = prop[:first]
262 @best[:first] = prop[:first]
260 @best[:first][:lang] = lang
263 @best[:first][:lang] = lang
261 end
264 end
262 end
265 end
263 end
266 end
264
267
265 @histogram[:summary][:max] = [@histogram[:data].max,1].max
268 @histogram[:summary][:max] = [@histogram[:data].max,1].max
266 @summary[:attempt] = user.count
269 @summary[:attempt] = user.count
267 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
270 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
268 end
271 end
269
272
270 def stuck #report struggling user,problem
273 def stuck #report struggling user,problem
271 # init
274 # init
272 user,problem = nil
275 user,problem = nil
273 solve = true
276 solve = true
274 tries = 0
277 tries = 0
275 @struggle = Array.new
278 @struggle = Array.new
276 record = {}
279 record = {}
277 Submission.includes(:problem,:user).order(:problem_id,:user_id).find_each do |sub|
280 Submission.includes(:problem,:user).order(:problem_id,:user_id).find_each do |sub|
278 next unless sub.problem and sub.user
281 next unless sub.problem and sub.user
279 if user != sub.user_id or problem != sub.problem_id
282 if user != sub.user_id or problem != sub.problem_id
280 @struggle << { user: record[:user], problem: record[:problem], tries: tries } unless solve
283 @struggle << { user: record[:user], problem: record[:problem], tries: tries } unless solve
281 record = {user: sub.user, problem: sub.problem}
284 record = {user: sub.user, problem: sub.problem}
282 user,problem = sub.user_id, sub.problem_id
285 user,problem = sub.user_id, sub.problem_id
283 solve = false
286 solve = false
284 tries = 0
287 tries = 0
285 end
288 end
286 if sub.points >= sub.problem.full_score
289 if sub.points >= sub.problem.full_score
287 solve = true
290 solve = true
288 else
291 else
289 tries += 1
292 tries += 1
290 end
293 end
291 end
294 end
292 @struggle.sort!{|a,b| b[:tries] <=> a[:tries] }
295 @struggle.sort!{|a,b| b[:tries] <=> a[:tries] }
293 @struggle = @struggle[0..50]
296 @struggle = @struggle[0..50]
294 end
297 end
295
298
296
299
297 def multiple_login
300 def multiple_login
298 #user with multiple IP
301 #user with multiple IP
299 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:login)
302 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:login)
300 last,count = 0,0
303 last,count = 0,0
301 first = 0
304 first = 0
302 @users = []
305 @users = []
303 raw.each do |r|
306 raw.each do |r|
304 if last != r.user.login
307 if last != r.user.login
305 count = 1
308 count = 1
306 last = r.user.login
309 last = r.user.login
307 first = r
310 first = r
308 else
311 else
309 @users << first if count == 1
312 @users << first if count == 1
310 @users << r
313 @users << r
311 count += 1
314 count += 1
312 end
315 end
313 end
316 end
314
317
315 #IP with multiple user
318 #IP with multiple user
316 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:ip_address)
319 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:ip_address)
317 last,count = 0,0
320 last,count = 0,0
318 first = 0
321 first = 0
319 @ip = []
322 @ip = []
320 raw.each do |r|
323 raw.each do |r|
321 if last != r.ip_address
324 if last != r.ip_address
322 count = 1
325 count = 1
323 last = r.ip_address
326 last = r.ip_address
324 first = r
327 first = r
325 else
328 else
326 @ip << first if count == 1
329 @ip << first if count == 1
327 @ip << r
330 @ip << r
328 count += 1
331 count += 1
329 end
332 end
330 end
333 end
331 end
334 end
332
335
333 def cheat_report
336 def cheat_report
334 date_and_time = '%Y-%m-%d %H:%M'
337 date_and_time = '%Y-%m-%d %H:%M'
335 begin
338 begin
336 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
339 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
337 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
340 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
338 rescue
341 rescue
339 @since_time = Time.zone.now.ago( 90.minutes)
342 @since_time = Time.zone.now.ago( 90.minutes)
340 end
343 end
341 begin
344 begin
342 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
345 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
343 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
346 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
344 rescue
347 rescue
345 @until_time = Time.zone.now
348 @until_time = Time.zone.now
346 end
349 end
347
350
348 #multi login
351 #multi login
349 @ml = Login.joins(:user).where("logins.created_at >= ? and logins.created_at <= ?",@since_time,@until_time).select('users.login,count(distinct ip_address) as count,users.full_name').group("users.id").having("count > 1")
352 @ml = Login.joins(:user).where("logins.created_at >= ? and logins.created_at <= ?",@since_time,@until_time).select('users.login,count(distinct ip_address) as count,users.full_name').group("users.id").having("count > 1")
350
353
351 st = <<-SQL
354 st = <<-SQL
352 SELECT l2.*
355 SELECT l2.*
353 FROM logins l2 INNER JOIN
356 FROM logins l2 INNER JOIN
354 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
357 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
355 FROM logins l
358 FROM logins l
356 INNER JOIN users u ON l.user_id = u.id
359 INNER JOIN users u ON l.user_id = u.id
357 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
360 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
358 GROUP BY u.id
361 GROUP BY u.id
359 HAVING count > 1
362 HAVING count > 1
360 ) ml ON l2.user_id = ml.id
363 ) ml ON l2.user_id = ml.id
361 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
364 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
362 UNION
365 UNION
363 SELECT l2.*
366 SELECT l2.*
364 FROM logins l2 INNER JOIN
367 FROM logins l2 INNER JOIN
365 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
368 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
366 FROM logins l
369 FROM logins l
367 INNER JOIN users u ON l.user_id = u.id
370 INNER JOIN users u ON l.user_id = u.id
368 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
371 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
369 GROUP BY l.ip_address
372 GROUP BY l.ip_address
370 HAVING count > 1
373 HAVING count > 1
371 ) ml on ml.ip_address = l2.ip_address
374 ) ml on ml.ip_address = l2.ip_address
372 INNER JOIN users u ON l2.user_id = u.id
375 INNER JOIN users u ON l2.user_id = u.id
373 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
376 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
374 ORDER BY ip_address,created_at
377 ORDER BY ip_address,created_at
375 SQL
378 SQL
376 @mld = Login.find_by_sql(st)
379 @mld = Login.find_by_sql(st)
377
380
378 st = <<-SQL
381 st = <<-SQL
379 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
382 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
380 FROM submissions s INNER JOIN
383 FROM submissions s INNER JOIN
381 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
384 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
382 FROM logins l
385 FROM logins l
383 INNER JOIN users u ON l.user_id = u.id
386 INNER JOIN users u ON l.user_id = u.id
384 WHERE l.created_at >= ? and l.created_at <= ?
387 WHERE l.created_at >= ? and l.created_at <= ?
385 GROUP BY u.id
388 GROUP BY u.id
386 HAVING count > 1
389 HAVING count > 1
387 ) ml ON s.user_id = ml.id
390 ) ml ON s.user_id = ml.id
388 WHERE s.submitted_at >= ? and s.submitted_at <= ?
391 WHERE s.submitted_at >= ? and s.submitted_at <= ?
389 UNION
392 UNION
390 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
393 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
391 FROM submissions s INNER JOIN
394 FROM submissions s INNER JOIN
392 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
395 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
393 FROM logins l
396 FROM logins l
394 INNER JOIN users u ON l.user_id = u.id
397 INNER JOIN users u ON l.user_id = u.id
395 WHERE l.created_at >= ? and l.created_at <= ?
398 WHERE l.created_at >= ? and l.created_at <= ?
396 GROUP BY l.ip_address
399 GROUP BY l.ip_address
397 HAVING count > 1
400 HAVING count > 1
398 ) ml on ml.ip_address = s.ip_address
401 ) ml on ml.ip_address = s.ip_address
399 WHERE s.submitted_at >= ? and s.submitted_at <= ?
402 WHERE s.submitted_at >= ? and s.submitted_at <= ?
400 ORDER BY ip_address,submitted_at
403 ORDER BY ip_address,submitted_at
401 SQL
404 SQL
402 @subs = Submission.joins(:problem).find_by_sql([st,@since_time,@until_time,
405 @subs = Submission.joins(:problem).find_by_sql([st,@since_time,@until_time,
403 @since_time,@until_time,
406 @since_time,@until_time,
404 @since_time,@until_time,
407 @since_time,@until_time,
405 @since_time,@until_time])
408 @since_time,@until_time])
406
409
407 end
410 end
408
411
409 def cheat_scruntinize
412 def cheat_scruntinize
410 #convert date & time
413 #convert date & time
411 date_and_time = '%Y-%m-%d %H:%M'
414 date_and_time = '%Y-%m-%d %H:%M'
412 begin
415 begin
413 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
416 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
414 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
417 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
415 rescue
418 rescue
416 @since_time = Time.zone.now.ago( 90.minutes)
419 @since_time = Time.zone.now.ago( 90.minutes)
417 end
420 end
418 begin
421 begin
419 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
422 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
420 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
423 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
421 rescue
424 rescue
422 @until_time = Time.zone.now
425 @until_time = Time.zone.now
423 end
426 end
424
427
425 #convert sid
428 #convert sid
426 @sid = params[:SID].split(/[,\s]/) if params[:SID]
429 @sid = params[:SID].split(/[,\s]/) if params[:SID]
427 unless @sid and @sid.size > 0
430 unless @sid and @sid.size > 0
428 return
431 return
429 redirect_to actoin: :cheat_scruntinize
432 redirect_to actoin: :cheat_scruntinize
430 flash[:notice] = 'Please enter at least 1 student id'
433 flash[:notice] = 'Please enter at least 1 student id'
431 end
434 end
432 mark = Array.new(@sid.size,'?')
435 mark = Array.new(@sid.size,'?')
433 condition = "(u.login = " + mark.join(' OR u.login = ') + ')'
436 condition = "(u.login = " + mark.join(' OR u.login = ') + ')'
434
437
435 @st = <<-SQL
438 @st = <<-SQL
436 SELECT l.created_at as submitted_at ,-1 as id,u.login,u.full_name,l.ip_address,"" as problem_id,"" as points,l.user_id
439 SELECT l.created_at as submitted_at ,-1 as id,u.login,u.full_name,l.ip_address,"" as problem_id,"" as points,l.user_id
437 FROM logins l INNER JOIN users u on l.user_id = u.id
440 FROM logins l INNER JOIN users u on l.user_id = u.id
438 WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition}
441 WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition}
@@ -1,84 +1,84
1 %header.navbar.navbar-default.navbar-fixed-top
1 %header.navbar.navbar-default.navbar-fixed-top
2 %nav
2 %nav
3 .container-fluid
3 .container-fluid
4 .navbar-header
4 .navbar-header
5 %a.navbar-brand{href: main_list_path}
5 %a.navbar-brand{href: main_list_path}
6 %span.glyphicon.glyphicon-home
6 %span.glyphicon.glyphicon-home
7 MAIN
7 MAIN
8 .collapse.navbar-collapse
8 .collapse.navbar-collapse
9 %ul.nav.navbar-nav
9 %ul.nav.navbar-nav
10 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
10 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
11 //= add_menu("#{I18n.t 'menu.tasks'}", 'tasks', 'list')
11 //= add_menu("#{I18n.t 'menu.tasks'}", 'tasks', 'list')
12 %li.dropdown
12 %li.dropdown
13 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
13 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
14 = "#{I18n.t 'menu.submissions'}"
14 = "#{I18n.t 'menu.submissions'}"
15 %span.caret
15 %span.caret
16 %ul.dropdown-menu
16 %ul.dropdown-menu
17 = add_menu("View", 'main', 'submission')
17 = add_menu("View", 'main', 'submission')
18 = add_menu("Self Test", 'test', 'index')
18 = add_menu("Self Test", 'test', 'index')
19 - if GraderConfiguration['right.user_hall_of_fame']
19 - if GraderConfiguration['right.user_hall_of_fame']
20 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
20 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
21 / display MODE button (with countdown in contest mode)
21 / display MODE button (with countdown in contest mode)
22 - if GraderConfiguration.analysis_mode?
22 - if GraderConfiguration.analysis_mode?
23 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
23 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
24 - elsif GraderConfiguration.time_limit_mode?
24 - elsif GraderConfiguration.time_limit_mode?
25 - if @current_user.contest_finished?
25 - if @current_user.contest_finished?
26 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
26 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
27 - elsif !@current_user.contest_started?
27 - elsif !@current_user.contest_started?
28 %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started')
28 %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started')
29 - else
29 - else
30 %div.navbar-btn.btn.btn-primary#countdown asdf
30 %div.navbar-btn.btn.btn-primary#countdown asdf
31 :javascript
31 :javascript
32 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
32 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
33 / admin section
33 / admin section
34 - if (@current_user!=nil) and (session[:admin])
34 - if (@current_user!=nil) and (session[:admin])
35 %li.dropdown
35 %li.dropdown
36 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
36 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
37 Manage
37 Manage
38 %span.caret
38 %span.caret
39 %ul.dropdown-menu
39 %ul.dropdown-menu
40 = add_menu( 'Announcements', 'announcements', 'index')
40 = add_menu( 'Announcements', 'announcements', 'index')
41 = add_menu( 'Problems', 'problems', 'index')
41 = add_menu( 'Problems', 'problems', 'index')
42 = add_menu( 'Users', 'user_admin', 'index')
42 = add_menu( 'Users', 'user_admin', 'index')
43 = add_menu( 'Graders', 'graders', 'list')
43 = add_menu( 'Graders', 'graders', 'list')
44 = add_menu( 'Message ', 'messages', 'console')
44 = add_menu( 'Message ', 'messages', 'console')
45 %li.divider{role: 'separator'}
45 %li.divider{role: 'separator'}
46 = add_menu( 'System config', 'configurations', 'index')
46 = add_menu( 'System config', 'configurations', 'index')
47 %li.divider{role: 'separator'}
47 %li.divider{role: 'separator'}
48 = add_menu( 'Sites', 'sites', 'index')
48 = add_menu( 'Sites', 'sites', 'index')
49 = add_menu( 'Contests', 'contest_management', 'index')
49 = add_menu( 'Contests', 'contest_management', 'index')
50 %li.dropdown
50 %li.dropdown
51 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
51 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
52 Report
52 Report
53 %span.caret
53 %span.caret
54 %ul.dropdown-menu
54 %ul.dropdown-menu
55 - = add_menu( 'Results', 'user_admin', 'user_stat')
55 + = add_menu( 'Results', 'report', 'current_score')
56 = add_menu( 'Report', 'report', 'multiple_login')
56 = add_menu( 'Report', 'report', 'multiple_login')
57 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
57 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
58 =link_to "#{ungraded} backlogs!",
58 =link_to "#{ungraded} backlogs!",
59 grader_list_path,
59 grader_list_path,
60 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
60 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
61
61
62 %ul.nav.navbar-nav.navbar-right
62 %ul.nav.navbar-nav.navbar-right
63 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
63 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
64 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
64 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
65 - if GraderConfiguration['system.user_setting_enabled']
65 - if GraderConfiguration['system.user_setting_enabled']
66 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog')}".html_safe, 'users', 'index', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
66 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog')}".html_safe, 'users', 'index', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
67 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
67 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
68
68
69 /
69 /
70 - if (@current_user!=nil) and (session[:admin])
70 - if (@current_user!=nil) and (session[:admin])
71 %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar
71 %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar
72 .container-fluid
72 .container-fluid
73 .collapse.navbar-collapse
73 .collapse.navbar-collapse
74 %ul.nav.navbar-nav
74 %ul.nav.navbar-nav
75 = add_menu( '[Announcements]', 'announcements', 'index')
75 = add_menu( '[Announcements]', 'announcements', 'index')
76 = add_menu( '[Msg console]', 'messages', 'console')
76 = add_menu( '[Msg console]', 'messages', 'console')
77 = add_menu( '[Problems]', 'problems', 'index')
77 = add_menu( '[Problems]', 'problems', 'index')
78 = add_menu( '[Users]', 'user_admin', 'index')
78 = add_menu( '[Users]', 'user_admin', 'index')
79 = add_menu( '[Results]', 'user_admin', 'user_stat')
79 = add_menu( '[Results]', 'user_admin', 'user_stat')
80 = add_menu( '[Report]', 'report', 'multiple_login')
80 = add_menu( '[Report]', 'report', 'multiple_login')
81 = add_menu( '[Graders]', 'graders', 'list')
81 = add_menu( '[Graders]', 'graders', 'list')
82 = add_menu( '[Contests]', 'contest_management', 'index')
82 = add_menu( '[Contests]', 'contest_management', 'index')
83 = add_menu( '[Sites]', 'sites', 'index')
83 = add_menu( '[Sites]', 'sites', 'index')
84 = add_menu( '[System config]', 'configurations', 'index')
84 = add_menu( '[System config]', 'configurations', 'index')
@@ -1,85 +1,49
1 %h1 Maximum score
1 %h1 Maximum score
2
2
3 = form_tag report_show_max_score_path
3 = form_tag report_show_max_score_path
4 .row
4 .row
5 .col-md-4
5 .col-md-4
6 .panel.panel-primary
6 .panel.panel-primary
7 .panel-heading
7 .panel-heading
8 Problems
8 Problems
9 .panel-body
9 .panel-body
10 %p
10 %p
11 Select problem(s) that we wish to know the score.
11 Select problem(s) that we wish to know the score.
12 = label_tag :problem_id, "Problems"
12 = label_tag :problem_id, "Problems"
13 = select_tag 'problem_id[]',
13 = select_tag 'problem_id[]',
14 options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}),
14 options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}),
15 { class: 'select2 form-control', multiple: "true" }
15 { class: 'select2 form-control', multiple: "true" }
16 .col-md-4
16 .col-md-4
17 .panel.panel-primary
17 .panel.panel-primary
18 .panel-heading
18 .panel-heading
19 Submission range
19 Submission range
20 .panel-body
20 .panel-body
21 %p
21 %p
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
23 .form-group
23 .form-group
24 = label_tag :from, "Min"
24 = label_tag :from, "Min"
25 = text_field_tag 'from_id', nil, class: "form-control"
25 = text_field_tag 'from_id', nil, class: "form-control"
26 .form-group
26 .form-group
27 = label_tag :from, "Max"
27 = label_tag :from, "Max"
28 = text_field_tag 'to_id', nil, class: "form-control"
28 = text_field_tag 'to_id', nil, class: "form-control"
29 .col-md-4
29 .col-md-4
30 .panel.panel-primary
30 .panel.panel-primary
31 .panel-heading
31 .panel-heading
32 Users
32 Users
33 .panel-body
33 .panel-body
34 .radio
34 .radio
35 %label
35 %label
36 = radio_button_tag 'users', 'all', true
36 = radio_button_tag 'users', 'all', true
37 All users
37 All users
38 .radio
38 .radio
39 %label
39 %label
40 = radio_button_tag 'users', 'enabled'
40 = radio_button_tag 'users', 'enabled'
41 Only enabled users
41 Only enabled users
42 .row
42 .row
43 .col-md-12
43 .col-md-12
44 = button_tag 'Show', class: "btn btn-primary btn-large"
44 = button_tag 'Show', class: "btn btn-primary btn-large"
45 = button_tag 'Download CSV', class: "btn btn-primary btn-large"
45 = button_tag 'Download CSV', class: "btn btn-primary btn-large"
46
46
47 - if @scorearray
47 - if @scorearray
48 %h2 Result
48 %h2 Result
49 - %table.table.sortable.table-striped.table-bordered.table-condensed
49 + =render "score_table"
50 - %thead
51 - %tr
52 - %th Login
53 - %th Name
54 - %th Activated?
55 - %th Logged_in
56 - %th Contest(s)
57 - %th Remark
58 - - @problems.each do |p|
59 - %th.text-right= p.name
60 - %th.text-right Total
61 - %th.text-right Passed
62 - %tbody
63 - - @scorearray.each do |sc|
64 - %tr
65 - - total,num_passed = 0,0
66 - - sc.each_index do |i|
67 - - if i == 0
68 - %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
69 - %td= sc[i].full_name
70 - %td= sc[i].activated
71 - %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
72 - %td= sc[i].contests.collect {|c| c.name}.join(', ')
73 - %td= sc[i].remark
74 - - else
75 - %td.text-right= sc[i][0]
76 - - total += sc[i][0]
77 - - num_passed += 1 if sc[i][1]
78 - %td.text-right= total
79 - %td.text-right= num_passed
80 - :javascript
81 - $.bootstrapSortable(true,'reversed')
82 - /.col-md-4.col-md-offset-1
83 - / = button_tag 'Show', class: "btn btn-primary btn-block"
84 - /.col-md-4.col-md-offset-2
85 - / = button_tag 'Download CSV', class: "btn btn-primary btn-block"
@@ -1,70 +1,71
1 CafeGrader::Application.routes.draw do
1 CafeGrader::Application.routes.draw do
2 get "sources/direct_edit"
2 get "sources/direct_edit"
3
3
4 root :to => 'main#login'
4 root :to => 'main#login'
5
5
6 resources :contests
6 resources :contests
7
7
8 resources :sites
8 resources :sites
9
9
10 resources :announcements do
10 resources :announcements do
11 member do
11 member do
12 get 'toggle','toggle_front'
12 get 'toggle','toggle_front'
13 end
13 end
14 end
14 end
15
15
16 resources :problems do
16 resources :problems do
17 member do
17 member do
18 get 'toggle'
18 get 'toggle'
19 get 'toggle_test'
19 get 'toggle_test'
20 end
20 end
21 collection do
21 collection do
22 get 'turn_all_off'
22 get 'turn_all_off'
23 get 'turn_all_on'
23 get 'turn_all_on'
24 get 'import'
24 get 'import'
25 get 'manage'
25 get 'manage'
26 end
26 end
27 end
27 end
28
28
29 resources :grader_configuration, controller: 'configurations'
29 resources :grader_configuration, controller: 'configurations'
30
30
31 resources :users do
31 resources :users do
32 member do
32 member do
33 get 'toggle_activate', 'toggle_enable'
33 get 'toggle_activate', 'toggle_enable'
34 end
34 end
35 end
35 end
36
36
37 resources :submissions do
37 resources :submissions do
38 collection do
38 collection do
39 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
39 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
40 get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
40 get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
41 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
41 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
42 end
42 end
43 end
43 end
44
44
45 match 'tasks/view/:file.:ext' => 'tasks#view'
45 match 'tasks/view/:file.:ext' => 'tasks#view'
46 match 'tasks/download/:id/:file.:ext' => 'tasks#download'
46 match 'tasks/download/:id/:file.:ext' => 'tasks#download'
47 match 'heartbeat/:id/edit' => 'heartbeat#edit'
47 match 'heartbeat/:id/edit' => 'heartbeat#edit'
48
48
49 #main
49 #main
50 get "main/list"
50 get "main/list"
51 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
51 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
52
52
53 #report
53 #report
54 + get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
54 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
55 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
55 get "report/login"
56 get "report/login"
56 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
57 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
57 post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
58 post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
58
59
59 #grader
60 #grader
60 get 'graders/list', to: 'graders#list', as: 'grader_list'
61 get 'graders/list', to: 'graders#list', as: 'grader_list'
61
62
62
63
63 match 'heartbeat/:id/edit' => 'heartbeat#edit'
64 match 'heartbeat/:id/edit' => 'heartbeat#edit'
64
65
65 # See how all your routes lay out with "rake routes"
66 # See how all your routes lay out with "rake routes"
66
67
67 # This is a legacy wild controller route that's not recommended for RESTful applications.
68 # This is a legacy wild controller route that's not recommended for RESTful applications.
68 # Note: This route will make all actions in every controller accessible via GET requests.
69 # Note: This route will make all actions in every controller accessible via GET requests.
69 match ':controller(/:action(/:id))(.:format)'
70 match ':controller(/:action(/:id))(.:format)'
70 end
71 end
You need to be logged in to leave comments. Login now