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

r649:3cb38436f7f6 - - 6 files changed: 41 inserted, 3 deleted

@@ -0,0 +1,9
1 + class AddHeartBeatFull < ActiveRecord::Migration
2 + def up
3 + GraderConfiguration.create key: 'right.heartbeat_response_full', value_type: 'string', value:'RESTART', description:'Heart beat response text when user got full score (set this value to the empty string to disable this feature)'
4 + end
5 +
6 + def down
7 +
8 + end
9 + end
@@ -1,31 +1,46
1 class HeartbeatController < ApplicationController
1 class HeartbeatController < ApplicationController
2 before_filter :admin_authorization, :only => ['index']
2 before_filter :admin_authorization, :only => ['index']
3
3
4 def edit
4 def edit
5 #@user = User.find_by_login(params[:id])
5 #@user = User.find_by_login(params[:id])
6 #unless @user
6 #unless @user
7 # render text: "LOGIN_NOT_FOUND"
7 # render text: "LOGIN_NOT_FOUND"
8 # return
8 # return
9 #end
9 #end
10
10
11 #hb = HeartBeat.where(user_id: @user.id, ip_address: request.remote_ip).first
11 #hb = HeartBeat.where(user_id: @user.id, ip_address: request.remote_ip).first
12 #puts "status = #{params[:status]}"
12 #puts "status = #{params[:status]}"
13 #if hb
13 #if hb
14 # if params[:status]
14 # if params[:status]
15 # hb.status = params[:status]
15 # hb.status = params[:status]
16 # hb.save
16 # hb.save
17 # end
17 # end
18 # hb.touch
18 # hb.touch
19 #else
19 #else
20 # HeartBeat.creae(user_id: @user.id, ip_address: request.remote_ip)
20 # HeartBeat.creae(user_id: @user.id, ip_address: request.remote_ip)
21 #end
21 #end
22 #HeartBeat.create(user_id: @user.id, ip_address: request.remote_ip, status: params[:status])
22 #HeartBeat.create(user_id: @user.id, ip_address: request.remote_ip, status: params[:status])
23
23
24 + res = GraderConfiguration['right.heartbeat_response']
25 + res.strip! if res
26 + full = GraderConfiguration['right.heartbeat_response_full']
27 + full.strip! if full
28 +
29 + if full and full != ''
30 + l = Login.where(ip_address: request.remote_ip).last
31 + @user = l.user
32 + if @user.solve_all_available_problems?
33 + render text: (full || 'OK')
34 + else
35 + render text: (res || 'OK')
36 + end
37 + else
24 render text: (GraderConfiguration['right.heartbeat_response'] || 'OK')
38 render text: (GraderConfiguration['right.heartbeat_response'] || 'OK')
25 end
39 end
40 + end
26
41
27 def index
42 def index
28 @hb = HeartBeat.where("updated_at >= ?",Time.zone.now-2.hours).includes(:user).order(:user_id).all
43 @hb = HeartBeat.where("updated_at >= ?",Time.zone.now-2.hours).includes(:user).order(:user_id).all
29 @num = HeartBeat.where("updated_at >= ?",Time.zone.now-5.minutes).count(:user_id,distinct: true)
44 @num = HeartBeat.where("updated_at >= ?",Time.zone.now-5.minutes).count(:user_id,distinct: true)
30 end
45 end
31 end
46 end
@@ -186,192 +186,201
186 return users.find_all { |u| u.contests.length == 0 }
186 return users.find_all { |u| u.contests.length == 0 }
187 end
187 end
188
188
189
189
190 def contest_time_left
190 def contest_time_left
191 if GraderConfiguration.contest_mode?
191 if GraderConfiguration.contest_mode?
192 return nil if site==nil
192 return nil if site==nil
193 return site.time_left
193 return site.time_left
194 elsif GraderConfiguration.indv_contest_mode?
194 elsif GraderConfiguration.indv_contest_mode?
195 time_limit = GraderConfiguration.contest_time_limit
195 time_limit = GraderConfiguration.contest_time_limit
196 if time_limit == nil
196 if time_limit == nil
197 return nil
197 return nil
198 end
198 end
199 if contest_stat==nil or contest_stat.started_at==nil
199 if contest_stat==nil or contest_stat.started_at==nil
200 return (Time.now.gmtime + time_limit) - Time.now.gmtime
200 return (Time.now.gmtime + time_limit) - Time.now.gmtime
201 else
201 else
202 finish_time = contest_stat.started_at + time_limit
202 finish_time = contest_stat.started_at + time_limit
203 current_time = Time.now.gmtime
203 current_time = Time.now.gmtime
204 if current_time > finish_time
204 if current_time > finish_time
205 return 0
205 return 0
206 else
206 else
207 return finish_time - current_time
207 return finish_time - current_time
208 end
208 end
209 end
209 end
210 else
210 else
211 return nil
211 return nil
212 end
212 end
213 end
213 end
214
214
215 def contest_finished?
215 def contest_finished?
216 if GraderConfiguration.contest_mode?
216 if GraderConfiguration.contest_mode?
217 return false if site==nil
217 return false if site==nil
218 return site.finished?
218 return site.finished?
219 elsif GraderConfiguration.indv_contest_mode?
219 elsif GraderConfiguration.indv_contest_mode?
220 return false if self.contest_stat(true)==nil
220 return false if self.contest_stat(true)==nil
221 return contest_time_left == 0
221 return contest_time_left == 0
222 else
222 else
223 return false
223 return false
224 end
224 end
225 end
225 end
226
226
227 def contest_started?
227 def contest_started?
228 if GraderConfiguration.indv_contest_mode?
228 if GraderConfiguration.indv_contest_mode?
229 stat = self.contest_stat
229 stat = self.contest_stat
230 return ((stat != nil) and (stat.started_at != nil))
230 return ((stat != nil) and (stat.started_at != nil))
231 elsif GraderConfiguration.contest_mode?
231 elsif GraderConfiguration.contest_mode?
232 return true if site==nil
232 return true if site==nil
233 return site.started
233 return site.started
234 else
234 else
235 return true
235 return true
236 end
236 end
237 end
237 end
238
238
239 def update_start_time
239 def update_start_time
240 stat = self.contest_stat
240 stat = self.contest_stat
241 if stat.nil? or stat.started_at.nil?
241 if stat.nil? or stat.started_at.nil?
242 stat ||= UserContestStat.new(:user => self)
242 stat ||= UserContestStat.new(:user => self)
243 stat.started_at = Time.now.gmtime
243 stat.started_at = Time.now.gmtime
244 stat.save
244 stat.save
245 end
245 end
246 end
246 end
247
247
248 def problem_in_user_contests?(problem)
248 def problem_in_user_contests?(problem)
249 problem_contests = problem.contests.all
249 problem_contests = problem.contests.all
250
250
251 if problem_contests.length == 0 # this is public contest
251 if problem_contests.length == 0 # this is public contest
252 return true
252 return true
253 end
253 end
254
254
255 contests.each do |contest|
255 contests.each do |contest|
256 if problem_contests.find {|c| c.id == contest.id }
256 if problem_contests.find {|c| c.id == contest.id }
257 return true
257 return true
258 end
258 end
259 end
259 end
260 return false
260 return false
261 end
261 end
262
262
263 def available_problems_group_by_contests
263 def available_problems_group_by_contests
264 contest_problems = []
264 contest_problems = []
265 pin = {}
265 pin = {}
266 contests.enabled.each do |contest|
266 contests.enabled.each do |contest|
267 available_problems = contest.problems.available
267 available_problems = contest.problems.available
268 contest_problems << {
268 contest_problems << {
269 :contest => contest,
269 :contest => contest,
270 :problems => available_problems
270 :problems => available_problems
271 }
271 }
272 available_problems.each {|p| pin[p.id] = true}
272 available_problems.each {|p| pin[p.id] = true}
273 end
273 end
274 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
274 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
275 contest_problems << {
275 contest_problems << {
276 :contest => nil,
276 :contest => nil,
277 :problems => other_avaiable_problems
277 :problems => other_avaiable_problems
278 }
278 }
279 return contest_problems
279 return contest_problems
280 end
280 end
281
281
282 + def solve_all_available_problems?
283 + available_problems.each do |p|
284 + u = self
285 + sub = Submission.find_last_by_user_and_problem(u.id,p.id)
286 + return false if !p or !sub or sub.points < p.full_score
287 + end
288 + return true
289 + end
290 +
282 def available_problems
291 def available_problems
283 if not GraderConfiguration.multicontests?
292 if not GraderConfiguration.multicontests?
284 return Problem.available_problems
293 return Problem.available_problems
285 else
294 else
286 contest_problems = []
295 contest_problems = []
287 pin = {}
296 pin = {}
288 contests.enabled.each do |contest|
297 contests.enabled.each do |contest|
289 contest.problems.available.each do |problem|
298 contest.problems.available.each do |problem|
290 if not pin.has_key? problem.id
299 if not pin.has_key? problem.id
291 contest_problems << problem
300 contest_problems << problem
292 end
301 end
293 pin[problem.id] = true
302 pin[problem.id] = true
294 end
303 end
295 end
304 end
296 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
305 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
297 return contest_problems + other_avaiable_problems
306 return contest_problems + other_avaiable_problems
298 end
307 end
299 end
308 end
300
309
301 def can_view_problem?(problem)
310 def can_view_problem?(problem)
302 if not GraderConfiguration.multicontests?
311 if not GraderConfiguration.multicontests?
303 return problem.available
312 return problem.available
304 else
313 else
305 return problem_in_user_contests? problem
314 return problem_in_user_contests? problem
306 end
315 end
307 end
316 end
308
317
309 def self.clear_last_login
318 def self.clear_last_login
310 User.update_all(:last_ip => nil)
319 User.update_all(:last_ip => nil)
311 end
320 end
312
321
313 protected
322 protected
314 def encrypt_new_password
323 def encrypt_new_password
315 return if password.blank?
324 return if password.blank?
316 self.salt = (10+rand(90)).to_s
325 self.salt = (10+rand(90)).to_s
317 self.hashed_password = User.encrypt(self.password,self.salt)
326 self.hashed_password = User.encrypt(self.password,self.salt)
318 end
327 end
319
328
320 def assign_default_site
329 def assign_default_site
321 # have to catch error when migrating (because self.site is not available).
330 # have to catch error when migrating (because self.site is not available).
322 begin
331 begin
323 if self.site==nil
332 if self.site==nil
324 self.site = Site.find_by_name('default')
333 self.site = Site.find_by_name('default')
325 if self.site==nil
334 if self.site==nil
326 self.site = Site.find(1) # when 'default has be renamed'
335 self.site = Site.find(1) # when 'default has be renamed'
327 end
336 end
328 end
337 end
329 rescue
338 rescue
330 end
339 end
331 end
340 end
332
341
333 def assign_default_contest
342 def assign_default_contest
334 # have to catch error when migrating (because self.site is not available).
343 # have to catch error when migrating (because self.site is not available).
335 begin
344 begin
336 if self.contests.length == 0
345 if self.contests.length == 0
337 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
346 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
338 if default_contest
347 if default_contest
339 self.contests = [default_contest]
348 self.contests = [default_contest]
340 end
349 end
341 end
350 end
342 rescue
351 rescue
343 end
352 end
344 end
353 end
345
354
346 def password_required?
355 def password_required?
347 self.hashed_password.blank? || !self.password.blank?
356 self.hashed_password.blank? || !self.password.blank?
348 end
357 end
349
358
350 def self.encrypt(string,salt)
359 def self.encrypt(string,salt)
351 Digest::SHA1.hexdigest(salt + string)
360 Digest::SHA1.hexdigest(salt + string)
352 end
361 end
353
362
354 def uniqueness_of_email_from_activated_users
363 def uniqueness_of_email_from_activated_users
355 user = User.activated_users.find_by_email(self.email)
364 user = User.activated_users.find_by_email(self.email)
356 if user and (user.login != self.login)
365 if user and (user.login != self.login)
357 self.errors.add(:base,"Email has already been taken")
366 self.errors.add(:base,"Email has already been taken")
358 end
367 end
359 end
368 end
360
369
361 def enough_time_interval_between_same_email_registrations
370 def enough_time_interval_between_same_email_registrations
362 return if !self.new_record?
371 return if !self.new_record?
363 return if self.activated
372 return if self.activated
364 open_user = User.find_by_email(self.email,
373 open_user = User.find_by_email(self.email,
365 :order => 'created_at DESC')
374 :order => 'created_at DESC')
366 if open_user and open_user.created_at and
375 if open_user and open_user.created_at and
367 (open_user.created_at > Time.now.gmtime - 5.minutes)
376 (open_user.created_at > Time.now.gmtime - 5.minutes)
368 self.errors.add(:base,"There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
377 self.errors.add(:base,"There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
369 end
378 end
370 end
379 end
371
380
372 def email_validation?
381 def email_validation?
373 begin
382 begin
374 return VALIDATE_USER_EMAILS
383 return VALIDATE_USER_EMAILS
375 rescue
384 rescue
376 return false
385 return false
377 end
386 end
@@ -1,100 +1,98
1 CafeGrader::Application.routes.draw do
1 CafeGrader::Application.routes.draw do
2 get "sources/direct_edit"
2 get "sources/direct_edit"
3
3
4 root :to => 'main#login'
4 root :to => 'main#login'
5
5
6 #logins
6 #logins
7 get 'login/login', to: 'login#login'
7 get 'login/login', to: 'login#login'
8
8
9 resources :contests
9 resources :contests
10
10
11 resources :sites
11 resources :sites
12
12
13 resources :announcements do
13 resources :announcements do
14 member do
14 member do
15 get 'toggle','toggle_front'
15 get 'toggle','toggle_front'
16 end
16 end
17 end
17 end
18
18
19 resources :problems do
19 resources :problems do
20 member do
20 member do
21 get 'toggle'
21 get 'toggle'
22 get 'toggle_test'
22 get 'toggle_test'
23 get 'toggle_view_testcase'
23 get 'toggle_view_testcase'
24 get 'stat'
24 get 'stat'
25 end
25 end
26 collection do
26 collection do
27 get 'turn_all_off'
27 get 'turn_all_off'
28 get 'turn_all_on'
28 get 'turn_all_on'
29 get 'import'
29 get 'import'
30 get 'manage'
30 get 'manage'
31 end
31 end
32
32
33 end
33 end
34
34
35 resources :testcases, only: [] do
35 resources :testcases, only: [] do
36 member do
36 member do
37 get 'download_input'
37 get 'download_input'
38 get 'download_sol'
38 get 'download_sol'
39 end
39 end
40 collection do
40 collection do
41 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
41 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
42 end
42 end
43 end
43 end
44
44
45 resources :grader_configuration, controller: 'configurations'
45 resources :grader_configuration, controller: 'configurations'
46
46
47 resources :users do
47 resources :users do
48 member do
48 member do
49 get 'toggle_activate', 'toggle_enable'
49 get 'toggle_activate', 'toggle_enable'
50 get 'stat'
50 get 'stat'
51 end
51 end
52 end
52 end
53
53
54 resources :submissions do
54 resources :submissions do
55 member do
55 member do
56 get 'download'
56 get 'download'
57 get 'compiler_msg'
57 get 'compiler_msg'
58 get 'rejudge'
58 get 'rejudge'
59 end
59 end
60 collection do
60 collection do
61 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
61 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
62 get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
62 get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
63 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
63 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
64 end
64 end
65 end
65 end
66
66
67
67
68
68
69 #main
69 #main
70 get "main/list"
70 get "main/list"
71 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
71 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
72
72
73 #user admin
73 #user admin
74 get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
74 get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
75
75
76 #report
76 #report
77 get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
77 get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
78 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
78 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
79 get "report/login"
79 get "report/login"
80 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
80 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
81 post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
81 post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
82
82
83
83
84 #
84 #
85 get 'tasks/view/:file.:ext' => 'tasks#view'
85 get 'tasks/view/:file.:ext' => 'tasks#view'
86 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
86 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
87 get 'heartbeat/:id/edit' => 'heartbeat#edit'
87 get 'heartbeat/:id/edit' => 'heartbeat#edit'
88
88
89 #grader
89 #grader
90 get 'graders/list', to: 'graders#list', as: 'grader_list'
90 get 'graders/list', to: 'graders#list', as: 'grader_list'
91
91
92
92
93 - get 'heartbeat/:id/edit' => 'heartbeat#edit'
94 -
95 # See how all your routes lay out with "rake routes"
93 # See how all your routes lay out with "rake routes"
96
94
97 # This is a legacy wild controller route that's not recommended for RESTful applications.
95 # This is a legacy wild controller route that's not recommended for RESTful applications.
98 # Note: This route will make all actions in every controller accessible via GET requests.
96 # Note: This route will make all actions in every controller accessible via GET requests.
99 match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
97 match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
100 end
98 end
@@ -1,110 +1,110
1 # encoding: UTF-8
1 # encoding: UTF-8
2 # This file is auto-generated from the current state of the database. Instead
2 # This file is auto-generated from the current state of the database. Instead
3 # of editing this file, please use the migrations feature of Active Record to
3 # of editing this file, please use the migrations feature of Active Record to
4 # incrementally modify your database, and then regenerate this schema definition.
4 # incrementally modify your database, and then regenerate this schema definition.
5 #
5 #
6 # Note that this schema.rb definition is the authoritative source for your
6 # Note that this schema.rb definition is the authoritative source for your
7 # database schema. If you need to create the application database on another
7 # database schema. If you need to create the application database on another
8 # system, you should be using db:schema:load, not running all the migrations
8 # system, you should be using db:schema:load, not running all the migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
11 #
11 #
12 # It's strongly recommended that you check this file into your version control system.
12 # It's strongly recommended that you check this file into your version control system.
13
13
14 - ActiveRecord::Schema.define(version: 20170310110146) do
14 + ActiveRecord::Schema.define(version: 20170427070345) do
15
15
16 create_table "announcements", force: :cascade do |t|
16 create_table "announcements", force: :cascade do |t|
17 t.string "author", limit: 255
17 t.string "author", limit: 255
18 t.text "body", limit: 65535
18 t.text "body", limit: 65535
19 t.boolean "published"
19 t.boolean "published"
20 t.datetime "created_at", null: false
20 t.datetime "created_at", null: false
21 t.datetime "updated_at", null: false
21 t.datetime "updated_at", null: false
22 t.boolean "frontpage", default: false
22 t.boolean "frontpage", default: false
23 t.boolean "contest_only", default: false
23 t.boolean "contest_only", default: false
24 t.string "title", limit: 255
24 t.string "title", limit: 255
25 t.string "notes", limit: 255
25 t.string "notes", limit: 255
26 end
26 end
27
27
28 create_table "contests", force: :cascade do |t|
28 create_table "contests", force: :cascade do |t|
29 t.string "title", limit: 255
29 t.string "title", limit: 255
30 t.boolean "enabled"
30 t.boolean "enabled"
31 t.datetime "created_at", null: false
31 t.datetime "created_at", null: false
32 t.datetime "updated_at", null: false
32 t.datetime "updated_at", null: false
33 t.string "name", limit: 255
33 t.string "name", limit: 255
34 end
34 end
35
35
36 create_table "contests_problems", id: false, force: :cascade do |t|
36 create_table "contests_problems", id: false, force: :cascade do |t|
37 t.integer "contest_id", limit: 4
37 t.integer "contest_id", limit: 4
38 t.integer "problem_id", limit: 4
38 t.integer "problem_id", limit: 4
39 end
39 end
40
40
41 create_table "contests_users", id: false, force: :cascade do |t|
41 create_table "contests_users", id: false, force: :cascade do |t|
42 t.integer "contest_id", limit: 4
42 t.integer "contest_id", limit: 4
43 t.integer "user_id", limit: 4
43 t.integer "user_id", limit: 4
44 end
44 end
45
45
46 create_table "countries", force: :cascade do |t|
46 create_table "countries", force: :cascade do |t|
47 t.string "name", limit: 255
47 t.string "name", limit: 255
48 t.datetime "created_at", null: false
48 t.datetime "created_at", null: false
49 t.datetime "updated_at", null: false
49 t.datetime "updated_at", null: false
50 end
50 end
51
51
52 create_table "descriptions", force: :cascade do |t|
52 create_table "descriptions", force: :cascade do |t|
53 t.text "body", limit: 65535
53 t.text "body", limit: 65535
54 t.boolean "markdowned"
54 t.boolean "markdowned"
55 t.datetime "created_at", null: false
55 t.datetime "created_at", null: false
56 t.datetime "updated_at", null: false
56 t.datetime "updated_at", null: false
57 end
57 end
58
58
59 create_table "grader_configurations", force: :cascade do |t|
59 create_table "grader_configurations", force: :cascade do |t|
60 t.string "key", limit: 255
60 t.string "key", limit: 255
61 t.string "value_type", limit: 255
61 t.string "value_type", limit: 255
62 t.string "value", limit: 255
62 t.string "value", limit: 255
63 t.datetime "created_at", null: false
63 t.datetime "created_at", null: false
64 t.datetime "updated_at", null: false
64 t.datetime "updated_at", null: false
65 t.text "description", limit: 65535
65 t.text "description", limit: 65535
66 end
66 end
67
67
68 create_table "grader_processes", force: :cascade do |t|
68 create_table "grader_processes", force: :cascade do |t|
69 t.string "host", limit: 255
69 t.string "host", limit: 255
70 t.integer "pid", limit: 4
70 t.integer "pid", limit: 4
71 t.string "mode", limit: 255
71 t.string "mode", limit: 255
72 t.boolean "active"
72 t.boolean "active"
73 t.datetime "created_at", null: false
73 t.datetime "created_at", null: false
74 t.datetime "updated_at", null: false
74 t.datetime "updated_at", null: false
75 t.integer "task_id", limit: 4
75 t.integer "task_id", limit: 4
76 t.string "task_type", limit: 255
76 t.string "task_type", limit: 255
77 t.boolean "terminated"
77 t.boolean "terminated"
78 end
78 end
79
79
80 add_index "grader_processes", ["host", "pid"], name: "index_grader_processes_on_ip_and_pid", using: :btree
80 add_index "grader_processes", ["host", "pid"], name: "index_grader_processes_on_ip_and_pid", using: :btree
81
81
82 create_table "heart_beats", force: :cascade do |t|
82 create_table "heart_beats", force: :cascade do |t|
83 t.integer "user_id", limit: 4
83 t.integer "user_id", limit: 4
84 t.string "ip_address", limit: 255
84 t.string "ip_address", limit: 255
85 t.datetime "created_at", null: false
85 t.datetime "created_at", null: false
86 t.datetime "updated_at", null: false
86 t.datetime "updated_at", null: false
87 t.string "status", limit: 255
87 t.string "status", limit: 255
88 end
88 end
89
89
90 add_index "heart_beats", ["updated_at"], name: "index_heart_beats_on_updated_at", using: :btree
90 add_index "heart_beats", ["updated_at"], name: "index_heart_beats_on_updated_at", using: :btree
91
91
92 create_table "languages", force: :cascade do |t|
92 create_table "languages", force: :cascade do |t|
93 t.string "name", limit: 10
93 t.string "name", limit: 10
94 t.string "pretty_name", limit: 255
94 t.string "pretty_name", limit: 255
95 t.string "ext", limit: 10
95 t.string "ext", limit: 10
96 t.string "common_ext", limit: 255
96 t.string "common_ext", limit: 255
97 end
97 end
98
98
99 create_table "logins", force: :cascade do |t|
99 create_table "logins", force: :cascade do |t|
100 t.integer "user_id", limit: 4
100 t.integer "user_id", limit: 4
101 t.string "ip_address", limit: 255
101 t.string "ip_address", limit: 255
102 t.datetime "created_at", null: false
102 t.datetime "created_at", null: false
103 t.datetime "updated_at", null: false
103 t.datetime "updated_at", null: false
104 end
104 end
105
105
106 create_table "messages", force: :cascade do |t|
106 create_table "messages", force: :cascade do |t|
107 t.integer "sender_id", limit: 4
107 t.integer "sender_id", limit: 4
108 t.integer "receiver_id", limit: 4
108 t.integer "receiver_id", limit: 4
109 t.integer "replying_message_id", limit: 4
109 t.integer "replying_message_id", limit: 4
110 t.text "body", limit: 65535
110 t.text "body", limit: 65535
@@ -1,188 +1,195
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 #---------------------------- 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',
94 + :value_type => 'string',
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)'
97 + },
98 +
99 + {
93 :key => 'right.view_testcase',
100 :key => 'right.view_testcase',
94 :value_type => 'boolean',
101 :value_type => 'boolean',
95 :default_value => 'false',
102 :default_value => 'false',
96 :description => 'When true, any user can view/download test data'
103 :description => 'When true, any user can view/download test data'
97 },
104 },
98 # If Configuration['system.online_registration'] is true, the
105 # If Configuration['system.online_registration'] is true, the
99 # system allows online registration, and will use these
106 # system allows online registration, and will use these
100 # information for sending confirmation emails.
107 # information for sending confirmation emails.
101 {
108 {
102 :key => 'system.online_registration.smtp',
109 :key => 'system.online_registration.smtp',
103 :value_type => 'string',
110 :value_type => 'string',
104 :default_value => 'smtp.somehost.com'
111 :default_value => 'smtp.somehost.com'
105 },
112 },
106
113
107 {
114 {
108 :key => 'system.online_registration.from',
115 :key => 'system.online_registration.from',
109 :value_type => 'string',
116 :value_type => 'string',
110 :default_value => 'your.email@address'
117 :default_value => 'your.email@address'
111 },
118 },
112
119
113 {
120 {
114 :key => 'system.admin_email',
121 :key => 'system.admin_email',
115 :value_type => 'string',
122 :value_type => 'string',
116 :default_value => 'admin@admin.email'
123 :default_value => 'admin@admin.email'
117 },
124 },
118
125
119 {
126 {
120 :key => 'system.user_setting_enabled',
127 :key => 'system.user_setting_enabled',
121 :value_type => 'boolean',
128 :value_type => 'boolean',
122 :default_value => 'true',
129 :default_value => 'true',
123 :description => 'If this option is true, users can change their settings'
130 :description => 'If this option is true, users can change their settings'
124 },
131 },
125
132
126 {
133 {
127 :key => 'system.user_setting_enabled',
134 :key => 'system.user_setting_enabled',
128 :value_type => 'boolean',
135 :value_type => 'boolean',
129 :default_value => 'true',
136 :default_value => 'true',
130 :description => 'If this option is true, users can change their settings'
137 :description => 'If this option is true, users can change their settings'
131 },
138 },
132
139
133 # If Configuration['contest.test_request.early_timeout'] is true
140 # If Configuration['contest.test_request.early_timeout'] is true
134 # the user will not be able to use test request at 30 minutes
141 # the user will not be able to use test request at 30 minutes
135 # before the contest ends.
142 # before the contest ends.
136 {
143 {
137 :key => 'contest.test_request.early_timeout',
144 :key => 'contest.test_request.early_timeout',
138 :value_type => 'boolean',
145 :value_type => 'boolean',
139 :default_value => 'false'
146 :default_value => 'false'
140 },
147 },
141
148
142 {
149 {
143 :key => 'system.multicontests',
150 :key => 'system.multicontests',
144 :value_type => 'boolean',
151 :value_type => 'boolean',
145 :default_value => 'false'
152 :default_value => 'false'
146 },
153 },
147
154
148 {
155 {
149 :key => 'contest.confirm_indv_contest_start',
156 :key => 'contest.confirm_indv_contest_start',
150 :value_type => 'boolean',
157 :value_type => 'boolean',
151 :default_value => 'false'
158 :default_value => 'false'
152 },
159 },
153
160
154 {
161 {
155 :key => 'contest.default_contest_name',
162 :key => 'contest.default_contest_name',
156 :value_type => 'string',
163 :value_type => 'string',
157 :default_value => 'none',
164 :default_value => 'none',
158 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
165 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
159 }
166 }
160
167
161 ]
168 ]
162
169
163
170
164 def create_configuration_key(key,
171 def create_configuration_key(key,
165 value_type,
172 value_type,
166 default_value,
173 default_value,
167 description='')
174 description='')
168 conf = (GraderConfiguration.find_by_key(key) ||
175 conf = (GraderConfiguration.find_by_key(key) ||
169 GraderConfiguration.new(:key => key,
176 GraderConfiguration.new(:key => key,
170 :value_type => value_type,
177 :value_type => value_type,
171 :value => default_value))
178 :value => default_value))
172 conf.description = description
179 conf.description = description
173 conf.save
180 conf.save
174 end
181 end
175
182
176 def seed_config
183 def seed_config
177 CONFIGURATIONS.each do |conf|
184 CONFIGURATIONS.each do |conf|
178 if conf.has_key? :description
185 if conf.has_key? :description
179 desc = conf[:description]
186 desc = conf[:description]
180 else
187 else
181 desc = ''
188 desc = ''
182 end
189 end
183 create_configuration_key(conf[:key],
190 create_configuration_key(conf[:key],
184 conf[:value_type],
191 conf[:value_type],
185 conf[:default_value],
192 conf[:default_value],
186 desc)
193 desc)
187 end
194 end
188 end
195 end
You need to be logged in to leave comments. Login now