Description:
- fix authorization for viewing submission, only admin can view all problems all the time, normal user depends on right.view_submission and problem.available? - add max score query
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r593:a1d7330b2f43 - - 6 files changed: 106 inserted, 7 deleted

@@ -0,0 +1,43
1 + %h1 Maximum score
2 +
3 + = form_tag report_max_score_path
4 + .row
5 + .col-md-4
6 + .panel.panel-primary
7 + .panel-heading
8 + Problems
9 + .panel-body
10 + = label_tag :problems, "Problems"
11 + = select 'problems', 'problem_id', [[(t 'main.specified_in_header'),'-1']] + Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}, {:selected => '-1'}, { class: 'select2 form-control' }
12 + .col-md-4
13 + .panel.panel-primary
14 + .panel-heading
15 + Submission range
16 + .panel-body
17 + .form-group
18 + = label_tag :from, "From"
19 + = text_field_tag 'from_id', nil, class: "form-control"
20 + .form-group
21 + = label_tag :from, "To"
22 + = text_field_tag 'to_id', nil, class: "form-control"
23 + .col-md-4
24 + .panel.panel-primary
25 + .panel-heading
26 + Users
27 + .panel-body
28 + .radio
29 + %label
30 + = radio_button_tag 'users', 'all', true
31 + All users
32 + .radio
33 + %label
34 + = radio_button_tag 'users', 'enabled'
35 + Only enabled users
36 + .row
37 + .col-md-12
38 + = button_tag 'Show', class: "btn btn-primary btn-large"
39 + = button_tag 'Download CSV', class: "btn btn-primary btn-large"
40 + /.col-md-4.col-md-offset-1
41 + / = button_tag 'Show', class: "btn btn-primary btn-block"
42 + /.col-md-4.col-md-offset-2
43 + / = button_tag 'Download CSV', class: "btn btn-primary btn-block"
@@ -1,29 +1,33
1 # See http://help.github.com/ignore-files/ for more about ignoring files.
1 # See http://help.github.com/ignore-files/ for more about ignoring files.
2 #
2 #
3 # If you find yourself ignoring temporary files generated by your text editor
3 # If you find yourself ignoring temporary files generated by your text editor
4 # or operating system, you probably want to add a global ignore instead:
4 # or operating system, you probably want to add a global ignore instead:
5 # git config --global core.excludesfile ~/.gitignore_global
5 # git config --global core.excludesfile ~/.gitignore_global
6
6
7 # Ignore bundler config
7 # Ignore bundler config
8 /.bundle
8 /.bundle
9
9
10 # Ignore the default SQLite database.
10 # Ignore the default SQLite database.
11 /db/*.sqlite3
11 /db/*.sqlite3
12
12
13 # Ignore all logfiles and tempfiles.
13 # Ignore all logfiles and tempfiles.
14 /log/*.log
14 /log/*.log
15 /tmp
15 /tmp
16
16
17 *~
17 *~
18
18
19 /vendor/plugins/rails_upgrade
19 /vendor/plugins/rails_upgrade
20
20
21 #ignore public assets???
21 #ignore public assets???
22 /public/assets
22 /public/assets
23 /public
23 /public
24
24
25 /data
25 /data
26
26
27 #ignore .orig and .swp
27 #ignore .orig and .swp
28 *.orig
28 *.orig
29 *.swp
29 *.swp
30 +
31 + #ignore rvm setting file
32 + .ruby-gemset
33 + .ruby-version
@@ -1,124 +1,128
1 class ApplicationController < ActionController::Base
1 class ApplicationController < ActionController::Base
2 protect_from_forgery
2 protect_from_forgery
3
3
4 before_filter :current_user
4 before_filter :current_user
5
5
6 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
6 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
7 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
7 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
8
8
9 + #report and redirect for unauthorized activities
10 + def unauthorized_redirect
11 + flash[:notice] = 'You are not authorized to view the page you requested'
12 + redirect_to :controller => 'main', :action => 'login'
13 + end
14 +
9 # Returns the current logged-in user (if any).
15 # Returns the current logged-in user (if any).
10 def current_user
16 def current_user
11 return nil unless session[:user_id]
17 return nil unless session[:user_id]
12 @current_user ||= User.find(session[:user_id])
18 @current_user ||= User.find(session[:user_id])
13 end
19 end
14
20
15 def admin_authorization
21 def admin_authorization
16 return false unless authenticate
22 return false unless authenticate
17 user = User.find(session[:user_id], :include => ['roles'])
23 user = User.find(session[:user_id], :include => ['roles'])
18 unless user.admin?
24 unless user.admin?
19 - flash[:notice] = 'You are not authorized to view the page you requested'
25 + unauthorized_redirect
20 - redirect_to :controller => 'main', :action => 'login' unless user.admin?
21 return false
26 return false
22 end
27 end
23 return true
28 return true
24 end
29 end
25
30
26 def authorization_by_roles(allowed_roles)
31 def authorization_by_roles(allowed_roles)
27 return false unless authenticate
32 return false unless authenticate
28 user = User.find(session[:user_id])
33 user = User.find(session[:user_id])
29 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
34 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
30 - flash[:notice] = 'You are not authorized to view the page you requested'
35 + unauthorized_redirect
31 - redirect_to :controller => 'main', :action => 'login'
32 return false
36 return false
33 end
37 end
34 end
38 end
35
39
36 protected
40 protected
37
41
38 def authenticate
42 def authenticate
39 unless session[:user_id]
43 unless session[:user_id]
40 flash[:notice] = 'You need to login'
44 flash[:notice] = 'You need to login'
41 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
45 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
42 flash[:notice] = 'You need to login but you cannot log in at this time'
46 flash[:notice] = 'You need to login but you cannot log in at this time'
43 end
47 end
44 redirect_to :controller => 'main', :action => 'login'
48 redirect_to :controller => 'main', :action => 'login'
45 return false
49 return false
46 end
50 end
47
51
48 # check if run in single user mode
52 # check if run in single user mode
49 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
53 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
50 user = User.find_by_id(session[:user_id])
54 user = User.find_by_id(session[:user_id])
51 if user==nil or (not user.admin?)
55 if user==nil or (not user.admin?)
52 flash[:notice] = 'You cannot log in at this time'
56 flash[:notice] = 'You cannot log in at this time'
53 redirect_to :controller => 'main', :action => 'login'
57 redirect_to :controller => 'main', :action => 'login'
54 return false
58 return false
55 end
59 end
56 unless user.enabled?
60 unless user.enabled?
57 flash[:notice] = 'Your account is disabled'
61 flash[:notice] = 'Your account is disabled'
58 redirect_to :controller => 'main', :action => 'login'
62 redirect_to :controller => 'main', :action => 'login'
59 return false
63 return false
60 end
64 end
61 return true
65 return true
62 end
66 end
63
67
64 if GraderConfiguration.multicontests?
68 if GraderConfiguration.multicontests?
65 user = User.find(session[:user_id])
69 user = User.find(session[:user_id])
66 return true if user.admin?
70 return true if user.admin?
67 begin
71 begin
68 if user.contest_stat(true).forced_logout
72 if user.contest_stat(true).forced_logout
69 flash[:notice] = 'You have been automatically logged out.'
73 flash[:notice] = 'You have been automatically logged out.'
70 redirect_to :controller => 'main', :action => 'index'
74 redirect_to :controller => 'main', :action => 'index'
71 end
75 end
72 rescue
76 rescue
73 end
77 end
74 end
78 end
75 return true
79 return true
76 end
80 end
77
81
78 def authenticate_by_ip_address
82 def authenticate_by_ip_address
79 #this assume that we have already authenticate normally
83 #this assume that we have already authenticate normally
80 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
84 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
81 user = User.find(session[:user_id])
85 user = User.find(session[:user_id])
82 if (not user.admin? and user.last_ip and user.last_ip != request.remote_ip)
86 if (not user.admin? and user.last_ip and user.last_ip != request.remote_ip)
83 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
87 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
84 redirect_to :controller => 'main', :action => 'login'
88 redirect_to :controller => 'main', :action => 'login'
85 puts "CHEAT: user #{user.login} tried to login from '#{request.remote_ip}' while last ip is '#{user.last_ip}' at #{Time.zone.now}"
89 puts "CHEAT: user #{user.login} tried to login from '#{request.remote_ip}' while last ip is '#{user.last_ip}' at #{Time.zone.now}"
86 return false
90 return false
87 end
91 end
88 unless user.last_ip
92 unless user.last_ip
89 user.last_ip = request.remote_ip
93 user.last_ip = request.remote_ip
90 user.save
94 user.save
91 end
95 end
92 end
96 end
93 return true
97 return true
94 end
98 end
95
99
96 def authorization
100 def authorization
97 return false unless authenticate
101 return false unless authenticate
98 user = User.find(session[:user_id])
102 user = User.find(session[:user_id])
99 unless user.roles.detect { |role|
103 unless user.roles.detect { |role|
100 role.rights.detect{ |right|
104 role.rights.detect{ |right|
101 right.controller == self.class.controller_name and
105 right.controller == self.class.controller_name and
102 (right.action == 'all' or right.action == action_name)
106 (right.action == 'all' or right.action == action_name)
103 }
107 }
104 }
108 }
105 flash[:notice] = 'You are not authorized to view the page you requested'
109 flash[:notice] = 'You are not authorized to view the page you requested'
106 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
110 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
107 redirect_to :controller => 'main', :action => 'login'
111 redirect_to :controller => 'main', :action => 'login'
108 return false
112 return false
109 end
113 end
110 end
114 end
111
115
112 def verify_time_limit
116 def verify_time_limit
113 return true if session[:user_id]==nil
117 return true if session[:user_id]==nil
114 user = User.find(session[:user_id], :include => :site)
118 user = User.find(session[:user_id], :include => :site)
115 return true if user==nil or user.site == nil
119 return true if user==nil or user.site == nil
116 if user.contest_finished?
120 if user.contest_finished?
117 flash[:notice] = 'Error: the contest you are participating is over.'
121 flash[:notice] = 'Error: the contest you are participating is over.'
118 redirect_to :back
122 redirect_to :back
119 return false
123 return false
120 end
124 end
121 return true
125 return true
122 end
126 end
123
127
124 end
128 end
@@ -1,123 +1,130
1 class GradersController < ApplicationController
1 class GradersController < ApplicationController
2
2
3 before_filter :admin_authorization, except: [ :submission ]
3 before_filter :admin_authorization, except: [ :submission ]
4 before_filter(only: [:submission]) {
4 before_filter(only: [:submission]) {
5 + #check if authenticated
5 return false unless authenticate
6 return false unless authenticate
6
7
7 - if GraderConfiguration["right.user_view_submission"]
8 + #admin always has privileged
8 - return true;
9 + if @current_user.admin?
10 + return true
9 end
11 end
10
12
11 - admin_authorization
13 + if GraderConfiguration["right.user_view_submission"] and Submission.find(params[:id]).problem.available?
14 + return true
15 + else
16 + unauthorized_redirect
17 + return false
18 + end
12 }
19 }
13
20
14 verify :method => :post, :only => ['clear_all',
21 verify :method => :post, :only => ['clear_all',
15 'start_exam',
22 'start_exam',
16 'start_grading',
23 'start_grading',
17 'stop_all',
24 'stop_all',
18 'clear_terminated'],
25 'clear_terminated'],
19 :redirect_to => {:action => 'index'}
26 :redirect_to => {:action => 'index'}
20
27
21 def index
28 def index
22 redirect_to :action => 'list'
29 redirect_to :action => 'list'
23 end
30 end
24
31
25 def list
32 def list
26 @grader_processes = GraderProcess.find_running_graders
33 @grader_processes = GraderProcess.find_running_graders
27 @stalled_processes = GraderProcess.find_stalled_process
34 @stalled_processes = GraderProcess.find_stalled_process
28
35
29 @terminated_processes = GraderProcess.find_terminated_graders
36 @terminated_processes = GraderProcess.find_terminated_graders
30
37
31 @last_task = Task.find(:first,
38 @last_task = Task.find(:first,
32 :order => 'created_at DESC')
39 :order => 'created_at DESC')
33 @last_test_request = TestRequest.find(:first,
40 @last_test_request = TestRequest.find(:first,
34 :order => 'created_at DESC')
41 :order => 'created_at DESC')
35 @submission = Submission.order("id desc").limit(20)
42 @submission = Submission.order("id desc").limit(20)
36 @backlog_submission = Submission.where('graded_at is null')
43 @backlog_submission = Submission.where('graded_at is null')
37 end
44 end
38
45
39 def clear
46 def clear
40 grader_proc = GraderProcess.find(params[:id])
47 grader_proc = GraderProcess.find(params[:id])
41 grader_proc.destroy if grader_proc!=nil
48 grader_proc.destroy if grader_proc!=nil
42 redirect_to :action => 'list'
49 redirect_to :action => 'list'
43 end
50 end
44
51
45 def clear_terminated
52 def clear_terminated
46 GraderProcess.find_terminated_graders.each do |p|
53 GraderProcess.find_terminated_graders.each do |p|
47 p.destroy
54 p.destroy
48 end
55 end
49 redirect_to :action => 'list'
56 redirect_to :action => 'list'
50 end
57 end
51
58
52 def clear_all
59 def clear_all
53 GraderProcess.find(:all).each do |p|
60 GraderProcess.find(:all).each do |p|
54 p.destroy
61 p.destroy
55 end
62 end
56 redirect_to :action => 'list'
63 redirect_to :action => 'list'
57 end
64 end
58
65
59 def view
66 def view
60 if params[:type]=='Task'
67 if params[:type]=='Task'
61 redirect_to :action => 'task', :id => params[:id]
68 redirect_to :action => 'task', :id => params[:id]
62 else
69 else
63 redirect_to :action => 'test_request', :id => params[:id]
70 redirect_to :action => 'test_request', :id => params[:id]
64 end
71 end
65 end
72 end
66
73
67 def test_request
74 def test_request
68 @test_request = TestRequest.find(params[:id])
75 @test_request = TestRequest.find(params[:id])
69 end
76 end
70
77
71 def task
78 def task
72 @task = Task.find(params[:id])
79 @task = Task.find(params[:id])
73 end
80 end
74
81
75 def submission
82 def submission
76 @submission = Submission.find(params[:id])
83 @submission = Submission.find(params[:id])
77 formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true )
84 formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true )
78 lexer = case @submission.language.name
85 lexer = case @submission.language.name
79 when "c" then Rouge::Lexers::C.new
86 when "c" then Rouge::Lexers::C.new
80 when "cpp" then Rouge::Lexers::Cpp.new
87 when "cpp" then Rouge::Lexers::Cpp.new
81 when "pas" then Rouge::Lexers::Pas.new
88 when "pas" then Rouge::Lexers::Pas.new
82 when "ruby" then Rouge::Lexers::Ruby.new
89 when "ruby" then Rouge::Lexers::Ruby.new
83 when "python" then Rouge::Lexers::Python.new
90 when "python" then Rouge::Lexers::Python.new
84 when "java" then Rouge::Lexers::Java.new
91 when "java" then Rouge::Lexers::Java.new
85 when "php" then Rouge::Lexers::PHP.new
92 when "php" then Rouge::Lexers::PHP.new
86 end
93 end
87 @formatted_code = formatter.format(lexer.lex(@submission.source))
94 @formatted_code = formatter.format(lexer.lex(@submission.source))
88 @css_style = Rouge::Themes::ThankfulEyes.render(scope: '.highlight')
95 @css_style = Rouge::Themes::ThankfulEyes.render(scope: '.highlight')
89
96
90 user = User.find(session[:user_id])
97 user = User.find(session[:user_id])
91 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
98 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
92
99
93 end
100 end
94
101
95 # various grader controls
102 # various grader controls
96
103
97 def stop
104 def stop
98 grader_proc = GraderProcess.find(params[:id])
105 grader_proc = GraderProcess.find(params[:id])
99 GraderScript.stop_grader(grader_proc.pid)
106 GraderScript.stop_grader(grader_proc.pid)
100 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
107 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
101 redirect_to :action => 'list'
108 redirect_to :action => 'list'
102 end
109 end
103
110
104 def stop_all
111 def stop_all
105 GraderScript.stop_graders(GraderProcess.find_running_graders +
112 GraderScript.stop_graders(GraderProcess.find_running_graders +
106 GraderProcess.find_stalled_process)
113 GraderProcess.find_stalled_process)
107 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
114 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
108 redirect_to :action => 'list'
115 redirect_to :action => 'list'
109 end
116 end
110
117
111 def start_grading
118 def start_grading
112 GraderScript.start_grader('grading')
119 GraderScript.start_grader('grading')
113 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
120 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
114 redirect_to :action => 'list'
121 redirect_to :action => 'list'
115 end
122 end
116
123
117 def start_exam
124 def start_exam
118 GraderScript.start_grader('exam')
125 GraderScript.start_grader('exam')
119 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
126 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
120 redirect_to :action => 'list'
127 redirect_to :action => 'list'
121 end
128 end
122
129
123 end
130 end
@@ -1,404 +1,443
1 class ReportController < ApplicationController
1 class ReportController < ApplicationController
2
2
3 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize]
3 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize]
4
4
5 before_filter(only: [:problem_hof]) { |c|
5 before_filter(only: [:problem_hof]) { |c|
6 return false unless authenticate
6 return false unless authenticate
7
7
8 if GraderConfiguration["right.user_view_submission"]
8 if GraderConfiguration["right.user_view_submission"]
9 return true;
9 return true;
10 end
10 end
11
11
12 admin_authorization
12 admin_authorization
13 }
13 }
14
14
15 + def show_max_score
16 + end
17 +
18 + def get_max_score
19 + #process list of problems
20 +
21 + #process submission range
22 + if params[:commit] == 'download csv'
23 + @problems = Problem.all
24 + else
25 + @problems = Problem.find_available_problems
26 + end
27 + @users = User.find(:all, :include => [:contests, :contest_stat])
28 + @scorearray = Array.new
29 + #set up range from param
30 + since_id = params.fetch(:since_id, 0).to_i
31 + until_id = params.fetch(:until_id, 0).to_i
32 + @users.each do |u|
33 + ustat = Array.new
34 + ustat[0] = u
35 + @problems.each do |p|
36 + max_points = 0
37 + Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
38 + max_points = sub.points if sub and sub.points and (sub.points > max_points)
39 + end
40 + ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
41 + end
42 + @scorearray << ustat
43 + end
44 +
45 + if params[:commit] == 'download csv' then
46 + csv = gen_csv_from_scorearray(@scorearray,@problems)
47 + send_data csv, filename: 'max_score.csv'
48 + else
49 + render template: 'user_admin/user_stat'
50 + end
51 +
52 + end
53 +
15 def score
54 def score
16 if params[:commit] == 'download csv'
55 if params[:commit] == 'download csv'
17 @problems = Problem.all
56 @problems = Problem.all
18 else
57 else
19 @problems = Problem.find_available_problems
58 @problems = Problem.find_available_problems
20 end
59 end
21 @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
60 @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
22 @scorearray = Array.new
61 @scorearray = Array.new
23 @users.each do |u|
62 @users.each do |u|
24 ustat = Array.new
63 ustat = Array.new
25 ustat[0] = u
64 ustat[0] = u
26 @problems.each do |p|
65 @problems.each do |p|
27 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
66 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
28 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
67 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
29 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
68 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
30 else
69 else
31 ustat << [0,false]
70 ustat << [0,false]
32 end
71 end
33 end
72 end
34 @scorearray << ustat
73 @scorearray << ustat
35 end
74 end
36 if params[:commit] == 'download csv' then
75 if params[:commit] == 'download csv' then
37 csv = gen_csv_from_scorearray(@scorearray,@problems)
76 csv = gen_csv_from_scorearray(@scorearray,@problems)
38 send_data csv, filename: 'last_score.csv'
77 send_data csv, filename: 'last_score.csv'
39 else
78 else
40 render template: 'user_admin/user_stat'
79 render template: 'user_admin/user_stat'
41 end
80 end
42
81
43 end
82 end
44
83
45 def login_stat
84 def login_stat
46 @logins = Array.new
85 @logins = Array.new
47
86
48 date_and_time = '%Y-%m-%d %H:%M'
87 date_and_time = '%Y-%m-%d %H:%M'
49 begin
88 begin
50 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
89 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
51 @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)
90 @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)
52 rescue
91 rescue
53 @since_time = DateTime.new(1000,1,1)
92 @since_time = DateTime.new(1000,1,1)
54 end
93 end
55 begin
94 begin
56 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
95 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
57 @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)
96 @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)
58 rescue
97 rescue
59 @until_time = DateTime.new(3000,1,1)
98 @until_time = DateTime.new(3000,1,1)
60 end
99 end
61
100
62 User.all.each do |user|
101 User.all.each do |user|
63 @logins << { id: user.id,
102 @logins << { id: user.id,
64 login: user.login,
103 login: user.login,
65 full_name: user.full_name,
104 full_name: user.full_name,
66 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
105 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
67 user.id,@since_time,@until_time)
106 user.id,@since_time,@until_time)
68 .count(:id),
107 .count(:id),
69 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
108 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
70 user.id,@since_time,@until_time)
109 user.id,@since_time,@until_time)
71 .minimum(:created_at),
110 .minimum(:created_at),
72 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
111 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
73 user.id,@since_time,@until_time)
112 user.id,@since_time,@until_time)
74 .maximum(:created_at),
113 .maximum(:created_at),
75 ip: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
114 ip: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
76 user.id,@since_time,@until_time)
115 user.id,@since_time,@until_time)
77 .select(:ip_address).uniq
116 .select(:ip_address).uniq
78
117
79 }
118 }
80 end
119 end
81 end
120 end
82
121
83 def submission_stat
122 def submission_stat
84
123
85 date_and_time = '%Y-%m-%d %H:%M'
124 date_and_time = '%Y-%m-%d %H:%M'
86 begin
125 begin
87 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
126 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
88 rescue
127 rescue
89 @since_time = DateTime.new(1000,1,1)
128 @since_time = DateTime.new(1000,1,1)
90 end
129 end
91 begin
130 begin
92 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
131 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
93 rescue
132 rescue
94 @until_time = DateTime.new(3000,1,1)
133 @until_time = DateTime.new(3000,1,1)
95 end
134 end
96
135
97 @submissions = {}
136 @submissions = {}
98
137
99 User.find_each do |user|
138 User.find_each do |user|
100 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
139 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
101 end
140 end
102
141
103 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
142 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
104 if @submissions[s.user_id]
143 if @submissions[s.user_id]
105 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
144 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
106 a = Problem.find_by_id(s.problem_id)
145 a = Problem.find_by_id(s.problem_id)
107 @submissions[s.user_id][:sub][s.problem_id] =
146 @submissions[s.user_id][:sub][s.problem_id] =
108 { prob_name: (a ? a.full_name : '(NULL)'),
147 { prob_name: (a ? a.full_name : '(NULL)'),
109 sub_ids: [s.id] }
148 sub_ids: [s.id] }
110 else
149 else
111 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
150 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
112 end
151 end
113 @submissions[s.user_id][:count] += 1
152 @submissions[s.user_id][:count] += 1
114 end
153 end
115 end
154 end
116 end
155 end
117
156
118 def problem_hof
157 def problem_hof
119 # gen problem list
158 # gen problem list
120 @user = User.find(session[:user_id])
159 @user = User.find(session[:user_id])
121 @problems = @user.available_problems
160 @problems = @user.available_problems
122
161
123 # get selected problems or the default
162 # get selected problems or the default
124 if params[:id]
163 if params[:id]
125 begin
164 begin
126 @problem = Problem.available.find(params[:id])
165 @problem = Problem.available.find(params[:id])
127 rescue
166 rescue
128 redirect_to action: :problem_hof
167 redirect_to action: :problem_hof
129 flash[:notice] = 'Error: submissions for that problem are not viewable.'
168 flash[:notice] = 'Error: submissions for that problem are not viewable.'
130 return
169 return
131 end
170 end
132 end
171 end
133
172
134 return unless @problem
173 return unless @problem
135
174
136 @by_lang = {} #aggregrate by language
175 @by_lang = {} #aggregrate by language
137
176
138 range =65
177 range =65
139 @histogram = { data: Array.new(range,0), summary: {} }
178 @histogram = { data: Array.new(range,0), summary: {} }
140 @summary = {count: 0, solve: 0, attempt: 0}
179 @summary = {count: 0, solve: 0, attempt: 0}
141 user = Hash.new(0)
180 user = Hash.new(0)
142 Submission.where(problem_id: @problem.id).find_each do |sub|
181 Submission.where(problem_id: @problem.id).find_each do |sub|
143 #histogram
182 #histogram
144 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
183 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
145 @histogram[:data][d.to_i] += 1 if d < range
184 @histogram[:data][d.to_i] += 1 if d < range
146
185
147 next unless sub.points
186 next unless sub.points
148 @summary[:count] += 1
187 @summary[:count] += 1
149 user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
188 user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
150
189
151 lang = Language.find_by_id(sub.language_id)
190 lang = Language.find_by_id(sub.language_id)
152 next unless lang
191 next unless lang
153 next unless sub.points >= @problem.full_score
192 next unless sub.points >= @problem.full_score
154
193
155 #initialize
194 #initialize
156 unless @by_lang.has_key?(lang.pretty_name)
195 unless @by_lang.has_key?(lang.pretty_name)
157 @by_lang[lang.pretty_name] = {
196 @by_lang[lang.pretty_name] = {
158 runtime: { avail: false, value: 2**30-1 },
197 runtime: { avail: false, value: 2**30-1 },
159 memory: { avail: false, value: 2**30-1 },
198 memory: { avail: false, value: 2**30-1 },
160 length: { avail: false, value: 2**30-1 },
199 length: { avail: false, value: 2**30-1 },
161 first: { avail: false, value: DateTime.new(3000,1,1) }
200 first: { avail: false, value: DateTime.new(3000,1,1) }
162 }
201 }
163 end
202 end
164
203
165 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
204 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
166 @by_lang[lang.pretty_name][:runtime] = { avail: true, user_id: sub.user_id, value: sub.max_runtime, sub_id: sub.id }
205 @by_lang[lang.pretty_name][:runtime] = { avail: true, user_id: sub.user_id, value: sub.max_runtime, sub_id: sub.id }
167 end
206 end
168
207
169 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
208 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
170 @by_lang[lang.pretty_name][:memory] = { avail: true, user_id: sub.user_id, value: sub.peak_memory, sub_id: sub.id }
209 @by_lang[lang.pretty_name][:memory] = { avail: true, user_id: sub.user_id, value: sub.peak_memory, sub_id: sub.id }
171 end
210 end
172
211
173 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
212 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
174 !sub.user.admin?
213 !sub.user.admin?
175 @by_lang[lang.pretty_name][:first] = { avail: true, user_id: sub.user_id, value: sub.submitted_at, sub_id: sub.id }
214 @by_lang[lang.pretty_name][:first] = { avail: true, user_id: sub.user_id, value: sub.submitted_at, sub_id: sub.id }
176 end
215 end
177
216
178 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
217 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
179 @by_lang[lang.pretty_name][:length] = { avail: true, user_id: sub.user_id, value: sub.effective_code_length, sub_id: sub.id }
218 @by_lang[lang.pretty_name][:length] = { avail: true, user_id: sub.user_id, value: sub.effective_code_length, sub_id: sub.id }
180 end
219 end
181 end
220 end
182
221
183 #process user_id
222 #process user_id
184 @by_lang.each do |lang,prop|
223 @by_lang.each do |lang,prop|
185 prop.each do |k,v|
224 prop.each do |k,v|
186 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
225 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
187 end
226 end
188 end
227 end
189
228
190 #sum into best
229 #sum into best
191 if @by_lang and @by_lang.first
230 if @by_lang and @by_lang.first
192 @best = @by_lang.first[1].clone
231 @best = @by_lang.first[1].clone
193 @by_lang.each do |lang,prop|
232 @by_lang.each do |lang,prop|
194 if @best[:runtime][:value] >= prop[:runtime][:value]
233 if @best[:runtime][:value] >= prop[:runtime][:value]
195 @best[:runtime] = prop[:runtime]
234 @best[:runtime] = prop[:runtime]
196 @best[:runtime][:lang] = lang
235 @best[:runtime][:lang] = lang
197 end
236 end
198 if @best[:memory][:value] >= prop[:memory][:value]
237 if @best[:memory][:value] >= prop[:memory][:value]
199 @best[:memory] = prop[:memory]
238 @best[:memory] = prop[:memory]
200 @best[:memory][:lang] = lang
239 @best[:memory][:lang] = lang
201 end
240 end
202 if @best[:length][:value] >= prop[:length][:value]
241 if @best[:length][:value] >= prop[:length][:value]
203 @best[:length] = prop[:length]
242 @best[:length] = prop[:length]
204 @best[:length][:lang] = lang
243 @best[:length][:lang] = lang
205 end
244 end
206 if @best[:first][:value] >= prop[:first][:value]
245 if @best[:first][:value] >= prop[:first][:value]
207 @best[:first] = prop[:first]
246 @best[:first] = prop[:first]
208 @best[:first][:lang] = lang
247 @best[:first][:lang] = lang
209 end
248 end
210 end
249 end
211 end
250 end
212
251
213 @histogram[:summary][:max] = [@histogram[:data].max,1].max
252 @histogram[:summary][:max] = [@histogram[:data].max,1].max
214 @summary[:attempt] = user.count
253 @summary[:attempt] = user.count
215 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
254 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
216 end
255 end
217
256
218 def stuck #report struggling user,problem
257 def stuck #report struggling user,problem
219 # init
258 # init
220 user,problem = nil
259 user,problem = nil
221 solve = true
260 solve = true
222 tries = 0
261 tries = 0
223 @struggle = Array.new
262 @struggle = Array.new
224 record = {}
263 record = {}
225 Submission.includes(:problem,:user).order(:problem_id,:user_id).find_each do |sub|
264 Submission.includes(:problem,:user).order(:problem_id,:user_id).find_each do |sub|
226 next unless sub.problem and sub.user
265 next unless sub.problem and sub.user
227 if user != sub.user_id or problem != sub.problem_id
266 if user != sub.user_id or problem != sub.problem_id
228 @struggle << { user: record[:user], problem: record[:problem], tries: tries } unless solve
267 @struggle << { user: record[:user], problem: record[:problem], tries: tries } unless solve
229 record = {user: sub.user, problem: sub.problem}
268 record = {user: sub.user, problem: sub.problem}
230 user,problem = sub.user_id, sub.problem_id
269 user,problem = sub.user_id, sub.problem_id
231 solve = false
270 solve = false
232 tries = 0
271 tries = 0
233 end
272 end
234 if sub.points >= sub.problem.full_score
273 if sub.points >= sub.problem.full_score
235 solve = true
274 solve = true
236 else
275 else
237 tries += 1
276 tries += 1
238 end
277 end
239 end
278 end
240 @struggle.sort!{|a,b| b[:tries] <=> a[:tries] }
279 @struggle.sort!{|a,b| b[:tries] <=> a[:tries] }
241 @struggle = @struggle[0..50]
280 @struggle = @struggle[0..50]
242 end
281 end
243
282
244
283
245 def multiple_login
284 def multiple_login
246 #user with multiple IP
285 #user with multiple IP
247 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:login)
286 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:login)
248 last,count = 0,0
287 last,count = 0,0
249 first = 0
288 first = 0
250 @users = []
289 @users = []
251 raw.each do |r|
290 raw.each do |r|
252 if last != r.user.login
291 if last != r.user.login
253 count = 1
292 count = 1
254 last = r.user.login
293 last = r.user.login
255 first = r
294 first = r
256 else
295 else
257 @users << first if count == 1
296 @users << first if count == 1
258 @users << r
297 @users << r
259 count += 1
298 count += 1
260 end
299 end
261 end
300 end
262
301
263 #IP with multiple user
302 #IP with multiple user
264 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:ip_address)
303 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:ip_address)
265 last,count = 0,0
304 last,count = 0,0
266 first = 0
305 first = 0
267 @ip = []
306 @ip = []
268 raw.each do |r|
307 raw.each do |r|
269 if last != r.ip_address
308 if last != r.ip_address
270 count = 1
309 count = 1
271 last = r.ip_address
310 last = r.ip_address
272 first = r
311 first = r
273 else
312 else
274 @ip << first if count == 1
313 @ip << first if count == 1
275 @ip << r
314 @ip << r
276 count += 1
315 count += 1
277 end
316 end
278 end
317 end
279 end
318 end
280
319
281 def cheat_report
320 def cheat_report
282 date_and_time = '%Y-%m-%d %H:%M'
321 date_and_time = '%Y-%m-%d %H:%M'
283 begin
322 begin
284 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
323 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
285 @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)
324 @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)
286 rescue
325 rescue
287 @since_time = Time.zone.now.ago( 90.minutes)
326 @since_time = Time.zone.now.ago( 90.minutes)
288 end
327 end
289 begin
328 begin
290 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
329 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
291 @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)
330 @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)
292 rescue
331 rescue
293 @until_time = Time.zone.now
332 @until_time = Time.zone.now
294 end
333 end
295
334
296 #multi login
335 #multi login
297 @ml = Login.joins(:user).where("logins.created_at >= ? and logins.created_at <= ?",@since_time,@until_time).select('users.login,count(distinct ip_address) as count,users.full_name').group("users.id").having("count > 1")
336 @ml = Login.joins(:user).where("logins.created_at >= ? and logins.created_at <= ?",@since_time,@until_time).select('users.login,count(distinct ip_address) as count,users.full_name').group("users.id").having("count > 1")
298
337
299 st = <<-SQL
338 st = <<-SQL
300 SELECT l2.*
339 SELECT l2.*
301 FROM logins l2 INNER JOIN
340 FROM logins l2 INNER JOIN
302 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
341 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
303 FROM logins l
342 FROM logins l
304 INNER JOIN users u ON l.user_id = u.id
343 INNER JOIN users u ON l.user_id = u.id
305 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
344 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
306 GROUP BY u.id
345 GROUP BY u.id
307 HAVING count > 1
346 HAVING count > 1
308 ) ml ON l2.user_id = ml.id
347 ) ml ON l2.user_id = ml.id
309 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
348 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
310 UNION
349 UNION
311 SELECT l2.*
350 SELECT l2.*
312 FROM logins l2 INNER JOIN
351 FROM logins l2 INNER JOIN
313 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
352 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
314 FROM logins l
353 FROM logins l
315 INNER JOIN users u ON l.user_id = u.id
354 INNER JOIN users u ON l.user_id = u.id
316 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
355 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
317 GROUP BY l.ip_address
356 GROUP BY l.ip_address
318 HAVING count > 1
357 HAVING count > 1
319 ) ml on ml.ip_address = l2.ip_address
358 ) ml on ml.ip_address = l2.ip_address
320 INNER JOIN users u ON l2.user_id = u.id
359 INNER JOIN users u ON l2.user_id = u.id
321 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
360 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
322 ORDER BY ip_address,created_at
361 ORDER BY ip_address,created_at
323 SQL
362 SQL
324 @mld = Login.find_by_sql(st)
363 @mld = Login.find_by_sql(st)
325
364
326 st = <<-SQL
365 st = <<-SQL
327 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
366 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
328 FROM submissions s INNER JOIN
367 FROM submissions s INNER JOIN
329 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
368 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
330 FROM logins l
369 FROM logins l
331 INNER JOIN users u ON l.user_id = u.id
370 INNER JOIN users u ON l.user_id = u.id
332 WHERE l.created_at >= ? and l.created_at <= ?
371 WHERE l.created_at >= ? and l.created_at <= ?
333 GROUP BY u.id
372 GROUP BY u.id
334 HAVING count > 1
373 HAVING count > 1
335 ) ml ON s.user_id = ml.id
374 ) ml ON s.user_id = ml.id
336 WHERE s.submitted_at >= ? and s.submitted_at <= ?
375 WHERE s.submitted_at >= ? and s.submitted_at <= ?
337 UNION
376 UNION
338 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
377 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
339 FROM submissions s INNER JOIN
378 FROM submissions s INNER JOIN
340 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
379 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
341 FROM logins l
380 FROM logins l
342 INNER JOIN users u ON l.user_id = u.id
381 INNER JOIN users u ON l.user_id = u.id
343 WHERE l.created_at >= ? and l.created_at <= ?
382 WHERE l.created_at >= ? and l.created_at <= ?
344 GROUP BY l.ip_address
383 GROUP BY l.ip_address
345 HAVING count > 1
384 HAVING count > 1
346 ) ml on ml.ip_address = s.ip_address
385 ) ml on ml.ip_address = s.ip_address
347 WHERE s.submitted_at >= ? and s.submitted_at <= ?
386 WHERE s.submitted_at >= ? and s.submitted_at <= ?
348 ORDER BY ip_address,submitted_at
387 ORDER BY ip_address,submitted_at
349 SQL
388 SQL
350 @subs = Submission.joins(:problem).find_by_sql([st,@since_time,@until_time,
389 @subs = Submission.joins(:problem).find_by_sql([st,@since_time,@until_time,
351 @since_time,@until_time,
390 @since_time,@until_time,
352 @since_time,@until_time,
391 @since_time,@until_time,
353 @since_time,@until_time])
392 @since_time,@until_time])
354
393
355 end
394 end
356
395
357 def cheat_scruntinize
396 def cheat_scruntinize
358 #convert date & time
397 #convert date & time
359 date_and_time = '%Y-%m-%d %H:%M'
398 date_and_time = '%Y-%m-%d %H:%M'
360 begin
399 begin
361 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
400 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
362 @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)
401 @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)
363 rescue
402 rescue
364 @since_time = Time.zone.now.ago( 90.minutes)
403 @since_time = Time.zone.now.ago( 90.minutes)
365 end
404 end
366 begin
405 begin
367 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
406 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
368 @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)
407 @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)
369 rescue
408 rescue
370 @until_time = Time.zone.now
409 @until_time = Time.zone.now
371 end
410 end
372
411
373 #convert sid
412 #convert sid
374 @sid = params[:SID].split(/[,\s]/) if params[:SID]
413 @sid = params[:SID].split(/[,\s]/) if params[:SID]
375 unless @sid and @sid.size > 0
414 unless @sid and @sid.size > 0
376 return
415 return
377 redirect_to actoin: :cheat_scruntinize
416 redirect_to actoin: :cheat_scruntinize
378 flash[:notice] = 'Please enter at least 1 student id'
417 flash[:notice] = 'Please enter at least 1 student id'
379 end
418 end
380 mark = Array.new(@sid.size,'?')
419 mark = Array.new(@sid.size,'?')
381 condition = "(u.login = " + mark.join(' OR u.login = ') + ')'
420 condition = "(u.login = " + mark.join(' OR u.login = ') + ')'
382
421
383 @st = <<-SQL
422 @st = <<-SQL
384 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
423 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
385 FROM logins l INNER JOIN users u on l.user_id = u.id
424 FROM logins l INNER JOIN users u on l.user_id = u.id
386 WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition}
425 WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition}
387 UNION
426 UNION
388 SELECT s.submitted_at,s.id,u.login,u.full_name,s.ip_address,s.problem_id,s.points,s.user_id
427 SELECT s.submitted_at,s.id,u.login,u.full_name,s.ip_address,s.problem_id,s.points,s.user_id
389 FROM submissions s INNER JOIN users u ON s.user_id = u.id
428 FROM submissions s INNER JOIN users u ON s.user_id = u.id
390 WHERE s.submitted_at >= ? AND s.submitted_at <= ? AND #{condition}
429 WHERE s.submitted_at >= ? AND s.submitted_at <= ? AND #{condition}
391 ORDER BY submitted_at
430 ORDER BY submitted_at
392 SQL
431 SQL
393
432
394 p = [@st,@since_time,@until_time] + @sid + [@since_time,@until_time] + @sid
433 p = [@st,@since_time,@until_time] + @sid + [@since_time,@until_time] + @sid
395 @logs = Submission.joins(:problem).find_by_sql(p)
434 @logs = Submission.joins(:problem).find_by_sql(p)
396
435
397
436
398
437
399
438
400
439
401 end
440 end
402
441
403
442
404 end
443 end
@@ -1,65 +1,67
1 CafeGrader::Application.routes.draw do
1 CafeGrader::Application.routes.draw do
2 get "sources/direct_edit"
2 get "sources/direct_edit"
3
3
4 root :to => 'main#login'
4 root :to => 'main#login'
5
5
6 resources :contests
6 resources :contests
7
7
8 resources :sites
8 resources :sites
9
9
10 resources :announcements do
10 resources :announcements do
11 member do
11 member do
12 get 'toggle','toggle_front'
12 get 'toggle','toggle_front'
13 end
13 end
14 end
14 end
15
15
16 resources :problems do
16 resources :problems do
17 member do
17 member do
18 get 'toggle'
18 get 'toggle'
19 get 'toggle_test'
19 get 'toggle_test'
20 end
20 end
21 collection do
21 collection do
22 get 'turn_all_off'
22 get 'turn_all_off'
23 get 'turn_all_on'
23 get 'turn_all_on'
24 get 'import'
24 get 'import'
25 get 'manage'
25 get 'manage'
26 end
26 end
27 end
27 end
28
28
29 resources :grader_configuration, controller: 'configurations'
29 resources :grader_configuration, controller: 'configurations'
30
30
31 resources :users do
31 resources :users do
32 member do
32 member do
33 get 'toggle_activate', 'toggle_enable'
33 get 'toggle_activate', 'toggle_enable'
34 end
34 end
35 end
35 end
36
36
37 #source code edit
37 #source code edit
38 get 'sources/direct_edit/:pid', to: 'sources#direct_edit', as: 'direct_edit'
38 get 'sources/direct_edit/:pid', to: 'sources#direct_edit', as: 'direct_edit'
39 get 'sources/direct_edit_submission/:sid', to: 'sources#direct_edit_submission', as: 'direct_edit_submission'
39 get 'sources/direct_edit_submission/:sid', to: 'sources#direct_edit_submission', as: 'direct_edit_submission'
40 get 'sources/get_latest_submission_status/:uid/:pid', to: 'sources#get_latest_submission_status', as: 'get_latest_submission_status'
40 get 'sources/get_latest_submission_status/:uid/:pid', to: 'sources#get_latest_submission_status', as: 'get_latest_submission_status'
41
41
42
42
43 match 'tasks/view/:file.:ext' => 'tasks#view'
43 match 'tasks/view/:file.:ext' => 'tasks#view'
44 match 'tasks/download/:id/:file.:ext' => 'tasks#download'
44 match 'tasks/download/:id/:file.:ext' => 'tasks#download'
45 match 'heartbeat/:id/edit' => 'heartbeat#edit'
45 match 'heartbeat/:id/edit' => 'heartbeat#edit'
46
46
47 #main
47 #main
48 get "main/list"
48 get "main/list"
49 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
49 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
50
50
51 #report
51 #report
52 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
52 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
53 get "report/login"
53 get "report/login"
54 + get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
54
55
55 #grader
56 #grader
56 get 'graders/list', to: 'graders#list', as: 'grader_list'
57 get 'graders/list', to: 'graders#list', as: 'grader_list'
57
58
59 +
58 match 'heartbeat/:id/edit' => 'heartbeat#edit'
60 match 'heartbeat/:id/edit' => 'heartbeat#edit'
59
61
60 # See how all your routes lay out with "rake routes"
62 # See how all your routes lay out with "rake routes"
61
63
62 # This is a legacy wild controller route that's not recommended for RESTful applications.
64 # This is a legacy wild controller route that's not recommended for RESTful applications.
63 # Note: This route will make all actions in every controller accessible via GET requests.
65 # Note: This route will make all actions in every controller accessible via GET requests.
64 match ':controller(/:action(/:id))(.:format)'
66 match ':controller(/:action(/:id))(.:format)'
65 end
67 end
You need to be logged in to leave comments. Login now