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

r880:31e27f513ce9 - - 9 files changed: 191 inserted, 160 deleted

@@ -127,48 +127,51
127 127 end
128 128 redirect_to action: :index
129 129 end
130 130
131 131 def stat
132 132 unless @problem.available or session[:admin]
133 133 redirect_to :controller => 'main', :action => 'list'
134 134 return
135 135 end
136 136 @submissions = Submission.includes(:user).includes(:language).where(problem_id: params[:id]).order(:user_id,:id)
137 137
138 138 #stat summary
139 139 range =65
140 140 @histogram = { data: Array.new(range,0), summary: {} }
141 141 user = Hash.new(0)
142 142 @submissions.find_each do |sub|
143 143 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
144 144 @histogram[:data][d.to_i] += 1 if d < range
145 145 user[sub.user_id] = [user[sub.user_id], ((sub.try(:points) || 0) >= @problem.full_score) ? 1 : 0].max
146 146 end
147 147 @histogram[:summary][:max] = [@histogram[:data].max,1].max
148 148
149 149 @summary = { attempt: user.count, solve: 0 }
150 150 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
151 +
152 + #for new graph
153 + @chart_dataset = @problem.get_jschart_history.to_json.html_safe
151 154 end
152 155
153 156 def manage
154 157 @problems = Problem.order(date_added: :desc)
155 158 end
156 159
157 160 def do_manage
158 161 if params.has_key? 'change_date_added' and params[:date_added].strip.empty? == false
159 162 change_date_added
160 163 elsif params.has_key? 'add_to_contest'
161 164 add_to_contest
162 165 elsif params.has_key? 'enable_problem'
163 166 set_available(true)
164 167 elsif params.has_key? 'disable_problem'
165 168 set_available(false)
166 169 elsif params.has_key? 'add_group'
167 170 group = Group.find(params[:group_id])
168 171 ok = []
169 172 failed = []
170 173 get_problems_from_params.each do |p|
171 174 begin
172 175 group.problems << p
173 176 ok << p.full_name
174 177 rescue => e
@@ -227,58 +227,59
227 227 # get selected problems or the default
228 228 if params[:id]
229 229 begin
230 230 @problem = Problem.available.find(params[:id])
231 231 rescue
232 232 redirect_to action: :problem_hof
233 233 flash[:notice] = 'Error: submissions for that problem are not viewable.'
234 234 return
235 235 end
236 236 end
237 237
238 238 return unless @problem
239 239
240 240 #model submisssion
241 241 @model_subs = Submission.where(problem: @problem,tag: Submission.tags[:model])
242 242
243 243
244 244 #calculate best submission
245 245 @by_lang = {} #aggregrate by language
246 246
247 247 range =65
248 248 #@histogram = { data: Array.new(range,0), summary: {} }
249 249 @summary = {count: 0, solve: 0, attempt: 0}
250 250 user = Hash.new(0)
251 - Submission.where(problem_id: @problem.id).find_each do |sub|
251 + Submission.where(problem_id: @problem.id).includes(:language).each do |sub|
252 252 #histogram
253 253 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
254 254 #@histogram[:data][d.to_i] += 1 if d < range
255 255
256 256 next unless sub.points
257 257 @summary[:count] += 1
258 258 user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
259 259
260 - lang = Language.find_by_id(sub.language_id)
260 + #lang = Language.find_by_id(sub.language_id)
261 + lang = sub.language
261 262 next unless lang
262 263 next unless sub.points >= @problem.full_score
263 264
264 265 #initialize
265 266 unless @by_lang.has_key?(lang.pretty_name)
266 267 @by_lang[lang.pretty_name] = {
267 268 runtime: { avail: false, value: 2**30-1 },
268 269 memory: { avail: false, value: 2**30-1 },
269 270 length: { avail: false, value: 2**30-1 },
270 271 first: { avail: false, value: DateTime.new(3000,1,1) }
271 272 }
272 273 end
273 274
274 275 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
275 276 @by_lang[lang.pretty_name][:runtime] = { avail: true, user_id: sub.user_id, value: sub.max_runtime, sub_id: sub.id }
276 277 end
277 278
278 279 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
279 280 @by_lang[lang.pretty_name][:memory] = { avail: true, user_id: sub.user_id, value: sub.peak_memory, sub_id: sub.id }
280 281 end
281 282
282 283 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and sub.user and
283 284 !sub.user.admin?
284 285 @by_lang[lang.pretty_name][:first] = { avail: true, user_id: sub.user_id, value: sub.submitted_at, sub_id: sub.id }
@@ -109,69 +109,63
109 109 render :action => 'forget', :layout => 'empty'
110 110 end
111 111
112 112 def retrieve_password
113 113 email = params[:email]
114 114 user = User.find_by_email(email)
115 115 if user
116 116 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
117 117 if last_updated_time > Time.now.gmtime - 5.minutes
118 118 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
119 119 else
120 120 user.password = user.password_confirmation = User.random_password
121 121 user.save
122 122 send_new_password_email(user)
123 123 flash[:notice] = 'New password has been mailed to you.'
124 124 end
125 125 else
126 126 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
127 127 end
128 128 redirect_to :action => 'forget'
129 129 end
130 130
131 131 def stat
132 132 @user = User.find(params[:id])
133 - @submission = Submission.joins(:problem).where(user_id: params[:id])
133 + @submission = Submission.joins(:problem).includes(:problem).includes(:language).where(user_id: params[:id])
134 134 @submission = @submission.where('problems.available = true') unless current_user.admin?
135 135
136 - range = 120
137 - @histogram = { data: Array.new(range,0), summary: {} }
138 136 @summary = {count: 0, solve: 0, attempt: 0}
139 137 problem = Hash.new(0)
140 138
141 139 @submission.find_each do |sub|
142 - #histogram
143 - d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
144 - @histogram[:data][d.to_i] += 1 if d < range
145 -
146 140 @summary[:count] += 1
147 141 next unless sub.problem
148 142 problem[sub.problem] = [problem[sub.problem], ( (sub.try(:points) || 0) >= sub.problem.full_score) ? 1 : 0].max
149 143 end
150 144
151 - @histogram[:summary][:max] = [@histogram[:data].max,1].max
152 145 @summary[:attempt] = problem.count
153 146 problem.each_value { |v| @summary[:solve] += 1 if v == 1 }
147 + @chart_dataset = @user.get_jschart_user_sub_history.to_json.html_safe
154 148 end
155 149
156 150 def toggle_activate
157 151 @user = User.find(params[:id])
158 152 @user.update_attributes( activated: !@user.activated? )
159 153 respond_to do |format|
160 154 format.js { render partial: 'toggle_button',
161 155 locals: {button_id: "#toggle_activate_user_#{@user.id}",button_on: @user.activated? } }
162 156 end
163 157 end
164 158
165 159 def toggle_enable
166 160 @user = User.find(params[:id])
167 161 @user.update_attributes( enabled: !@user.enabled? )
168 162 respond_to do |format|
169 163 format.js { render partial: 'toggle_button',
170 164 locals: {button_id: "#toggle_enable_user_#{@user.id}",button_on: @user.enabled? } }
171 165 end
172 166 end
173 167
174 168 protected
175 169
176 170 def verify_online_registration
177 171 if !GraderConfiguration['system.online_registration']
@@ -293,48 +293,63
293 293 1
294 294 when a.date_added > b.date_added
295 295 -1
296 296 else
297 297 a.name <=> b.name
298 298 end
299 299 end
300 300 return problem
301 301 else
302 302 return []
303 303 end
304 304 end
305 305
306 306 #check if the user has the right to view that problem
307 307 #this also consider group based problem policy
308 308 def can_view_problem?(problem)
309 309 return true if admin?
310 310 return available_problems.include? problem
311 311 end
312 312
313 313 def self.clear_last_login
314 314 User.update_all(:last_ip => nil)
315 315 end
316 316
317 + def get_jschart_user_sub_history
318 + start = 4.month.ago.beginning_of_day
319 + start_date = start.to_date
320 + count = Submission.where(user: self).where('submitted_at >= ?', start).group('DATE(submitted_at)').count
321 + i = 0
322 + label = []
323 + value = []
324 + while (start_date + i < Time.zone.now.to_date)
325 + label << (start_date+i).strftime("%d-%b")
326 + value << (count[start_date+i] || 0)
327 + i+=1
328 + end
329 + return {labels: label,datasets: [label:'sub',data: value, backgroundColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgb(75, 192, 192)']}
330 + end
331 +
317 332 #create multiple user, one per lines of input
318 333 def self.create_from_list(lines)
319 334 error_logins = []
320 335 first_error = nil
321 336 created_users = []
322 337
323 338 lines.split("\n").each do |line|
324 339 #split with large limit, this will cause consecutive ',' to be result in a blank
325 340 items = line.chomp.split(',',1000)
326 341 if items.length>=2
327 342 login = items[0]
328 343 full_name = items[1]
329 344 remark =''
330 345 user_alias = ''
331 346
332 347 added_random_password = false
333 348 added_password = false
334 349
335 350 #given password?
336 351 if items.length >= 3
337 352 if items[2].chomp(" ").length > 0
338 353 password = items[2].chomp(" ")
339 354 added_password = true
340 355 end
@@ -1,33 +1,33
1 1 - if submission.nil?
2 2 = "-"
3 3 - else
4 4 - if local_assigns[:show_id]
5 5 .row
6 - .col-3.text-secondary
7 - Sub ID:
8 - %strong.col-9= submission.id
6 + .col-3.fw-bold
7 + Sub ID
8 + .col-9.text-secondary-x= submission.id
9 9 - unless submission.graded_at
10 10 .row
11 - .col-3.text-secondary= t 'main.submitted_at'
12 - %strong.col-9= format_full_time_ago(submission.submitted_at.localtime)
11 + .col-3.fw-bold= t 'main.submitted_at'
12 + .col-9.text-secondary-x= format_full_time_ago(submission.submitted_at.localtime)
13 13 - else
14 14 .row
15 - .col-3.text-secondary= t 'main.graded_at'
16 - %strong.col-9= format_full_time_ago(submission.graded_at.localtime)
15 + .col-3.fw-bold= t 'main.graded_at'
16 + .col-9.text-secondary-x= format_full_time_ago(submission.graded_at.localtime)
17 17 - if GraderConfiguration['ui.show_score']
18 18 .row
19 - .col-3.text-secondary=t 'main.score'
20 - %strong.col-9
19 + .col-3.fw-bold=t 'main.score'
20 + .col-9.text-secondary-x
21 21 = (submission.points*100/submission.problem.full_score).to_i
22 22 %tt.grader-comment
23 23 = " [#{submission.grader_comment}]"
24 24 - if local_assigns[:show_button]
25 25 - if submission.graded_at
26 26 - if GraderConfiguration.show_grading_result
27 27 = link_to '[detailed result]', :action => 'result', :id => submission.id
28 28 = link_to "#{t 'main.cmp_msg'}", compiler_msg_submission_path(submission), {popup: true,remote: true,class: 'btn btn-sm btn-info'}
29 29 = link_to "#{t 'main.src_link'}",download_submission_path(submission), class: 'btn btn-sm btn-info'
30 30 = link_to "#{t 'main.submissions_link'}", problem_submissions_path(submission.problem.id), class: 'btn btn-sm btn-info'
31 31 - if GraderConfiguration.show_testcase
32 32 = link_to "testcases", show_problem_testcases_path(submission.problem.id), class: 'btn btn-sm btn-info'
33 33
@@ -1,73 +1,51
1 1 - content_for :head do
2 2 = stylesheet_link_tag 'problems'
3 3 = javascript_include_tag 'local_jquery'
4 4
5 - :javascript
6 - $(document).ready( function() {
7 - function shiftclick(start,stop,value) {
8 - $('tr input').each( function(id,input) {
9 - var $input=$(input);
10 - var iid=parseInt($input.attr('id').split('-')[2]);
11 - if(iid>=start&&iid<=stop){
12 - $input.prop('checked',value)
13 - }
14 - });
15 - }
16 -
17 - $('tr input').click( function(e) {
18 - if (e.shiftKey) {
19 - stop = parseInt($(this).attr('id').split('-')[2]);
20 - var orig_stop = stop
21 - if (typeof start !== 'undefined') {
22 - if (start > stop) {
23 - var tmp = start;
24 - start = stop;
25 - stop = tmp;
26 - }
27 - shiftclick(start,stop,$(this).is(':checked') )
28 - }
29 - start = orig_stop
30 - } else {
31 - start = parseInt($(this).attr('id').split('-')[2]);
32 - }
33 - });
34 - });
35 5
36 6
37 7 %h1 Manage problems
38 8
39 9 %p= link_to '[Back to problem list]', problems_path
40 10
41 - = form_tag :action=>'do_manage' do
42 - .panel.panel-primary
43 - .panel-heading
11 + = form_with url: do_manage_problems_path do |f|
12 + .card.border-primary.mb-2
13 + .card-header.text-bg-primary.border-primary
44 14 Action
45 - .panel-body
15 + .card-body
46 16 .submit-box
47 17 What do you want to do to the selected problem?
48 18 %br/
49 19 (You can shift-click to select a range of problems)
20 + .row
21 + .col-md-auto
22 + = f.check_box :change_date_added, class: 'form-check-input'
23 + .col-md-auto
24 + .form-check-label
25 + Change "Date added" to
26 + .col-md-auto
27 +
50 28 %ul.form-inline
51 29 %li
52 30 Change "Date added" to
53 31 .input-group.date
54 32 = text_field_tag :date_added, class: 'form-control'
55 33 %span.input-group-addon
56 34 %span.glyphicon.glyphicon-calendar
57 35 -# = select_date Date.current, :prefix => 'date_added'
58 36 &nbsp;&nbsp;&nbsp;
59 37 = submit_tag 'Change', :name => 'change_date_added', class: 'btn btn-primary btn-sm'
60 38 %li
61 39 Set "Available" to
62 40 = submit_tag 'True', :name => 'enable_problem', class: 'btn btn-primary btn-sm'
63 41 = submit_tag 'False', :name => 'disable_problem', class: 'btn btn-primary btn-sm'
64 42
65 43 - if GraderConfiguration.multicontests?
66 44 %li
67 45 Add selected problems to contest
68 46 = select("contest","id",Contest.all.collect {|c| [c.title, c.id]})
69 47 = submit_tag 'Add', :name => 'add_to_contest', class: 'btn btn-primary btn-sm'
70 48 %li
71 49 Add selected problems to user group
72 50 = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2'
73 51 = submit_tag 'Add', name: 'add_group', class: 'btn btn-primary'
@@ -86,34 +64,66
86 64 %th Available
87 65 %th Date added
88 66 - if GraderConfiguration.multicontests?
89 67 %th Contests
90 68
91 69 %tbody
92 70 - num = 0
93 71 - for problem in @problems
94 72 - num += 1
95 73 %tr{:id => "row-prob-#{problem.id}", :name=> "prob-#{problem.id}"}
96 74 %td= check_box_tag "prob-#{problem.id}-#{num}"
97 75 %td= problem.name
98 76 %td= problem.full_name
99 77 %td
100 78 - problem.tags.each do |t|
101 79 %span.label.label-default= t.name
102 80 %td= problem.available
103 81 %td= problem.date_added
104 82 - if GraderConfiguration.multicontests?
105 83 %td
106 84 - problem.contests.each do |contest|
107 85 = "(#{contest.name} [#{link_to 'x', :action => 'remove_contest', :id => problem.id, :contest_id => contest.id }])"
108 86
109 87 :javascript
110 - $('.input-group.date').datetimepicker({
111 - format: 'DD/MMM/YYYY',
112 - showTodayButton: true,
113 - locale: 'en',
114 - widgetPositioning: {horizontal: 'auto', vertical: 'bottom'},
88 +
89 + $(document).on('import-map-loaded', function() {
90 + function shiftclick(start,stop,value) {
91 + $('tr input').each( function(id,input) {
92 + var $input=$(input);
93 + var iid=parseInt($input.attr('id').split('-')[2]);
94 + if(iid>=start&&iid<=stop){
95 + $input.prop('checked',value)
96 + }
97 + });
98 + }
115 99
100 + $('tr input').click( function(e) {
101 + if (e.shiftKey) {
102 + stop = parseInt($(this).attr('id').split('-')[2]);
103 + var orig_stop = stop
104 + if (typeof start !== 'undefined') {
105 + if (start > stop) {
106 + var tmp = start;
107 + start = stop;
108 + stop = tmp;
109 + }
110 + shiftclick(start,stop,$(this).is(':checked') )
111 + }
112 + start = orig_stop
113 + } else {
114 + start = parseInt($(this).attr('id').split('-')[2]);
115 + }
116 + });
117 +
118 + $('.input-group.date').datetimepicker({
119 + format: 'DD/MMM/YYYY',
120 + showTodayButton: true,
121 + locale: 'en',
122 + widgetPositioning: {horizontal: 'auto', vertical: 'bottom'},
123 +
124 + });
125 +
126 + $('.datatable').DataTable({
127 + paging: false
128 + });
116 129 });
117 - $('.datatable').DataTable({
118 - paging: false
119 - });
@@ -1,63 +1,90
1 1 :css
2 2 .fix-width {
3 3 font-family: "Consolas, Monaco, Droid Sans Mono,Mono, Monospace,Courier"
4 4 }
5 5
6 6 %h1 Problem stat: #{@problem.name}
7 - %h2 Overview
7 +
8 + .row.mb-3
9 + .col-md-8
10 + .card
11 + .card-body
12 + %h2.card-title Submission History
13 + %canvas#chart{height: '50px'}
8 14
9 - .row
10 - .col-md-2
11 - %strong Name:
12 - .col-md-10
13 - = @problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
14 - = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, @problem
15 - .row
16 - .col-md-2.strong
17 - %strong Submissions:
18 - .col-md-10
19 - = @submissions.count
20 - .row
21 - .col-md-2.strong
22 - %strong Solved/Attemped User
23 - .col-md-10
24 - #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
25 -
26 -
27 - %h2 Submissions Count
28 - = render partial: 'application/bar_graph', locals: { histogram: @histogram }
15 + .col-md-4
16 + .card
17 + .card-body
18 + %h2.card-title General Info
19 + .row
20 + .col-sm-6
21 + Name
22 + .col-sm-6
23 + = @problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
24 + = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, @problem
25 + .row
26 + .col-sm-6
27 + Subs
28 + .col-sm-6
29 + = @submissions.count
30 + .row
31 + .col-sm-6
32 + Solved/Attempted User
33 + .col-sm-6
34 + #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
29 35
30 36 %h2 Submissions
31 37 - if @submissions and @submissions.count > 0
32 38 %table#main_table.table.table-condensed.table-striped
33 39 %thead
34 40 %tr
35 41 %th ID
36 42 %th Login
37 43 %th Name
38 44 %th Submitted_at
39 45 %th language
40 46 %th Points
41 47 %th comment
42 48 %th IP
43 49 %tbody
44 50 - row_odd,curr = true,''
45 51 - @submissions.each do |sub|
46 52 - next unless sub.user
47 53 - row_odd,curr = !row_odd, sub.user if curr != sub.user
48 54 %tr
49 55 %td= link_to sub.id, submission_path(sub)
50 56 %td= link_to sub.user.login, stat_user_path(sub.user)
51 57 %td= sub.user.full_name
52 58 %td{data: {order: sub.submitted_at}}= time_ago_in_words(sub.submitted_at) + " ago"
53 59 %td= sub.language.name
54 60 %td= sub.points
55 61 %td.fix-width= sub.grader_comment
56 62 %td= sub.ip_address
57 63 - else
58 64 No submission
59 65
60 66 :javascript
61 - $("#main_table").DataTable({
62 - paging: false
67 + $(document).on('import-map-loaded',(e) => {
68 + //init datatable
69 + $("#main_table").DataTable({
70 + paging: false
71 + });
72 +
73 + //history graph
74 + data = #{@chart_dataset}
75 + config = {
76 + type: 'bar',
77 + data: data,
78 + options: {
79 + plugins: {
80 + legend: {
81 + display: false
82 + },
83 + },
84 + }
85 + }
86 + Chart.defaults.font.size = 15
87 + //Chart.defaults.font.family = 'Sarabun Light'
88 + chart = new Chart($('#chart'),config)
63 89 });
90 +
@@ -1,70 +1,95
1 - - content_for :header do
2 - = javascript_include_tag 'local_jquery'
3 -
4 - :javascript
5 - $(function () {
6 - $('#submission_table').tablesorter({widgets: ['zebra']});
7 - });
8 1
9 2 :css
10 3 .fix-width {
11 4 font-family: Droid Sans Mono,Consolas, monospace, mono, Courier New, Courier;
12 5 }
13 6
14 - %h1= @user.full_name
7 + %h1 User stats
8 + %h5.text-secondary= @user.login
9 +
10 + .row.my-3
11 + .col-md-8
12 + .card
13 + .card-body
14 + %h2.card-title Sub Info
15 + %canvas#chart{height: '50px'}
15 16
16 - <b>Login:</b> #{@user.login} <br/>
17 - <b>Full name:</b> #{@user.full_name} <br />
17 + .col-md-4
18 + .card
19 + .card-body
20 + %h2.card-title General Info
21 + .row
22 + .col-sm-6.fw-bold
23 + Login
24 + .col-sm-6
25 + = @user.login
26 + .row
27 + .col-sm-6.fw-bold
28 + Full name
29 + .col-sm-6
30 + = @user.full_name
31 + .row
32 + .col-sm-6.fw-bold
33 + Subs
34 + .col-sm-6
35 + = @summary[:count]
36 + .row
37 + .col-sm-6.fw-bold
38 + Solved/Attempted Problem
39 + .col-sm-6
40 + #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
18 41
19 42
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)}%)
33 -
34 - %h2 Submission History
35 -
36 - =render partial: 'application/bar_graph', locals: {histogram: @histogram, param: {bar_width: 7}}
37 -
38 -
39 - %table#submission_table.table.table-striped
43 + %table#main_table.table.table-striped
40 44 %thead
41 45 %tr
42 46 %th ID
43 47 %th Problem code
44 48 %th Problem full name
45 49 %th Language
46 50 %th Submitted at
47 51 %th Result
48 52 %th Score
49 53 - if session[:admin]
50 54 %th IP
51 55 %tbody
52 56 - @submission.each do |s|
53 57 - next unless s.problem
54 58 %tr
55 59 %td= link_to s.id, submission_path(s)
56 60 %td= link_to s.problem.name, stat_problem_path(s.problem)
57 61 %td= s.problem.full_name
58 62 %td= s.language.pretty_name
59 63 %td #{s.submitted_at.strftime('%Y-%m-%d %H:%M')} (#{time_ago_in_words(s.submitted_at)} ago)
60 64 %td.fix-width= s.grader_comment
61 65 %td= ( s.try(:points) ? (s.points*100/s.problem.full_score) : '' )
62 66 - if session[:admin]
63 67 %td= s.ip_address
64 68
65 69
66 70
67 71 :javascript
68 - $("#submission_table").DataTable({
69 - paging: false
72 + $(document).on('import-map-loaded',(e) => {
73 + //init datatable
74 + $("#main_table").DataTable({
75 + paging: false
76 + });
77 +
78 + //history graph
79 + data = #{@chart_dataset}
80 + config = {
81 + type: 'bar',
82 + data: data,
83 + options: {
84 + plugins: {
85 + legend: {
86 + display: false
87 + },
88 + },
89 + }
90 + }
91 + Chart.defaults.font.size = 15
92 + //Chart.defaults.font.family = 'Sarabun Light'
93 + chart = new Chart($('#chart'),config)
70 94 });
95 +
deleted file
You need to be logged in to leave comments. Login now