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

r514:41d1cd2793ff - - 11 files changed: 228 inserted, 59 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: 125px; 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')}
@@ -105,101 +105,115
105 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
105 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
106 if FileTest.exists? out_filename
106 if FileTest.exists? out_filename
107 File.delete out_filename
107 File.delete out_filename
108 end
108 end
109
109
110 File.open(out_filename,"wb") do |file|
110 File.open(out_filename,"wb") do |file|
111 file.write(params[:file].read)
111 file.write(params[:file].read)
112 end
112 end
113 @problem.description_filename = "#{@problem.name}.pdf"
113 @problem.description_filename = "#{@problem.name}.pdf"
114 @problem.save
114 @problem.save
115 end
115 end
116 redirect_to :action => 'show', :id => @problem
116 redirect_to :action => 'show', :id => @problem
117 else
117 else
118 render :action => 'edit'
118 render :action => 'edit'
119 end
119 end
120 end
120 end
121
121
122 def destroy
122 def destroy
123 Problem.find(params[:id]).destroy
123 Problem.find(params[:id]).destroy
124 redirect_to :action => 'list'
124 redirect_to :action => 'list'
125 end
125 end
126
126
127 def toggle
127 def toggle
128 @problem = Problem.find(params[:id])
128 @problem = Problem.find(params[:id])
129 @problem.available = !(@problem.available)
129 @problem.available = !(@problem.available)
130 @problem.save
130 @problem.save
131 end
131 end
132
132
133 def turn_all_off
133 def turn_all_off
134 Problem.find(:all,
134 Problem.find(:all,
135 :conditions => "available = 1").each do |problem|
135 :conditions => "available = 1").each do |problem|
136 problem.available = false
136 problem.available = false
137 problem.save
137 problem.save
138 end
138 end
139 redirect_to :action => 'list'
139 redirect_to :action => 'list'
140 end
140 end
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 + user = Hash.new(0)
163 + @submissions.find_each do |sub|
164 + d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
165 + @histogram[:data][d.to_i] += 1 if d < range
166 + user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
157 end
167 end
168 + @histogram[:summary][:max] = [@histogram[:data].max,1].max
169 +
170 + @summary = { attempt: user.count, solve: 0 }
171 + user.each_value { |v| @summary[:solve] += 1 if v == 1 }
158 end
172 end
159
173
160 def manage
174 def manage
161 @problems = Problem.find(:all, :order => 'date_added DESC')
175 @problems = Problem.find(:all, :order => 'date_added DESC')
162 end
176 end
163
177
164 def do_manage
178 def do_manage
165 if params.has_key? 'change_date_added'
179 if params.has_key? 'change_date_added'
166 change_date_added
180 change_date_added
167 elsif params.has_key? 'add_to_contest'
181 elsif params.has_key? 'add_to_contest'
168 add_to_contest
182 add_to_contest
169 elsif params.has_key? 'enable_problem'
183 elsif params.has_key? 'enable_problem'
170 set_available(true)
184 set_available(true)
171 elsif params.has_key? 'disable_problem'
185 elsif params.has_key? 'disable_problem'
172 set_available(false)
186 set_available(false)
173 end
187 end
174 redirect_to :action => 'manage'
188 redirect_to :action => 'manage'
175 end
189 end
176
190
177 def import
191 def import
178 @allow_test_pair_import = allow_test_pair_import?
192 @allow_test_pair_import = allow_test_pair_import?
179 end
193 end
180
194
181 def do_import
195 def do_import
182 old_problem = Problem.find_by_name(params[:name])
196 old_problem = Problem.find_by_name(params[:name])
183 if !allow_test_pair_import? and params.has_key? :import_to_db
197 if !allow_test_pair_import? and params.has_key? :import_to_db
184 params.delete :import_to_db
198 params.delete :import_to_db
185 end
199 end
186 @problem, import_log = Problem.create_from_import_form_params(params,
200 @problem, import_log = Problem.create_from_import_form_params(params,
187 old_problem)
201 old_problem)
188
202
189 if !@problem.errors.empty?
203 if !@problem.errors.empty?
190 render :action => 'import' and return
204 render :action => 'import' and return
191 end
205 end
192
206
193 if old_problem!=nil
207 if old_problem!=nil
194 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
208 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
195 end
209 end
196 @log = import_log
210 @log = import_log
197 end
211 end
198
212
199 def remove_contest
213 def remove_contest
200 problem = Problem.find(params[:id])
214 problem = Problem.find(params[:id])
201 contest = Contest.find(params[:contest_id])
215 contest = Contest.find(params[:contest_id])
202 if problem!=nil and contest!=nil
216 if problem!=nil and contest!=nil
203 problem.contests.delete(contest)
217 problem.contests.delete(contest)
204 end
218 end
205 redirect_to :action => 'manage'
219 redirect_to :action => 'manage'
@@ -212,49 +226,52
212 if defined? ALLOW_TEST_PAIR_IMPORT
226 if defined? ALLOW_TEST_PAIR_IMPORT
213 return ALLOW_TEST_PAIR_IMPORT
227 return ALLOW_TEST_PAIR_IMPORT
214 else
228 else
215 return false
229 return false
216 end
230 end
217 end
231 end
218
232
219 def change_date_added
233 def change_date_added
220 problems = get_problems_from_params
234 problems = get_problems_from_params
221 year = params[:date_added][:year].to_i
235 year = params[:date_added][:year].to_i
222 month = params[:date_added][:month].to_i
236 month = params[:date_added][:month].to_i
223 day = params[:date_added][:day].to_i
237 day = params[:date_added][:day].to_i
224 date = Date.new(year,month,day)
238 date = Date.new(year,month,day)
225 problems.each do |p|
239 problems.each do |p|
226 p.date_added = date
240 p.date_added = date
227 p.save
241 p.save
228 end
242 end
229 end
243 end
230
244
231 def add_to_contest
245 def add_to_contest
232 problems = get_problems_from_params
246 problems = get_problems_from_params
233 contest = Contest.find(params[:contest][:id])
247 contest = Contest.find(params[:contest][:id])
234 if contest!=nil and contest.enabled
248 if contest!=nil and contest.enabled
235 problems.each do |p|
249 problems.each do |p|
236 p.contests << contest
250 p.contests << contest
237 end
251 end
238 end
252 end
239 end
253 end
240
254
241 def set_available(avail)
255 def set_available(avail)
242 problems = get_problems_from_params
256 problems = get_problems_from_params
243 problems.each do |p|
257 problems.each do |p|
244 p.available = avail
258 p.available = avail
245 p.save
259 p.save
246 end
260 end
247 end
261 end
248
262
249 def get_problems_from_params
263 def get_problems_from_params
250 problems = []
264 problems = []
251 params.keys.each do |k|
265 params.keys.each do |k|
252 if k.index('prob-')==0
266 if k.index('prob-')==0
253 name, id, order = k.split('-')
267 name, id, order = k.split('-')
254 problems << Problem.find(id)
268 problems << Problem.find(id)
255 end
269 end
256 end
270 end
257 problems
271 problems
258 end
272 end
259
273
274 + def get_problems_stat
260 end
275 end
276 +
277 + end
@@ -60,136 +60,132
60 begin
60 begin
61 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
61 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
62 rescue
62 rescue
63 @until_time = DateTime.new(3000,1,1)
63 @until_time = DateTime.new(3000,1,1)
64 end
64 end
65
65
66 @submissions = {}
66 @submissions = {}
67
67
68 User.find_each do |user|
68 User.find_each do |user|
69 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
69 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
70 end
70 end
71
71
72 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
72 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
73 if @submissions[s.user_id]
73 if @submissions[s.user_id]
74 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
74 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
75 a = nil
75 a = nil
76 begin
76 begin
77 a = Problem.find(s.problem_id)
77 a = Problem.find(s.problem_id)
78 rescue
78 rescue
79 a = nil
79 a = nil
80 end
80 end
81 @submissions[s.user_id][:sub][s.problem_id] =
81 @submissions[s.user_id][:sub][s.problem_id] =
82 { prob_name: (a ? a.full_name : '(NULL)'),
82 { prob_name: (a ? a.full_name : '(NULL)'),
83 sub_ids: [s.id] }
83 sub_ids: [s.id] }
84 else
84 else
85 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
85 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
86 end
86 end
87 @submissions[s.user_id][:count] += 1
87 @submissions[s.user_id][:count] += 1
88 end
88 end
89 end
89 end
90 end
90 end
91
91
92 def problem_hof
92 def problem_hof
93 # gen problem list
93 # gen problem list
94 @user = User.find(session[:user_id])
94 @user = User.find(session[:user_id])
95 @problems = @user.available_problems
95 @problems = @user.available_problems
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 + @summary = {count: 0, solve: 0, attempt: 0}
115 + user = Hash.new(0)
111 Submission.where(problem_id: @problem.id).find_each do |sub|
116 Submission.where(problem_id: @problem.id).find_each do |sub|
117 + #histogram
118 + d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
119 + @histogram[:data][d.to_i] += 1 if d < range
120 +
121 + @summary[:count] += 1
122 + user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
123 +
112 lang = Language.find_by_id(sub.language_id)
124 lang = Language.find_by_id(sub.language_id)
113 next unless lang
125 next unless lang
114 next unless sub.points >= @problem.full_score
126 next unless sub.points >= @problem.full_score
115
127
116 #initialize
128 #initialize
117 unless @by_lang.has_key?(lang.pretty_name)
129 unless @by_lang.has_key?(lang.pretty_name)
118 @by_lang[lang.pretty_name] = {
130 @by_lang[lang.pretty_name] = {
119 runtime: { avail: false, value: 2**30-1 },
131 runtime: { avail: false, value: 2**30-1 },
120 memory: { avail: false, value: 2**30-1 },
132 memory: { avail: false, value: 2**30-1 },
121 length: { avail: false, value: 2**30-1 },
133 length: { avail: false, value: 2**30-1 },
122 first: { avail: false, value: DateTime.new(3000,1,1) }
134 first: { avail: false, value: DateTime.new(3000,1,1) }
123 }
135 }
124 end
136 end
125
137
126 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
138 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
127 - @by_lang[lang.pretty_name][:runtime] = {
139 + @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
140 end
134
141
135 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
142 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
136 - @by_lang[lang.pretty_name][:memory] = {
143 + @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
144 end
143
145
144 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
146 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
145 !sub.user.admin?
147 !sub.user.admin?
146 - @by_lang[lang.pretty_name][:first] = {
148 + @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
149 end
153
150
154 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
151 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
155 - @by_lang[lang.pretty_name][:length] = {
152 + @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
153 end
162 end
154 end
163
155
164 #process user_id
156 #process user_id
165 @by_lang.each do |lang,prop|
157 @by_lang.each do |lang,prop|
166 prop.each do |k,v|
158 prop.each do |k,v|
167 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
159 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
168 end
160 end
169 end
161 end
170
162
171 #sum into best
163 #sum into best
172 if @by_lang and @by_lang.first
164 if @by_lang and @by_lang.first
173 @best = @by_lang.first[1].clone
165 @best = @by_lang.first[1].clone
174 @by_lang.each do |lang,prop|
166 @by_lang.each do |lang,prop|
175 if @best[:runtime][:value] >= prop[:runtime][:value]
167 if @best[:runtime][:value] >= prop[:runtime][:value]
176 @best[:runtime] = prop[:runtime]
168 @best[:runtime] = prop[:runtime]
177 @best[:runtime][:lang] = lang
169 @best[:runtime][:lang] = lang
178 end
170 end
179 if @best[:memory][:value] >= prop[:memory][:value]
171 if @best[:memory][:value] >= prop[:memory][:value]
180 @best[:memory] = prop[:memory]
172 @best[:memory] = prop[:memory]
181 @best[:memory][:lang] = lang
173 @best[:memory][:lang] = lang
182 end
174 end
183 if @best[:length][:value] >= prop[:length][:value]
175 if @best[:length][:value] >= prop[:length][:value]
184 @best[:length] = prop[:length]
176 @best[:length] = prop[:length]
185 @best[:length][:lang] = lang
177 @best[:length][:lang] = lang
186 end
178 end
187 if @best[:first][:value] >= prop[:first][:value]
179 if @best[:first][:value] >= prop[:first][:value]
188 @best[:first] = prop[:first]
180 @best[:first] = prop[:first]
189 @best[:first][:lang] = lang
181 @best[:first][:lang] = lang
190 end
182 end
191 end
183 end
192 end
184 end
193 - end
185 +
186 + @histogram[:summary][:max] = [@histogram[:data].max,1].max
187 + @summary[:attempt] = user.count
188 + user.each_value { |v| @summary[:solve] += 1 if v == 1 }
194 end
189 end
190 +
195 end
191 end
@@ -66,97 +66,115
66 @user.errors.add_to_base("Email cannot be blank") if @user.email==''
66 @user.errors.add_to_base("Email cannot be blank") if @user.email==''
67 render :action => 'new', :layout => 'empty'
67 render :action => 'new', :layout => 'empty'
68 end
68 end
69 end
69 end
70
70
71 def confirm
71 def confirm
72 login = params[:login]
72 login = params[:login]
73 key = params[:activation]
73 key = params[:activation]
74 @user = User.find_by_login(login)
74 @user = User.find_by_login(login)
75 if (@user) and (@user.verify_activation_key(key))
75 if (@user) and (@user.verify_activation_key(key))
76 if @user.valid? # check uniquenss of email
76 if @user.valid? # check uniquenss of email
77 @user.activated = true
77 @user.activated = true
78 @user.save
78 @user.save
79 @result = :successful
79 @result = :successful
80 else
80 else
81 @result = :email_used
81 @result = :email_used
82 end
82 end
83 else
83 else
84 @result = :failed
84 @result = :failed
85 end
85 end
86 render :action => 'confirm', :layout => 'empty'
86 render :action => 'confirm', :layout => 'empty'
87 end
87 end
88
88
89 def forget
89 def forget
90 render :action => 'forget', :layout => 'empty'
90 render :action => 'forget', :layout => 'empty'
91 end
91 end
92
92
93 def retrieve_password
93 def retrieve_password
94 email = params[:email]
94 email = params[:email]
95 user = User.find_by_email(email)
95 user = User.find_by_email(email)
96 if user
96 if user
97 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
97 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
98 if last_updated_time > Time.now.gmtime - 5.minutes
98 if last_updated_time > Time.now.gmtime - 5.minutes
99 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
99 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
100 else
100 else
101 user.password = user.password_confirmation = User.random_password
101 user.password = user.password_confirmation = User.random_password
102 user.save
102 user.save
103 send_new_password_email(user)
103 send_new_password_email(user)
104 flash[:notice] = 'New password has been mailed to you.'
104 flash[:notice] = 'New password has been mailed to you.'
105 end
105 end
106 else
106 else
107 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
107 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
108 end
108 end
109 redirect_to :action => 'forget'
109 redirect_to :action => 'forget'
110 end
110 end
111
111
112 def profile
112 def profile
113 @user = User.find(params[:id])
113 @user = User.find(params[:id])
114 - @submission = Submission.where(user_id: params[:id]).all
114 + @submission = Submission.includes(:problem).where(user_id: params[:id])
115 +
116 + range = 120
117 + @histogram = { data: Array.new(range,0), summary: {} }
118 + @summary = {count: 0, solve: 0, attempt: 0}
119 + problem = Hash.new(0)
120 +
121 + @submission.find_each do |sub|
122 + #histogram
123 + d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
124 + @histogram[:data][d.to_i] += 1 if d < range
125 +
126 + @summary[:count] += 1
127 + problem[sub.problem] = [problem[sub.problem], (sub.points >= sub.problem.full_score) ? 1 : 0].max
128 + end
129 +
130 + @histogram[:summary][:max] = [@histogram[:data].max,1].max
131 + @summary[:attempt] = problem.count
132 + problem.each_value { |v| @summary[:solve] += 1 if v == 1 }
115 end
133 end
116
134
117 protected
135 protected
118
136
119 def verify_online_registration
137 def verify_online_registration
120 if !GraderConfiguration['system.online_registration']
138 if !GraderConfiguration['system.online_registration']
121 redirect_to :controller => 'main', :action => 'login'
139 redirect_to :controller => 'main', :action => 'login'
122 end
140 end
123 end
141 end
124
142
125 def send_confirmation_email(user)
143 def send_confirmation_email(user)
126 contest_name = GraderConfiguration['contest.name']
144 contest_name = GraderConfiguration['contest.name']
127 activation_url = url_for(:action => 'confirm',
145 activation_url = url_for(:action => 'confirm',
128 :login => user.login,
146 :login => user.login,
129 :activation => user.activation_key)
147 :activation => user.activation_key)
130 home_url = url_for(:controller => 'main', :action => 'index')
148 home_url = url_for(:controller => 'main', :action => 'index')
131 mail_subject = "[#{contest_name}] Confirmation"
149 mail_subject = "[#{contest_name}] Confirmation"
132 mail_body = t('registration.email_body', {
150 mail_body = t('registration.email_body', {
133 :full_name => user.full_name,
151 :full_name => user.full_name,
134 :contest_name => contest_name,
152 :contest_name => contest_name,
135 :login => user.login,
153 :login => user.login,
136 :password => user.password,
154 :password => user.password,
137 :activation_url => activation_url,
155 :activation_url => activation_url,
138 :admin_email => admin_email
156 :admin_email => admin_email
139 })
157 })
140
158
141 logger.info mail_body
159 logger.info mail_body
142
160
143 send_mail(user.email, mail_subject, mail_body)
161 send_mail(user.email, mail_subject, mail_body)
144 end
162 end
145
163
146 def send_new_password_email(user)
164 def send_new_password_email(user)
147 contest_name = GraderConfiguration['contest.name']
165 contest_name = GraderConfiguration['contest.name']
148 mail_subject = "[#{contest_name}] Password recovery"
166 mail_subject = "[#{contest_name}] Password recovery"
149 mail_body = t('registration.password_retrieval.email_body', {
167 mail_body = t('registration.password_retrieval.email_body', {
150 :full_name => user.full_name,
168 :full_name => user.full_name,
151 :contest_name => contest_name,
169 :contest_name => contest_name,
152 :login => user.login,
170 :login => user.login,
153 :password => user.password,
171 :password => user.password,
154 :admin_email => admin_email
172 :admin_email => admin_email
155 })
173 })
156
174
157 logger.info mail_body
175 logger.info mail_body
158
176
159 send_mail(user.email, mail_subject, mail_body)
177 send_mail(user.email, mail_subject, mail_body)
160 end
178 end
161
179
162 # allow viewing of regular user profile only when options allow so
180 # allow viewing of regular user profile only when options allow so
@@ -10,96 +10,103
10
10
11 scope :available, :conditions => {:available => true}
11 scope :available, :conditions => {:available => true}
12
12
13 DEFAULT_TIME_LIMIT = 1
13 DEFAULT_TIME_LIMIT = 1
14 DEFAULT_MEMORY_LIMIT = 32
14 DEFAULT_MEMORY_LIMIT = 32
15
15
16 def self.find_available_problems
16 def self.find_available_problems
17 Problem.available.all(:order => "date_added DESC, name ASC")
17 Problem.available.all(:order => "date_added DESC, name ASC")
18 end
18 end
19
19
20 def self.create_from_import_form_params(params, old_problem=nil)
20 def self.create_from_import_form_params(params, old_problem=nil)
21 org_problem = old_problem || Problem.new
21 org_problem = old_problem || Problem.new
22 import_params, problem = Problem.extract_params_and_check(params,
22 import_params, problem = Problem.extract_params_and_check(params,
23 org_problem)
23 org_problem)
24
24
25 if !problem.errors.empty?
25 if !problem.errors.empty?
26 return problem, 'Error importing'
26 return problem, 'Error importing'
27 end
27 end
28
28
29 problem.full_score = 100
29 problem.full_score = 100
30 problem.date_added = Time.new
30 problem.date_added = Time.new
31 problem.test_allowed = true
31 problem.test_allowed = true
32 problem.output_only = false
32 problem.output_only = false
33 problem.available = false
33 problem.available = false
34
34
35 if not problem.save
35 if not problem.save
36 return problem, 'Error importing'
36 return problem, 'Error importing'
37 end
37 end
38
38
39 import_to_db = params.has_key? :import_to_db
39 import_to_db = params.has_key? :import_to_db
40
40
41 importer = TestdataImporter.new(problem)
41 importer = TestdataImporter.new(problem)
42
42
43 if not importer.import_from_file(import_params[:file],
43 if not importer.import_from_file(import_params[:file],
44 import_params[:time_limit],
44 import_params[:time_limit],
45 import_params[:memory_limit],
45 import_params[:memory_limit],
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
70 end
77 end
71 result ||= default
78 result ||= default
72 end
79 end
73
80
74 def self.extract_params_and_check(params, problem)
81 def self.extract_params_and_check(params, problem)
75 time_limit = Problem.to_f_or_default(params[:time_limit],
82 time_limit = Problem.to_f_or_default(params[:time_limit],
76 DEFAULT_TIME_LIMIT)
83 DEFAULT_TIME_LIMIT)
77 memory_limit = Problem.to_i_or_default(params[:memory_limit],
84 memory_limit = Problem.to_i_or_default(params[:memory_limit],
78 DEFAULT_MEMORY_LIMIT)
85 DEFAULT_MEMORY_LIMIT)
79
86
80 if time_limit<=0 or time_limit >60
87 if time_limit<=0 or time_limit >60
81 problem.errors.add_to_base('Time limit out of range.')
88 problem.errors.add_to_base('Time limit out of range.')
82 end
89 end
83
90
84 if memory_limit==0 and params[:memory_limit]!='0'
91 if memory_limit==0 and params[:memory_limit]!='0'
85 problem.errors.add_to_base('Memory limit format errors.')
92 problem.errors.add_to_base('Memory limit format errors.')
86 elsif memory_limit<=0 or memory_limit >512
93 elsif memory_limit<=0 or memory_limit >512
87 problem.errors.add_to_base('Memory limit out of range.')
94 problem.errors.add_to_base('Memory limit out of range.')
88 end
95 end
89
96
90 if params[:file]==nil or params[:file]==''
97 if params[:file]==nil or params[:file]==''
91 problem.errors.add_to_base('No testdata file.')
98 problem.errors.add_to_base('No testdata file.')
92 end
99 end
93
100
94 checker_name = 'text'
101 checker_name = 'text'
95 if ['text','float'].include? params[:checker]
102 if ['text','float'].include? params[:checker]
96 checker_name = params[:checker]
103 checker_name = params[:checker]
97 end
104 end
98
105
99 file = params[:file]
106 file = params[:file]
100
107
101 if !problem.errors.empty?
108 if !problem.errors.empty?
102 return nil, problem
109 return nil, problem
103 end
110 end
104
111
105 problem.name = params[:name]
112 problem.name = params[:name]
@@ -1,61 +1,67
1 %style{type: "text/css"}
1 %style{type: "text/css"}
2 = @css_style
2 = @css_style
3 :css
3 :css
4 .field {
4 .field {
5 font-weight: bold;
5 font-weight: bold;
6 text-align: right;
6 text-align: right;
7 padding: 3px;
7 padding: 3px;
8 }
8 }
9
9
10
10
11 %h1= "Submission: #{@submission.id}"
11 %h1= "Submission: #{@submission.id}"
12
12
13
13
14 %h2 Stat
14 %h2 Stat
15
15
16 %table.info
16 %table.info
17 %thead
17 %thead
18 %tr.info-head
18 %tr.info-head
19 %th Field
19 %th Field
20 %th Value
20 %th Value
21 %tbody
21 %tbody
22 %tr{class: cycle('info-even','info-odd')}
22 %tr{class: cycle('info-even','info-odd')}
23 %td.field User:
23 %td.field User:
24 - %td.value= "(#{@submission.user.login}) #{@submission.user.full_name}"
24 + %td.value
25 + - if @submission.user
26 + = link_to "(#{@submission.user.login})", controller: "users", action: "profile", id: @submission.user
27 + = @submission.user.full_name
28 + - else
29 + = "(n/a)"
25 %tr{class: cycle('info-even','info-odd')}
30 %tr{class: cycle('info-even','info-odd')}
26 %td.field Problem:
31 %td.field Problem:
27 %td.value
32 %td.value
28 - if @submission.problem!=nil
33 - if @submission.problem!=nil
29 - = "(#{@submission.problem.name}) #{@submission.problem.full_name}"
34 + = link_to "(#{@submission.problem.name})", controller: "problems", action: "stat", id: @submission.problem
35 + = @submission.problem.full_name
30 - else
36 - else
31 = "(n/a)"
37 = "(n/a)"
32 %tr{class: cycle('info-even','info-odd')}
38 %tr{class: cycle('info-even','info-odd')}
33 %td.field Tries:
39 %td.field Tries:
34 %td.value= @submission.number
40 %td.value= @submission.number
35 %tr{class: cycle('info-even','info-odd')}
41 %tr{class: cycle('info-even','info-odd')}
36 %td.field Submitted:
42 %td.field Submitted:
37 %td.value #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)})
43 %td.value #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)})
38 %tr{class: cycle('info-even','info-odd')}
44 %tr{class: cycle('info-even','info-odd')}
39 %td.field Graded:
45 %td.field Graded:
40 %td.value #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
46 %td.value #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
41 %tr{class: cycle('info-even','info-odd')}
47 %tr{class: cycle('info-even','info-odd')}
42 %td.field Points:
48 %td.field Points:
43 %td.value #{@submission.points}/#{@submission.problem.full_score}
49 %td.value #{@submission.points}/#{@submission.problem.full_score}
44 %tr{class: cycle('info-even','info-odd')}
50 %tr{class: cycle('info-even','info-odd')}
45 %td.field Comment:
51 %td.field Comment:
46 %td.value #{@submission.grader_comment}
52 %td.value #{@submission.grader_comment}
47 %tr{class: cycle('info-even','info-odd')}
53 %tr{class: cycle('info-even','info-odd')}
48 %td.field Runtime (s):
54 %td.field Runtime (s):
49 %td.value #{@submission.max_runtime}
55 %td.value #{@submission.max_runtime}
50 %tr{class: cycle('info-even','info-odd')}
56 %tr{class: cycle('info-even','info-odd')}
51 %td.field Memory (kb):
57 %td.field Memory (kb):
52 %td.value #{@submission.peak_memory}
58 %td.value #{@submission.peak_memory}
53 - if session[:admin]
59 - if session[:admin]
54 %tr{class: cycle('info-even','info-odd')}
60 %tr{class: cycle('info-even','info-odd')}
55 %td.field IP:
61 %td.field IP:
56 %td.value #{@submission.ip_address}
62 %td.value #{@submission.ip_address}
57
63
58 %h2 Source code
64 %h2 Source code
59 //%div.highlight{:style => "border: 1px solid black;"}
65 //%div.highlight{:style => "border: 1px solid black;"}
60 =@formatted_code.html_safe
66 =@formatted_code.html_safe
61
67
@@ -1,34 +1,51
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
21 - row_odd,curr = true,''
38 - row_odd,curr = true,''
22 - @submissions.each do |sub|
39 - @submissions.each do |sub|
23 - next unless sub.user
40 - next unless sub.user
24 - row_odd,curr = !row_odd, sub.user if curr != sub.user
41 - row_odd,curr = !row_odd, sub.user if curr != sub.user
25 %tr{class: row_odd ? "info-odd" : "info-even"}
42 %tr{class: row_odd ? "info-odd" : "info-even"}
26 %td= link_to sub.id, controller: 'graders', action: 'submission', id: sub.id
43 %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
44 %td= link_to sub.user.login, controller: :users, action: :profile, id: sub.user.id
28 %td= sub.user.full_name
45 %td= sub.user.full_name
29 %td= time_ago_in_words(sub.submitted_at) + " ago"
46 %td= time_ago_in_words(sub.submitted_at) + " ago"
30 %td= sub.points
47 %td= sub.points
31 %td.fix-width= sub.grader_comment
48 %td.fix-width= sub.grader_comment
32 - else
49 - else
33 No submission
50 No submission
34
51
@@ -1,79 +1,128
1 + - content_for :header do
2 + = javascript_include_tag 'local_jquery'
3 +
4 + :javascript
5 + $(document).ready( function() {
6 + $("#mem_remark").hover( function() {
7 + $("#mem_remark_box").show();
8 + }, function() {
9 + $("#mem_remark_box").hide();
10 + });
11 + });
12 + alert("hahaha");
1 :css
13 :css
2 .hof_user { color: orangered; font-style: italic; }
14 .hof_user { color: orangered; font-style: italic; }
3 .hof_language { color: green; font-style: italic; }
15 .hof_language { color: green; font-style: italic; }
4 .hof_value { color: deeppink;font-style: italic; }
16 .hof_value { color: deeppink;font-style: italic; }
5 -
17 + .info_param { font-weight: bold;text-align: right; }
6 - %h2 Overall of #{Problem.find(params[:id]).full_name}
18 + .tooltip {
19 + font-family: Verdana,sans-serif;
20 + font-weight: normal;
21 + text-align: left;
22 + font-size: 1.0em;
23 + color: black;
24 + line-height: 1.1;
25 + display: none;
26 + min-width: 20em;
27 + position: absolute;
28 + left: 25px;
29 + bottom: 5px;
30 + border: 1px solid;
31 + padding: 5px;
32 + background-color: #FFF;
33 + word-wrap: break-word;
34 + z-index: 9999;
35 + overflow: auto;
36 + }
7
37
38 + %h1 (#{Problem.find(params[:id]).name}) #{Problem.find(params[:id]).full_name}
39 +
40 + %h2 Problem Stat
41 + %table.info
42 + %thead
43 + %tr.info-head
44 + %th Stat
45 + %th Value
46 + %tbody
47 + %tr{class: cycle('info-even','info-odd')}
48 + %td.info_param Submissions
49 + %td= @summary[:count]
50 + %tr{class: cycle('info-even','info-odd')}
51 + %td.info_param Solved/Attempted User
52 + %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
8 - if @best
53 - if @best
9 - %b Best Runtime:
54 + %tr{class: cycle('info-even','info-odd')}
55 + %td.info_param Best Runtime
56 + %td
10 by #{link_to @best[:runtime][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
57 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>
58 using <span class="hof_language">#{@best[:runtime][:lang]}</span>
12 with <span class="hof_value">#{@best[:runtime][:value] * 1000} milliseconds</span>
59 with <span class="hof_value">#{@best[:runtime][:value] * 1000} milliseconds</span>
13 at submission
60 at submission
14 = link_to("#" + @best[:runtime][:sub_id].to_s, controller: 'graders', action: 'submission', id:@best[:runtime][:sub_id])
61 = link_to("#" + @best[:runtime][:sub_id].to_s, controller: 'graders', action: 'submission', id:@best[:runtime][:sub_id])
15 - %br/
16
62
17 - %b Best Memory Usage:
63 + %tr{class: cycle('info-even','info-odd')}
64 + %td.info_param
65 + Best Memory Usage
66 + %sup{ id: "mem_remark", style: "position:relative; color: blue;"}
67 + [?]
68 + %span.tooltip#mem_remark_box
69 + This counts only for submission with 100% score.
70 + Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)
71 + %td
18 by #{link_to @best[:memory][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
72 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>
73 using <span class="hof_language">#{@best[:memory][:lang]}</span>
20 with <span class="hof_value">#{number_with_delimiter(@best[:memory][:value])} kbytes </span>
74 with <span class="hof_value">#{number_with_delimiter(@best[:memory][:value])} kbytes </span>
21 at submission
75 at submission
22 = link_to("#" + @best[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id:@best[:memory][:sub_id])
76 = link_to("#" + @best[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id:@best[:memory][:sub_id])
23 - %br/
24
77
25 - %b Shortest Code:
78 + %tr{class: cycle('info-even','info-odd')}
79 + %td.info_param Shortest Code
80 + %td
26 by #{link_to @best[:length][:user], controller:'users', action:'profile', id:@best[:length][:user_id]}
81 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>
82 using <span class="hof_language">#{@best[:length][:lang]}</span>
28 with <span class="hof_value">#{@best[:length][:value]} bytes</span>
83 with <span class="hof_value">#{@best[:length][:value]} bytes</span>
29 at submission
84 at submission
30 = link_to("#" + @best[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:length][:sub_id])
85 = link_to("#" + @best[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:length][:sub_id])
31 - %br/
32
86
33 - %b First solver:
87 + %tr{class: cycle('info-even','info-odd')}
88 + %td.info_param First solver
89 + %td
34 #{link_to @best[:first][:user], controller:'users', action:'profile', id:@best[:first][:user_id]} is the first solver
90 #{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>
91 using <span class="hof_language">#{@best[:first][:lang]}</span>
36 on <span class="hof_value">#{@best[:first][:value]}</span>
92 on <span class="hof_value">#{@best[:first][:value]}</span>
37 at submission
93 at submission
38 = link_to("#" + @best[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:first][:sub_id])
94 = link_to("#" + @best[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:first][:sub_id])
39 - %br/
40
95
41 -
96 + - if @best
42 - %p
43 - 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...)
45 -
46 %h2 By language
97 %h2 By language
47
98
48 %table.info
99 %table.info
49 %thead
100 %thead
50 %tr.info-head
101 %tr.info-head
51 %th Language
102 %th Language
52 %th Best runtime (ms)
103 %th Best runtime (ms)
53 %th Best memory (kbytes)
104 %th Best memory (kbytes)
54 %th Shortest Code (bytes)
105 %th Shortest Code (bytes)
55 %th First solver
106 %th First solver
56 %tbody
107 %tbody
57 - @by_lang.each do |lang,value|
108 - @by_lang.each do |lang,value|
58 %tr{class: cycle('info-even','info-odd')}
109 %tr{class: cycle('info-even','info-odd')}
59 %td= lang
110 %td= lang
60 %td
111 %td
61 = link_to value[:runtime][:user], controller: 'users', action: 'profile', id: value[:runtime][:user_id]
112 = link_to value[:runtime][:user], controller: 'users', action: 'profile', id: value[:runtime][:user_id]
62 = "(#{(value[:runtime][:value] * 1000).to_i} @"
113 = "(#{(value[:runtime][:value] * 1000).to_i} @"
63 = "#{link_to("#" + value[:runtime][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:runtime][:sub_id])} )".html_safe
114 = "#{link_to("#" + value[:runtime][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:runtime][:sub_id])} )".html_safe
64 %td
115 %td
65 = link_to value[:memory][:user], controller: 'users', action: 'profile', id: value[:memory][:user_id]
116 = link_to value[:memory][:user], controller: 'users', action: 'profile', id: value[:memory][:user_id]
66 = "(#{number_with_delimiter(value[:memory][:value])} @"
117 = "(#{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
118 = "#{link_to("#" + value[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:memory][:sub_id])} )".html_safe
68 %td
119 %td
69 = link_to value[:length][:user], controller: 'users', action: 'profile', id: value[:length][:user_id]
120 = link_to value[:length][:user], controller: 'users', action: 'profile', id: value[:length][:user_id]
70 = "(#{value[:length][:value]} @"
121 = "(#{value[:length][:value]} @"
71 = "#{link_to("#" + value[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:length][:sub_id])} )".html_safe
122 = "#{link_to("#" + value[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:length][:sub_id])} )".html_safe
72 %td
123 %td
73 - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong...
124 - 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]
125 = link_to value[:first][:user], controller: 'users', action: 'profile', id: value[:first][:user_id]
75 = "(#{value[:first][:value]} @"
126 = "(#{value[:first][:value]} @"
76 = "#{link_to("#" + value[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:first][:sub_id])} )".html_safe
127 = "#{link_to("#" + value[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:first][:sub_id])} )".html_safe
77
128
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 -
@@ -1,52 +1,66
1 - content_for :header do
1 - content_for :header do
2 = javascript_include_tag 'local_jquery'
2 = javascript_include_tag 'local_jquery'
3
3
4 - %script{:type=>"text/javascript"}
4 + :javascript
5 $(function () {
5 $(function () {
6 $('#submission_table').tablesorter({widgets: ['zebra']});
6 $('#submission_table').tablesorter({widgets: ['zebra']});
7 });
7 });
8
8
9 :css
9 :css
10 .fix-width {
10 .fix-width {
11 font-family: Droid Sans Mono,Consolas, monospace, mono, Courier New, Courier;
11 font-family: Droid Sans Mono,Consolas, monospace, mono, Courier New, Courier;
12 }
12 }
13
13
14 - %h1= @user.full_name + ' Profile'
14 + %h1= @user.full_name
15
15
16 - %h2 Basic info
17 <b>Login:</b> #{@user.login} <br/>
16 <b>Login:</b> #{@user.login} <br/>
18 <b>Full name:</b> #{@user.full_name} <br />
17 <b>Full name:</b> #{@user.full_name} <br />
19
18
20
19
21 %h2 Problem Stat
20 %h2 Problem Stat
21 + %table.info
22 + %thead
23 + %tr.info-head
24 + %th Stat
25 + %th Value
26 + %tbody
27 + %tr{class: cycle('info-even','info-odd')}
28 + %td.info_param Submissions
29 + %td= @summary[:count]
30 + %tr{class: cycle('info-even','info-odd')}
31 + %td.info_param Solved/Attempted Problem
32 + %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
22
33
23 - %h2 Submissions
34 + %h2 Submission History
35 +
36 + =render partial: 'application/bar_graph', locals: {histogram: @histogram, param: {bar_width: 7}}
37 +
24
38
25 %table.tablesorter-cafe#submission_table
39 %table.tablesorter-cafe#submission_table
26 %thead
40 %thead
27 %tr
41 %tr
28 %th ID
42 %th ID
29 %th Problem code
43 %th Problem code
30 %th Problem full name
44 %th Problem full name
31 %th Language
45 %th Language
32 %th Submitted at
46 %th Submitted at
33 %th Result
47 %th Result
34 %th Score
48 %th Score
35 - if session[:admin]
49 - if session[:admin]
36 %th IP
50 %th IP
37 %tbody
51 %tbody
38 - @submission.each do |s|
52 - @submission.each do |s|
39 - next unless s.problem
53 - next unless s.problem
40 %tr
54 %tr
41 %td= link_to "#{s.id}", controller: "graders", action: "submission", id: s.id
55 %td= link_to "#{s.id}", controller: "graders", action: "submission", id: s.id
42 - %td= s.problem.name
56 + %td= link_to s.problem.name, controller: "problems", action: "stat", id: s.problem
43 %td= s.problem.full_name
57 %td= s.problem.full_name
44 %td= s.language.pretty_name
58 %td= s.language.pretty_name
45 %td #{s.submitted_at.strftime('%Y-%m-%d %H:%M')} (#{time_ago_in_words(s.submitted_at)} ago)
59 %td #{s.submitted_at.strftime('%Y-%m-%d %H:%M')} (#{time_ago_in_words(s.submitted_at)} ago)
46 %td.fix-width= s.grader_comment
60 %td.fix-width= s.grader_comment
47 %td= (s.points*100)/s.problem.full_score
61 %td= (s.points*100)/s.problem.full_score
48 - if session[:admin]
62 - if session[:admin]
49 %td= s.ip_address
63 %td= s.ip_address
50
64
51
65
52
66
@@ -1,58 +1,58
1 module GraderScript
1 module GraderScript
2
2
3 def self.grader_control_enabled?
3 def self.grader_control_enabled?
4 if defined? GRADER_ROOT_DIR
4 if defined? GRADER_ROOT_DIR
5 GRADER_ROOT_DIR != ''
5 GRADER_ROOT_DIR != ''
6 else
6 else
7 false
7 false
8 end
8 end
9 end
9 end
10
10
11 def self.raw_dir
11 def self.raw_dir
12 File.join GRADER_ROOT_DIR, "raw"
12 File.join GRADER_ROOT_DIR, "raw"
13 end
13 end
14
14
15 def self.call_grader(params)
15 def self.call_grader(params)
16 if GraderScript.grader_control_enabled?
16 if GraderScript.grader_control_enabled?
17 cmd = File.join(GRADER_ROOT_DIR, "scripts/grader") + " " + params
17 cmd = File.join(GRADER_ROOT_DIR, "scripts/grader") + " " + params
18 system(cmd)
18 system(cmd)
19 end
19 end
20 end
20 end
21
21
22 def self.stop_grader(pid)
22 def self.stop_grader(pid)
23 GraderScript.call_grader "stop #{pid}"
23 GraderScript.call_grader "stop #{pid}"
24 end
24 end
25
25
26 def self.stop_graders(pids)
26 def self.stop_graders(pids)
27 pid_str = (pids.map { |process| process.pid.to_s }).join ' '
27 pid_str = (pids.map { |process| process.pid.to_s }).join ' '
28 GraderScript.call_grader "stop #{pid_str}"
28 GraderScript.call_grader "stop #{pid_str}"
29 end
29 end
30
30
31 def self.start_grader(env)
31 def self.start_grader(env)
32 - GraderScript.call_grader "#{env} queue &"
32 + GraderScript.call_grader "#{env} queue --err-log &"
33 - GraderScript.call_grader "#{env} test_request &"
33 + GraderScript.call_grader "#{env} test_request -err-log &"
34 end
34 end
35
35
36 def self.call_import_problem(problem_name,
36 def self.call_import_problem(problem_name,
37 problem_dir,
37 problem_dir,
38 time_limit=1,
38 time_limit=1,
39 memory_limit=32,
39 memory_limit=32,
40 checker_name='text')
40 checker_name='text')
41 if GraderScript.grader_control_enabled?
41 if GraderScript.grader_control_enabled?
42 cur_dir = `pwd`.chomp
42 cur_dir = `pwd`.chomp
43 Dir.chdir(GRADER_ROOT_DIR)
43 Dir.chdir(GRADER_ROOT_DIR)
44
44
45 script_name = File.join(GRADER_ROOT_DIR, "scripts/import_problem")
45 script_name = File.join(GRADER_ROOT_DIR, "scripts/import_problem")
46 cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" +
46 cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" +
47 " -t #{time_limit} -m #{memory_limit}"
47 " -t #{time_limit} -m #{memory_limit}"
48
48
49 output = `#{cmd}`
49 output = `#{cmd}`
50
50
51 Dir.chdir(cur_dir)
51 Dir.chdir(cur_dir)
52
52
53 return "import CMD: #{cmd}\n" + output
53 return "import CMD: #{cmd}\n" + output
54 end
54 end
55 return ''
55 return ''
56 end
56 end
57
57
58 end
58 end
You need to be logged in to leave comments. Login now