Description:
added individual contest mode
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r217:f2fe2340b1dc - - 24 files changed: 299 inserted, 58 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,2
1 + .sass-cache
2 +
@@ -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
@@ -62,8 +62,8
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
@@ -9,12 +9,9
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'
@@ -1,7 +1,5
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
@@ -59,8 +57,7
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
@@ -1,7 +1,5
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 #
@@ -26,8 +24,8
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
@@ -1,8 +1,6
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])
@@ -12,10 +10,11
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/>"
@@ -57,6 +56,12
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)
@@ -71,27 +76,25
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
90 + time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
86 - time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
91 + " #{format_short_duration(user.contest_time_left)}"
87 - " #{Time.at(user.site.time_left).gmtime.strftime("%X")}"
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>
@@ -59,9 +59,8
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
@@ -89,10 +88,48
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)
@@ -10,29 +10,23
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 -
18 - contest_time = h.hour + m.minute
19
14
20 - return contest_time if !self.started
15 + return nil if contest_time == nil
16 +
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
32 - finish_time - current_time
33 - end
34 else
28 else
35 - nil
29 + return finish_time - current_time
36 end
30 end
37 end
31 end
38
32
@@ -41,11 +35,9
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
@@ -16,6 +16,8
16 :foreign_key => "receiver_id",
16 :foreign_key => "receiver_id",
17 :order => 'created_at DESC'
17 :order => 'created_at DESC'
18
18
19 + has_one :contest_stat, :class_name => "UserContestStat"
20 +
19 belongs_to :site
21 belongs_to :site
20 belongs_to :country
22 belongs_to :country
21
23
@@ -118,6 +120,54
118 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
120 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
119 end
121 end
120
122
123 + # Contest information
124 +
125 + def contest_time_left
126 + if Configuration.contest_mode?
127 + return nil if site==nil
128 + return site.time_left
129 + elsif Configuration.indv_contest_mode?
130 + time_limit = Configuration.contest_time_limit
131 + if contest_stat==nil
132 + return (Time.now.gmtime + time_limit) - Time.now.gmtime
133 + else
134 + finish_time = contest_stat.started_at + time_limit
135 + current_time = Time.now.gmtime
136 + if current_time > finish_time
137 + return 0
138 + else
139 + return finish_time - current_time
140 + end
141 + end
142 + else
143 + return nil
144 + end
145 + end
146 +
147 + def contest_finished?
148 + if Configuration.contest_mode?
149 + return false if site==nil
150 + return site.finished?
151 + elsif Configuration.indv_contest_mode?
152 + time_limit = Configuration.contest_time_limit
153 +
154 + return false if contest_stat==nil
155 +
156 + return contest_time_left == 0
157 + else
158 + return false
159 + end
160 + end
161 +
162 + def contest_started?
163 + if Configuration.contest_mode?
164 + return true if site==nil
165 + return site.started
166 + else
167 + return true
168 + end
169 + end
170 +
121 protected
171 protected
122 def encrypt_new_password
172 def encrypt_new_password
123 return if password.blank?
173 return if password.blank?
@@ -19,8 +19,7
19
19
20 %hr/
20 %hr/
21
21
22 - - if (Configuration.contest_mode) and (@user.site!=nil) |
22 + - if (Configuration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true)
23 - and (@user.site.started!=true)
24 %p=t 'main.start_soon'
23 %p=t 'main.start_soon'
25
24
26 - if Configuration.show_tasks_to?(@user)
25 - if Configuration.show_tasks_to?(@user)
@@ -9,7 +9,7
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 => 20100113094740) 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"
@@ -28,6 +28,7
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|
@@ -129,6 +130,15
129 t.string "password"
130 t.string "password"
130 end
131 end
131
132
133 + create_table "submission_statuses", :force => true do |t|
134 + t.integer "user_id"
135 + t.integer "problem_id"
136 + t.boolean "passed"
137 + t.integer "submission_count"
138 + t.datetime "created_at"
139 + t.datetime "updated_at"
140 + end
141 +
132 create_table "submissions", :force => true do |t|
142 create_table "submissions", :force => true do |t|
133 t.integer "user_id"
143 t.integer "user_id"
134 t.integer "problem_id"
144 t.integer "problem_id"
@@ -155,12 +165,24
155 t.datetime "updated_at"
165 t.datetime "updated_at"
156 end
166 end
157
167
168 + create_table "test_pair_assignments", :force => true do |t|
169 + t.integer "user_id"
170 + t.integer "problem_id"
171 + t.integer "test_pair_id"
172 + t.integer "test_pair_number"
173 + t.integer "request_number"
174 + t.datetime "created_at"
175 + t.datetime "updated_at"
176 + t.boolean "submitted"
177 + end
178 +
158 create_table "test_pairs", :force => true do |t|
179 create_table "test_pairs", :force => true do |t|
159 t.integer "problem_id"
180 t.integer "problem_id"
160 t.text "input"
181 t.text "input"
161 t.text "solution"
182 t.text "solution"
162 t.datetime "created_at"
183 t.datetime "created_at"
163 t.datetime "updated_at"
184 t.datetime "updated_at"
185 + t.integer "number"
164 end
186 end
165
187
166 create_table "test_requests", :force => true do |t|
188 create_table "test_requests", :force => true do |t|
@@ -185,6 +207,13
185
207
186 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"
187
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 +
188 create_table "users", :force => true do |t|
217 create_table "users", :force => true do |t|
189 t.string "login", :limit => 50
218 t.string "login", :limit => 50
190 t.string "full_name"
219 t.string "full_name"
You need to be logged in to leave comments. Login now