Description:
prepare for better hall of fame
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r425:b86f327e0d75 - - 8 files changed: 46 inserted, 70 deleted

@@ -1,87 +1,92
1 class ApplicationController < ActionController::Base
1 class ApplicationController < ActionController::Base
2 protect_from_forgery
2 protect_from_forgery
3
3
4 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
4 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
5
5
6 def admin_authorization
6 def admin_authorization
7 return false unless authenticate
7 return false unless authenticate
8 user = User.find(session[:user_id], :include => ['roles'])
8 user = User.find(session[:user_id], :include => ['roles'])
9 - redirect_to :controller => 'main', :action => 'login' unless user.admin?
9 + unless user.admin?
10 + flash[:notice] = 'You are not authorized to view the page you requested'
11 + redirect_to :controller => 'main', :action => 'login' unless user.admin?
12 + return false
13 + end
14 + return true
10 end
15 end
11
16
12 def authorization_by_roles(allowed_roles)
17 def authorization_by_roles(allowed_roles)
13 return false unless authenticate
18 return false unless authenticate
14 user = User.find(session[:user_id])
19 user = User.find(session[:user_id])
15 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
20 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
16 flash[:notice] = 'You are not authorized to view the page you requested'
21 flash[:notice] = 'You are not authorized to view the page you requested'
17 redirect_to :controller => 'main', :action => 'login'
22 redirect_to :controller => 'main', :action => 'login'
18 return false
23 return false
19 end
24 end
20 end
25 end
21
26
22 protected
27 protected
23
28
24 def authenticate
29 def authenticate
25 unless session[:user_id]
30 unless session[:user_id]
26 flash[:notice] = 'You need to login'
31 flash[:notice] = 'You need to login'
27 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
32 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
28 flash[:notice] = 'You need to login but you cannot log in at this time'
33 flash[:notice] = 'You need to login but you cannot log in at this time'
29 end
34 end
30 redirect_to :controller => 'main', :action => 'login'
35 redirect_to :controller => 'main', :action => 'login'
31 return false
36 return false
32 end
37 end
33
38
34 # check if run in single user mode
39 # check if run in single user mode
35 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
40 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
36 user = User.find(session[:user_id])
41 user = User.find(session[:user_id])
37 if user==nil or (not user.admin?)
42 if user==nil or (not user.admin?)
38 flash[:notice] = 'You cannot log in at this time'
43 flash[:notice] = 'You cannot log in at this time'
39 redirect_to :controller => 'main', :action => 'login'
44 redirect_to :controller => 'main', :action => 'login'
40 return false
45 return false
41 end
46 end
42 return true
47 return true
43 end
48 end
44
49
45 if GraderConfiguration.multicontests?
50 if GraderConfiguration.multicontests?
46 user = User.find(session[:user_id])
51 user = User.find(session[:user_id])
47 return true if user.admin?
52 return true if user.admin?
48 begin
53 begin
49 if user.contest_stat(true).forced_logout
54 if user.contest_stat(true).forced_logout
50 flash[:notice] = 'You have been automatically logged out.'
55 flash[:notice] = 'You have been automatically logged out.'
51 redirect_to :controller => 'main', :action => 'index'
56 redirect_to :controller => 'main', :action => 'index'
52 end
57 end
53 rescue
58 rescue
54 end
59 end
55 end
60 end
56 return true
61 return true
57 end
62 end
58
63
59 def authorization
64 def authorization
60 return false unless authenticate
65 return false unless authenticate
61 user = User.find(session[:user_id])
66 user = User.find(session[:user_id])
62 unless user.roles.detect { |role|
67 unless user.roles.detect { |role|
63 role.rights.detect{ |right|
68 role.rights.detect{ |right|
64 right.controller == self.class.controller_name and
69 right.controller == self.class.controller_name and
65 (right.action == 'all' or right.action == action_name)
70 (right.action == 'all' or right.action == action_name)
66 }
71 }
67 }
72 }
68 flash[:notice] = 'You are not authorized to view the page you requested'
73 flash[:notice] = 'You are not authorized to view the page you requested'
69 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
74 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
70 redirect_to :controller => 'main', :action => 'login'
75 redirect_to :controller => 'main', :action => 'login'
71 return false
76 return false
72 end
77 end
73 end
78 end
74
79
75 def verify_time_limit
80 def verify_time_limit
76 return true if session[:user_id]==nil
81 return true if session[:user_id]==nil
77 user = User.find(session[:user_id], :include => :site)
82 user = User.find(session[:user_id], :include => :site)
78 return true if user==nil or user.site == nil
83 return true if user==nil or user.site == nil
79 if user.contest_finished?
84 if user.contest_finished?
80 flash[:notice] = 'Error: the contest you are participating is over.'
85 flash[:notice] = 'Error: the contest you are participating is over.'
81 redirect_to :back
86 redirect_to :back
82 return false
87 return false
83 end
88 end
84 return true
89 return true
85 end
90 end
86
91
87 end
92 end
@@ -1,99 +1,108
1 class GradersController < ApplicationController
1 class GradersController < ApplicationController
2
2
3 - before_filter :admin_authorization
3 + before_filter :admin_authorization, except: [ :submission ]
4 + before_filter(only: [:submission]) {
5 + return false unless authenticate
6 +
7 + if GraderConfiguration["right.user_view_submission"]
8 + return true;
9 + end
10 +
11 + admin_authorization
12 + }
4
13
5 verify :method => :post, :only => ['clear_all',
14 verify :method => :post, :only => ['clear_all',
6 'start_exam',
15 'start_exam',
7 'start_grading',
16 'start_grading',
8 'stop_all',
17 'stop_all',
9 'clear_terminated'],
18 'clear_terminated'],
10 :redirect_to => {:action => 'index'}
19 :redirect_to => {:action => 'index'}
11
20
12 def index
21 def index
13 redirect_to :action => 'list'
22 redirect_to :action => 'list'
14 end
23 end
15
24
16 def list
25 def list
17 @grader_processes = GraderProcess.find_running_graders
26 @grader_processes = GraderProcess.find_running_graders
18 @stalled_processes = GraderProcess.find_stalled_process
27 @stalled_processes = GraderProcess.find_stalled_process
19
28
20 @terminated_processes = GraderProcess.find_terminated_graders
29 @terminated_processes = GraderProcess.find_terminated_graders
21
30
22 @last_task = Task.find(:first,
31 @last_task = Task.find(:first,
23 :order => 'created_at DESC')
32 :order => 'created_at DESC')
24 @last_test_request = TestRequest.find(:first,
33 @last_test_request = TestRequest.find(:first,
25 :order => 'created_at DESC')
34 :order => 'created_at DESC')
26 end
35 end
27
36
28 def clear
37 def clear
29 grader_proc = GraderProcess.find(params[:id])
38 grader_proc = GraderProcess.find(params[:id])
30 grader_proc.destroy if grader_proc!=nil
39 grader_proc.destroy if grader_proc!=nil
31 redirect_to :action => 'list'
40 redirect_to :action => 'list'
32 end
41 end
33
42
34 def clear_terminated
43 def clear_terminated
35 GraderProcess.find_terminated_graders.each do |p|
44 GraderProcess.find_terminated_graders.each do |p|
36 p.destroy
45 p.destroy
37 end
46 end
38 redirect_to :action => 'list'
47 redirect_to :action => 'list'
39 end
48 end
40
49
41 def clear_all
50 def clear_all
42 GraderProcess.find(:all).each do |p|
51 GraderProcess.find(:all).each do |p|
43 p.destroy
52 p.destroy
44 end
53 end
45 redirect_to :action => 'list'
54 redirect_to :action => 'list'
46 end
55 end
47
56
48 def view
57 def view
49 if params[:type]=='Task'
58 if params[:type]=='Task'
50 redirect_to :action => 'task', :id => params[:id]
59 redirect_to :action => 'task', :id => params[:id]
51 else
60 else
52 redirect_to :action => 'test_request', :id => params[:id]
61 redirect_to :action => 'test_request', :id => params[:id]
53 end
62 end
54 end
63 end
55
64
56 def test_request
65 def test_request
57 @test_request = TestRequest.find(params[:id])
66 @test_request = TestRequest.find(params[:id])
58 end
67 end
59
68
60 def task
69 def task
61 @task = Task.find(params[:id])
70 @task = Task.find(params[:id])
62 end
71 end
63
72
64 def submission
73 def submission
65 @submission = Submission.find(params[:id])
74 @submission = Submission.find(params[:id])
66 formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true )
75 formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true )
67 lexer = case @submission.language.name
76 lexer = case @submission.language.name
68 when "c" then Rouge::Lexers::C.new
77 when "c" then Rouge::Lexers::C.new
69 when "cpp" then Rouge::Lexers::Cpp.new
78 when "cpp" then Rouge::Lexers::Cpp.new
70 when "pas" then Rouge::Lexers::Pas.new
79 when "pas" then Rouge::Lexers::Pas.new
71 when "ruby" then Rouge::Lexers::Ruby.new
80 when "ruby" then Rouge::Lexers::Ruby.new
72 when "python" then Rouge::Lexers::Python.new
81 when "python" then Rouge::Lexers::Python.new
73 when "java" then Rouge::Lexers::Java.new
82 when "java" then Rouge::Lexers::Java.new
74 end
83 end
75 @formatted_code = formatter.format(lexer.lex(@submission.source))
84 @formatted_code = formatter.format(lexer.lex(@submission.source))
76 @css_style = Rouge::Themes::ThankfulEyes.render(scope: '.highlight')
85 @css_style = Rouge::Themes::ThankfulEyes.render(scope: '.highlight')
77
86
78 end
87 end
79
88
80 # various grader controls
89 # various grader controls
81
90
82 def stop
91 def stop
83 grader_proc = GraderProcess.find(params[:id])
92 grader_proc = GraderProcess.find(params[:id])
84 GraderScript.stop_grader(grader_proc.pid)
93 GraderScript.stop_grader(grader_proc.pid)
85 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
94 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
86 redirect_to :action => 'list'
95 redirect_to :action => 'list'
87 end
96 end
88
97
89 def stop_all
98 def stop_all
90 GraderScript.stop_graders(GraderProcess.find_running_graders +
99 GraderScript.stop_graders(GraderProcess.find_running_graders +
91 GraderProcess.find_stalled_process)
100 GraderProcess.find_stalled_process)
92 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
101 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
93 redirect_to :action => 'list'
102 redirect_to :action => 'list'
94 end
103 end
95
104
96 def start_grading
105 def start_grading
97 GraderScript.start_grader('grading')
106 GraderScript.start_grader('grading')
98 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
107 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
99 redirect_to :action => 'list'
108 redirect_to :action => 'list'
@@ -1,187 +1,187
1 class ReportController < ApplicationController
1 class ReportController < ApplicationController
2
2
3 before_filter :admin_authorization, only: [:login_stat,:submission_stat]
3 before_filter :admin_authorization, only: [:login_stat,:submission_stat]
4 - before_filter { |c|
4 + before_filter(only: [:problem_hof]) { |c|
5 return false unless authenticate
5 return false unless authenticate
6
6
7 - if GraderConfiguration["system.hall_of_fame_available"]
7 + if GraderConfiguration["right.user_view_submission"]
8 return true;
8 return true;
9 end
9 end
10
10
11 admin_authorization
11 admin_authorization
12 }
12 }
13
13
14 def login_stat
14 def login_stat
15 @logins = Array.new
15 @logins = Array.new
16
16
17 date_and_time = '%Y-%m-%d %H:%M'
17 date_and_time = '%Y-%m-%d %H:%M'
18 begin
18 begin
19 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
19 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
20 rescue
20 rescue
21 @since_time = DateTime.new(1000,1,1)
21 @since_time = DateTime.new(1000,1,1)
22 end
22 end
23 begin
23 begin
24 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
24 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
25 rescue
25 rescue
26 @until_time = DateTime.new(3000,1,1)
26 @until_time = DateTime.new(3000,1,1)
27 end
27 end
28
28
29 User.all.each do |user|
29 User.all.each do |user|
30 @logins << { login: user.login,
30 @logins << { login: user.login,
31 full_name: user.full_name,
31 full_name: user.full_name,
32 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
32 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
33 user.id,@since_time,@until_time)
33 user.id,@since_time,@until_time)
34 .count(:id),
34 .count(:id),
35 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
35 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
36 user.id,@since_time,@until_time)
36 user.id,@since_time,@until_time)
37 .minimum(:created_at),
37 .minimum(:created_at),
38 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
38 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
39 user.id,@since_time,@until_time)
39 user.id,@since_time,@until_time)
40 .maximum(:created_at)
40 .maximum(:created_at)
41 }
41 }
42 end
42 end
43 end
43 end
44
44
45 def submission_stat
45 def submission_stat
46
46
47 date_and_time = '%Y-%m-%d %H:%M'
47 date_and_time = '%Y-%m-%d %H:%M'
48 begin
48 begin
49 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
49 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
50 rescue
50 rescue
51 @since_time = DateTime.new(1000,1,1)
51 @since_time = DateTime.new(1000,1,1)
52 end
52 end
53 begin
53 begin
54 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
54 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
55 rescue
55 rescue
56 @until_time = DateTime.new(3000,1,1)
56 @until_time = DateTime.new(3000,1,1)
57 end
57 end
58
58
59 @submissions = {}
59 @submissions = {}
60
60
61 User.find_each do |user|
61 User.find_each do |user|
62 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
62 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
63 end
63 end
64
64
65 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
65 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
66 if @submissions[s.user_id]
66 if @submissions[s.user_id]
67 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
67 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
68 a = nil
68 a = nil
69 begin
69 begin
70 a = Problem.find(s.problem_id)
70 a = Problem.find(s.problem_id)
71 rescue
71 rescue
72 a = nil
72 a = nil
73 end
73 end
74 @submissions[s.user_id][:sub][s.problem_id] =
74 @submissions[s.user_id][:sub][s.problem_id] =
75 { prob_name: (a ? a.full_name : '(NULL)'),
75 { prob_name: (a ? a.full_name : '(NULL)'),
76 sub_ids: [s.id] }
76 sub_ids: [s.id] }
77 else
77 else
78 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
78 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
79 end
79 end
80 @submissions[s.user_id][:count] += 1
80 @submissions[s.user_id][:count] += 1
81 end
81 end
82 end
82 end
83 end
83 end
84
84
85 def problem_hof
85 def problem_hof
86 # gen problem list
86 # gen problem list
87 @user = User.find(session[:user_id])
87 @user = User.find(session[:user_id])
88 @problems = @user.available_problems
88 @problems = @user.available_problems
89
89
90 # get selected problems or the default
90 # get selected problems or the default
91 if params[:id]
91 if params[:id]
92 begin
92 begin
93 @problem = Problem.available.find(params[:id])
93 @problem = Problem.available.find(params[:id])
94 rescue
94 rescue
95 redirect_to action: :problem_hof
95 redirect_to action: :problem_hof
96 flash[:notice] = 'Error: submissions for that problem are not viewable.'
96 flash[:notice] = 'Error: submissions for that problem are not viewable.'
97 return
97 return
98 end
98 end
99 end
99 end
100
100
101 if @problem
101 if @problem
102 #aggregrate by language
102 #aggregrate by language
103 @by_lang = {}
103 @by_lang = {}
104 Submission.where(problem_id: @problem.id).find_each do |sub|
104 Submission.where(problem_id: @problem.id).find_each do |sub|
105 lang = Language.find_by_id(sub.language_id)
105 lang = Language.find_by_id(sub.language_id)
106 next unless lang
106 next unless lang
107 next unless sub.points >= @problem.full_score
107 next unless sub.points >= @problem.full_score
108
108
109 #initialize
109 #initialize
110 unless @by_lang.has_key?(lang.pretty_name)
110 unless @by_lang.has_key?(lang.pretty_name)
111 @by_lang[lang.pretty_name] = {
111 @by_lang[lang.pretty_name] = {
112 runtime: { avail: false, value: 2**30-1 },
112 runtime: { avail: false, value: 2**30-1 },
113 memory: { avail: false, value: 2**30-1 },
113 memory: { avail: false, value: 2**30-1 },
114 length: { avail: false, value: 2**30-1 },
114 length: { avail: false, value: 2**30-1 },
115 first: { avail: false, value: DateTime.new(3000,1,1) }
115 first: { avail: false, value: DateTime.new(3000,1,1) }
116 }
116 }
117 end
117 end
118
118
119 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
119 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
120 @by_lang[lang.pretty_name][:runtime] = {
120 @by_lang[lang.pretty_name][:runtime] = {
121 avail: true,
121 avail: true,
122 user_id: sub.user_id,
122 user_id: sub.user_id,
123 value: sub.max_runtime,
123 value: sub.max_runtime,
124 sub_id: sub.id
124 sub_id: sub.id
125 }
125 }
126 end
126 end
127
127
128 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
128 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
129 @by_lang[lang.pretty_name][:memory] = {
129 @by_lang[lang.pretty_name][:memory] = {
130 avail: true,
130 avail: true,
131 user_id: sub.user_id,
131 user_id: sub.user_id,
132 value: sub.peak_memory,
132 value: sub.peak_memory,
133 sub_id: sub.id
133 sub_id: sub.id
134 }
134 }
135 end
135 end
136
136
137 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value]
137 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value]
138 @by_lang[lang.pretty_name][:first] = {
138 @by_lang[lang.pretty_name][:first] = {
139 avail: true,
139 avail: true,
140 user_id: sub.user_id,
140 user_id: sub.user_id,
141 value: sub.submitted_at,
141 value: sub.submitted_at,
142 sub_id: sub.id
142 sub_id: sub.id
143 }
143 }
144 end
144 end
145
145
146 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
146 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
147 @by_lang[lang.pretty_name][:length] = {
147 @by_lang[lang.pretty_name][:length] = {
148 avail: true,
148 avail: true,
149 user_id: sub.user_id,
149 user_id: sub.user_id,
150 value: sub.effective_code_length,
150 value: sub.effective_code_length,
151 sub_id: sub.id
151 sub_id: sub.id
152 }
152 }
153 end
153 end
154 end
154 end
155
155
156 #process user_id
156 #process user_id
157 @by_lang.each do |lang,prop|
157 @by_lang.each do |lang,prop|
158 prop.each do |k,v|
158 prop.each do |k,v|
159 - v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).login : "(NULL)"
159 + v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
160 end
160 end
161 end
161 end
162
162
163 #sum into best
163 #sum into best
164 if @by_lang and @by_lang.first
164 if @by_lang and @by_lang.first
165 @best = @by_lang.first[1]
165 @best = @by_lang.first[1]
166 @by_lang.each do |lang,prop|
166 @by_lang.each do |lang,prop|
167 - if @best[:runtime][:value] > prop[:runtime][:value]
167 + if @best[:runtime][:value] >= prop[:runtime][:value]
168 @best[:runtime] = prop[:runtime]
168 @best[:runtime] = prop[:runtime]
169 @best[:runtime][:lang] = lang
169 @best[:runtime][:lang] = lang
170 end
170 end
171 - if @best[:memory][:value] > prop[:memory][:value]
171 + if @best[:memory][:value] >= prop[:memory][:value]
172 @best[:memory] = prop[:memory]
172 @best[:memory] = prop[:memory]
173 @best[:memory][:lang] = lang
173 @best[:memory][:lang] = lang
174 end
174 end
175 - if @best[:length][:value] > prop[:length][:value]
175 + if @best[:length][:value] >= prop[:length][:value]
176 @best[:length] = prop[:length]
176 @best[:length] = prop[:length]
177 @best[:length][:lang] = lang
177 @best[:length][:lang] = lang
178 end
178 end
179 - if @best[:first][:value] > prop[:first][:value]
179 + if @best[:first][:value] >= prop[:first][:value]
180 @best[:first] = prop[:first]
180 @best[:first] = prop[:first]
181 @best[:first][:lang] = lang
181 @best[:first][:lang] = lang
182 end
182 end
183 end
183 end
184 end
184 end
185 end
185 end
186 end
186 end
187 end
187 end
@@ -1,130 +1,130
1 # Methods added to this helper will be available to all templates in the application.
1 # Methods added to this helper will be available to all templates in the application.
2 module ApplicationHelper
2 module ApplicationHelper
3
3
4 def user_header
4 def user_header
5 menu_items = ''
5 menu_items = ''
6 user = User.find(session[:user_id])
6 user = User.find(session[:user_id])
7
7
8 if (user!=nil) and (session[:admin])
8 if (user!=nil) and (session[:admin])
9 # admin menu
9 # admin menu
10 menu_items << "<b>Administrative task:</b> "
10 menu_items << "<b>Administrative task:</b> "
11 append_to menu_items, '[Announcements]', 'announcements', 'index'
11 append_to menu_items, '[Announcements]', 'announcements', 'index'
12 append_to menu_items, '[Msg console]', 'messages', 'console'
12 append_to menu_items, '[Msg console]', 'messages', 'console'
13 append_to menu_items, '[Problems]', 'problems', 'index'
13 append_to menu_items, '[Problems]', 'problems', 'index'
14 append_to menu_items, '[Users]', 'user_admin', 'index'
14 append_to menu_items, '[Users]', 'user_admin', 'index'
15 append_to menu_items, '[Results]', 'user_admin', 'user_stat'
15 append_to menu_items, '[Results]', 'user_admin', 'user_stat'
16 append_to menu_items, '[Report]', 'report', 'login_stat'
16 append_to menu_items, '[Report]', 'report', 'login_stat'
17 append_to menu_items, '[Graders]', 'graders', 'list'
17 append_to menu_items, '[Graders]', 'graders', 'list'
18 append_to menu_items, '[Contests]', 'contest_management', 'index'
18 append_to menu_items, '[Contests]', 'contest_management', 'index'
19 append_to menu_items, '[Sites]', 'sites', 'index'
19 append_to menu_items, '[Sites]', 'sites', 'index'
20 append_to menu_items, '[System config]', 'configurations', 'index'
20 append_to menu_items, '[System config]', 'configurations', 'index'
21 menu_items << "<br/>"
21 menu_items << "<br/>"
22 end
22 end
23
23
24 # main page
24 # main page
25 append_to menu_items, "[#{I18n.t 'menu.main'}]", 'main', 'list'
25 append_to menu_items, "[#{I18n.t 'menu.main'}]", 'main', 'list'
26 append_to menu_items, "[#{I18n.t 'menu.messages'}]", 'messages', 'list'
26 append_to menu_items, "[#{I18n.t 'menu.messages'}]", 'messages', 'list'
27
27
28 if (user!=nil) and (GraderConfiguration.show_tasks_to?(user))
28 if (user!=nil) and (GraderConfiguration.show_tasks_to?(user))
29 append_to menu_items, "[#{I18n.t 'menu.tasks'}]", 'tasks', 'list'
29 append_to menu_items, "[#{I18n.t 'menu.tasks'}]", 'tasks', 'list'
30 append_to menu_items, "[#{I18n.t 'menu.submissions'}]", 'main', 'submission'
30 append_to menu_items, "[#{I18n.t 'menu.submissions'}]", 'main', 'submission'
31 append_to menu_items, "[#{I18n.t 'menu.test'}]", 'test', 'index'
31 append_to menu_items, "[#{I18n.t 'menu.test'}]", 'test', 'index'
32 end
32 end
33
33
34 - if GraderConfiguration['system.hall_of_fame_available']
34 + if GraderConfiguration['right.user_hall_of_fame']
35 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
35 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
36 end
36 end
37 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
37 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
38
38
39 if GraderConfiguration['system.user_setting_enabled']
39 if GraderConfiguration['system.user_setting_enabled']
40 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
40 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
41 end
41 end
42 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
42 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
43
43
44 menu_items.html_safe
44 menu_items.html_safe
45 end
45 end
46
46
47 def append_to(option,label, controller, action)
47 def append_to(option,label, controller, action)
48 option << ' ' if option!=''
48 option << ' ' if option!=''
49 option << link_to_unless_current(label,
49 option << link_to_unless_current(label,
50 :controller => controller,
50 :controller => controller,
51 :action => action)
51 :action => action)
52 end
52 end
53
53
54 def format_short_time(time)
54 def format_short_time(time)
55 now = Time.now.gmtime
55 now = Time.now.gmtime
56 st = ''
56 st = ''
57 if (time.yday != now.yday) or
57 if (time.yday != now.yday) or
58 (time.year != now.year)
58 (time.year != now.year)
59 st = time.strftime("%x ")
59 st = time.strftime("%x ")
60 end
60 end
61 st + time.strftime("%X")
61 st + time.strftime("%X")
62 end
62 end
63
63
64 def format_short_duration(duration)
64 def format_short_duration(duration)
65 return '' if duration==nil
65 return '' if duration==nil
66 d = duration.to_f
66 d = duration.to_f
67 return Time.at(d).gmtime.strftime("%X")
67 return Time.at(d).gmtime.strftime("%X")
68 end
68 end
69
69
70 def read_textfile(fname,max_size=2048)
70 def read_textfile(fname,max_size=2048)
71 begin
71 begin
72 File.open(fname).read(max_size)
72 File.open(fname).read(max_size)
73 rescue
73 rescue
74 nil
74 nil
75 end
75 end
76 end
76 end
77
77
78 def user_title_bar(user)
78 def user_title_bar(user)
79 header = ''
79 header = ''
80 time_left = ''
80 time_left = ''
81
81
82 #
82 #
83 # if the contest is over
83 # if the contest is over
84 if GraderConfiguration.time_limit_mode?
84 if GraderConfiguration.time_limit_mode?
85 if user.contest_finished?
85 if user.contest_finished?
86 header = <<CONTEST_OVER
86 header = <<CONTEST_OVER
87 <tr><td colspan="2" align="center">
87 <tr><td colspan="2" align="center">
88 <span class="contest-over-msg">THE CONTEST IS OVER</span>
88 <span class="contest-over-msg">THE CONTEST IS OVER</span>
89 </td></tr>
89 </td></tr>
90 CONTEST_OVER
90 CONTEST_OVER
91 end
91 end
92 if !user.contest_started?
92 if !user.contest_started?
93 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
93 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
94 else
94 else
95 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
95 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
96 " #{format_short_duration(user.contest_time_left)}"
96 " #{format_short_duration(user.contest_time_left)}"
97 end
97 end
98 end
98 end
99
99
100 #
100 #
101 # if the contest is in the anaysis mode
101 # if the contest is in the anaysis mode
102 if GraderConfiguration.analysis_mode?
102 if GraderConfiguration.analysis_mode?
103 header = <<ANALYSISMODE
103 header = <<ANALYSISMODE
104 <tr><td colspan="2" align="center">
104 <tr><td colspan="2" align="center">
105 <span class="contest-over-msg">ANALYSIS MODE</span>
105 <span class="contest-over-msg">ANALYSIS MODE</span>
106 </td></tr>
106 </td></tr>
107 ANALYSISMODE
107 ANALYSISMODE
108 end
108 end
109
109
110 contest_name = GraderConfiguration['contest.name']
110 contest_name = GraderConfiguration['contest.name']
111
111
112 #
112 #
113 # build real title bar
113 # build real title bar
114 result = <<TITLEBAR
114 result = <<TITLEBAR
115 <div class="title">
115 <div class="title">
116 <table>
116 <table>
117 #{header}
117 #{header}
118 <tr>
118 <tr>
119 <td class="left-col">
119 <td class="left-col">
120 #{user.full_name}<br/>
120 #{user.full_name}<br/>
121 #{t 'title_bar.current_time'} #{format_short_time(Time.new)}
121 #{t 'title_bar.current_time'} #{format_short_time(Time.new)}
122 #{time_left}
122 #{time_left}
123 <br/>
123 <br/>
124 </td>
124 </td>
125 <td class="right-col">#{contest_name}</td>
125 <td class="right-col">#{contest_name}</td>
126 </tr>
126 </tr>
127 </table>
127 </table>
128 </div>
128 </div>
129 TITLEBAR
129 TITLEBAR
130 result.html_safe
130 result.html_safe
@@ -1,27 +1,27
1 %style{type: "text/css"}
1 %style{type: "text/css"}
2 = @css_style
2 = @css_style
3
3
4 %h1= "Submission: #{@submission.id}"
4 %h1= "Submission: #{@submission.id}"
5
5
6 %p
6 %p
7 User:
7 User:
8 - = "#{@submission.user.login}"
8 + = "(#{@submission.user.login}) #{@submission.user.full_name}"
9 %br/
9 %br/
10 Problem:
10 Problem:
11 - if @submission.problem!=nil
11 - if @submission.problem!=nil
12 = "#{@submission.problem.full_name}"
12 = "#{@submission.problem.full_name}"
13 - else
13 - else
14 = "(n/a)"
14 = "(n/a)"
15 %br/
15 %br/
16 = "Number: #{@submission.number}"
16 = "Number: #{@submission.number}"
17 %br/
17 %br/
18 = "Submitted at: #{format_short_time(@submission.submitted_at)}"
18 = "Submitted at: #{format_short_time(@submission.submitted_at)}"
19 %br/
19 %br/
20 = "Points : #{@submission.points}/#{@submission.problem.full_score}"
20 = "Points : #{@submission.points}/#{@submission.problem.full_score}"
21 %br/
21 %br/
22 = "Comment : #{@submission.grader_comment}"
22 = "Comment : #{@submission.grader_comment}"
23
23
24 %b Source code (first 10kb)
24 %b Source code (first 10kb)
25 //%div.highlight{:style => "border: 1px solid black;"}
25 //%div.highlight{:style => "border: 1px solid black;"}
26 =@formatted_code.html_safe
26 =@formatted_code.html_safe
27
27
@@ -1,33 +1,31
1 - content_for :header do
1 - content_for :header do
2 = javascript_include_tag 'new'
2 = javascript_include_tag 'new'
3
3
4 %script{:type=>"text/javascript"}
4 %script{:type=>"text/javascript"}
5 $(function () {
5 $(function () {
6 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
6 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
7 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
7 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 });
8 });
9
9
10 -
11 %h1 Login status
10 %h1 Login status
12
11
13 -
14 =render partial: 'report_menu'
12 =render partial: 'report_menu'
15 =render partial: 'date_range', locals: {param_text: 'Login date range:', title: 'Query login stat in the range' }
13 =render partial: 'date_range', locals: {param_text: 'Login date range:', title: 'Query login stat in the range' }
16
14
17 %table.info
15 %table.info
18 %thead
16 %thead
19 %tr.info-head
17 %tr.info-head
20 %th login
18 %th login
21 %th full name
19 %th full name
22 %th login count
20 %th login count
23 %th earliest
21 %th earliest
24 %th latest
22 %th latest
25 %tbody
23 %tbody
26 - @logins.each do |l|
24 - @logins.each do |l|
27 %tr{class: cycle('info-even','info-odd')}
25 %tr{class: cycle('info-even','info-odd')}
28 %td= l[:login]
26 %td= l[:login]
29 %td= l[:full_name]
27 %td= l[:full_name]
30 %td= l[:count]
28 %td= l[:count]
31 %td= l[:min] ? l[:min].in_time_zone.strftime('%Y-%m-%d %H:%M') : ''
29 %td= l[:min] ? l[:min].in_time_zone.strftime('%Y-%m-%d %H:%M') : ''
32 %td= l[:max] ? l[:max].in_time_zone.strftime('%Y-%m-%d %H:%M') : ''
30 %td= l[:max] ? l[:max].in_time_zone.strftime('%Y-%m-%d %H:%M') : ''
33
31
@@ -1,65 +1,22
1 +
2 + /- if params[:id]
3 + / %h1 Tasks Hall of Fame
4 + / = link_to('[back to All-Time Hall of Fame]', action: 'problem_hof', id: nil )
5 + /- else
6 + / %h1 All-Time Hall of Fame
7 +
8 +
1 %h1 Tasks Hall of Fame
9 %h1 Tasks Hall of Fame
2 -
3 .task-menu
10 .task-menu
4 Tasks
11 Tasks
5 %br/
12 %br/
6 - @problems.each do |prob|
13 - @problems.each do |prob|
7 = link_to( "[#{prob.name}]", {id: prob.id})
14 = link_to( "[#{prob.name}]", {id: prob.id})
8
15
9 -
16 + - unless params[:id]
10 -
17 + /=render partial: 'all_time_hof'
11 -
18 + Please select a problem.
12 - %h2 Overall
19 + - else
13 -
20 + =render partial: 'task_hof'
14 - - if @best
15 - %b Best Runtime:
16 - = " by #{@best[:runtime][:user]} with #{@best[:runtime][:value] * 1000} milliseconds at submission " \
17 - = link_to("#" + @best[:runtime][:sub_id].to_s, controller: 'graders', action: 'submission', id:@best[:runtime][:sub_id])
18 - %br/
19 - %b Best Memory Usage:
20 - = " by #{@best[:memory][:user]} with #{@best[:memory][:value]} kbytes at submission "
21 - = link_to("#" + @best[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id:@best[:memory][:sub_id])
22 - %br/
23 - %b Shortest Code:
24 - = " by #{@best[:length][:user]} with #{@best[:length][:value]} at submission "
25 - = link_to("#" + @best[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:length][:sub_id])
26 - %br/
27 - %b First solver:
28 - = " by #{@best[:first][:user]} is the first solver on #{@best[:first][:value]} at submission "
29 - = link_to("#" + @best[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:first][:sub_id])
30 - %br/
31
21
32
22
33 - %p
34 - This counts only for submission with 100% score <br/>
35 - Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)
36 -
37 - %h2 By language
38 -
39 - %table.info
40 - %thead
41 - %tr.info-head
42 - %th Language
43 - %th Best runtime (ms)
44 - %th Best memory (kbytes)
45 - %th Shortest Code (bytes)
46 - %th First solver
47 - %tbody
48 - - @by_lang.each do |lang,value|
49 - %tr{class: cycle('info-even','info-odd')}
50 - %td= lang
51 - %td
52 - = "#{value[:runtime][:user]} (#{(value[:runtime][:value] * 1000).to_i} @"
53 - = "#{link_to("#" + value[:runtime][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:runtime][:sub_id])} )".html_safe
54 - %td
55 - = "#{value[:memory][:user]} (#{value[:memory][:value]} @"
56 - = "#{link_to("#" + value[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:memory][:sub_id])} )".html_safe
57 - %td
58 - = "#{value[:length][:user]} (#{value[:length][:value]} @"
59 - = "#{link_to("#" + value[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:length][:sub_id])} )".html_safe
60 - %td
61 - = "#{value[:first][:user]} (#{value[:first][:value]} @"
62 - = "#{link_to("#" + value[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:first][:sub_id])} )".html_safe
63 -
64 - - else
65 - %h3 No submissions
@@ -1,158 +1,165
1 CONFIGURATIONS =
1 CONFIGURATIONS =
2 [
2 [
3 {
3 {
4 :key => 'system.single_user_mode',
4 :key => 'system.single_user_mode',
5 :value_type => 'boolean',
5 :value_type => 'boolean',
6 :default_value => 'false',
6 :default_value => 'false',
7 :description => 'Only admins can log in to the system when running under single user mode.'
7 :description => 'Only admins can log in to the system when running under single user mode.'
8 },
8 },
9
9
10 {
10 {
11 :key => 'ui.front.title',
11 :key => 'ui.front.title',
12 :value_type => 'string',
12 :value_type => 'string',
13 :default_value => 'Grader'
13 :default_value => 'Grader'
14 },
14 },
15
15
16 {
16 {
17 :key => 'ui.front.welcome_message',
17 :key => 'ui.front.welcome_message',
18 :value_type => 'string',
18 :value_type => 'string',
19 :default_value => 'Welcome!'
19 :default_value => 'Welcome!'
20 },
20 },
21
21
22 {
22 {
23 :key => 'ui.show_score',
23 :key => 'ui.show_score',
24 :value_type => 'boolean',
24 :value_type => 'boolean',
25 :default_value => 'true'
25 :default_value => 'true'
26 },
26 },
27
27
28 {
28 {
29 :key => 'contest.time_limit',
29 :key => 'contest.time_limit',
30 :value_type => 'string',
30 :value_type => 'string',
31 :default_value => 'unlimited',
31 :default_value => 'unlimited',
32 :description => 'Time limit in format hh:mm, or "unlimited" for contests with no time limits. This config is CACHED. Restart the server before the change can take effect.'
32 :description => 'Time limit in format hh:mm, or "unlimited" for contests with no time limits. This config is CACHED. Restart the server before the change can take effect.'
33 },
33 },
34
34
35 {
35 {
36 :key => 'system.mode',
36 :key => 'system.mode',
37 :value_type => 'string',
37 :value_type => 'string',
38 :default_value => 'standard',
38 :default_value => 'standard',
39 :description => 'Current modes are "standard", "contest", "indv-contest", and "analysis".'
39 :description => 'Current modes are "standard", "contest", "indv-contest", and "analysis".'
40 },
40 },
41
41
42 {
42 {
43 :key => 'contest.name',
43 :key => 'contest.name',
44 :value_type => 'string',
44 :value_type => 'string',
45 :default_value => 'Grader',
45 :default_value => 'Grader',
46 :description => 'This name will be shown on the user header bar.'
46 :description => 'This name will be shown on the user header bar.'
47 },
47 },
48
48
49 {
49 {
50 :key => 'contest.multisites',
50 :key => 'contest.multisites',
51 :value_type => 'boolean',
51 :value_type => 'boolean',
52 :default_value => 'false',
52 :default_value => 'false',
53 :description => 'If the server is in contest mode and this option is true, on the log in of the admin a menu for site selections is shown.'
53 :description => 'If the server is in contest mode and this option is true, on the log in of the admin a menu for site selections is shown.'
54 },
54 },
55
55
56 {
56 {
57 - :key => 'system.hall_of_fame_available',
57 + :key => 'right.user_hall_of_fame',
58 :value_type => 'boolean',
58 :value_type => 'boolean',
59 :default_value => 'false',
59 :default_value => 'false',
60 :description => 'If true, any user can access hall of fame page.'
60 :description => 'If true, any user can access hall of fame page.'
61 },
61 },
62
62
63 + {
64 + :key => 'right.user_view_submission',
65 + :value_type => 'boolean',
66 + :default_value => 'false',
67 + :description => 'If true, any user can view submissions of every one.'
68 + },
69 +
63 # If Configuration['system.online_registration'] is true, the
70 # If Configuration['system.online_registration'] is true, the
64 # system allows online registration, and will use these
71 # system allows online registration, and will use these
65 # information for sending confirmation emails.
72 # information for sending confirmation emails.
66 {
73 {
67 :key => 'system.online_registration.smtp',
74 :key => 'system.online_registration.smtp',
68 :value_type => 'string',
75 :value_type => 'string',
69 :default_value => 'smtp.somehost.com'
76 :default_value => 'smtp.somehost.com'
70 },
77 },
71
78
72 {
79 {
73 :key => 'system.online_registration.from',
80 :key => 'system.online_registration.from',
74 :value_type => 'string',
81 :value_type => 'string',
75 :default_value => 'your.email@address'
82 :default_value => 'your.email@address'
76 },
83 },
77
84
78 {
85 {
79 :key => 'system.admin_email',
86 :key => 'system.admin_email',
80 :value_type => 'string',
87 :value_type => 'string',
81 :default_value => 'admin@admin.email'
88 :default_value => 'admin@admin.email'
82 },
89 },
83
90
84 {
91 {
85 :key => 'system.user_setting_enabled',
92 :key => 'system.user_setting_enabled',
86 :value_type => 'boolean',
93 :value_type => 'boolean',
87 :default_value => 'true',
94 :default_value => 'true',
88 :description => 'If this option is true, users can change their settings'
95 :description => 'If this option is true, users can change their settings'
89 },
96 },
90
97
91 {
98 {
92 :key => 'system.user_setting_enabled',
99 :key => 'system.user_setting_enabled',
93 :value_type => 'boolean',
100 :value_type => 'boolean',
94 :default_value => 'true',
101 :default_value => 'true',
95 :description => 'If this option is true, users can change their settings'
102 :description => 'If this option is true, users can change their settings'
96 }
103 }
97
104
98 # If Configuration['contest.test_request.early_timeout'] is true
105 # If Configuration['contest.test_request.early_timeout'] is true
99 # the user will not be able to use test request at 30 minutes
106 # the user will not be able to use test request at 30 minutes
100 # before the contest ends.
107 # before the contest ends.
101 {
108 {
102 :key => 'contest.test_request.early_timeout',
109 :key => 'contest.test_request.early_timeout',
103 :value_type => 'boolean',
110 :value_type => 'boolean',
104 :default_value => 'false'
111 :default_value => 'false'
105 },
112 },
106
113
107 {
114 {
108 :key => 'system.multicontests',
115 :key => 'system.multicontests',
109 :value_type => 'boolean',
116 :value_type => 'boolean',
110 :default_value => 'false'
117 :default_value => 'false'
111 },
118 },
112
119
113 {
120 {
114 :key => 'contest.confirm_indv_contest_start',
121 :key => 'contest.confirm_indv_contest_start',
115 :value_type => 'boolean',
122 :value_type => 'boolean',
116 :default_value => 'false'
123 :default_value => 'false'
117 },
124 },
118
125
119 {
126 {
120 :key => 'contest.default_contest_name',
127 :key => 'contest.default_contest_name',
121 :value_type => 'string',
128 :value_type => 'string',
122 :default_value => 'none',
129 :default_value => 'none',
123 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
130 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
124 }
131 }
125
132
126 ]
133 ]
127
134
128
135
129 def create_configuration_key(key,
136 def create_configuration_key(key,
130 value_type,
137 value_type,
131 default_value,
138 default_value,
132 description='')
139 description='')
133 conf = (GraderConfiguration.find_by_key(key) ||
140 conf = (GraderConfiguration.find_by_key(key) ||
134 GraderConfiguration.new(:key => key,
141 GraderConfiguration.new(:key => key,
135 :value_type => value_type,
142 :value_type => value_type,
136 :value => default_value))
143 :value => default_value))
137 conf.description = description
144 conf.description = description
138 conf.save
145 conf.save
139 end
146 end
140
147
141 def seed_config
148 def seed_config
142 CONFIGURATIONS.each do |conf|
149 CONFIGURATIONS.each do |conf|
143 if conf.has_key? :description
150 if conf.has_key? :description
144 desc = conf[:description]
151 desc = conf[:description]
145 else
152 else
146 desc = ''
153 desc = ''
147 end
154 end
148 create_configuration_key(conf[:key],
155 create_configuration_key(conf[:key],
149 conf[:value_type],
156 conf[:value_type],
150 conf[:default_value],
157 conf[:default_value],
151 desc)
158 desc)
152 end
159 end
153 end
160 end
154
161
155 def seed_roles
162 def seed_roles
156 return if Role.find_by_name('admin')
163 return if Role.find_by_name('admin')
157
164
158 role = Role.create(:name => 'admin')
165 role = Role.create(:name => 'admin')
You need to be logged in to leave comments. Login now