Description:
make report max_score remember user options
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r647:bb242b3ef68d - - 3 files changed: 8 inserted, 6 deleted

@@ -1,247 +1,249
1 1 require 'csv'
2 2
3 3 class ReportController < ApplicationController
4 4
5 5 before_filter :authenticate
6 6
7 7 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize, :show_max_score]
8 8
9 9 before_filter(only: [:problem_hof]) { |c|
10 10 return false unless authenticate
11 11
12 12 admin_authorization unless GraderConfiguration["right.user_view_submission"]
13 13 }
14 14
15 15 def max_score
16 16 end
17 17
18 18 def current_score
19 19 @problems = Problem.available_problems
20 20 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
21 21 @scorearray = calculate_max_score(@problems, @users,0,0,true)
22 22
23 23 #rencer accordingly
24 24 if params[:button] == 'download' then
25 25 csv = gen_csv_from_scorearray(@scorearray,@problems)
26 26 send_data csv, filename: 'max_score.csv'
27 27 else
28 28 #render template: 'user_admin/user_stat'
29 29 render 'current_score'
30 30 end
31 31 end
32 32
33 33 def show_max_score
34 34 #process parameters
35 35 #problems
36 36 @problems = []
37 + if params[:problem_id]
37 38 params[:problem_id].each do |id|
38 39 next unless id.strip != ""
39 40 pid = Problem.find_by_id(id.to_i)
40 41 @problems << pid if pid
41 42 end
43 + end
42 44
43 45 #users
44 46 @users = if params[:user] == "all" then
45 47 User.includes(:contests).includes(:contest_stat)
46 48 else
47 49 User.includes(:contests).includes(:contest_stat).where(enabled: true)
48 50 end
49 51
50 52 #set up range from param
51 - since_id = params.fetch(:from_id, 0).to_i
52 - until_id = params.fetch(:to_id, 0).to_i
53 + @since_id = params.fetch(:from_id, 0).to_i
54 + @until_id = params.fetch(:to_id, 0).to_i
53 55
54 56 #calculate the routine
55 - @scorearray = calculate_max_score(@problems, @users,since_id,until_id)
57 + @scorearray = calculate_max_score(@problems, @users, @since_id, @until_id)
56 58
57 59 #rencer accordingly
58 60 if params[:button] == 'download' then
59 61 csv = gen_csv_from_scorearray(@scorearray,@problems)
60 62 send_data csv, filename: 'max_score.csv'
61 63 else
62 64 #render template: 'user_admin/user_stat'
63 65 render 'max_score'
64 66 end
65 67
66 68 end
67 69
68 70 def score
69 71 if params[:commit] == 'download csv'
70 72 @problems = Problem.all
71 73 else
72 74 @problems = Problem.available_problems
73 75 end
74 76 @users = User.includes(:contests, :contest_stat).where(enabled: true)
75 77 @scorearray = Array.new
76 78 @users.each do |u|
77 79 ustat = Array.new
78 80 ustat[0] = u
79 81 @problems.each do |p|
80 82 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
81 83 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
82 84 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
83 85 else
84 86 ustat << [0,false]
85 87 end
86 88 end
87 89 @scorearray << ustat
88 90 end
89 91 if params[:commit] == 'download csv' then
90 92 csv = gen_csv_from_scorearray(@scorearray,@problems)
91 93 send_data csv, filename: 'last_score.csv'
92 94 else
93 95 render template: 'user_admin/user_stat'
94 96 end
95 97
96 98 end
97 99
98 100 def login_stat
99 101 @logins = Array.new
100 102
101 103 date_and_time = '%Y-%m-%d %H:%M'
102 104 begin
103 105 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
104 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)
105 107 rescue
106 108 @since_time = DateTime.new(1000,1,1)
107 109 end
108 110 begin
109 111 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
110 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)
111 113 rescue
112 114 @until_time = DateTime.new(3000,1,1)
113 115 end
114 116
115 117 User.all.each do |user|
116 118 @logins << { id: user.id,
117 119 login: user.login,
118 120 full_name: user.full_name,
119 121 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
120 122 user.id,@since_time,@until_time)
121 123 .count(:id),
122 124 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
123 125 user.id,@since_time,@until_time)
124 126 .minimum(:created_at),
125 127 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
126 128 user.id,@since_time,@until_time)
127 129 .maximum(:created_at),
128 130 ip: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
129 131 user.id,@since_time,@until_time)
130 132 .select(:ip_address).uniq
131 133
132 134 }
133 135 end
134 136 end
135 137
136 138 def submission_stat
137 139
138 140 date_and_time = '%Y-%m-%d %H:%M'
139 141 begin
140 142 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
141 143 rescue
142 144 @since_time = DateTime.new(1000,1,1)
143 145 end
144 146 begin
145 147 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
146 148 rescue
147 149 @until_time = DateTime.new(3000,1,1)
148 150 end
149 151
150 152 @submissions = {}
151 153
152 154 User.find_each do |user|
153 155 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
154 156 end
155 157
156 158 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
157 159 if @submissions[s.user_id]
158 160 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
159 161 a = Problem.find_by_id(s.problem_id)
160 162 @submissions[s.user_id][:sub][s.problem_id] =
161 163 { prob_name: (a ? a.full_name : '(NULL)'),
162 164 sub_ids: [s.id] }
163 165 else
164 166 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
165 167 end
166 168 @submissions[s.user_id][:count] += 1
167 169 end
168 170 end
169 171 end
170 172
171 173 def problem_hof
172 174 # gen problem list
173 175 @user = User.find(session[:user_id])
174 176 @problems = @user.available_problems
175 177
176 178 # get selected problems or the default
177 179 if params[:id]
178 180 begin
179 181 @problem = Problem.available.find(params[:id])
180 182 rescue
181 183 redirect_to action: :problem_hof
182 184 flash[:notice] = 'Error: submissions for that problem are not viewable.'
183 185 return
184 186 end
185 187 end
186 188
187 189 return unless @problem
188 190
189 191 @by_lang = {} #aggregrate by language
190 192
191 193 range =65
192 194 @histogram = { data: Array.new(range,0), summary: {} }
193 195 @summary = {count: 0, solve: 0, attempt: 0}
194 196 user = Hash.new(0)
195 197 Submission.where(problem_id: @problem.id).find_each do |sub|
196 198 #histogram
197 199 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
198 200 @histogram[:data][d.to_i] += 1 if d < range
199 201
200 202 next unless sub.points
201 203 @summary[:count] += 1
202 204 user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
203 205
204 206 lang = Language.find_by_id(sub.language_id)
205 207 next unless lang
206 208 next unless sub.points >= @problem.full_score
207 209
208 210 #initialize
209 211 unless @by_lang.has_key?(lang.pretty_name)
210 212 @by_lang[lang.pretty_name] = {
211 213 runtime: { avail: false, value: 2**30-1 },
212 214 memory: { avail: false, value: 2**30-1 },
213 215 length: { avail: false, value: 2**30-1 },
214 216 first: { avail: false, value: DateTime.new(3000,1,1) }
215 217 }
216 218 end
217 219
218 220 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
219 221 @by_lang[lang.pretty_name][:runtime] = { avail: true, user_id: sub.user_id, value: sub.max_runtime, sub_id: sub.id }
220 222 end
221 223
222 224 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
223 225 @by_lang[lang.pretty_name][:memory] = { avail: true, user_id: sub.user_id, value: sub.peak_memory, sub_id: sub.id }
224 226 end
225 227
226 228 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
227 229 !sub.user.admin?
228 230 @by_lang[lang.pretty_name][:first] = { avail: true, user_id: sub.user_id, value: sub.submitted_at, sub_id: sub.id }
229 231 end
230 232
231 233 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
232 234 @by_lang[lang.pretty_name][:length] = { avail: true, user_id: sub.user_id, value: sub.effective_code_length, sub_id: sub.id }
233 235 end
234 236 end
235 237
236 238 #process user_id
237 239 @by_lang.each do |lang,prop|
238 240 prop.each do |k,v|
239 241 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
240 242 end
241 243 end
242 244
243 245 #sum into best
244 246 if @by_lang and @by_lang.first
245 247 @best = @by_lang.first[1].clone
246 248 @by_lang.each do |lang,prop|
247 249 if @best[:runtime][:value] >= prop[:runtime][:value]
@@ -1,49 +1,49
1 1 %h1 Maximum score
2 2
3 3 = form_tag report_show_max_score_path
4 4 .row
5 5 .col-md-4
6 6 .panel.panel-primary
7 7 .panel-heading
8 8 Problems
9 9 .panel-body
10 10 %p
11 11 Select problem(s) that we wish to know the score.
12 12 = label_tag :problem_id, "Problems"
13 13 = select_tag 'problem_id[]',
14 14 options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]},params[:problem_id]),
15 15 { class: 'select2 form-control', multiple: "true" }
16 16 .col-md-4
17 17 .panel.panel-primary
18 18 .panel-heading
19 19 Submission range
20 20 .panel-body
21 21 %p
22 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 23 .form-group
24 24 = label_tag :from, "Min"
25 - = text_field_tag 'from_id', nil, class: "form-control"
25 + = text_field_tag 'from_id', @since_id, class: "form-control"
26 26 .form-group
27 27 = label_tag :from, "Max"
28 - = text_field_tag 'to_id', nil, class: "form-control"
28 + = text_field_tag 'to_id', @until_id, class: "form-control"
29 29 .col-md-4
30 30 .panel.panel-primary
31 31 .panel-heading
32 32 Users
33 33 .panel-body
34 34 .radio
35 35 %label
36 36 = radio_button_tag 'users', 'all', true
37 37 All users
38 38 .radio
39 39 %label
40 40 = radio_button_tag 'users', 'enabled'
41 41 Only enabled users
42 42 .row
43 43 .col-md-12
44 44 = button_tag 'Show', class: "btn btn-primary btn-large", value: "show"
45 45 = button_tag 'Download CSV', class: "btn btn-primary btn-large", value: "download"
46 46
47 47 - if @scorearray
48 48 %h2 Result
49 49 =render "score_table"
@@ -1,2 +1,2
1 1 :plain
2 - $("body").prepend("<div class=\"alert alert-info\"> Submission #{@submission.id}'s task status has been chaned to \"#{@task.status_str}\" </div>")
2 + $("body").prepend("<div class=\"alert alert-info\"> Submission #{@submission.id}'s task status has been changed to \"#{@task.status_str}\". It will be re-judged soon. </div>")
You need to be logged in to leave comments. Login now