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
@@ -59,14 +59,14
59 59 end
60 60
61 61 def verify_time_limit
62 62 return true if session[:user_id]==nil
63 63 user = User.find(session[:user_id], :include => :site)
64 64 return true if user==nil or user.site == nil
65 - if user.site.finished?
66 - flash[:notice] = 'Error: the contest on your site is over.'
65 + if user.contest_finished?
66 + flash[:notice] = 'Error: the contest you are participating is over.'
67 67 redirect_to :back
68 68 return false
69 69 end
70 70 return true
71 71 end
72 72
@@ -6,18 +6,15
6 6 redirect_to :controller => 'main', :action => 'login'
7 7 end
8 8
9 9 def login
10 10 if user = User.authenticate(params[:login], params[:password])
11 11 session[:user_id] = user.id
12 + session[:admin] = user.admin?
13 + UserContestStat.update_user_start_time(user)
12 14 redirect_to :controller => 'main', :action => 'list'
13 - if user.admin?
14 - session[:admin] = true
15 - else
16 - session[:admin] = false
17 - end
18 15 else
19 16 flash[:notice] = 'Wrong password'
20 17 redirect_to :controller => 'main', :action => 'login'
21 18 end
22 19 end
23 20
@@ -1,10 +1,8
1 1 class MainController < ApplicationController
2 2
3 - SYSTEM_MODE_CONF_KEY = 'system.mode'
4 -
5 3 before_filter :authenticate, :except => [:index, :login]
6 4 before_filter :check_viewability, :except => [:index, :login]
7 5
8 6 # COMMENTED OUT: filter in each action instead
9 7 # before_filter :verify_time_limit, :only => [:submit]
10 8
@@ -56,14 +54,13
56 54 if (params['file']) and (params['file']!='')
57 55 @submission.source = params['file'].read
58 56 @submission.source_filename = params['file'].original_filename
59 57 end
60 58 @submission.submitted_at = Time.new.gmtime
61 59
62 - if Configuration[SYSTEM_MODE_CONF_KEY]=='contest' and
63 - user.site!=nil and user.site.finished?
60 + if Configuration.time_limit_mode? and user.contest_finished?
64 61 @submission.errors.add_to_base "The contest is over."
65 62 prepare_list_information
66 63 render :action => 'list' and return
67 64 end
68 65
69 66 if @submission.valid?
@@ -1,10 +1,8
1 1 class TestController < ApplicationController
2 2
3 - SYSTEM_MODE_CONF_KEY = 'system.mode'
4 -
5 3 before_filter :authenticate, :check_viewability
6 4
7 5 #
8 6 # COMMENT OUT: filter in each action instead
9 7 #
10 8 # before_filter :verify_time_limit, :only => [:submit]
@@ -23,14 +21,14
23 21
24 22 if @submitted_test_request.errors.length != 0
25 23 prepare_index_information
26 24 render :action => 'index' and return
27 25 end
28 26
29 - if Configuration[SYSTEM_MODE_CONF_KEY]=='contest'
30 - if @user.site!=nil and @user.site.finished?
27 + if Configuration.time_limit_mode?
28 + if @user.contest_finished?
31 29 @submitted_test_request.errors.add_to_base('Contest is over.')
32 30 prepare_index_information
33 31 render :action => 'index' and return
34 32 end
35 33
36 34 if !Configuration.allow_test_request(@user)
@@ -1,24 +1,23
1 1 # Methods added to this helper will be available to all templates in the application.
2 2 module ApplicationHelper
3 3
4 - SYSTEM_MODE_CONF_KEY = 'system.mode'
5 -
6 4 def user_header
7 5 menu_items = ''
8 6 user = User.find(session[:user_id])
9 7
10 8 if (user!=nil) and (session[:admin])
11 9 # admin menu
12 10 menu_items << "<b>Administrative task:</b> "
13 11 append_to menu_items, '[Announcements]', 'announcements', 'index'
14 12 append_to menu_items, '[Msg console]', 'messages', 'console'
15 - append_to menu_items, '[Problem admin]', 'problems', 'index'
16 - append_to menu_items, '[User admin]', 'user_admin', 'index'
13 + append_to menu_items, '[Problems]', 'problems', 'index'
14 + append_to menu_items, '[Users]', 'user_admin', 'index'
17 15 append_to menu_items, '[Results]', 'user_admin', 'user_stat'
18 16 append_to menu_items, '[Graders]', 'graders', 'list'
17 + append_to menu_items, '[Contests]', 'contests', 'index'
19 18 append_to menu_items, '[Sites]', 'sites', 'index'
20 19 append_to menu_items, '[System config]', 'configurations', 'index'
21 20 menu_items << "<br/>"
22 21 end
23 22
24 23 # main page
@@ -54,12 +53,18
54 53 (time.year != now.year)
55 54 st = time.strftime("%x ")
56 55 end
57 56 st + time.strftime("%X")
58 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 65 def read_textfile(fname,max_size=2048)
61 66 begin
62 67 File.open(fname).read(max_size)
63 68 rescue
64 69 nil
65 70 end
@@ -68,33 +73,31
68 73 def user_title_bar(user)
69 74 header = ''
70 75 time_left = ''
71 76
72 77 #
73 78 # if the contest is over
74 - if Configuration[SYSTEM_MODE_CONF_KEY]=='contest'
75 - if user.site!=nil and user.site.finished?
79 + if Configuration.time_limit_mode?
80 + if user.contest_finished?
76 81 header = <<CONTEST_OVER
77 82 <tr><td colspan="2" align="center">
78 83 <span class="contest-over-msg">THE CONTEST IS OVER</span>
79 84 </td></tr>
80 85 CONTEST_OVER
81 86 end
82 - if !user.site.started
87 + if !user.contest_started?
83 88 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
84 89 else
85 - if user.site!=nil
86 - time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
87 - " #{Time.at(user.site.time_left).gmtime.strftime("%X")}"
88 - end
90 + time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
91 + " #{format_short_duration(user.contest_time_left)}"
89 92 end
90 93 end
91 94
92 95 #
93 96 # if the contest is in the anaysis mode
94 - if Configuration[SYSTEM_MODE_CONF_KEY]=='analysis'
97 + if Configuration.analysis_mode?
95 98 header = <<ANALYSISMODE
96 99 <tr><td colspan="2" align="center">
97 100 <span class="contest-over-msg">ANALYSIS MODE</span>
98 101 </td></tr>
99 102 ANALYSISMODE
100 103 end
@@ -56,15 +56,14
56 56 ((user.site.started!=true) or (user.site.finished?))
57 57 end
58 58 return true
59 59 end
60 60
61 61 def self.show_tasks_to?(user)
62 - mode = get(SYSTEM_MODE_CONF_KEY)
63 - if (mode=='contest')
64 - return false if (user.site!=nil) and (user.site.started!=true)
62 + if time_limit_mode?
63 + return false if not user.contest_started?
65 64 end
66 65 return true
67 66 end
68 67
69 68 def self.show_grading_result
70 69 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
@@ -86,16 +85,54
86 85 if @@task_grading_info==nil
87 86 read_grading_info
88 87 end
89 88 return @@task_grading_info
90 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 96 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
94 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 133 protected
97 134
98 135 def self.convert_type(val,type)
99 136 case type
100 137 when 'string'
101 138 return val
@@ -7,48 +7,40
7 7 if !self.started
8 8 self.start_time = nil
9 9 end
10 10 end
11 11
12 12 def time_left
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
13 + contest_time = Configuration.contest_time_limit
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
23 - if self.start_time!=nil
24 - finish_time = self.start_time + contest_time
25 - else
26 - finish_time = current_time + contest_time
27 - end
19 + current_time = Time.now.gmtime
20 + if self.start_time!=nil
21 + finish_time = self.start_time + contest_time
22 + else
23 + finish_time = current_time + contest_time
24 + end
28 25
29 - if current_time > finish_time
30 - return current_time - current_time
31 - else
32 - finish_time - current_time
33 - end
26 + if current_time > finish_time
27 + return current_time - current_time
34 28 else
35 - nil
29 + return finish_time - current_time
36 30 end
37 31 end
38 32
39 33 def finished?
40 34 if !self.started
41 35 return false
42 36 end
43 37
44 - contest_time = Configuration['contest.time_limit']
45 - if tmatch = /(\d+):(\d+)/.match(contest_time)
46 - h = tmatch[1].to_i
47 - m = tmatch[2].to_i
48 - return Time.now.gmtime > (self.start_time + h.hour + m.minute)
38 + contest_time = Configuration.contest_time_limit
39 + if contest_time!=nil
40 + return Time.now.gmtime > (self.start_time + contest_time)
49 41 else
50 42 false
51 43 end
52 44 end
53 45
54 46 end
@@ -13,12 +13,14
13 13
14 14 has_many :replied_messages,
15 15 :class_name => "Message",
16 16 :foreign_key => "receiver_id",
17 17 :order => 'created_at DESC'
18 18
19 + has_one :contest_stat, :class_name => "UserContestStat"
20 +
19 21 belongs_to :site
20 22 belongs_to :country
21 23
22 24 named_scope :activated_users, :conditions => {:activated => true}
23 25
24 26 validates_presence_of :login
@@ -115,12 +117,60
115 117
116 118 def self.find_non_admin_with_prefix(prefix='')
117 119 users = User.find(:all)
118 120 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
119 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 171 protected
122 172 def encrypt_new_password
123 173 return if password.blank?
124 174 self.salt = (10+rand(90)).to_s
125 175 self.hashed_password = User.encrypt(self.password,self.salt)
126 176 end
@@ -16,14 +16,13
16 16 = error_messages_for 'submission'
17 17 = render :partial => 'submission_box'
18 18
19 19
20 20 %hr/
21 21
22 - - if (Configuration.contest_mode) and (@user.site!=nil) |
23 - and (@user.site.started!=true)
22 + - if (Configuration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true)
24 23 %p=t 'main.start_soon'
25 24
26 25 - if Configuration.show_tasks_to?(@user)
27 26 %table.info
28 27 %tr.info-head
29 28 %th
@@ -6,13 +6,13
6 6 # to create the application database on another system, you should be using db:schema:load, not running
7 7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 9 #
10 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 14 create_table "announcements", :force => true do |t|
15 15 t.string "author"
16 16 t.text "body"
17 17 t.boolean "published"
18 18 t.datetime "created_at"
@@ -25,12 +25,13
25 25 create_table "configurations", :force => true do |t|
26 26 t.string "key"
27 27 t.string "value_type"
28 28 t.string "value"
29 29 t.datetime "created_at"
30 30 t.datetime "updated_at"
31 + t.text "description"
31 32 end
32 33
33 34 create_table "countries", :force => true do |t|
34 35 t.string "name"
35 36 t.datetime "created_at"
36 37 t.datetime "updated_at"
@@ -126,12 +127,21
126 127 t.datetime "created_at"
127 128 t.datetime "updated_at"
128 129 t.integer "country_id"
129 130 t.string "password"
130 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 142 create_table "submissions", :force => true do |t|
133 143 t.integer "user_id"
134 144 t.integer "problem_id"
135 145 t.integer "language_id"
136 146 t.text "source"
137 147 t.binary "binary"
@@ -152,18 +162,30
152 162 t.integer "submission_id"
153 163 t.datetime "created_at"
154 164 t.integer "status"
155 165 t.datetime "updated_at"
156 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 179 create_table "test_pairs", :force => true do |t|
159 180 t.integer "problem_id"
160 181 t.text "input"
161 182 t.text "solution"
162 183 t.datetime "created_at"
163 184 t.datetime "updated_at"
185 + t.integer "number"
164 186 end
165 187
166 188 create_table "test_requests", :force => true do |t|
167 189 t.integer "user_id"
168 190 t.integer "problem_id"
169 191 t.integer "submission_id"
@@ -182,12 +204,19
182 204 t.string "exit_status"
183 205 t.integer "memory_usage"
184 206 end
185 207
186 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 217 create_table "users", :force => true do |t|
189 218 t.string "login", :limit => 50
190 219 t.string "full_name"
191 220 t.string "hashed_password"
192 221 t.string "salt", :limit => 5
193 222 t.string "alias"
You need to be logged in to leave comments. Login now