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

r837:b9faf3362123 - - 7 files changed: 24 inserted, 11 deleted

@@ -1,268 +1,268
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 before_action :check_valid_login, :except => [:login]
3 before_action :check_valid_login, :except => [:login]
4 before_action :check_viewability, :except => [:index, :login]
4 before_action :check_viewability, :except => [:index, :login]
5
5
6 append_before_action :confirm_and_update_start_time,
6 append_before_action :confirm_and_update_start_time,
7 :except => [:index,
7 :except => [:index,
8 :login,
8 :login,
9 :confirm_contest_start]
9 :confirm_contest_start]
10
10
11 # to prevent log in box to be shown when user logged out of the
11 # to prevent log in box to be shown when user logged out of the
12 # system only in some tab
12 # system only in some tab
13 prepend_before_action :reject_announcement_refresh_when_logged_out,
13 prepend_before_action :reject_announcement_refresh_when_logged_out,
14 :only => [:announcements]
14 :only => [:announcements]
15
15
16 before_action :authenticate_by_ip_address, :only => [:list]
16 before_action :authenticate_by_ip_address, :only => [:list]
17
17
18 #reset login, clear session
18 #reset login, clear session
19 #front page
19 #front page
20 def login
20 def login
21 saved_notice = flash[:notice]
21 saved_notice = flash[:notice]
22 reset_session
22 reset_session
23 flash.now[:notice] = saved_notice
23 flash.now[:notice] = saved_notice
24 @remote_ip = request.remote_ip
24 @remote_ip = request.remote_ip
25
25
26 # EXPERIMENT:
26 # EXPERIMENT:
27 # Hide login if in single user mode and the url does not
27 # Hide login if in single user mode and the url does not
28 # explicitly specify /login
28 # explicitly specify /login
29 #
29 #
30 # logger.info "PATH: #{request.path}"
30 # logger.info "PATH: #{request.path}"
31 # if GraderConfiguration['system.single_user_mode'] and
31 # if GraderConfiguration['system.single_user_mode'] and
32 # request.path!='/main/login'
32 # request.path!='/main/login'
33 # @hidelogin = true
33 # @hidelogin = true
34 # end
34 # end
35
35
36 @announcements = Announcement.frontpage
36 @announcements = Announcement.frontpage
37 render :action => 'login', :layout => 'empty'
37 render :action => 'login', :layout => 'empty'
38 end
38 end
39
39
40 def logout
40 def logout
41 reset_session
41 reset_session
42 redirect_to root_path
42 redirect_to root_path
43 end
43 end
44
44
45 def list
45 def list
46 prepare_list_information
46 prepare_list_information
47 end
47 end
48
48
49 def help
49 def help
50 @user = User.find(session[:user_id])
50 @user = User.find(session[:user_id])
51 end
51 end
52
52
53 def submit
53 def submit
54 user = User.find(session[:user_id])
54 user = User.find(session[:user_id])
55
55
56 @submission = Submission.new
56 @submission = Submission.new
57 @submission.problem_id = params[:submission][:problem_id]
57 @submission.problem_id = params[:submission][:problem_id]
58 @submission.user = user
58 @submission.user = user
59 @submission.language_id = 0
59 @submission.language_id = 0
60 if (params['file']) and (params['file']!='')
60 if (params['file']) and (params['file']!='')
61 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
61 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
62 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
62 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
63 @submission.source_filename = params['file'].original_filename
63 @submission.source_filename = params['file'].original_filename
64 end
64 end
65
65
66 if (params[:editor_text])
66 if (params[:editor_text])
67 language = Language.find_by_id(params[:language_id])
67 language = Language.find_by_id(params[:language_id])
68 @submission.source = params[:editor_text]
68 @submission.source = params[:editor_text]
69 @submission.source_filename = "live_edit.#{language.ext}"
69 @submission.source_filename = "live_edit.#{language.ext}"
70 @submission.language = language
70 @submission.language = language
71 end
71 end
72
72
73 @submission.submitted_at = Time.new.gmtime
73 @submission.submitted_at = Time.new.gmtime
74 @submission.ip_address = request.remote_ip
74 @submission.ip_address = request.remote_ip
75
75
76 - if GraderConfiguration.time_limit_mode? and user.contest_finished?
76 + if @current_user.admin? == false && GraderConfiguration.time_limit_mode? && @current_user.contest_finished?
77 @submission.errors.add(:base,"The contest is over.")
77 @submission.errors.add(:base,"The contest is over.")
78 prepare_list_information
78 prepare_list_information
79 render :action => 'list' and return
79 render :action => 'list' and return
80 end
80 end
81
81
82 if @submission.valid?(@current_user)
82 if @submission.valid?(@current_user)
83 if @submission.save == false
83 if @submission.save == false
84 flash[:notice] = 'Error saving your submission'
84 flash[:notice] = 'Error saving your submission'
85 elsif Task.create(:submission_id => @submission.id,
85 elsif Task.create(:submission_id => @submission.id,
86 :status => Task::STATUS_INQUEUE) == false
86 :status => Task::STATUS_INQUEUE) == false
87 flash[:notice] = 'Error adding your submission to task queue'
87 flash[:notice] = 'Error adding your submission to task queue'
88 end
88 end
89 else
89 else
90 prepare_list_information
90 prepare_list_information
91 render :action => 'list' and return
91 render :action => 'list' and return
92 end
92 end
93 redirect_to edit_submission_path(@submission)
93 redirect_to edit_submission_path(@submission)
94 end
94 end
95
95
96 def source
96 def source
97 submission = Submission.find(params[:id])
97 submission = Submission.find(params[:id])
98 if ((submission.user_id == session[:user_id]) and
98 if ((submission.user_id == session[:user_id]) and
99 (submission.problem != nil) and
99 (submission.problem != nil) and
100 (submission.problem.available))
100 (submission.problem.available))
101 send_data(submission.source,
101 send_data(submission.source,
102 {:filename => submission.download_filename,
102 {:filename => submission.download_filename,
103 :type => 'text/plain'})
103 :type => 'text/plain'})
104 else
104 else
105 flash[:notice] = 'Error viewing source'
105 flash[:notice] = 'Error viewing source'
106 redirect_to :action => 'list'
106 redirect_to :action => 'list'
107 end
107 end
108 end
108 end
109
109
110 def compiler_msg
110 def compiler_msg
111 @submission = Submission.find(params[:id])
111 @submission = Submission.find(params[:id])
112 if @submission.user_id == session[:user_id]
112 if @submission.user_id == session[:user_id]
113 render :action => 'compiler_msg', :layout => 'empty'
113 render :action => 'compiler_msg', :layout => 'empty'
114 else
114 else
115 flash[:notice] = 'Error viewing source'
115 flash[:notice] = 'Error viewing source'
116 redirect_to :action => 'list'
116 redirect_to :action => 'list'
117 end
117 end
118 end
118 end
119
119
120 def result
120 def result
121 if !GraderConfiguration.show_grading_result
121 if !GraderConfiguration.show_grading_result
122 redirect_to :action => 'list' and return
122 redirect_to :action => 'list' and return
123 end
123 end
124 @user = User.find(session[:user_id])
124 @user = User.find(session[:user_id])
125 @submission = Submission.find(params[:id])
125 @submission = Submission.find(params[:id])
126 if @submission.user!=@user
126 if @submission.user!=@user
127 flash[:notice] = 'You are not allowed to view result of other users.'
127 flash[:notice] = 'You are not allowed to view result of other users.'
128 redirect_to :action => 'list' and return
128 redirect_to :action => 'list' and return
129 end
129 end
130 prepare_grading_result(@submission)
130 prepare_grading_result(@submission)
131 end
131 end
132
132
133 def load_output
133 def load_output
134 if !GraderConfiguration.show_grading_result or params[:num]==nil
134 if !GraderConfiguration.show_grading_result or params[:num]==nil
135 redirect_to :action => 'list' and return
135 redirect_to :action => 'list' and return
136 end
136 end
137 @user = User.find(session[:user_id])
137 @user = User.find(session[:user_id])
138 @submission = Submission.find(params[:id])
138 @submission = Submission.find(params[:id])
139 if @submission.user!=@user
139 if @submission.user!=@user
140 flash[:notice] = 'You are not allowed to view result of other users.'
140 flash[:notice] = 'You are not allowed to view result of other users.'
141 redirect_to :action => 'list' and return
141 redirect_to :action => 'list' and return
142 end
142 end
143 case_num = params[:num].to_i
143 case_num = params[:num].to_i
144 out_filename = output_filename(@user.login,
144 out_filename = output_filename(@user.login,
145 @submission.problem.name,
145 @submission.problem.name,
146 @submission.id,
146 @submission.id,
147 case_num)
147 case_num)
148 if !FileTest.exists?(out_filename)
148 if !FileTest.exists?(out_filename)
149 flash[:notice] = 'Output not found.'
149 flash[:notice] = 'Output not found.'
150 redirect_to :action => 'list' and return
150 redirect_to :action => 'list' and return
151 end
151 end
152
152
153 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
153 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
154 response.headers['Content-Type'] = "application/force-download"
154 response.headers['Content-Type'] = "application/force-download"
155 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
155 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
156 response.headers["X-Sendfile"] = out_filename
156 response.headers["X-Sendfile"] = out_filename
157 response.headers['Content-length'] = File.size(out_filename)
157 response.headers['Content-length'] = File.size(out_filename)
158 render :nothing => true
158 render :nothing => true
159 else
159 else
160 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
160 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
161 end
161 end
162 end
162 end
163
163
164 def error
164 def error
165 @user = User.find(session[:user_id])
165 @user = User.find(session[:user_id])
166 end
166 end
167
167
168 # announcement refreshing and hiding methods
168 # announcement refreshing and hiding methods
169
169
170 def announcements
170 def announcements
171 if params.has_key? 'recent'
171 if params.has_key? 'recent'
172 prepare_announcements(params[:recent])
172 prepare_announcements(params[:recent])
173 else
173 else
174 prepare_announcements
174 prepare_announcements
175 end
175 end
176 render(:partial => 'announcement',
176 render(:partial => 'announcement',
177 :collection => @announcements,
177 :collection => @announcements,
178 :locals => {:announcement_effect => true})
178 :locals => {:announcement_effect => true})
179 end
179 end
180
180
181 def confirm_contest_start
181 def confirm_contest_start
182 user = User.find(session[:user_id])
182 user = User.find(session[:user_id])
183 if request.method == 'POST'
183 if request.method == 'POST'
184 user.update_start_time
184 user.update_start_time
185 redirect_to :action => 'list'
185 redirect_to :action => 'list'
186 else
186 else
187 @contests = user.contests
187 @contests = user.contests
188 @user = user
188 @user = user
189 end
189 end
190 end
190 end
191
191
192 protected
192 protected
193
193
194 def prepare_announcements(recent=nil)
194 def prepare_announcements(recent=nil)
195 if GraderConfiguration.show_tasks_to?(@user)
195 if GraderConfiguration.show_tasks_to?(@user)
196 @announcements = Announcement.published(true)
196 @announcements = Announcement.published(true)
197 else
197 else
198 @announcements = Announcement.published
198 @announcements = Announcement.published
199 end
199 end
200 if recent!=nil
200 if recent!=nil
201 recent_id = recent.to_i
201 recent_id = recent.to_i
202 @announcements = @announcements.find_all { |a| a.id > recent_id }
202 @announcements = @announcements.find_all { |a| a.id > recent_id }
203 end
203 end
204 end
204 end
205
205
206 def prepare_list_information
206 def prepare_list_information
207 @user = User.find(session[:user_id])
207 @user = User.find(session[:user_id])
208 if not GraderConfiguration.multicontests?
208 if not GraderConfiguration.multicontests?
209 @problems = @user.available_problems
209 @problems = @user.available_problems
210 else
210 else
211 @contest_problems = @user.available_problems_group_by_contests
211 @contest_problems = @user.available_problems_group_by_contests
212 @problems = @user.available_problems
212 @problems = @user.available_problems
213 end
213 end
214 @prob_submissions = {}
214 @prob_submissions = {}
215 @problems.each do |p|
215 @problems.each do |p|
216 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
216 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
217 if sub!=nil
217 if sub!=nil
218 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
218 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
219 else
219 else
220 @prob_submissions[p.id] = { :count => 0, :submission => nil }
220 @prob_submissions[p.id] = { :count => 0, :submission => nil }
221 end
221 end
222 end
222 end
223 prepare_announcements
223 prepare_announcements
224 end
224 end
225
225
226 def check_viewability
226 def check_viewability
227 @user = User.find(session[:user_id])
227 @user = User.find(session[:user_id])
228 if (!GraderConfiguration.show_tasks_to?(@user)) and
228 if (!GraderConfiguration.show_tasks_to?(@user)) and
229 ((action_name=='submission') or (action_name=='submit'))
229 ((action_name=='submission') or (action_name=='submit'))
230 redirect_to :action => 'list' and return
230 redirect_to :action => 'list' and return
231 end
231 end
232 end
232 end
233
233
234 def prepare_grading_result(submission)
234 def prepare_grading_result(submission)
235 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
235 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
236 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
236 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
237 else
237 else
238 # guess task info from problem.full_score
238 # guess task info from problem.full_score
239 cases = submission.problem.full_score / 10
239 cases = submission.problem.full_score / 10
240 grading_info = {
240 grading_info = {
241 'testruns' => cases,
241 'testruns' => cases,
242 'testcases' => cases
242 'testcases' => cases
243 }
243 }
244 end
244 end
245 @test_runs = []
245 @test_runs = []
246 if grading_info['testruns'].is_a? Integer
246 if grading_info['testruns'].is_a? Integer
247 trun_count = grading_info['testruns']
247 trun_count = grading_info['testruns']
248 trun_count.times do |i|
248 trun_count.times do |i|
249 @test_runs << [ read_grading_result(@user.login,
249 @test_runs << [ read_grading_result(@user.login,
250 submission.problem.name,
250 submission.problem.name,
251 submission.id,
251 submission.id,
252 i+1) ]
252 i+1) ]
253 end
253 end
254 else
254 else
255 grading_info['testruns'].keys.sort.each do |num|
255 grading_info['testruns'].keys.sort.each do |num|
256 run = []
256 run = []
257 testrun = grading_info['testruns'][num]
257 testrun = grading_info['testruns'][num]
258 testrun.each do |c|
258 testrun.each do |c|
259 run << read_grading_result(@user.login,
259 run << read_grading_result(@user.login,
260 submission.problem.name,
260 submission.problem.name,
261 submission.id,
261 submission.id,
262 c)
262 c)
263 end
263 end
264 @test_runs << run
264 @test_runs << run
265 end
265 end
266 end
266 end
267 end
267 end
268
268
@@ -1,248 +1,250
1 require 'csv'
1 require 'csv'
2
2
3 class ReportController < ApplicationController
3 class ReportController < ApplicationController
4
4
5 before_action :check_valid_login
5 before_action :check_valid_login
6
6
7 before_action :admin_authorization, only: [:login_stat,:submission, :submission_query,
7 before_action :admin_authorization, only: [:login_stat,:submission, :submission_query,
8 :login, :login_detail_query, :login_summary_query,
8 :login, :login_detail_query, :login_summary_query,
9 :stuck, :cheat_report, :cheat_scrutinize, :show_max_score, :current_score]
9 :stuck, :cheat_report, :cheat_scrutinize, :show_max_score, :current_score]
10
10
11 before_action(only: [:problem_hof]) { |c|
11 before_action(only: [:problem_hof]) { |c|
12 return false unless check_valid_login
12 return false unless check_valid_login
13
13
14 admin_authorization unless GraderConfiguration["right.user_view_submission"]
14 admin_authorization unless GraderConfiguration["right.user_view_submission"]
15 }
15 }
16
16
17 def max_score
17 def max_score
18 end
18 end
19
19
20 def current_score
20 def current_score
21 @problems = Problem.available_problems
21 @problems = Problem.available_problems
22 - if params[:group_id]
22 + if params[:group_id] && params[:users] == 'group'
23 @group = Group.find(params[:group_id])
23 @group = Group.find(params[:group_id])
24 @users = @group.users.where(enabled: true)
24 @users = @group.users.where(enabled: true)
25 else
25 else
26 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
26 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
27 end
27 end
28 @scorearray = calculate_max_score(@problems, @users,0,0,true)
28 @scorearray = calculate_max_score(@problems, @users,0,0,true)
29
29
30 #rencer accordingly
30 #rencer accordingly
31 if params[:button] == 'download' then
31 if params[:button] == 'download' then
32 csv = gen_csv_from_scorearray(@scorearray,@problems)
32 csv = gen_csv_from_scorearray(@scorearray,@problems)
33 send_data csv, filename: 'max_score.csv'
33 send_data csv, filename: 'max_score.csv'
34 else
34 else
35 #render template: 'user_admin/user_stat'
35 #render template: 'user_admin/user_stat'
36 render 'current_score'
36 render 'current_score'
37 end
37 end
38 end
38 end
39
39
40 def show_max_score
40 def show_max_score
41 #process parameters
41 #process parameters
42 #problems
42 #problems
43 @problems = []
43 @problems = []
44 if params[:problem_id]
44 if params[:problem_id]
45 params[:problem_id].each do |id|
45 params[:problem_id].each do |id|
46 next unless id.strip != ""
46 next unless id.strip != ""
47 pid = Problem.find_by_id(id.to_i)
47 pid = Problem.find_by_id(id.to_i)
48 @problems << pid if pid
48 @problems << pid if pid
49 end
49 end
50 end
50 end
51
51
52 #users
52 #users
53 - @users = if params[:users] == "all" then
53 + @users = if params[:users] == "group" then
54 + Group.find(params[:group_id]).users.all
55 + elsif params[:users] == 'enabled'
56 + User.includes(:contests).includes(:contest_stat).where(enabled: true)
57 + else
54 User.includes(:contests).includes(:contest_stat)
58 User.includes(:contests).includes(:contest_stat)
55 - else
56 - User.includes(:contests).includes(:contest_stat).where(enabled: true)
57 end
59 end
58
60
59 #set up range from param
61 #set up range from param
60 @since_id = params.fetch(:from_id, 0).to_i
62 @since_id = params.fetch(:from_id, 0).to_i
61 @until_id = params.fetch(:to_id, 0).to_i
63 @until_id = params.fetch(:to_id, 0).to_i
62 @since_id = nil if @since_id == 0
64 @since_id = nil if @since_id == 0
63 @until_id = nil if @until_id == 0
65 @until_id = nil if @until_id == 0
64
66
65 #calculate the routine
67 #calculate the routine
66 @scorearray = calculate_max_score(@problems, @users, @since_id, @until_id)
68 @scorearray = calculate_max_score(@problems, @users, @since_id, @until_id)
67
69
68 #rencer accordingly
70 #rencer accordingly
69 if params[:button] == 'download' then
71 if params[:button] == 'download' then
70 csv = gen_csv_from_scorearray(@scorearray,@problems)
72 csv = gen_csv_from_scorearray(@scorearray,@problems)
71 send_data csv, filename: 'max_score.csv'
73 send_data csv, filename: 'max_score.csv'
72 else
74 else
73 #render template: 'user_admin/user_stat'
75 #render template: 'user_admin/user_stat'
74 render 'max_score'
76 render 'max_score'
75 end
77 end
76
78
77 end
79 end
78
80
79 def score
81 def score
80 if params[:commit] == 'download csv'
82 if params[:commit] == 'download csv'
81 @problems = Problem.all
83 @problems = Problem.all
82 else
84 else
83 @problems = Problem.available_problems
85 @problems = Problem.available_problems
84 end
86 end
85 @users = User.includes(:contests, :contest_stat).where(enabled: true)
87 @users = User.includes(:contests, :contest_stat).where(enabled: true)
86 @scorearray = Array.new
88 @scorearray = Array.new
87 @users.each do |u|
89 @users.each do |u|
88 ustat = Array.new
90 ustat = Array.new
89 ustat[0] = u
91 ustat[0] = u
90 @problems.each do |p|
92 @problems.each do |p|
91 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
93 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
92 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
94 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
93 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
95 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
94 else
96 else
95 ustat << [0,false]
97 ustat << [0,false]
96 end
98 end
97 end
99 end
98 @scorearray << ustat
100 @scorearray << ustat
99 end
101 end
100 if params[:commit] == 'download csv' then
102 if params[:commit] == 'download csv' then
101 csv = gen_csv_from_scorearray(@scorearray,@problems)
103 csv = gen_csv_from_scorearray(@scorearray,@problems)
102 send_data csv, filename: 'last_score.csv'
104 send_data csv, filename: 'last_score.csv'
103 else
105 else
104 render template: 'user_admin/user_stat'
106 render template: 'user_admin/user_stat'
105 end
107 end
106
108
107 end
109 end
108
110
109 def login
111 def login
110 end
112 end
111
113
112 def login_summary_query
114 def login_summary_query
113 @users = Array.new
115 @users = Array.new
114
116
115 date_and_time = '%Y-%m-%d %H:%M'
117 date_and_time = '%Y-%m-%d %H:%M'
116 begin
118 begin
117 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
119 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
118 @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)
120 @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)
119 rescue
121 rescue
120 @since_time = DateTime.new(1000,1,1)
122 @since_time = DateTime.new(1000,1,1)
121 end
123 end
122 begin
124 begin
123 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
125 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
124 @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)
126 @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)
125 rescue
127 rescue
126 @until_time = DateTime.new(3000,1,1)
128 @until_time = DateTime.new(3000,1,1)
127 end
129 end
128
130
129 record = User
131 record = User
130 .left_outer_joins(:logins).group('users.id')
132 .left_outer_joins(:logins).group('users.id')
131 .where("logins.created_at >= ? AND logins.created_at <= ?",@since_time, @until_time)
133 .where("logins.created_at >= ? AND logins.created_at <= ?",@since_time, @until_time)
132 case params[:users]
134 case params[:users]
133 when 'enabled'
135 when 'enabled'
134 record = record.where(enabled: true)
136 record = record.where(enabled: true)
135 when 'group'
137 when 'group'
136 record = record.joins(:groups).where(groups: {id: params[:groups]}) if params[:groups]
138 record = record.joins(:groups).where(groups: {id: params[:groups]}) if params[:groups]
137 end
139 end
138
140
139 record = record.pluck("users.id,users.login,users.full_name,count(logins.created_at),min(logins.created_at),max(logins.created_at)")
141 record = record.pluck("users.id,users.login,users.full_name,count(logins.created_at),min(logins.created_at),max(logins.created_at)")
140 record.each do |user|
142 record.each do |user|
141 x = Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
143 x = Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
142 user[0],@since_time,@until_time)
144 user[0],@since_time,@until_time)
143 .pluck(:ip_address).uniq
145 .pluck(:ip_address).uniq
144 @users << { id: user[0],
146 @users << { id: user[0],
145 login: user[1],
147 login: user[1],
146 full_name: user[2],
148 full_name: user[2],
147 count: user[3],
149 count: user[3],
148 min: user[4],
150 min: user[4],
149 max: user[5],
151 max: user[5],
150 ip: x
152 ip: x
151 }
153 }
152 end
154 end
153 end
155 end
154
156
155 def login_detail_query
157 def login_detail_query
156 @logins = Array.new
158 @logins = Array.new
157
159
158 date_and_time = '%Y-%m-%d %H:%M'
160 date_and_time = '%Y-%m-%d %H:%M'
159 begin
161 begin
160 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
162 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
161 @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)
163 @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)
162 rescue
164 rescue
163 @since_time = DateTime.new(1000,1,1)
165 @since_time = DateTime.new(1000,1,1)
164 end
166 end
165 begin
167 begin
166 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
168 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
167 @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)
169 @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)
168 rescue
170 rescue
169 @until_time = DateTime.new(3000,1,1)
171 @until_time = DateTime.new(3000,1,1)
170 end
172 end
171
173
172 @logins = Login.includes(:user).where("logins.created_at >= ? AND logins.created_at <= ?",@since_time, @until_time)
174 @logins = Login.includes(:user).where("logins.created_at >= ? AND logins.created_at <= ?",@since_time, @until_time)
173 case params[:users]
175 case params[:users]
174 when 'enabled'
176 when 'enabled'
175 @logins = @logins.where(users: {enabled: true})
177 @logins = @logins.where(users: {enabled: true})
176 when 'group'
178 when 'group'
177 @logins = @logins.joins(user: :groups).where(user: {groups: {id: params[:groups]}}) if params[:groups]
179 @logins = @logins.joins(user: :groups).where(user: {groups: {id: params[:groups]}}) if params[:groups]
178 end
180 end
179 end
181 end
180
182
181 def submission
183 def submission
182 end
184 end
183
185
184 def submission_query
186 def submission_query
185 @submissions = Submission
187 @submissions = Submission
186 .includes(:problem).includes(:user).includes(:language)
188 .includes(:problem).includes(:user).includes(:language)
187
189
188 case params[:users]
190 case params[:users]
189 when 'enabled'
191 when 'enabled'
190 @submissions = @submissions.where(users: {enabled: true})
192 @submissions = @submissions.where(users: {enabled: true})
191 when 'group'
193 when 'group'
192 @submissions = @submissions.joins(user: :groups).where(user: {groups: {id: params[:groups]}}) if params[:groups]
194 @submissions = @submissions.joins(user: :groups).where(user: {groups: {id: params[:groups]}}) if params[:groups]
193 end
195 end
194
196
195 case params[:problems]
197 case params[:problems]
196 when 'enabled'
198 when 'enabled'
197 @submissions = @submissions.where(problems: {available: true})
199 @submissions = @submissions.where(problems: {available: true})
198 when 'selected'
200 when 'selected'
199 @submissions = @submissions.where(problem_id: params[:problem_id])
201 @submissions = @submissions.where(problem_id: params[:problem_id])
200 end
202 end
201
203
202 #set default
204 #set default
203 params[:since_datetime] = Date.today.to_s if params[:since_datetime].blank?
205 params[:since_datetime] = Date.today.to_s if params[:since_datetime].blank?
204
206
205 @submissions, @recordsTotal, @recordsFiltered = process_query_record( @submissions,
207 @submissions, @recordsTotal, @recordsFiltered = process_query_record( @submissions,
206 global_search: ['user.login','user.full_name','problem.name','problem.full_name','points'],
208 global_search: ['user.login','user.full_name','problem.name','problem.full_name','points'],
207 date_filter: 'submitted_at',
209 date_filter: 'submitted_at',
208 date_param_since: 'since_datetime',
210 date_param_since: 'since_datetime',
209 date_param_until: 'until_datetime',
211 date_param_until: 'until_datetime',
210 hard_limit: 100_000
212 hard_limit: 100_000
211 )
213 )
212 end
214 end
213
215
214 def login
216 def login
215 end
217 end
216
218
217 def problem_hof
219 def problem_hof
218 # gen problem list
220 # gen problem list
219 @user = User.find(session[:user_id])
221 @user = User.find(session[:user_id])
220 @problems = @user.available_problems
222 @problems = @user.available_problems
221
223
222 # get selected problems or the default
224 # get selected problems or the default
223 if params[:id]
225 if params[:id]
224 begin
226 begin
225 @problem = Problem.available.find(params[:id])
227 @problem = Problem.available.find(params[:id])
226 rescue
228 rescue
227 redirect_to action: :problem_hof
229 redirect_to action: :problem_hof
228 flash[:notice] = 'Error: submissions for that problem are not viewable.'
230 flash[:notice] = 'Error: submissions for that problem are not viewable.'
229 return
231 return
230 end
232 end
231 end
233 end
232
234
233 return unless @problem
235 return unless @problem
234
236
235 @by_lang = {} #aggregrate by language
237 @by_lang = {} #aggregrate by language
236
238
237 range =65
239 range =65
238 @histogram = { data: Array.new(range,0), summary: {} }
240 @histogram = { data: Array.new(range,0), summary: {} }
239 @summary = {count: 0, solve: 0, attempt: 0}
241 @summary = {count: 0, solve: 0, attempt: 0}
240 user = Hash.new(0)
242 user = Hash.new(0)
241 Submission.where(problem_id: @problem.id).find_each do |sub|
243 Submission.where(problem_id: @problem.id).find_each do |sub|
242 #histogram
244 #histogram
243 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
245 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
244 @histogram[:data][d.to_i] += 1 if d < range
246 @histogram[:data][d.to_i] += 1 if d < range
245
247
246 next unless sub.points
248 next unless sub.points
247 @summary[:count] += 1
249 @summary[:count] += 1
248 user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
250 user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
@@ -1,111 +1,111
1 class SubmissionsController < ApplicationController
1 class SubmissionsController < ApplicationController
2 before_action :check_valid_login
2 before_action :check_valid_login
3 before_action :submission_authorization, only: [:show, :download, :edit]
3 before_action :submission_authorization, only: [:show, :download, :edit]
4 before_action :admin_authorization, only: [:rejudge]
4 before_action :admin_authorization, only: [:rejudge]
5
5
6 # GET /submissions
6 # GET /submissions
7 # GET /submissions.json
7 # GET /submissions.json
8 # Show problem selection and user's submission of that problem
8 # Show problem selection and user's submission of that problem
9 def index
9 def index
10 @user = @current_user
10 @user = @current_user
11 @problems = @user.available_problems
11 @problems = @user.available_problems
12
12
13 if params[:problem_id]==nil
13 if params[:problem_id]==nil
14 @problem = nil
14 @problem = nil
15 @submissions = nil
15 @submissions = nil
16 else
16 else
17 @problem = Problem.find_by_id(params[:problem_id])
17 @problem = Problem.find_by_id(params[:problem_id])
18 if (@problem == nil) or (not @problem.available)
18 if (@problem == nil) or (not @problem.available)
19 redirect_to list_main_path
19 redirect_to list_main_path
20 flash[:error] = 'Authorization error: You have no right to view submissions for this problem'
20 flash[:error] = 'Authorization error: You have no right to view submissions for this problem'
21 return
21 return
22 end
22 end
23 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
23 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
24 end
24 end
25 end
25 end
26
26
27 # GET /submissions/1
27 # GET /submissions/1
28 # GET /submissions/1.json
28 # GET /submissions/1.json
29 def show
29 def show
30 @submission = Submission.find(params[:id])
30 @submission = Submission.find(params[:id])
31
31
32 #log the viewing
32 #log the viewing
33 user = User.find(session[:user_id])
33 user = User.find(session[:user_id])
34 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
34 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
35
35
36 @task = @submission.task
36 @task = @submission.task
37 end
37 end
38
38
39 def download
39 def download
40 @submission = Submission.find(params[:id])
40 @submission = Submission.find(params[:id])
41 send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'})
41 send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'})
42 end
42 end
43
43
44 def compiler_msg
44 def compiler_msg
45 @submission = Submission.find(params[:id])
45 @submission = Submission.find(params[:id])
46 respond_to do |format|
46 respond_to do |format|
47 format.js
47 format.js
48 end
48 end
49 end
49 end
50
50
51 #on-site new submission on specific problem
51 #on-site new submission on specific problem
52 def direct_edit_problem
52 def direct_edit_problem
53 @problem = Problem.find(params[:problem_id])
53 @problem = Problem.find(params[:problem_id])
54 unless @current_user.can_view_problem?(@problem)
54 unless @current_user.can_view_problem?(@problem)
55 unauthorized_redirect
55 unauthorized_redirect
56 return
56 return
57 end
57 end
58 @source = ''
58 @source = ''
59 if (params[:view_latest])
59 if (params[:view_latest])
60 sub = Submission.find_last_by_user_and_problem(@current_user.id,@problem.id)
60 sub = Submission.find_last_by_user_and_problem(@current_user.id,@problem.id)
61 @source = @submission.source.to_s if @submission and @submission.source
61 @source = @submission.source.to_s if @submission and @submission.source
62 end
62 end
63 render 'edit'
63 render 'edit'
64 end
64 end
65
65
66 # GET /submissions/1/edit
66 # GET /submissions/1/edit
67 def edit
67 def edit
68 @submission = Submission.find(params[:id])
68 @submission = Submission.find(params[:id])
69 @source = @submission.source.to_s
69 @source = @submission.source.to_s
70 @problem = @submission.problem
70 @problem = @submission.problem
71 @lang_id = @submission.language.id
71 @lang_id = @submission.language.id
72 end
72 end
73
73
74
74
75 def get_latest_submission_status
75 def get_latest_submission_status
76 @problem = Problem.find(params[:pid])
76 @problem = Problem.find(params[:pid])
77 @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
77 @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
78 respond_to do |format|
78 respond_to do |format|
79 format.js
79 format.js
80 end
80 end
81 end
81 end
82
82
83 # GET /submissions/:id/rejudge
83 # GET /submissions/:id/rejudge
84 def rejudge
84 def rejudge
85 @submission = Submission.find(params[:id])
85 @submission = Submission.find(params[:id])
86 @task = @submission.task
86 @task = @submission.task
87 @task.status_inqueue! if @task
87 @task.status_inqueue! if @task
88 respond_to do |format|
88 respond_to do |format|
89 format.js
89 format.js
90 end
90 end
91 end
91 end
92
92
93 protected
93 protected
94
94
95 def submission_authorization
95 def submission_authorization
96 #admin always has privileged
96 #admin always has privileged
97 return true if @current_user.admin?
97 return true if @current_user.admin?
98 - return true if @current_user.has_role?('TA') && (['show','download'].include? action_name)
98 + return true if @current_user.has_role?('ta') && (['show','download'].include? action_name)
99
99
100 sub = Submission.find(params[:id])
100 sub = Submission.find(params[:id])
101 if @current_user.available_problems.include? sub.problem
101 if @current_user.available_problems.include? sub.problem
102 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
102 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
103 end
103 end
104
104
105 #default to NO
105 #default to NO
106 unauthorized_redirect
106 unauthorized_redirect
107 return false
107 return false
108 end
108 end
109
109
110
110
111 end
111 end
@@ -1,11 +1,15
1 .container-fluid
1 .container-fluid
2 %h1 Current Score
2 %h1 Current Score
3 = form_tag current_score_report_path, method: 'get' do
3 = form_tag current_score_report_path, method: 'get' do
4 - Show only users from this group
4 + .radio-inline
5 + = radio_button_tag 'users', 'all', (params[:users] == 'all')
6 + = label_tag(:users_all,'Show all users')
7 + %br
8 + .radio-inline
9 + = radio_button_tag 'users', 'group', (params[:users] == 'group')
10 + = label_tag(:users_group, 'Show only users from this group')
5 = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_id]), id: 'group_name',class: 'select2', style: 'width: 20em';
11 = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_id]), id: 'group_name',class: 'select2', style: 'width: 20em';
6 = submit_tag 'Apply',class: 'btn btn-default'
12 = submit_tag 'Apply',class: 'btn btn-default'
7
13
8 %br
14 %br
9 -
10 -
11 = render "score_table"
15 = render "score_table"
@@ -1,49 +1,54
1 %h1 Maximum score
1 %h1 Maximum score
2
2
3 = form_tag show_max_score_report_path
3 = form_tag show_max_score_report_path
4 .row
4 .row
5 .col-md-4
5 .col-md-4
6 .panel.panel-primary
6 .panel.panel-primary
7 .panel-heading
7 .panel-heading
8 Problems
8 Problems
9 .panel-body
9 .panel-body
10 %p
10 %p
11 Select problem(s) that we wish to know the score.
11 Select problem(s) that we wish to know the score.
12 = label_tag :problem_id, "Problems"
12 = label_tag :problem_id, "Problems"
13 = select_tag 'problem_id[]',
13 = select_tag 'problem_id[]',
14 options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]},params[:problem_id]),
14 options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]},params[:problem_id]),
15 { class: 'select2 form-control', multiple: "true" }
15 { class: 'select2 form-control', multiple: "true" }
16 .col-md-4
16 .col-md-4
17 .panel.panel-primary
17 .panel.panel-primary
18 .panel-heading
18 .panel-heading
19 Submission range
19 Submission range
20 .panel-body
20 .panel-body
21 %p
21 %p
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
23 .form-group
23 .form-group
24 = label_tag :from, "Min"
24 = label_tag :from, "Min"
25 = text_field_tag 'from_id', @since_id, class: "form-control"
25 = text_field_tag 'from_id', @since_id, class: "form-control"
26 .form-group
26 .form-group
27 = label_tag :from, "Max"
27 = label_tag :from, "Max"
28 = text_field_tag 'to_id', @until_id, class: "form-control"
28 = text_field_tag 'to_id', @until_id, class: "form-control"
29 .col-md-4
29 .col-md-4
30 .panel.panel-primary
30 .panel.panel-primary
31 .panel-heading
31 .panel-heading
32 Users
32 Users
33 .panel-body
33 .panel-body
34 .radio
34 .radio
35 %label
35 %label
36 = radio_button_tag 'users', 'all', (params[:users] == "all")
36 = radio_button_tag 'users', 'all', (params[:users] == "all")
37 All users
37 All users
38 .radio
38 .radio
39 %label
39 %label
40 = radio_button_tag 'users', 'enabled', (params[:users] == "enabled")
40 = radio_button_tag 'users', 'enabled', (params[:users] == "enabled")
41 Only enabled users
41 Only enabled users
42 + .radio
43 + %label
44 + = radio_button_tag 'users', 'group', (params[:users] == "group")
45 + Only users from this group
46 + = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_id]), id: 'group_name',class: 'select2', style: 'width: 20em';
42 .row
47 .row
43 .col-md-12
48 .col-md-12
44 = button_tag 'Show', class: "btn btn-primary btn-large", value: "show"
49 = button_tag 'Show', class: "btn btn-primary btn-large", value: "show"
45 = button_tag 'Download CSV', class: "btn btn-primary btn-large", value: "download"
50 = button_tag 'Download CSV', class: "btn btn-primary btn-large", value: "download"
46
51
47 - if @scorearray
52 - if @scorearray
48 %h2 Result
53 %h2 Result
49 =render "score_table"
54 =render "score_table"
@@ -1,308 +1,310
1 # This file is auto-generated from the current state of the database. Instead
1 # This file is auto-generated from the current state of the database. Instead
2 # of editing this file, please use the migrations feature of Active Record to
2 # of editing this file, please use the migrations feature of Active Record to
3 # incrementally modify your database, and then regenerate this schema definition.
3 # incrementally modify your database, and then regenerate this schema definition.
4 #
4 #
5 # Note that this schema.rb definition is the authoritative source for your
5 # Note that this schema.rb definition is the authoritative source for your
6 # database schema. If you need to create the application database on another
6 # database schema. If you need to create the application database on another
7 # system, you should be using db:schema:load, not running all the migrations
7 # system, you should be using db:schema:load, not running all the migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 #
10 #
11 # It's strongly recommended that you check this file into your version control system.
11 # It's strongly recommended that you check this file into your version control system.
12
12
13 ActiveRecord::Schema.define(version: 2020_08_13_083020) do
13 ActiveRecord::Schema.define(version: 2020_08_13_083020) do
14
14
15 create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
15 create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
16 t.string "author"
16 t.string "author"
17 t.text "body"
17 t.text "body"
18 t.boolean "published"
18 t.boolean "published"
19 t.datetime "created_at", null: false
19 t.datetime "created_at", null: false
20 t.datetime "updated_at", null: false
20 t.datetime "updated_at", null: false
21 t.boolean "frontpage", default: false
21 t.boolean "frontpage", default: false
22 t.boolean "contest_only", default: false
22 t.boolean "contest_only", default: false
23 t.string "title"
23 t.string "title"
24 t.string "notes"
24 t.string "notes"
25 end
25 end
26
26
27 create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
27 create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
28 t.string "title"
28 t.string "title"
29 t.boolean "enabled"
29 t.boolean "enabled"
30 t.datetime "created_at", null: false
30 t.datetime "created_at", null: false
31 t.datetime "updated_at", null: false
31 t.datetime "updated_at", null: false
32 t.string "name"
32 t.string "name"
33 end
33 end
34
34
35 create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
35 create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
36 t.integer "contest_id"
36 t.integer "contest_id"
37 t.integer "problem_id"
37 t.integer "problem_id"
38 end
38 end
39
39
40 create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
40 create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
41 t.integer "contest_id"
41 t.integer "contest_id"
42 t.integer "user_id"
42 t.integer "user_id"
43 end
43 end
44
44
45 create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
45 create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
46 t.string "name"
46 t.string "name"
47 t.datetime "created_at", null: false
47 t.datetime "created_at", null: false
48 t.datetime "updated_at", null: false
48 t.datetime "updated_at", null: false
49 end
49 end
50
50
51 create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
51 create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
52 t.text "body"
52 t.text "body"
53 t.boolean "markdowned"
53 t.boolean "markdowned"
54 t.datetime "created_at", null: false
54 t.datetime "created_at", null: false
55 t.datetime "updated_at", null: false
55 t.datetime "updated_at", null: false
56 end
56 end
57
57
58 create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
58 create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
59 t.string "key"
59 t.string "key"
60 t.string "value_type"
60 t.string "value_type"
61 t.string "value"
61 t.string "value"
62 t.datetime "created_at", null: false
62 t.datetime "created_at", null: false
63 t.datetime "updated_at", null: false
63 t.datetime "updated_at", null: false
64 t.text "description"
64 t.text "description"
65 end
65 end
66
66
67 create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
67 create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
68 t.string "host"
68 t.string "host"
69 t.integer "pid"
69 t.integer "pid"
70 t.string "mode"
70 t.string "mode"
71 t.boolean "active"
71 t.boolean "active"
72 t.datetime "created_at", null: false
72 t.datetime "created_at", null: false
73 t.datetime "updated_at", null: false
73 t.datetime "updated_at", null: false
74 t.integer "task_id"
74 t.integer "task_id"
75 t.string "task_type"
75 t.string "task_type"
76 t.boolean "terminated"
76 t.boolean "terminated"
77 t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
77 t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
78 end
78 end
79
79
80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
81 t.string "name"
81 t.string "name"
82 t.string "description"
82 t.string "description"
83 t.boolean "enabled", default: true
83 t.boolean "enabled", default: true
84 end
84 end
85
85
86 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
86 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
87 t.integer "problem_id", null: false
87 t.integer "problem_id", null: false
88 t.integer "group_id", null: false
88 t.integer "group_id", null: false
89 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
89 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
90 end
90 end
91
91
92 - create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
92 + create_table "groups_users", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
93 t.integer "group_id", null: false
93 t.integer "group_id", null: false
94 t.integer "user_id", null: false
94 t.integer "user_id", null: false
95 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
95 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
96 end
96 end
97
97
98 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
98 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
99 t.integer "user_id"
99 t.integer "user_id"
100 t.string "ip_address"
100 t.string "ip_address"
101 t.datetime "created_at", null: false
101 t.datetime "created_at", null: false
102 t.datetime "updated_at", null: false
102 t.datetime "updated_at", null: false
103 t.string "status"
103 t.string "status"
104 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
104 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
105 end
105 end
106
106
107 create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
107 create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
108 t.string "name", limit: 10
108 t.string "name", limit: 10
109 t.string "pretty_name"
109 t.string "pretty_name"
110 t.string "ext", limit: 10
110 t.string "ext", limit: 10
111 t.string "common_ext"
111 t.string "common_ext"
112 end
112 end
113
113
114 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
114 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
115 t.integer "user_id"
115 t.integer "user_id"
116 t.string "ip_address"
116 t.string "ip_address"
117 t.datetime "created_at", null: false
117 t.datetime "created_at", null: false
118 t.datetime "updated_at", null: false
118 t.datetime "updated_at", null: false
119 + t.index ["user_id"], name: "index_logins_on_user_id"
119 end
120 end
120
121
121 create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
122 create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
122 t.integer "sender_id"
123 t.integer "sender_id"
123 t.integer "receiver_id"
124 t.integer "receiver_id"
124 t.integer "replying_message_id"
125 t.integer "replying_message_id"
125 t.text "body"
126 t.text "body"
126 t.boolean "replied"
127 t.boolean "replied"
127 t.datetime "created_at", null: false
128 t.datetime "created_at", null: false
128 t.datetime "updated_at", null: false
129 t.datetime "updated_at", null: false
129 end
130 end
130
131
131 create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
132 create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
132 t.string "name", limit: 30
133 t.string "name", limit: 30
133 t.string "full_name"
134 t.string "full_name"
134 t.integer "full_score"
135 t.integer "full_score"
135 t.date "date_added"
136 t.date "date_added"
136 t.boolean "available"
137 t.boolean "available"
137 t.string "url"
138 t.string "url"
138 t.integer "description_id"
139 t.integer "description_id"
139 t.boolean "test_allowed"
140 t.boolean "test_allowed"
140 t.boolean "output_only"
141 t.boolean "output_only"
141 t.string "description_filename"
142 t.string "description_filename"
142 t.boolean "view_testcase"
143 t.boolean "view_testcase"
143 end
144 end
144
145
145 create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
146 create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
146 t.integer "problem_id"
147 t.integer "problem_id"
147 t.integer "tag_id"
148 t.integer "tag_id"
148 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
149 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
149 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
150 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
150 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
151 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
151 end
152 end
152
153
153 create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
154 create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
154 t.string "name"
155 t.string "name"
155 t.string "controller"
156 t.string "controller"
156 t.string "action"
157 t.string "action"
157 end
158 end
158
159
159 create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
160 create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
160 t.integer "right_id"
161 t.integer "right_id"
161 t.integer "role_id"
162 t.integer "role_id"
162 t.index ["role_id"], name: "index_rights_roles_on_role_id"
163 t.index ["role_id"], name: "index_rights_roles_on_role_id"
163 end
164 end
164
165
165 create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
166 create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
166 t.string "name"
167 t.string "name"
167 end
168 end
168
169
169 create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
170 create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
170 t.integer "role_id"
171 t.integer "role_id"
171 t.integer "user_id"
172 t.integer "user_id"
172 t.index ["user_id"], name: "index_roles_users_on_user_id"
173 t.index ["user_id"], name: "index_roles_users_on_user_id"
173 end
174 end
174
175
175 create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
176 create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
176 t.string "session_id"
177 t.string "session_id"
177 t.text "data"
178 t.text "data"
178 t.datetime "updated_at"
179 t.datetime "updated_at"
179 t.index ["session_id"], name: "index_sessions_on_session_id"
180 t.index ["session_id"], name: "index_sessions_on_session_id"
180 t.index ["updated_at"], name: "index_sessions_on_updated_at"
181 t.index ["updated_at"], name: "index_sessions_on_updated_at"
181 end
182 end
182
183
183 create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
184 create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
184 t.string "name"
185 t.string "name"
185 t.boolean "started"
186 t.boolean "started"
186 t.datetime "start_time"
187 t.datetime "start_time"
187 t.datetime "created_at", null: false
188 t.datetime "created_at", null: false
188 t.datetime "updated_at", null: false
189 t.datetime "updated_at", null: false
189 t.integer "country_id"
190 t.integer "country_id"
190 t.string "password"
191 t.string "password"
191 end
192 end
192
193
193 create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
194 create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
194 t.integer "user_id"
195 t.integer "user_id"
195 t.integer "submission_id"
196 t.integer "submission_id"
196 t.datetime "created_at", null: false
197 t.datetime "created_at", null: false
197 t.datetime "updated_at", null: false
198 t.datetime "updated_at", null: false
198 end
199 end
199
200
200 create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
201 create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
201 t.integer "user_id"
202 t.integer "user_id"
202 t.integer "problem_id"
203 t.integer "problem_id"
203 t.integer "language_id"
204 t.integer "language_id"
204 t.text "source", limit: 16777215
205 t.text "source", limit: 16777215
205 t.binary "binary"
206 t.binary "binary"
206 t.datetime "submitted_at"
207 t.datetime "submitted_at"
207 t.datetime "compiled_at"
208 t.datetime "compiled_at"
208 t.text "compiler_message"
209 t.text "compiler_message"
209 t.datetime "graded_at"
210 t.datetime "graded_at"
210 t.integer "points"
211 t.integer "points"
211 t.text "grader_comment"
212 t.text "grader_comment"
212 t.integer "number"
213 t.integer "number"
213 t.string "source_filename"
214 t.string "source_filename"
214 t.float "max_runtime"
215 t.float "max_runtime"
215 t.integer "peak_memory"
216 t.integer "peak_memory"
216 t.integer "effective_code_length"
217 t.integer "effective_code_length"
217 t.string "ip_address"
218 t.string "ip_address"
219 + t.index ["submitted_at"], name: "index_submissions_on_submitted_at"
218 t.index ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true
220 t.index ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true
219 t.index ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id"
221 t.index ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id"
220 end
222 end
221
223
222 create_table "tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
224 create_table "tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
223 t.string "name", null: false
225 t.string "name", null: false
224 t.text "description"
226 t.text "description"
225 t.boolean "public"
227 t.boolean "public"
226 t.datetime "created_at", null: false
228 t.datetime "created_at", null: false
227 t.datetime "updated_at", null: false
229 t.datetime "updated_at", null: false
228 end
230 end
229
231
230 create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
232 create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
231 t.integer "submission_id"
233 t.integer "submission_id"
232 t.datetime "created_at"
234 t.datetime "created_at"
233 t.integer "status"
235 t.integer "status"
234 t.datetime "updated_at"
236 t.datetime "updated_at"
235 t.index ["submission_id"], name: "index_tasks_on_submission_id"
237 t.index ["submission_id"], name: "index_tasks_on_submission_id"
236 end
238 end
237
239
238 create_table "test_pairs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
240 create_table "test_pairs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
239 t.integer "problem_id"
241 t.integer "problem_id"
240 t.text "input", limit: 16777215
242 t.text "input", limit: 16777215
241 t.text "solution", limit: 16777215
243 t.text "solution", limit: 16777215
242 t.datetime "created_at", null: false
244 t.datetime "created_at", null: false
243 t.datetime "updated_at", null: false
245 t.datetime "updated_at", null: false
244 end
246 end
245
247
246 create_table "test_requests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
248 create_table "test_requests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
247 t.integer "user_id"
249 t.integer "user_id"
248 t.integer "problem_id"
250 t.integer "problem_id"
249 t.integer "submission_id"
251 t.integer "submission_id"
250 t.string "input_file_name"
252 t.string "input_file_name"
251 t.string "output_file_name"
253 t.string "output_file_name"
252 t.string "running_stat"
254 t.string "running_stat"
253 t.integer "status"
255 t.integer "status"
254 t.datetime "updated_at", null: false
256 t.datetime "updated_at", null: false
255 t.datetime "submitted_at"
257 t.datetime "submitted_at"
256 t.datetime "compiled_at"
258 t.datetime "compiled_at"
257 t.text "compiler_message"
259 t.text "compiler_message"
258 t.datetime "graded_at"
260 t.datetime "graded_at"
259 t.string "grader_comment"
261 t.string "grader_comment"
260 t.datetime "created_at", null: false
262 t.datetime "created_at", null: false
261 t.float "running_time"
263 t.float "running_time"
262 t.string "exit_status"
264 t.string "exit_status"
263 t.integer "memory_usage"
265 t.integer "memory_usage"
264 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
266 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
265 end
267 end
266
268
267 create_table "testcases", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
269 create_table "testcases", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
268 t.integer "problem_id"
270 t.integer "problem_id"
269 t.integer "num"
271 t.integer "num"
270 t.integer "group"
272 t.integer "group"
271 t.integer "score"
273 t.integer "score"
272 t.text "input", limit: 4294967295
274 t.text "input", limit: 4294967295
273 t.text "sol", limit: 4294967295
275 t.text "sol", limit: 4294967295
274 t.datetime "created_at"
276 t.datetime "created_at"
275 t.datetime "updated_at"
277 t.datetime "updated_at"
276 t.index ["problem_id"], name: "index_testcases_on_problem_id"
278 t.index ["problem_id"], name: "index_testcases_on_problem_id"
277 end
279 end
278
280
279 create_table "user_contest_stats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
281 create_table "user_contest_stats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
280 t.integer "user_id"
282 t.integer "user_id"
281 t.datetime "started_at"
283 t.datetime "started_at"
282 t.datetime "created_at", null: false
284 t.datetime "created_at", null: false
283 t.datetime "updated_at", null: false
285 t.datetime "updated_at", null: false
284 t.boolean "forced_logout"
286 t.boolean "forced_logout"
285 end
287 end
286
288
287 create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
289 create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
288 t.string "login", limit: 50
290 t.string "login", limit: 50
289 t.string "full_name"
291 t.string "full_name"
290 t.string "hashed_password"
292 t.string "hashed_password"
291 t.string "salt", limit: 5
293 t.string "salt", limit: 5
292 t.string "alias"
294 t.string "alias"
293 t.string "email"
295 t.string "email"
294 t.integer "site_id"
296 t.integer "site_id"
295 t.integer "country_id"
297 t.integer "country_id"
296 t.boolean "activated", default: false
298 t.boolean "activated", default: false
297 t.datetime "created_at"
299 t.datetime "created_at"
298 t.datetime "updated_at"
300 t.datetime "updated_at"
299 t.boolean "enabled", default: true
301 t.boolean "enabled", default: true
300 t.string "remark"
302 t.string "remark"
301 t.string "last_ip"
303 t.string "last_ip"
302 t.string "section"
304 t.string "section"
303 t.index ["login"], name: "index_users_on_login", unique: true
305 t.index ["login"], name: "index_users_on_login", unique: true
304 end
306 end
305
307
306 add_foreign_key "problems_tags", "problems"
308 add_foreign_key "problems_tags", "problems"
307 add_foreign_key "problems_tags", "tags"
309 add_foreign_key "problems_tags", "tags"
308 end
310 end
@@ -36,254 +36,254
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 #---------------------------- right --------------------------------
56 #---------------------------- right --------------------------------
57 {
57 {
58 :key => 'right.user_hall_of_fame',
58 :key => 'right.user_hall_of_fame',
59 :value_type => 'boolean',
59 :value_type => 'boolean',
60 :default_value => 'false',
60 :default_value => 'false',
61 :description => 'If true, any user can access hall of fame page.'
61 :description => 'If true, any user can access hall of fame page.'
62 },
62 },
63
63
64 {
64 {
65 :key => 'right.multiple_ip_login',
65 :key => 'right.multiple_ip_login',
66 :value_type => 'boolean',
66 :value_type => 'boolean',
67 :default_value => 'true',
67 :default_value => 'true',
68 :description => 'When change from true to false, a user can login from the first IP they logged into afterward.'
68 :description => 'When change from true to false, a user can login from the first IP they logged into afterward.'
69 },
69 },
70
70
71 {
71 {
72 :key => 'right.user_view_submission',
72 :key => 'right.user_view_submission',
73 :value_type => 'boolean',
73 :value_type => 'boolean',
74 :default_value => 'false',
74 :default_value => 'false',
75 :description => 'If true, any user can view submissions of every one.'
75 :description => 'If true, any user can view submissions of every one.'
76 },
76 },
77
77
78 {
78 {
79 :key => 'right.bypass_agreement',
79 :key => 'right.bypass_agreement',
80 :value_type => 'boolean',
80 :value_type => 'boolean',
81 :default_value => 'true',
81 :default_value => 'true',
82 :description => 'When false, a user must accept usage agreement before login'
82 :description => 'When false, a user must accept usage agreement before login'
83 },
83 },
84
84
85 {
85 {
86 :key => 'right.heartbeat_response',
86 :key => 'right.heartbeat_response',
87 :value_type => 'string',
87 :value_type => 'string',
88 :default_value => 'OK',
88 :default_value => 'OK',
89 :description => 'Heart beat response text'
89 :description => 'Heart beat response text'
90 },
90 },
91
91
92 {
92 {
93 :key => 'right.heartbeat_response_full',
93 :key => 'right.heartbeat_response_full',
94 :value_type => 'string',
94 :value_type => 'string',
95 :default_value => 'OK',
95 :default_value => 'OK',
96 :description => 'Heart beat response text when user got full score (set this value to the empty string to disable this feature)'
96 :description => 'Heart beat response text when user got full score (set this value to the empty string to disable this feature)'
97 },
97 },
98
98
99 {
99 {
100 :key => 'right.view_testcase',
100 :key => 'right.view_testcase',
101 :value_type => 'boolean',
101 :value_type => 'boolean',
102 :default_value => 'false',
102 :default_value => 'false',
103 :description => 'If true, any user can view/download test data'
103 :description => 'If true, any user can view/download test data'
104 },
104 },
105
105
106 {
106 {
107 :key => 'system.online_registration',
107 :key => 'system.online_registration',
108 :value_type => 'boolean',
108 :value_type => 'boolean',
109 :default_value => 'false',
109 :default_value => 'false',
110 :description => 'This option enables online registration.'
110 :description => 'This option enables online registration.'
111 },
111 },
112
112
113 # If Configuration['system.online_registration'] is true, the
113 # If Configuration['system.online_registration'] is true, the
114 # system allows online registration, and will use these
114 # system allows online registration, and will use these
115 # information for sending confirmation emails.
115 # information for sending confirmation emails.
116 {
116 {
117 :key => 'system.online_registration.smtp',
117 :key => 'system.online_registration.smtp',
118 :value_type => 'string',
118 :value_type => 'string',
119 :default_value => 'smtp.somehost.com'
119 :default_value => 'smtp.somehost.com'
120 },
120 },
121
121
122 {
122 {
123 :key => 'system.online_registration.from',
123 :key => 'system.online_registration.from',
124 :value_type => 'string',
124 :value_type => 'string',
125 :default_value => 'your.email@address'
125 :default_value => 'your.email@address'
126 },
126 },
127
127
128 {
128 {
129 :key => 'system.admin_email',
129 :key => 'system.admin_email',
130 :value_type => 'string',
130 :value_type => 'string',
131 :default_value => 'admin@admin.email'
131 :default_value => 'admin@admin.email'
132 },
132 },
133
133
134 {
134 {
135 :key => 'system.user_setting_enabled',
135 :key => 'system.user_setting_enabled',
136 :value_type => 'boolean',
136 :value_type => 'boolean',
137 :default_value => 'true',
137 :default_value => 'true',
138 :description => 'If this option is true, users can change their settings'
138 :description => 'If this option is true, users can change their settings'
139 },
139 },
140
140
141 {
141 {
142 :key => 'system.user_setting_enabled',
142 :key => 'system.user_setting_enabled',
143 :value_type => 'boolean',
143 :value_type => 'boolean',
144 :default_value => 'true',
144 :default_value => 'true',
145 :description => 'If this option is true, users can change their settings'
145 :description => 'If this option is true, users can change their settings'
146 },
146 },
147
147
148 # If Configuration['contest.test_request.early_timeout'] is true
148 # If Configuration['contest.test_request.early_timeout'] is true
149 # the user will not be able to use test request at 30 minutes
149 # the user will not be able to use test request at 30 minutes
150 # before the contest ends.
150 # before the contest ends.
151 {
151 {
152 :key => 'contest.test_request.early_timeout',
152 :key => 'contest.test_request.early_timeout',
153 :value_type => 'boolean',
153 :value_type => 'boolean',
154 :default_value => 'false'
154 :default_value => 'false'
155 },
155 },
156
156
157 {
157 {
158 :key => 'system.multicontests',
158 :key => 'system.multicontests',
159 :value_type => 'boolean',
159 :value_type => 'boolean',
160 :default_value => 'false'
160 :default_value => 'false'
161 },
161 },
162
162
163 {
163 {
164 :key => 'contest.confirm_indv_contest_start',
164 :key => 'contest.confirm_indv_contest_start',
165 :value_type => 'boolean',
165 :value_type => 'boolean',
166 :default_value => 'false'
166 :default_value => 'false'
167 },
167 },
168
168
169 {
169 {
170 :key => 'contest.default_contest_name',
170 :key => 'contest.default_contest_name',
171 :value_type => 'string',
171 :value_type => 'string',
172 :default_value => 'none',
172 :default_value => 'none',
173 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
173 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
174 },
174 },
175
175
176 {
176 {
177 :key => 'system.use_problem_group',
177 :key => 'system.use_problem_group',
178 :value_type => 'boolean',
178 :value_type => 'boolean',
179 :default_value => 'false',
179 :default_value => 'false',
180 :description => "If true, available problem to the user will be only ones associated with the group of the user."
180 :description => "If true, available problem to the user will be only ones associated with the group of the user."
181 },
181 },
182
182
183
183
184 {
184 {
185 :key => 'right.whitelist_ignore',
185 :key => 'right.whitelist_ignore',
186 :value_type => 'boolean',
186 :value_type => 'boolean',
187 :default_value => 'true',
187 :default_value => 'true',
188 :description => "If true, no IP check against whitelist_ip is perform. However, when false, non-admin user must have their ip in 'whitelist_ip' to be able to login."
188 :description => "If true, no IP check against whitelist_ip is perform. However, when false, non-admin user must have their ip in 'whitelist_ip' to be able to login."
189 },
189 },
190
190
191 {
191 {
192 :key => 'right.whitelist_ip',
192 :key => 'right.whitelist_ip',
193 :value_type => 'string',
193 :value_type => 'string',
194 :default_value => '0.0.0.0/0',
194 :default_value => '0.0.0.0/0',
195 :description => "list of whitelist ip, given in comma separated CIDR notation. For example '192.168.90.0/23, 192.168.1.23/32'"
195 :description => "list of whitelist ip, given in comma separated CIDR notation. For example '192.168.90.0/23, 192.168.1.23/32'"
196 },
196 },
197
197
198 ]
198 ]
199
199
200
200
201 def create_configuration_key(key,
201 def create_configuration_key(key,
202 value_type,
202 value_type,
203 default_value,
203 default_value,
204 description='')
204 description='')
205 conf = (GraderConfiguration.find_by_key(key) ||
205 conf = (GraderConfiguration.find_by_key(key) ||
206 GraderConfiguration.new(:key => key,
206 GraderConfiguration.new(:key => key,
207 :value_type => value_type,
207 :value_type => value_type,
208 :value => default_value))
208 :value => default_value))
209 conf.description = description
209 conf.description = description
210 conf.save
210 conf.save
211 end
211 end
212
212
213 def seed_config
213 def seed_config
214 CONFIGURATIONS.each do |conf|
214 CONFIGURATIONS.each do |conf|
215 if conf.has_key? :description
215 if conf.has_key? :description
216 desc = conf[:description]
216 desc = conf[:description]
217 else
217 else
218 desc = ''
218 desc = ''
219 end
219 end
220 create_configuration_key(conf[:key],
220 create_configuration_key(conf[:key],
221 conf[:value_type],
221 conf[:value_type],
222 conf[:default_value],
222 conf[:default_value],
223 desc)
223 desc)
224 end
224 end
225 end
225 end
226
226
227 def seed_roles
227 def seed_roles
228 - Role.find_or_create_by(name: 'TA')
228 + Role.find_or_create_by(name: 'ta')
229 return if Role.find_by_name('admin')
229 return if Role.find_by_name('admin')
230
230
231 role = Role.create(:name => 'admin')
231 role = Role.create(:name => 'admin')
232 user_admin_right = Right.create(:name => 'user_admin',
232 user_admin_right = Right.create(:name => 'user_admin',
233 :controller => 'user_admin',
233 :controller => 'user_admin',
234 :action => 'all')
234 :action => 'all')
235 problem_admin_right = Right.create(:name=> 'problem_admin',
235 problem_admin_right = Right.create(:name=> 'problem_admin',
236 :controller => 'problems',
236 :controller => 'problems',
237 :action => 'all')
237 :action => 'all')
238
238
239 graders_right = Right.create(:name => 'graders_admin',
239 graders_right = Right.create(:name => 'graders_admin',
240 :controller => 'graders',
240 :controller => 'graders',
241 :action => 'all')
241 :action => 'all')
242
242
243 role.rights << user_admin_right;
243 role.rights << user_admin_right;
244 role.rights << problem_admin_right;
244 role.rights << problem_admin_right;
245 role.rights << graders_right;
245 role.rights << graders_right;
246 role.save
246 role.save
247 end
247 end
248
248
249 def seed_root
249 def seed_root
250 return if User.find_by_login('root')
250 return if User.find_by_login('root')
251
251
252 root = User.new(:login => 'root',
252 root = User.new(:login => 'root',
253 :full_name => 'Administrator',
253 :full_name => 'Administrator',
254 :alias => 'root')
254 :alias => 'root')
255 root.password = 'ioionrails';
255 root.password = 'ioionrails';
256
256
257 class << root
257 class << root
258 public :encrypt_new_password
258 public :encrypt_new_password
259 def valid?(context=nil)
259 def valid?(context=nil)
260 true
260 true
261 end
261 end
262 end
262 end
263
263
264 root.encrypt_new_password
264 root.encrypt_new_password
265
265
266 root.roles << Role.find_by_name('admin')
266 root.roles << Role.find_by_name('admin')
267
267
268 root.activated = true
268 root.activated = true
269 root.save
269 root.save
270 end
270 end
271
271
272 def seed_users_and_roles
272 def seed_users_and_roles
273 seed_roles
273 seed_roles
274 seed_root
274 seed_root
275 end
275 end
276
276
277 def seed_more_languages
277 def seed_more_languages
278 #Language.delete_all
278 #Language.delete_all
279 Language.find_or_create_by( name: 'c', pretty_name: 'C', ext: 'c', common_ext: 'c' )
279 Language.find_or_create_by( name: 'c', pretty_name: 'C', ext: 'c', common_ext: 'c' )
280 Language.find_or_create_by( name: 'cpp', pretty_name: 'C++', ext: 'cpp', common_ext: 'cpp,cc' )
280 Language.find_or_create_by( name: 'cpp', pretty_name: 'C++', ext: 'cpp', common_ext: 'cpp,cc' )
281 Language.find_or_create_by( name: 'pas', pretty_name: 'Pascal', ext: 'pas', common_ext: 'pas' )
281 Language.find_or_create_by( name: 'pas', pretty_name: 'Pascal', ext: 'pas', common_ext: 'pas' )
282 Language.find_or_create_by( name: 'ruby', pretty_name: 'Ruby', ext: 'rb', common_ext: 'rb' )
282 Language.find_or_create_by( name: 'ruby', pretty_name: 'Ruby', ext: 'rb', common_ext: 'rb' )
283 Language.find_or_create_by( name: 'python', pretty_name: 'Python', ext: 'py', common_ext: 'py' )
283 Language.find_or_create_by( name: 'python', pretty_name: 'Python', ext: 'py', common_ext: 'py' )
284 Language.find_or_create_by( name: 'java', pretty_name: 'Java', ext: 'java', common_ext: 'java' )
284 Language.find_or_create_by( name: 'java', pretty_name: 'Java', ext: 'java', common_ext: 'java' )
285 end
285 end
286
286
287 seed_config
287 seed_config
288 seed_users_and_roles
288 seed_users_and_roles
289 seed_more_languages
289 seed_more_languages
You need to be logged in to leave comments. Login now