Description:
Merge branch 'master' into codejom: added individual contest mode
Commit status:
[Not Reviewed]
References:
merge default
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r218:915a5c2d7529 - - 22 files changed: 263 inserted, 47 deleted

@@ -0,0 +1,30
1 + class ContestsController < ApplicationController
2 +
3 + before_filter :admin_authorization
4 +
5 + def index
6 + end
7 +
8 + def user_stat
9 + if not Configuration.indv_contest_mode?
10 + redirect_to :action => 'index' and return
11 + end
12 +
13 + @users = User.find(:all)
14 + @start_times = {}
15 + UserContestStat.find(:all).each do |stat|
16 + @start_times[stat.user_id] = stat.started_at
17 + end
18 + end
19 +
20 + def clear_all_stat
21 + if not Configuration.indv_contest_mode?
22 + redirect_to :action => 'index' and return
23 + end
24 +
25 + UserContestStat.delete_all()
26 + flash[:notice] = 'All start time statistic cleared.'
27 + redirect_to :action => 'index'
28 + end
29 +
30 + end
@@ -0,0 +1,2
1 + module ContestsHelper
2 + end
@@ -0,0 +1,14
1 + class UserContestStat < ActiveRecord::Base
2 +
3 + belongs_to :user
4 +
5 + def self.update_user_start_time(user)
6 + stat = user.contest_stat
7 + if stat == nil
8 + stat = UserContestStat.new(:user => user,
9 + :started_at => Time.now.gmtime)
10 + stat.save
11 + end
12 + end
13 +
14 + end
@@ -0,0 +1,4
1 + .submitbox
2 + %b Menu:
3 + = link_to '[View user start time]', :action => 'user_stat'
4 + = link_to '[Clear all start times]', {:action => 'clear_all_stat'}, {:confirm => 'Do you really want to clear all start time statistics?'}
@@ -0,0 +1,9
1 + %h1 Contest management
2 +
3 + - if (not Configuration.contest_mode?) and (not Configuration.indv_contest_mode?)
4 + Currently the system is not running in contest mode.
5 + - elsif Configuration.contest_mode?
6 + System running in normal contest mode.
7 + - else
8 + System running in individual contest mode.
9 + = render :partial => 'indv_contest_mode_index'
@@ -0,0 +1,24
1 + %h1 Individual Contest: User start time
2 +
3 + If you want to restart contest, you may want to
4 + %b
5 + = link_to '[clear all start times]', {:action => 'clear_all_stat'}, {:confirm => 'Do you really want to clear all start time statistics?'}
6 + so that users can participate again.
7 +
8 + %table.info
9 + %tr.info-head
10 + %th Login
11 + %th Start time
12 + %th Time left
13 + %th
14 + - @users.each_with_index do |user,i|
15 + %tr{:class => 'info-' + cycle('even','odd')}
16 + %td= user.login
17 + %td
18 + - if @start_times.has_key? user.id
19 + = @start_times[user.id]
20 + - else
21 + n/a
22 + %td= format_short_duration(user.contest_time_left)
23 + %td
24 + = link_to '[reset]', {:action => 'clear_stat', :id => user.id}, :confirm => 'Are you sure?'
@@ -0,0 +1,9
1 + class AddDescriptionToConfig < ActiveRecord::Migration
2 + def self.up
3 + add_column :configurations, :description, :text
4 + end
5 +
6 + def self.down
7 + remove_column :configurations, :description
8 + end
9 + end
@@ -0,0 +1,14
1 + class CreateUserContestStats < ActiveRecord::Migration
2 + def self.up
3 + create_table :user_contest_stats do |t|
4 + t.integer :user_id
5 + t.timestamp :started_at
6 +
7 + t.timestamps
8 + end
9 + end
10 +
11 + def self.down
12 + drop_table :user_contest_stats
13 + end
14 + end
@@ -0,0 +1,9
1 + # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 +
3 + one:
4 + user_id: 1
5 + started_at: 2010-01-24 12:44:58
6 +
7 + two:
8 + user_id: 1
9 + started_at: 2010-01-24 12:44:58
@@ -0,0 +1,8
1 + require 'test_helper'
2 +
3 + class ContestsControllerTest < ActionController::TestCase
4 + # Replace this with your real tests.
5 + test "the truth" do
6 + assert true
7 + end
8 + end
@@ -0,0 +1,4
1 + require 'test_helper'
2 +
3 + class ContestsHelperTest < ActionView::TestCase
4 + end
@@ -0,0 +1,8
1 + require 'test_helper'
2 +
3 + class UserContestStatTest < ActiveSupport::TestCase
4 + # Replace this with your real tests.
5 + test "the truth" do
6 + assert true
7 + end
8 + end
@@ -53,22 +53,22
53 }
53 }
54 flash[:notice] = 'You are not authorized to view the page you requested'
54 flash[:notice] = 'You are not authorized to view the page you requested'
55 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
55 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
56 redirect_to :controller => 'main', :action => 'login'
56 redirect_to :controller => 'main', :action => 'login'
57 return false
57 return false
58 end
58 end
59 end
59 end
60
60
61 def verify_time_limit
61 def verify_time_limit
62 return true if session[:user_id]==nil
62 return true if session[:user_id]==nil
63 user = User.find(session[:user_id], :include => :site)
63 user = User.find(session[:user_id], :include => :site)
64 return true if user==nil or user.site == nil
64 return true if user==nil or user.site == nil
65 - if user.site.finished?
65 + if user.contest_finished?
66 - flash[:notice] = 'Error: the contest on your site is over.'
66 + flash[:notice] = 'Error: the contest you are participating is over.'
67 redirect_to :back
67 redirect_to :back
68 return false
68 return false
69 end
69 end
70 return true
70 return true
71 end
71 end
72
72
73 end
73 end
74
74
@@ -1,29 +1,26
1 class LoginController < ApplicationController
1 class LoginController < ApplicationController
2
2
3 def index
3 def index
4 # show login screen
4 # show login screen
5 reset_session
5 reset_session
6 redirect_to :controller => 'main', :action => 'login'
6 redirect_to :controller => 'main', :action => 'login'
7 end
7 end
8
8
9 def login
9 def login
10 if user = User.authenticate(params[:login], params[:password])
10 if user = User.authenticate(params[:login], params[:password])
11 session[:user_id] = user.id
11 session[:user_id] = user.id
12 + session[:admin] = user.admin?
13 + UserContestStat.update_user_start_time(user)
12 redirect_to :controller => 'main', :action => 'list'
14 redirect_to :controller => 'main', :action => 'list'
13 - if user.admin?
14 - session[:admin] = true
15 - else
16 - session[:admin] = false
17 - end
18 else
15 else
19 flash[:notice] = 'Wrong password'
16 flash[:notice] = 'Wrong password'
20 redirect_to :controller => 'main', :action => 'login'
17 redirect_to :controller => 'main', :action => 'login'
21 end
18 end
22 end
19 end
23
20
24 def site_login
21 def site_login
25 begin
22 begin
26 site = Site.find(params[:login][:site_id])
23 site = Site.find(params[:login][:site_id])
27 rescue ActiveRecord::RecordNotFound
24 rescue ActiveRecord::RecordNotFound
28 site = nil
25 site = nil
29 end
26 end
@@ -1,16 +1,14
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 - SYSTEM_MODE_CONF_KEY = 'system.mode'
4 -
5 before_filter :authenticate, :except => [:index, :login]
3 before_filter :authenticate, :except => [:index, :login]
6 before_filter :check_viewability, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
7
5
8 # COMMENTED OUT: filter in each action instead
6 # COMMENTED OUT: filter in each action instead
9 # before_filter :verify_time_limit, :only => [:submit]
7 # before_filter :verify_time_limit, :only => [:submit]
10
8
11 verify :method => :post, :only => [:submit, :download_input, :submit_solution],
9 verify :method => :post, :only => [:submit, :download_input, :submit_solution],
12 :redirect_to => { :action => :index }
10 :redirect_to => { :action => :index }
13
11
14 # COMMENT OUT: only need when having high load
12 # COMMENT OUT: only need when having high load
15 # caches_action :index, :login
13 # caches_action :index, :login
16
14
@@ -50,26 +48,25
50 def submit
48 def submit
51 user = User.find(session[:user_id])
49 user = User.find(session[:user_id])
52
50
53 @submission = Submission.new(params[:submission])
51 @submission = Submission.new(params[:submission])
54 @submission.user = user
52 @submission.user = user
55 @submission.language_id = 0
53 @submission.language_id = 0
56 if (params['file']) and (params['file']!='')
54 if (params['file']) and (params['file']!='')
57 @submission.source = params['file'].read
55 @submission.source = params['file'].read
58 @submission.source_filename = params['file'].original_filename
56 @submission.source_filename = params['file'].original_filename
59 end
57 end
60 @submission.submitted_at = Time.new.gmtime
58 @submission.submitted_at = Time.new.gmtime
61
59
62 - if Configuration[SYSTEM_MODE_CONF_KEY]=='contest' and
60 + if Configuration.time_limit_mode? and user.contest_finished?
63 - user.site!=nil and user.site.finished?
64 @submission.errors.add_to_base "The contest is over."
61 @submission.errors.add_to_base "The contest is over."
65 prepare_list_information
62 prepare_list_information
66 render :action => 'list' and return
63 render :action => 'list' and return
67 end
64 end
68
65
69 if @submission.valid?
66 if @submission.valid?
70 if @submission.save == false
67 if @submission.save == false
71 flash[:notice] = 'Error saving your submission'
68 flash[:notice] = 'Error saving your submission'
72 elsif Task.create(:submission_id => @submission.id,
69 elsif Task.create(:submission_id => @submission.id,
73 :status => Task::STATUS_INQUEUE) == false
70 :status => Task::STATUS_INQUEUE) == false
74 flash[:notice] = 'Error adding your submission to task queue'
71 flash[:notice] = 'Error adding your submission to task queue'
75 end
72 end
@@ -1,42 +1,40
1 class TestController < ApplicationController
1 class TestController < ApplicationController
2
2
3 - SYSTEM_MODE_CONF_KEY = 'system.mode'
4 -
5 before_filter :authenticate, :check_viewability
3 before_filter :authenticate, :check_viewability
6
4
7 #
5 #
8 # COMMENT OUT: filter in each action instead
6 # COMMENT OUT: filter in each action instead
9 #
7 #
10 # before_filter :verify_time_limit, :only => [:submit]
8 # before_filter :verify_time_limit, :only => [:submit]
11
9
12 verify :method => :post, :only => [:submit],
10 verify :method => :post, :only => [:submit],
13 :redirect_to => { :action => :index }
11 :redirect_to => { :action => :index }
14
12
15 def index
13 def index
16 prepare_index_information
14 prepare_index_information
17 end
15 end
18
16
19 def submit
17 def submit
20 @user = User.find(session[:user_id])
18 @user = User.find(session[:user_id])
21
19
22 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
20 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
23
21
24 if @submitted_test_request.errors.length != 0
22 if @submitted_test_request.errors.length != 0
25 prepare_index_information
23 prepare_index_information
26 render :action => 'index' and return
24 render :action => 'index' and return
27 end
25 end
28
26
29 - if Configuration[SYSTEM_MODE_CONF_KEY]=='contest'
27 + if Configuration.time_limit_mode?
30 - if @user.site!=nil and @user.site.finished?
28 + if @user.contest_finished?
31 @submitted_test_request.errors.add_to_base('Contest is over.')
29 @submitted_test_request.errors.add_to_base('Contest is over.')
32 prepare_index_information
30 prepare_index_information
33 render :action => 'index' and return
31 render :action => 'index' and return
34 end
32 end
35
33
36 if !Configuration.allow_test_request(@user)
34 if !Configuration.allow_test_request(@user)
37 prepare_index_information
35 prepare_index_information
38 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
36 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
39 redirect_to :action => 'index' and return
37 redirect_to :action => 'index' and return
40 end
38 end
41 end
39 end
42
40
@@ -1,30 +1,29
1 # Methods added to this helper will be available to all templates in the application.
1 # Methods added to this helper will be available to all templates in the application.
2 module ApplicationHelper
2 module ApplicationHelper
3
3
4 - SYSTEM_MODE_CONF_KEY = 'system.mode'
5 -
6 def user_header
4 def user_header
7 menu_items = ''
5 menu_items = ''
8 user = User.find(session[:user_id])
6 user = User.find(session[:user_id])
9
7
10 if (user!=nil) and (session[:admin])
8 if (user!=nil) and (session[:admin])
11 # admin menu
9 # admin menu
12 menu_items << "<b>Administrative task:</b> "
10 menu_items << "<b>Administrative task:</b> "
13 append_to menu_items, '[Announcements]', 'announcements', 'index'
11 append_to menu_items, '[Announcements]', 'announcements', 'index'
14 append_to menu_items, '[Msg console]', 'messages', 'console'
12 append_to menu_items, '[Msg console]', 'messages', 'console'
15 - append_to menu_items, '[Problem admin]', 'problems', 'index'
13 + append_to menu_items, '[Problems]', 'problems', 'index'
16 - append_to menu_items, '[User admin]', 'user_admin', 'index'
14 + append_to menu_items, '[Users]', 'user_admin', 'index'
17 append_to menu_items, '[Results]', 'user_admin', 'user_stat'
15 append_to menu_items, '[Results]', 'user_admin', 'user_stat'
18 append_to menu_items, '[Graders]', 'graders', 'list'
16 append_to menu_items, '[Graders]', 'graders', 'list'
17 + append_to menu_items, '[Contests]', 'contests', 'index'
19 append_to menu_items, '[Sites]', 'sites', 'index'
18 append_to menu_items, '[Sites]', 'sites', 'index'
20 append_to menu_items, '[System config]', 'configurations', 'index'
19 append_to menu_items, '[System config]', 'configurations', 'index'
21 menu_items << "<br/>"
20 menu_items << "<br/>"
22 end
21 end
23
22
24 # main page
23 # main page
25 append_to menu_items, "[#{I18n.t 'menu.main'}]", 'main', 'list'
24 append_to menu_items, "[#{I18n.t 'menu.main'}]", 'main', 'list'
26 append_to menu_items, "[#{I18n.t 'menu.messages'}]", 'messages', 'list'
25 append_to menu_items, "[#{I18n.t 'menu.messages'}]", 'messages', 'list'
27
26
28 if (user!=nil) and (Configuration.show_tasks_to?(user))
27 if (user!=nil) and (Configuration.show_tasks_to?(user))
29 append_to menu_items, "[#{I18n.t 'menu.tasks'}]", 'tasks', 'list'
28 append_to menu_items, "[#{I18n.t 'menu.tasks'}]", 'tasks', 'list'
30 append_to menu_items, "[#{I18n.t 'menu.submissions'}]", 'main', 'submission'
29 append_to menu_items, "[#{I18n.t 'menu.submissions'}]", 'main', 'submission'
@@ -48,59 +47,63
48 end
47 end
49
48
50 def format_short_time(time)
49 def format_short_time(time)
51 now = Time.now.gmtime
50 now = Time.now.gmtime
52 st = ''
51 st = ''
53 if (time.yday != now.yday) or
52 if (time.yday != now.yday) or
54 (time.year != now.year)
53 (time.year != now.year)
55 st = time.strftime("%x ")
54 st = time.strftime("%x ")
56 end
55 end
57 st + time.strftime("%X")
56 st + time.strftime("%X")
58 end
57 end
59
58
59 + def format_short_duration(duration)
60 + return '' if duration==nil
61 + d = duration.to_f
62 + return Time.at(d).gmtime.strftime("%X")
63 + end
64 +
60 def read_textfile(fname,max_size=2048)
65 def read_textfile(fname,max_size=2048)
61 begin
66 begin
62 File.open(fname).read(max_size)
67 File.open(fname).read(max_size)
63 rescue
68 rescue
64 nil
69 nil
65 end
70 end
66 end
71 end
67
72
68 def user_title_bar(user)
73 def user_title_bar(user)
69 header = ''
74 header = ''
70 time_left = ''
75 time_left = ''
71
76
72 #
77 #
73 # if the contest is over
78 # if the contest is over
74 - if Configuration[SYSTEM_MODE_CONF_KEY]=='contest'
79 + if Configuration.time_limit_mode?
75 - if user.site!=nil and user.site.finished?
80 + if user.contest_finished?
76 header = <<CONTEST_OVER
81 header = <<CONTEST_OVER
77 <tr><td colspan="2" align="center">
82 <tr><td colspan="2" align="center">
78 <span class="contest-over-msg">THE CONTEST IS OVER</span>
83 <span class="contest-over-msg">THE CONTEST IS OVER</span>
79 </td></tr>
84 </td></tr>
80 CONTEST_OVER
85 CONTEST_OVER
81 end
86 end
82 - if !user.site.started
87 + if !user.contest_started?
83 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
88 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
84 else
89 else
85 - if user.site!=nil
86 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
90 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
87 - " #{Time.at(user.site.time_left).gmtime.strftime("%X")}"
91 + " #{format_short_duration(user.contest_time_left)}"
88 - end
89 end
92 end
90 end
93 end
91
94
92 #
95 #
93 # if the contest is in the anaysis mode
96 # if the contest is in the anaysis mode
94 - if Configuration[SYSTEM_MODE_CONF_KEY]=='analysis'
97 + if Configuration.analysis_mode?
95 header = <<ANALYSISMODE
98 header = <<ANALYSISMODE
96 <tr><td colspan="2" align="center">
99 <tr><td colspan="2" align="center">
97 <span class="contest-over-msg">ANALYSIS MODE</span>
100 <span class="contest-over-msg">ANALYSIS MODE</span>
98 </td></tr>
101 </td></tr>
99 ANALYSISMODE
102 ANALYSISMODE
100 end
103 end
101
104
102 contest_name = Configuration['contest.name']
105 contest_name = Configuration['contest.name']
103
106
104 #
107 #
105 # build real title bar
108 # build real title bar
106 <<TITLEBAR
109 <<TITLEBAR
@@ -50,27 +50,26
50 #
50 #
51 def self.show_submitbox_to?(user)
51 def self.show_submitbox_to?(user)
52 mode = get(SYSTEM_MODE_CONF_KEY)
52 mode = get(SYSTEM_MODE_CONF_KEY)
53 return false if mode=='analysis'
53 return false if mode=='analysis'
54 if (mode=='contest')
54 if (mode=='contest')
55 return false if (user.site!=nil) and
55 return false if (user.site!=nil) and
56 ((user.site.started!=true) or (user.site.finished?))
56 ((user.site.started!=true) or (user.site.finished?))
57 end
57 end
58 return true
58 return true
59 end
59 end
60
60
61 def self.show_tasks_to?(user)
61 def self.show_tasks_to?(user)
62 - mode = get(SYSTEM_MODE_CONF_KEY)
62 + if time_limit_mode?
63 - if (mode=='contest')
63 + return false if not user.contest_started?
64 - return false if (user.site!=nil) and (user.site.started!=true)
65 end
64 end
66 return true
65 return true
67 end
66 end
68
67
69 def self.show_grading_result
68 def self.show_grading_result
70 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
69 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
71 end
70 end
72
71
73 def self.allow_test_request(user)
72 def self.allow_test_request(user)
74 mode = get(SYSTEM_MODE_CONF_KEY)
73 mode = get(SYSTEM_MODE_CONF_KEY)
75 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
74 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
76 if (mode=='contest')
75 if (mode=='contest')
@@ -80,28 +79,66
80 end
79 end
81 return false if mode=='analysis'
80 return false if mode=='analysis'
82 return true
81 return true
83 end
82 end
84
83
85 def self.task_grading_info
84 def self.task_grading_info
86 if @@task_grading_info==nil
85 if @@task_grading_info==nil
87 read_grading_info
86 read_grading_info
88 end
87 end
89 return @@task_grading_info
88 return @@task_grading_info
90 end
89 end
91
90
92 - def self.contest_mode
91 + def self.standard_mode?
92 + return get(SYSTEM_MODE_CONF_KEY) == 'standard'
93 + end
94 +
95 + def self.contest_mode?
93 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
96 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
94 end
97 end
95
98
99 + def self.indv_contest_mode?
100 + return get(SYSTEM_MODE_CONF_KEY) == 'indv-contest'
101 + end
102 +
103 + def self.time_limit_mode?
104 + mode = get(SYSTEM_MODE_CONF_KEY)
105 + return ((mode == 'contest') or (mode == 'indv-contest'))
106 + end
107 +
108 + def self.analysis_mode?
109 + return get(SYSTEM_MODE_CONF_KEY) == 'analysis'
110 + end
111 +
112 + def self.contest_time_limit
113 + contest_time_str = Configuration['contest.time_limit']
114 +
115 + if not defined? @@contest_time_str
116 + @@contest_time_str = nil
117 + end
118 +
119 + if @@contest_time_str != contest_time_str
120 + @@contest_time_str = contest_time_str
121 + if tmatch = /(\d+):(\d+)/.match(contest_time_str)
122 + h = tmatch[1].to_i
123 + m = tmatch[2].to_i
124 +
125 + @@contest_time = h.hour + m.minute
126 + else
127 + @@contest_time = nil
128 + end
129 + end
130 + return @@contest_time
131 + end
132 +
96 protected
133 protected
97
134
98 def self.convert_type(val,type)
135 def self.convert_type(val,type)
99 case type
136 case type
100 when 'string'
137 when 'string'
101 return val
138 return val
102
139
103 when 'integer'
140 when 'integer'
104 return val.to_i
141 return val.to_i
105
142
106 when 'boolean'
143 when 'boolean'
107 return (val=='true')
144 return (val=='true')
@@ -1,54 +1,46
1 class Site < ActiveRecord::Base
1 class Site < ActiveRecord::Base
2
2
3 belongs_to :country
3 belongs_to :country
4 has_many :users
4 has_many :users
5
5
6 def clear_start_time_if_not_started
6 def clear_start_time_if_not_started
7 if !self.started
7 if !self.started
8 self.start_time = nil
8 self.start_time = nil
9 end
9 end
10 end
10 end
11
11
12 def time_left
12 def time_left
13 - contest_time = Configuration['contest.time_limit']
13 + contest_time = Configuration.contest_time_limit
14 - if tmatch = /(\d+):(\d+)/.match(contest_time)
15 - h = tmatch[1].to_i
16 - m = tmatch[2].to_i
17
14
18 - contest_time = h.hour + m.minute
15 + return nil if contest_time == nil
19
16
20 return contest_time if !self.started
17 return contest_time if !self.started
21
18
22 current_time = Time.now.gmtime
19 current_time = Time.now.gmtime
23 if self.start_time!=nil
20 if self.start_time!=nil
24 finish_time = self.start_time + contest_time
21 finish_time = self.start_time + contest_time
25 else
22 else
26 finish_time = current_time + contest_time
23 finish_time = current_time + contest_time
27 end
24 end
28
25
29 if current_time > finish_time
26 if current_time > finish_time
30 return current_time - current_time
27 return current_time - current_time
31 else
28 else
32 - finish_time - current_time
29 + return finish_time - current_time
33 - end
34 - else
35 - nil
36 end
30 end
37 end
31 end
38
32
39 def finished?
33 def finished?
40 if !self.started
34 if !self.started
41 return false
35 return false
42 end
36 end
43
37
44 - contest_time = Configuration['contest.time_limit']
38 + contest_time = Configuration.contest_time_limit
45 - if tmatch = /(\d+):(\d+)/.match(contest_time)
39 + if contest_time!=nil
46 - h = tmatch[1].to_i
40 + return Time.now.gmtime > (self.start_time + contest_time)
47 - m = tmatch[2].to_i
48 - return Time.now.gmtime > (self.start_time + h.hour + m.minute)
49 else
41 else
50 false
42 false
51 end
43 end
52 end
44 end
53
45
54 end
46 end
@@ -10,24 +10,26
10 :class_name => "Message",
10 :class_name => "Message",
11 :foreign_key => "sender_id",
11 :foreign_key => "sender_id",
12 :order => 'created_at DESC'
12 :order => 'created_at DESC'
13
13
14 has_many :replied_messages,
14 has_many :replied_messages,
15 :class_name => "Message",
15 :class_name => "Message",
16 :foreign_key => "receiver_id",
16 :foreign_key => "receiver_id",
17 :order => 'created_at DESC'
17 :order => 'created_at DESC'
18
18
19 has_many :test_pair_assignments, :dependent => :delete_all
19 has_many :test_pair_assignments, :dependent => :delete_all
20 has_many :submission_statuses
20 has_many :submission_statuses
21
21
22 + has_one :contest_stat, :class_name => "UserContestStat"
23 +
22 belongs_to :site
24 belongs_to :site
23 belongs_to :country
25 belongs_to :country
24
26
25 named_scope :activated_users, :conditions => {:activated => true}
27 named_scope :activated_users, :conditions => {:activated => true}
26
28
27 validates_presence_of :login
29 validates_presence_of :login
28 validates_uniqueness_of :login
30 validates_uniqueness_of :login
29 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
31 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
30 validates_length_of :login, :within => 3..30
32 validates_length_of :login, :within => 3..30
31
33
32 validates_presence_of :full_name
34 validates_presence_of :full_name
33 validates_length_of :full_name, :minimum => 1
35 validates_length_of :full_name, :minimum => 1
@@ -162,24 +164,72
162 def self.random_password(length=5)
164 def self.random_password(length=5)
163 chars = 'abcdefghjkmnopqrstuvwxyz'
165 chars = 'abcdefghjkmnopqrstuvwxyz'
164 password = ''
166 password = ''
165 length.times { password << chars[rand(chars.length - 1)] }
167 length.times { password << chars[rand(chars.length - 1)] }
166 password
168 password
167 end
169 end
168
170
169 def self.find_non_admin_with_prefix(prefix='')
171 def self.find_non_admin_with_prefix(prefix='')
170 users = User.find(:all)
172 users = User.find(:all)
171 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
173 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
172 end
174 end
173
175
176 + # Contest information
177 +
178 + def contest_time_left
179 + if Configuration.contest_mode?
180 + return nil if site==nil
181 + return site.time_left
182 + elsif Configuration.indv_contest_mode?
183 + time_limit = Configuration.contest_time_limit
184 + if contest_stat==nil
185 + return (Time.now.gmtime + time_limit) - Time.now.gmtime
186 + else
187 + finish_time = contest_stat.started_at + time_limit
188 + current_time = Time.now.gmtime
189 + if current_time > finish_time
190 + return 0
191 + else
192 + return finish_time - current_time
193 + end
194 + end
195 + else
196 + return nil
197 + end
198 + end
199 +
200 + def contest_finished?
201 + if Configuration.contest_mode?
202 + return false if site==nil
203 + return site.finished?
204 + elsif Configuration.indv_contest_mode?
205 + time_limit = Configuration.contest_time_limit
206 +
207 + return false if contest_stat==nil
208 +
209 + return contest_time_left == 0
210 + else
211 + return false
212 + end
213 + end
214 +
215 + def contest_started?
216 + if Configuration.contest_mode?
217 + return true if site==nil
218 + return site.started
219 + else
220 + return true
221 + end
222 + end
223 +
174 protected
224 protected
175 def encrypt_new_password
225 def encrypt_new_password
176 return if password.blank?
226 return if password.blank?
177 self.salt = (10+rand(90)).to_s
227 self.salt = (10+rand(90)).to_s
178 self.hashed_password = User.encrypt(self.password,self.salt)
228 self.hashed_password = User.encrypt(self.password,self.salt)
179 end
229 end
180
230
181 def assign_default_site
231 def assign_default_site
182 # have to catch error when migrating (because self.site is not available).
232 # have to catch error when migrating (because self.site is not available).
183 begin
233 begin
184 if self.site==nil
234 if self.site==nil
185 self.site = Site.find_by_name('default')
235 self.site = Site.find_by_name('default')
@@ -4,26 +4,25
4
4
5 = user_title_bar(@user)
5 = user_title_bar(@user)
6
6
7 - if @announcements.length!=0
7 - if @announcements.length!=0
8 .announcementbox
8 .announcementbox
9 %span{:class => 'title'}
9 %span{:class => 'title'}
10 Announcements
10 Announcements
11 #announcementbox-body
11 #announcementbox-body
12 = render :partial => 'announcement', :collection => @announcements
12 = render :partial => 'announcement', :collection => @announcements
13
13
14 %hr/
14 %hr/
15
15
16 - - if (Configuration.contest_mode) and (@user.site!=nil) |
16 + - if (Configuration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true)
17 - and (@user.site.started!=true)
18 %p=t 'main.start_soon'
17 %p=t 'main.start_soon'
19
18
20 - if Configuration.show_tasks_to?(@user)
19 - if Configuration.show_tasks_to?(@user)
21 .problem-list
20 .problem-list
22 = render :partial => 'problem_title', :collection => @problems, :as => :problem
21 = render :partial => 'problem_title', :collection => @problems, :as => :problem
23 .problem-content
22 .problem-content
24 %span{:id => "problem-panel-filler"}
23 %span{:id => "problem-panel-filler"}
25 %b Welcome to Code Jom
24 %b Welcome to Code Jom
26 %br/
25 %br/
27 Choose problems from the list on the right.
26 Choose problems from the list on the right.
28 = render :partial => 'problem', :collection => @problems
27 = render :partial => 'problem', :collection => @problems
29
28
@@ -1,42 +1,43
1 # This file is auto-generated from the current state of the database. Instead of editing this file,
1 # This file is auto-generated from the current state of the database. Instead of editing this file,
2 # please use the migrations feature of Active Record to incrementally modify your database, and
2 # please use the migrations feature of Active Record to incrementally modify your database, and
3 # then regenerate this schema definition.
3 # then regenerate this schema definition.
4 #
4 #
5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6 # to create the application database on another system, you should be using db:schema:load, not running
6 # to create the application database on another system, you should be using db:schema:load, not running
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 #
9 #
10 # It's strongly recommended to check this file into your version control system.
10 # It's strongly recommended to check this file into your version control system.
11
11
12 - ActiveRecord::Schema.define(:version => 20100123154326) do
12 + ActiveRecord::Schema.define(:version => 20100124054458) do
13
13
14 create_table "announcements", :force => true do |t|
14 create_table "announcements", :force => true do |t|
15 t.string "author"
15 t.string "author"
16 t.text "body"
16 t.text "body"
17 t.boolean "published"
17 t.boolean "published"
18 t.datetime "created_at"
18 t.datetime "created_at"
19 t.datetime "updated_at"
19 t.datetime "updated_at"
20 t.boolean "frontpage", :default => false
20 t.boolean "frontpage", :default => false
21 t.boolean "contest_only", :default => false
21 t.boolean "contest_only", :default => false
22 t.string "title"
22 t.string "title"
23 end
23 end
24
24
25 create_table "configurations", :force => true do |t|
25 create_table "configurations", :force => true do |t|
26 t.string "key"
26 t.string "key"
27 t.string "value_type"
27 t.string "value_type"
28 t.string "value"
28 t.string "value"
29 t.datetime "created_at"
29 t.datetime "created_at"
30 t.datetime "updated_at"
30 t.datetime "updated_at"
31 + t.text "description"
31 end
32 end
32
33
33 create_table "countries", :force => true do |t|
34 create_table "countries", :force => true do |t|
34 t.string "name"
35 t.string "name"
35 t.datetime "created_at"
36 t.datetime "created_at"
36 t.datetime "updated_at"
37 t.datetime "updated_at"
37 end
38 end
38
39
39 create_table "descriptions", :force => true do |t|
40 create_table "descriptions", :force => true do |t|
40 t.text "body"
41 t.text "body"
41 t.boolean "markdowned"
42 t.boolean "markdowned"
42 t.datetime "created_at"
43 t.datetime "created_at"
@@ -197,24 +198,31
197 t.datetime "compiled_at"
198 t.datetime "compiled_at"
198 t.text "compiler_message"
199 t.text "compiler_message"
199 t.datetime "graded_at"
200 t.datetime "graded_at"
200 t.string "grader_comment"
201 t.string "grader_comment"
201 t.datetime "created_at"
202 t.datetime "created_at"
202 t.float "running_time"
203 t.float "running_time"
203 t.string "exit_status"
204 t.string "exit_status"
204 t.integer "memory_usage"
205 t.integer "memory_usage"
205 end
206 end
206
207
207 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
208 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
208
209
210 + create_table "user_contest_stats", :force => true do |t|
211 + t.integer "user_id"
212 + t.datetime "started_at"
213 + t.datetime "created_at"
214 + t.datetime "updated_at"
215 + end
216 +
209 create_table "users", :force => true do |t|
217 create_table "users", :force => true do |t|
210 t.string "login", :limit => 50
218 t.string "login", :limit => 50
211 t.string "full_name"
219 t.string "full_name"
212 t.string "hashed_password"
220 t.string "hashed_password"
213 t.string "salt", :limit => 5
221 t.string "salt", :limit => 5
214 t.string "alias"
222 t.string "alias"
215 t.string "email"
223 t.string "email"
216 t.integer "site_id"
224 t.integer "site_id"
217 t.integer "country_id"
225 t.integer "country_id"
218 t.boolean "activated", :default => false
226 t.boolean "activated", :default => false
219 t.datetime "created_at"
227 t.datetime "created_at"
220 t.datetime "updated_at"
228 t.datetime "updated_at"
You need to be logged in to leave comments. Login now