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

r793:8cbec24011e9 - - 4 files changed: 112 inserted, 87 deleted

@@ -0,0 +1,107
1 + - content_for :header do
2 + = stylesheet_link_tag 'tablesorter-theme.cafe'
3 + = javascript_include_tag 'local_jquery'
4 +
5 + %script{:type=>"text/javascript"}
6 + $(function () {
7 + $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 + $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
9 + $('#my_table').tablesorter({widthFixed: true, widgets: ['zebra']});
10 + $('#my_table2').tablesorter({widthFixed: true, widgets: ['zebra']});
11 + $('#sub_table').tablesorter({widthFixed: true, widgets: ['zebra']});
12 + });
13 +
14 + %h1 Login status
15 +
16 + .panel.panel-primary
17 + .panel-heading
18 + User ID and time rnage
19 + .panel-body
20 + = form_tag({session: :url }) do
21 + .row.form-group
22 + .col-md-2
23 + From Date:
24 + .col-md-4
25 + .input-group.date
26 + = text_field_tag :since_datetime, @since_time, class: 'form-control'
27 + %span.input-group-addon
28 + %span.glyphicon.glyphicon-calendar
29 + .row.form-group
30 + .col-md-2
31 + Until Date:
32 + .col-md-4
33 + .input-group.date
34 + = text_field_tag :until_datetime, @until_time, class: 'form-control'
35 + %span.input-group-addon
36 + %span.glyphicon.glyphicon-calendar
37 + .row.form-group
38 + .col-md-2
39 + IDs (separated by space):
40 + .col-md-10
41 + = text_field_tag 'SID', @sid, size: 40, class: 'form-control'
42 + .row.form-group
43 + .col-md-2
44 + .col-md-10
45 + =submit_tag 'query', class: 'btn btn-primary'
46 +
47 + -#
48 + %table
49 + %tr
50 + %td{style: 'width: 120px; font-weight: bold'}= 'Login date range'
51 + %td{align: 'right'} since:
52 + %td= text_field_tag 'since_datetime', @since_time, class: 'form-control datetimepicker'
53 + %tr
54 + %td
55 + %td{align: 'right'} until:
56 + %td= text_field_tag 'until_datetime', @until_time
57 + %tr
58 + %td
59 + %td
60 + %td Blank mean no condition
61 + %tr
62 + %td{style: 'width: 120px; font-weight: bold'}= "ID"
63 + %td{colspan: 2}= text_field_tag 'SID', @sid, size: 40
64 + %tr
65 + %td
66 + %td
67 + %td= submit_tag 'query'
68 +
69 +
70 + %h2 Logs
71 +
72 + - if @sid
73 + %table
74 + %tbody
75 + - @sid.each do |id|
76 + - user = User.where("login = ?",id).first
77 + %tr
78 + //%td= link_to id, controller: :user, action: :profile, id: id
79 + %td= link_to id, "https://www.nattee.net/java/users/profile/#{user.id}"
80 + %td= user.full_name
81 +
82 + //%table.tablesorter-cafe#my_table
83 + %table.info
84 + %thead
85 + %tr.info-head
86 + %th Time
87 + %th Action
88 + %th IP
89 + %th login
90 + %th name
91 + %th problem
92 + %th score
93 + %tbody
94 + - if @logs
95 + - @logs.each do |l|
96 + %tr{class: cycle('info-even','info-odd')}
97 + %td= l[:submitted_at].strftime "%Y.%b.%d %H:%M:%S"
98 + //%td= l[:id] == -1 ? "LOGIN" : link_to("submit #{l[:id]}", controller: 'graders' , action: 'submission', id: l[:id])
99 + %td= l[:id] == -1 ? "LOGIN" : link_to( "submit #{l[:id]}", "https://www.nattee.net/java/graders/submission/#{l[:id]}")
100 + %td= l[:ip_address]
101 + //%td= link_to l[:login], controller: 'users', action: 'profile', id: l[:id]
102 + %td= link_to( l[:login], "https://www.nattee.net/java/users/profile/#{l.user_id}")
103 + %td= l[:full_name]
104 + %td= l[:id] == -1 ? "" : l.problem.name
105 + %td= l[:id] == -1 ? "" : l.points * 100/ l.problem.full_score
106 +
107 +
@@ -1,57 +1,57
1 1 require 'csv'
2 2
3 3 class ReportController < ApplicationController
4 4
5 5 before_action :check_valid_login
6 6
7 7 before_action :admin_authorization, only: [:login_stat,:submission, :submission_query,
8 8 :login, :login_detail_query, :login_summary_query,
9 - :stuck, :cheat_report, :cheat_scruntinize, :show_max_score, :current_score]
9 + :stuck, :cheat_report, :cheat_scrutinize, :show_max_score, :current_score]
10 10
11 11 before_action(only: [:problem_hof]) { |c|
12 12 return false unless check_valid_login
13 13
14 14 admin_authorization unless GraderConfiguration["right.user_view_submission"]
15 15 }
16 16
17 17 def max_score
18 18 end
19 19
20 20 def current_score
21 21 @problems = Problem.available_problems
22 22 if params[:group_id]
23 23 @group = Group.find(params[:group_id])
24 24 @users = @group.users.where(enabled: true)
25 25 else
26 26 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
27 27 end
28 28 @scorearray = calculate_max_score(@problems, @users,0,0,true)
29 29
30 30 #rencer accordingly
31 31 if params[:button] == 'download' then
32 32 csv = gen_csv_from_scorearray(@scorearray,@problems)
33 33 send_data csv, filename: 'max_score.csv'
34 34 else
35 35 #render template: 'user_admin/user_stat'
36 36 render 'current_score'
37 37 end
38 38 end
39 39
40 40 def show_max_score
41 41 #process parameters
42 42 #problems
43 43 @problems = []
44 44 if params[:problem_id]
45 45 params[:problem_id].each do |id|
46 46 next unless id.strip != ""
47 47 pid = Problem.find_by_id(id.to_i)
48 48 @problems << pid if pid
49 49 end
50 50 end
51 51
52 52 #users
53 53 @users = if params[:users] == "all" then
54 54 User.includes(:contests).includes(:contest_stat)
55 55 else
56 56 User.includes(:contests).includes(:contest_stat).where(enabled: true)
57 57 end
@@ -408,117 +408,117
408 408 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
409 409 UNION
410 410 SELECT l2.*
411 411 FROM logins l2 INNER JOIN
412 412 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
413 413 FROM logins l
414 414 INNER JOIN users u ON l.user_id = u.id
415 415 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
416 416 GROUP BY l.ip_address
417 417 HAVING count > 1
418 418 ) ml on ml.ip_address = l2.ip_address
419 419 INNER JOIN users u ON l2.user_id = u.id
420 420 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
421 421 ORDER BY ip_address,created_at
422 422 SQL
423 423 @mld = Login.find_by_sql(st)
424 424
425 425 st = <<-SQL
426 426 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
427 427 FROM submissions s INNER JOIN
428 428 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
429 429 FROM logins l
430 430 INNER JOIN users u ON l.user_id = u.id
431 431 WHERE l.created_at >= ? and l.created_at <= ?
432 432 GROUP BY u.id
433 433 HAVING count > 1
434 434 ) ml ON s.user_id = ml.id
435 435 WHERE s.submitted_at >= ? and s.submitted_at <= ?
436 436 UNION
437 437 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
438 438 FROM submissions s INNER JOIN
439 439 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
440 440 FROM logins l
441 441 INNER JOIN users u ON l.user_id = u.id
442 442 WHERE l.created_at >= ? and l.created_at <= ?
443 443 GROUP BY l.ip_address
444 444 HAVING count > 1
445 445 ) ml on ml.ip_address = s.ip_address
446 446 WHERE s.submitted_at >= ? and s.submitted_at <= ?
447 447 ORDER BY ip_address,submitted_at
448 448 SQL
449 449 @subs = Submission.joins(:problem).find_by_sql([st,@since_time,@until_time,
450 450 @since_time,@until_time,
451 451 @since_time,@until_time,
452 452 @since_time,@until_time])
453 453
454 454 end
455 455
456 - def cheat_scruntinize
456 + def cheat_scrutinize
457 457 #convert date & time
458 458 date_and_time = '%Y-%m-%d %H:%M'
459 459 begin
460 460 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
461 461 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
462 462 rescue
463 463 @since_time = Time.zone.now.ago( 90.minutes)
464 464 end
465 465 begin
466 466 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
467 467 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
468 468 rescue
469 469 @until_time = Time.zone.now
470 470 end
471 471
472 472 #convert sid
473 473 @sid = params[:SID].split(/[,\s]/) if params[:SID]
474 474 unless @sid and @sid.size > 0
475 475 return
476 - redirect_to actoin: :cheat_scruntinize
476 + redirect_to actoin: :cheat_scrutinize
477 477 flash[:notice] = 'Please enter at least 1 student id'
478 478 end
479 479 mark = Array.new(@sid.size,'?')
480 480 condition = "(u.login = " + mark.join(' OR u.login = ') + ')'
481 481
482 482 @st = <<-SQL
483 483 SELECT l.created_at as submitted_at ,-1 as id,u.login,u.full_name,l.ip_address,"" as problem_id,"" as points,l.user_id
484 484 FROM logins l INNER JOIN users u on l.user_id = u.id
485 485 WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition}
486 486 UNION
487 487 SELECT s.submitted_at,s.id,u.login,u.full_name,s.ip_address,s.problem_id,s.points,s.user_id
488 488 FROM submissions s INNER JOIN users u ON s.user_id = u.id
489 489 WHERE s.submitted_at >= ? AND s.submitted_at <= ? AND #{condition}
490 490 ORDER BY submitted_at
491 491 SQL
492 492
493 493 p = [@st,@since_time,@until_time] + @sid + [@since_time,@until_time] + @sid
494 494 @logs = Submission.joins(:problem).find_by_sql(p)
495 495
496 496
497 497
498 498
499 499
500 500 end
501 501
502 502 protected
503 503
504 504 def calculate_max_score(problems, users,since_id,until_id, get_last_score = false)
505 505 #scorearray[i] = user #i's user stat where i is the index (not id)
506 506 scorearray = Array.new
507 507 users.each do |u|
508 508 ustat = Array.new
509 509 ustat[0] = u
510 510 problems.each do |p|
511 511 unless get_last_score
512 512 #get max score
513 513 max_points = 0
514 514 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
515 515 max_points = sub.points if sub and sub.points and (sub.points > max_points)
516 516 end
517 517 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
518 518 else
519 519 #get latest score
520 520 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
521 521 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
522 522 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
523 523 else
524 524 ustat << [0,false]
@@ -105,98 +105,98
105 105 #user admin
106 106 resources :user_admin do
107 107 collection do
108 108 match 'bulk_manage', via: [:get, :post]
109 109 get 'bulk_mail'
110 110 get 'user_stat'
111 111 get 'import'
112 112 get 'new_list'
113 113 get 'admin'
114 114 get 'active'
115 115 get 'mass_mailing'
116 116 get 'revoke_admin'
117 117 post 'grant_admin'
118 118 match 'create_from_list', via: [:get, :post]
119 119 match 'random_all_passwords', via: [:get, :post]
120 120 end
121 121 member do
122 122 get 'clear_last_ip'
123 123 end
124 124 end
125 125
126 126 resources :contest_management, only: [:index] do
127 127 collection do
128 128 get 'user_stat'
129 129 get 'clear_stat'
130 130 get 'clear_all_stat'
131 131 get 'change_contest_mode'
132 132 end
133 133 end
134 134
135 135 #get 'user_admin', to: 'user_admin#index'
136 136 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
137 137 #post 'user_admin', to: 'user_admin#create'
138 138 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
139 139
140 140 #singular resource
141 141 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
142 142 #report
143 143 resource :report, only: [], controller: 'report' do
144 144 get 'login'
145 145 get 'multiple_login'
146 146 get 'problem_hof(/:id)', action: 'problem_hof', as: 'problem_hof'
147 147 get 'current_score(/:group_id)', action: 'current_score', as: 'current_score'
148 148 get 'max_score'
149 149 post 'show_max_score'
150 150 get 'stuck'
151 151 get 'cheat_report'
152 152 post 'cheat_report'
153 - get 'cheat_scruntinize'
154 - post 'cheat_scruntinize'
153 + get 'cheat_scrutinize'
154 + post 'cheat_scrutinize'
155 155 get 'submission'
156 156 post 'submission_query'
157 157 get 'login_stat'
158 158 post 'login_stat'
159 159 get 'login'
160 160 post 'login_summary_query'
161 161 post 'login_detail_query'
162 162 end
163 163 #get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
164 164 #get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
165 165 #get "report/login"
166 166 #get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
167 167 #post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
168 168
169 169 resource :main, only: [], controller: 'main' do
170 170 get 'login'
171 171 get 'logout'
172 172 get 'list'
173 173 get 'submission(/:id)', action: 'submission', as: 'main_submission'
174 174 get 'announcements'
175 175 get 'help'
176 176 post 'submit'
177 177 end
178 178 #main
179 179 #get "main/list"
180 180 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
181 181 #post 'main/submit', to: 'main#submit'
182 182 #get 'main/announcements', to: 'main#announcements'
183 183
184 184
185 185 #
186 186 get 'tasks/view/:file.:ext' => 'tasks#view'
187 187 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
188 188 get 'heartbeat/:id/edit' => 'heartbeat#edit'
189 189
190 190 #grader
191 191 get 'graders/list', to: 'graders#list', as: 'grader_list'
192 192 namespace :graders do
193 193 get 'task/:id/:type', action: 'task', as: 'task'
194 194 get 'view/:id/:type', action: 'view', as: 'view'
195 195 get 'clear/:id', action: 'clear', as: 'clear'
196 196 get 'stop'
197 197 get 'stop_all'
198 198 get 'clear_all'
199 199 get 'clear_terminated'
200 200 get 'start_grading'
201 201 get 'start_exam'
202 202
deleted file
You need to be logged in to leave comments. Login now