Description:
add more problem stat
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r457:c81651eecbbd - - 7 files changed: 144 inserted, 43 deleted

@@ -0,0 +1,44
1 + - param = {} unless param
2 + - graph_height = param[:graph_height] || 100
3 + - bar_width = param[:bar_width] || 14
4 + - graph_width = (bar_width * histogram[:data].count) + 20
5 + :css
6 + .hist_bar {
7 + width: #{bar_width-1}px;
8 + position: absolute;
9 + background-color: lightblue;
10 + }
11 + .hist_fill {
12 + width: #{bar_width-1}px;
13 + position: absolute;
14 + background-color: #eee;
15 + }
16 + .hist_text {
17 + position: absolute;
18 + font-size:5px;
19 + }
20 +
21 + %div{style: "position: relative; width: #{graph_width}px; height: 150px; background-color:#fff;" }
22 + //draw background
23 + - histogram[:data].each_index do |i|
24 + - height = histogram[:data][i] * graph_height / histogram[:summary][:max]
25 + - top = graph_height - height
26 + - left = graph_width - (i+1)*bar_width
27 + %div.hist_fill{style: "top: 0px; height: #{graph_height - height}px; left: #{left}px;" }
28 + // draw horizontal line
29 + - line = 3
30 + - line.times do |i|
31 + - top = graph_height - graph_height * (i+0.5)/ line
32 + %div{style: "position:absolute;width: #{graph_width-21}px;height: 1px;left: 20px;top:#{top}px;background-color: #333;"}
33 + %div.hist_text{style: "position:absolute;left: 0px;top:#{top-6}px"}
34 + =((i+0.5) * histogram[:summary][:max] / line).to_i
35 + // draw the actual bar and text
36 + - @histogram[:data].each_index do |i|
37 + - height = histogram[:data][i] * graph_height / histogram[:summary][:max]
38 + - top = graph_height - height
39 + - left = graph_width - (i+1)*bar_width
40 + %div.hist_bar{style: "top: #{top}px; height: #{height}px; left: #{left}px; dae: #{histogram[:data][i]}" }
41 + - if i % 7 == 1
42 + %div.hist_text{style: "top:#{graph_height + 5}px;left: #{left}px;"} #{(Time.zone.today - i.day).strftime('%-d')}
43 + - if (Time.now.in_time_zone - i.day).day == 15
44 + %div.hist_text{style: "top:#{graph_height + 15}px;left: #{left}px;"} #{(Time.zone.today - i.day).strftime('%b')}
@@ -141,29 +141,44
141
141
142 def turn_all_on
142 def turn_all_on
143 Problem.find(:all,
143 Problem.find(:all,
144 :conditions => "available = 0").each do |problem|
144 :conditions => "available = 0").each do |problem|
145 problem.available = true
145 problem.available = true
146 problem.save
146 problem.save
147 end
147 end
148 redirect_to :action => 'list'
148 redirect_to :action => 'list'
149 end
149 end
150
150
151 def stat
151 def stat
152 @problem = Problem.find(params[:id])
152 @problem = Problem.find(params[:id])
153 - if !@problem.available
153 + unless @problem.available or session[:admin]
154 redirect_to :controller => 'main', :action => 'list'
154 redirect_to :controller => 'main', :action => 'list'
155 - else
155 + return
156 + end
156 @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
157 @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
158 +
159 + #stat summary
160 + range =65
161 + @histogram = { data: Array.new(range,0), summary: {} }
162 + @histogram[:data] = Array.new(range,0)
163 + user = Hash.new(0)
164 + @submissions.find_each do |sub|
165 + d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
166 + @histogram[:data][d.to_i] += 1 if d < range
167 + user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
157 end
168 end
169 + @histogram[:summary][:max] = [@histogram[:data].max,1].max
170 +
171 + @summary = { attempt: user.count, solve: 0 }
172 + user.each_value { |v| @summary[:solve] += 1 if v == 1 }
158 end
173 end
159
174
160 def manage
175 def manage
161 @problems = Problem.find(:all, :order => 'date_added DESC')
176 @problems = Problem.find(:all, :order => 'date_added DESC')
162 end
177 end
163
178
164 def do_manage
179 def do_manage
165 if params.has_key? 'change_date_added'
180 if params.has_key? 'change_date_added'
166 change_date_added
181 change_date_added
167 elsif params.has_key? 'add_to_contest'
182 elsif params.has_key? 'add_to_contest'
168 add_to_contest
183 add_to_contest
169 elsif params.has_key? 'enable_problem'
184 elsif params.has_key? 'enable_problem'
@@ -248,13 +263,16
248
263
249 def get_problems_from_params
264 def get_problems_from_params
250 problems = []
265 problems = []
251 params.keys.each do |k|
266 params.keys.each do |k|
252 if k.index('prob-')==0
267 if k.index('prob-')==0
253 name, id, order = k.split('-')
268 name, id, order = k.split('-')
254 problems << Problem.find(id)
269 problems << Problem.find(id)
255 end
270 end
256 end
271 end
257 problems
272 problems
258 end
273 end
259
274
275 + def get_problems_stat
260 end
276 end
277 +
278 + end
@@ -96,77 +96,70
96
96
97 # get selected problems or the default
97 # get selected problems or the default
98 if params[:id]
98 if params[:id]
99 begin
99 begin
100 @problem = Problem.available.find(params[:id])
100 @problem = Problem.available.find(params[:id])
101 rescue
101 rescue
102 redirect_to action: :problem_hof
102 redirect_to action: :problem_hof
103 flash[:notice] = 'Error: submissions for that problem are not viewable.'
103 flash[:notice] = 'Error: submissions for that problem are not viewable.'
104 return
104 return
105 end
105 end
106 end
106 end
107
107
108 - if @problem
108 + return unless @problem
109 - #aggregrate by language
109 +
110 - @by_lang = {}
110 + @by_lang = {} #aggregrate by language
111 +
112 + range =65
113 + @histogram = { data: Array.new(range,0), summary: {} }
114 + @histogram[:data] = Array.new(range,0)
115 + @summary = {count: 0, solve: 0, attempt: 0}
116 + user = Hash.new(0)
111 Submission.where(problem_id: @problem.id).find_each do |sub|
117 Submission.where(problem_id: @problem.id).find_each do |sub|
118 + #histogram
119 + d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
120 + @histogram[:data][d.to_i] += 1 if d < range
121 +
122 + @summary[:count] += 1
123 + user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
124 +
112 lang = Language.find_by_id(sub.language_id)
125 lang = Language.find_by_id(sub.language_id)
113 next unless lang
126 next unless lang
114 next unless sub.points >= @problem.full_score
127 next unless sub.points >= @problem.full_score
115
128
116 #initialize
129 #initialize
117 unless @by_lang.has_key?(lang.pretty_name)
130 unless @by_lang.has_key?(lang.pretty_name)
118 @by_lang[lang.pretty_name] = {
131 @by_lang[lang.pretty_name] = {
119 runtime: { avail: false, value: 2**30-1 },
132 runtime: { avail: false, value: 2**30-1 },
120 memory: { avail: false, value: 2**30-1 },
133 memory: { avail: false, value: 2**30-1 },
121 length: { avail: false, value: 2**30-1 },
134 length: { avail: false, value: 2**30-1 },
122 first: { avail: false, value: DateTime.new(3000,1,1) }
135 first: { avail: false, value: DateTime.new(3000,1,1) }
123 }
136 }
124 end
137 end
125
138
126 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
139 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
127 - @by_lang[lang.pretty_name][:runtime] = {
140 + @by_lang[lang.pretty_name][:runtime] = { avail: true, user_id: sub.user_id, value: sub.max_runtime, sub_id: sub.id }
128 - avail: true,
129 - user_id: sub.user_id,
130 - value: sub.max_runtime,
131 - sub_id: sub.id
132 - }
133 end
141 end
134
142
135 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
143 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
136 - @by_lang[lang.pretty_name][:memory] = {
144 + @by_lang[lang.pretty_name][:memory] = { avail: true, user_id: sub.user_id, value: sub.peak_memory, sub_id: sub.id }
137 - avail: true,
138 - user_id: sub.user_id,
139 - value: sub.peak_memory,
140 - sub_id: sub.id
141 - }
142 end
145 end
143
146
144 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
147 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
145 !sub.user.admin?
148 !sub.user.admin?
146 - @by_lang[lang.pretty_name][:first] = {
149 + @by_lang[lang.pretty_name][:first] = { avail: true, user_id: sub.user_id, value: sub.submitted_at, sub_id: sub.id }
147 - avail: true,
148 - user_id: sub.user_id,
149 - value: sub.submitted_at,
150 - sub_id: sub.id
151 - }
152 end
150 end
153
151
154 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
152 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
155 - @by_lang[lang.pretty_name][:length] = {
153 + @by_lang[lang.pretty_name][:length] = { avail: true, user_id: sub.user_id, value: sub.effective_code_length, sub_id: sub.id }
156 - avail: true,
157 - user_id: sub.user_id,
158 - value: sub.effective_code_length,
159 - sub_id: sub.id
160 - }
161 end
154 end
162 end
155 end
163
156
164 #process user_id
157 #process user_id
165 @by_lang.each do |lang,prop|
158 @by_lang.each do |lang,prop|
166 prop.each do |k,v|
159 prop.each do |k,v|
167 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
160 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
168 end
161 end
169 end
162 end
170
163
171 #sum into best
164 #sum into best
172 if @by_lang and @by_lang.first
165 if @by_lang and @by_lang.first
@@ -181,15 +174,19
181 @best[:memory][:lang] = lang
174 @best[:memory][:lang] = lang
182 end
175 end
183 if @best[:length][:value] >= prop[:length][:value]
176 if @best[:length][:value] >= prop[:length][:value]
184 @best[:length] = prop[:length]
177 @best[:length] = prop[:length]
185 @best[:length][:lang] = lang
178 @best[:length][:lang] = lang
186 end
179 end
187 if @best[:first][:value] >= prop[:first][:value]
180 if @best[:first][:value] >= prop[:first][:value]
188 @best[:first] = prop[:first]
181 @best[:first] = prop[:first]
189 @best[:first][:lang] = lang
182 @best[:first][:lang] = lang
190 end
183 end
191 end
184 end
192 end
185 end
193 - end
186 +
187 + @histogram[:summary][:max] = [@histogram[:data].max,1].max
188 + @summary[:attempt] = user.count
189 + user.each_value { |v| @summary[:solve] += 1 if v == 1 }
194 end
190 end
191 +
195 end
192 end
@@ -46,24 +46,31
46 import_params[:checker_name],
46 import_params[:checker_name],
47 import_to_db)
47 import_to_db)
48 problem.errors.add_to_base('Import error.')
48 problem.errors.add_to_base('Import error.')
49 end
49 end
50
50
51 return problem, importer.log_msg
51 return problem, importer.log_msg
52 end
52 end
53
53
54 def self.download_file_basedir
54 def self.download_file_basedir
55 return "#{Rails.root}/data/tasks"
55 return "#{Rails.root}/data/tasks"
56 end
56 end
57
57
58 + def get_submission_stat
59 + result = Hash.new
60 + #total number of submission
61 + result[:total_sub] = Submission.where(problem_id: self.id).count
62 + result[:attempted_user] = Submission.where(problem_id: self.id).group_by(:user_id)
63 + end
64 +
58 protected
65 protected
59
66
60 def self.to_i_or_default(st, default)
67 def self.to_i_or_default(st, default)
61 if st!=''
68 if st!=''
62 result = st.to_i
69 result = st.to_i
63 end
70 end
64 result ||= default
71 result ||= default
65 end
72 end
66
73
67 def self.to_f_or_default(st, default)
74 def self.to_f_or_default(st, default)
68 if st!=''
75 if st!=''
69 result = st.to_f
76 result = st.to_f
@@ -1,20 +1,37
1 :css
1 :css
2 .fix-width {
2 .fix-width {
3 font-family: "Consolas, Monaco, Droid Sans Mono,Mono, Monospace,Courier"
3 font-family: "Consolas, Monaco, Droid Sans Mono,Mono, Monospace,Courier"
4 }
4 }
5
5
6 %h1 Problem stat: #{@problem.name}
6 %h1 Problem stat: #{@problem.name}
7 %h2 Overview
7 %h2 Overview
8
8
9 +
10 + %table.info
11 + %thead
12 + %tr.info-head
13 + %th Stat
14 + %th Value
15 + %tbody
16 + %tr{class: cycle('info-even','info-odd')}
17 + %td Submissions
18 + %td= @submissions.count
19 + %tr{class: cycle('info-even','info-odd')}
20 + %td Solved/Attempted User
21 + %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
22 +
23 + %h2 Submissions Count
24 + = render partial: 'application/bar_graph', locals: { histogram: @histogram }
25 +
9 %h2 Submissions
26 %h2 Submissions
10 - if @submissions and @submissions.count > 0
27 - if @submissions and @submissions.count > 0
11 %table.info#main_table
28 %table.info#main_table
12 %thead
29 %thead
13 %tr.info-head
30 %tr.info-head
14 %th ID
31 %th ID
15 %th Login
32 %th Login
16 %th Name
33 %th Name
17 %th Submitted_at
34 %th Submitted_at
18 %th Points
35 %th Points
19 %th comment
36 %th comment
20 %tbody
37 %tbody
@@ -1,57 +1,76
1 :css
1 :css
2 .hof_user { color: orangered; font-style: italic; }
2 .hof_user { color: orangered; font-style: italic; }
3 .hof_language { color: green; font-style: italic; }
3 .hof_language { color: green; font-style: italic; }
4 .hof_value { color: deeppink;font-style: italic; }
4 .hof_value { color: deeppink;font-style: italic; }
5 + .info_param { font-weight: bold;text-align: right; }
5
6
6 - %h2 Overall of #{Problem.find(params[:id]).full_name}
7 + %h1 (#{Problem.find(params[:id]).name}) #{Problem.find(params[:id]).full_name}
7
8
9 + %h2 Problem Stat
10 + %table.info
11 + %thead
12 + %tr.info-head
13 + %th Stat
14 + %th Value
15 + %tbody
16 + %tr{class: cycle('info-even','info-odd')}
17 + %td.info_param Submissions
18 + %td= @summary[:count]
19 + %tr{class: cycle('info-even','info-odd')}
20 + %td.info_param Solved/Attempted User
21 + %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
8 - if @best
22 - if @best
9 - %b Best Runtime:
23 + %tr{class: cycle('info-even','info-odd')}
24 + %td.info_param Best Runtime
25 + %td
10 by #{link_to @best[:runtime][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
26 by #{link_to @best[:runtime][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
11 using <span class="hof_language">#{@best[:runtime][:lang]}</span>
27 using <span class="hof_language">#{@best[:runtime][:lang]}</span>
12 with <span class="hof_value">#{@best[:runtime][:value] * 1000} milliseconds</span>
28 with <span class="hof_value">#{@best[:runtime][:value] * 1000} milliseconds</span>
13 at submission
29 at submission
14 = link_to("#" + @best[:runtime][:sub_id].to_s, controller: 'graders', action: 'submission', id:@best[:runtime][:sub_id])
30 = link_to("#" + @best[:runtime][:sub_id].to_s, controller: 'graders', action: 'submission', id:@best[:runtime][:sub_id])
15 - %br/
16
31
17 - %b Best Memory Usage:
32 + %tr{class: cycle('info-even','info-odd')}
33 + %td.info_param Best Memory Usage
34 + %td
18 by #{link_to @best[:memory][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
35 by #{link_to @best[:memory][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
19 using <span class="hof_language">#{@best[:memory][:lang]}</span>
36 using <span class="hof_language">#{@best[:memory][:lang]}</span>
20 with <span class="hof_value">#{number_with_delimiter(@best[:memory][:value])} kbytes </span>
37 with <span class="hof_value">#{number_with_delimiter(@best[:memory][:value])} kbytes </span>
21 at submission
38 at submission
22 = link_to("#" + @best[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id:@best[:memory][:sub_id])
39 = link_to("#" + @best[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id:@best[:memory][:sub_id])
23 - %br/
24
40
25 - %b Shortest Code:
41 + %tr{class: cycle('info-even','info-odd')}
42 + %td.info_param Shortest Code
43 + %td
26 by #{link_to @best[:length][:user], controller:'users', action:'profile', id:@best[:length][:user_id]}
44 by #{link_to @best[:length][:user], controller:'users', action:'profile', id:@best[:length][:user_id]}
27 using <span class="hof_language">#{@best[:length][:lang]}</span>
45 using <span class="hof_language">#{@best[:length][:lang]}</span>
28 with <span class="hof_value">#{@best[:length][:value]} bytes</span>
46 with <span class="hof_value">#{@best[:length][:value]} bytes</span>
29 at submission
47 at submission
30 = link_to("#" + @best[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:length][:sub_id])
48 = link_to("#" + @best[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:length][:sub_id])
31 - %br/
32
49
33 - %b First solver:
50 + %tr{class: cycle('info-even','info-odd')}
51 + %td.info_param First solver
52 + %td
34 #{link_to @best[:first][:user], controller:'users', action:'profile', id:@best[:first][:user_id]} is the first solver
53 #{link_to @best[:first][:user], controller:'users', action:'profile', id:@best[:first][:user_id]} is the first solver
35 using <span class="hof_language">#{@best[:first][:lang]}</span>
54 using <span class="hof_language">#{@best[:first][:lang]}</span>
36 on <span class="hof_value">#{@best[:first][:value]}</span>
55 on <span class="hof_value">#{@best[:first][:value]}</span>
37 at submission
56 at submission
38 = link_to("#" + @best[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:first][:sub_id])
57 = link_to("#" + @best[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:first][:sub_id])
39 - %br/
40
58
41
59
42 %p
60 %p
43 This counts only for submission with 100% score <br/>
61 This counts only for submission with 100% score <br/>
44 Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)
62 Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)
45
63
64 + - if @best
46 %h2 By language
65 %h2 By language
47
66
48 %table.info
67 %table.info
49 %thead
68 %thead
50 %tr.info-head
69 %tr.info-head
51 %th Language
70 %th Language
52 %th Best runtime (ms)
71 %th Best runtime (ms)
53 %th Best memory (kbytes)
72 %th Best memory (kbytes)
54 %th Shortest Code (bytes)
73 %th Shortest Code (bytes)
55 %th First solver
74 %th First solver
56 %tbody
75 %tbody
57 - @by_lang.each do |lang,value|
76 - @by_lang.each do |lang,value|
@@ -66,14 +85,12
66 = "(#{number_with_delimiter(value[:memory][:value])} @"
85 = "(#{number_with_delimiter(value[:memory][:value])} @"
67 = "#{link_to("#" + value[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:memory][:sub_id])} )".html_safe
86 = "#{link_to("#" + value[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:memory][:sub_id])} )".html_safe
68 %td
87 %td
69 = link_to value[:length][:user], controller: 'users', action: 'profile', id: value[:length][:user_id]
88 = link_to value[:length][:user], controller: 'users', action: 'profile', id: value[:length][:user_id]
70 = "(#{value[:length][:value]} @"
89 = "(#{value[:length][:value]} @"
71 = "#{link_to("#" + value[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:length][:sub_id])} )".html_safe
90 = "#{link_to("#" + value[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:length][:sub_id])} )".html_safe
72 %td
91 %td
73 - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong...
92 - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong...
74 = link_to value[:first][:user], controller: 'users', action: 'profile', id: value[:first][:user_id]
93 = link_to value[:first][:user], controller: 'users', action: 'profile', id: value[:first][:user_id]
75 = "(#{value[:first][:value]} @"
94 = "(#{value[:first][:value]} @"
76 = "#{link_to("#" + value[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:first][:sub_id])} )".html_safe
95 = "#{link_to("#" + value[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:first][:sub_id])} )".html_safe
77
96
78 - - else
79 - %h3 No submissions
@@ -1,22 +1,23
1
1
2 /- if params[:id]
2 /- if params[:id]
3 / %h1 Tasks Hall of Fame
3 / %h1 Tasks Hall of Fame
4 / = link_to('[back to All-Time Hall of Fame]', action: 'problem_hof', id: nil )
4 / = link_to('[back to All-Time Hall of Fame]', action: 'problem_hof', id: nil )
5 /- else
5 /- else
6 / %h1 All-Time Hall of Fame
6 / %h1 All-Time Hall of Fame
7
7
8
8
9 - %h1 Tasks Hall of Fame
9 + %h1 Hall of Fame
10 .task-menu
10 .task-menu
11 Tasks
11 Tasks
12 %br/
12 %br/
13 - @problems.each do |prob|
13 - @problems.each do |prob|
14 = link_to( "[#{prob.name}]", {id: prob.id})
14 = link_to( "[#{prob.name}]", {id: prob.id})
15
15
16 - unless params[:id]
16 - unless params[:id]
17 /=render partial: 'all_time_hof'
17 /=render partial: 'all_time_hof'
18 Please select a problem.
18 Please select a problem.
19 - else
19 - else
20 =render partial: 'task_hof'
20 =render partial: 'task_hof'
21 + %h2 Submission History
22 + =render partial: 'application/bar_graph', locals: { histogram: @histogram }
21
23
22 -
You need to be logged in to leave comments. Login now