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

r795:08d968fa05d5 - - 11 files changed: 54 inserted, 17 deleted

@@ -0,0 +1,8
1 + = render partial: 'toggle_button',
2 + locals: {button_id: "#group-enabled-#{@group.id}",button_on: @group.enabled }
3 + :plain
4 + r = $("#group-#{@group.id}");
5 + r.removeClass('success');
6 + r.removeClass('danger');
7 + r.addClass("#{@group.enabled? ? 'success' : 'danger'}");
8 +
@@ -0,0 +1,5
1 + class AddEnabledToGroup < ActiveRecord::Migration[5.2]
2 + def change
3 + add_column :groups, :enabled, :boolean, default: true
4 + end
5 + end
@@ -1,104 +1,110
1 1 class GroupsController < ApplicationController
2 2 before_action :set_group, only: [:show, :edit, :update, :destroy,
3 3 :add_user, :remove_user,:remove_all_user,
4 4 :add_problem, :remove_problem,:remove_all_problem,
5 + :toggle,
5 6 ]
6 7 before_action :admin_authorization
7 8
8 9 # GET /groups
9 10 def index
10 11 @groups = Group.all
11 12 end
12 13
13 14 # GET /groups/1
14 15 def show
15 16 end
16 17
17 18 # GET /groups/new
18 19 def new
19 20 @group = Group.new
20 21 end
21 22
22 23 # GET /groups/1/edit
23 24 def edit
24 25 end
25 26
26 27 # POST /groups
27 28 def create
28 29 @group = Group.new(group_params)
29 30
30 31 if @group.save
31 32 redirect_to @group, notice: 'Group was successfully created.'
32 33 else
33 34 render :new
34 35 end
35 36 end
36 37
37 38 # PATCH/PUT /groups/1
38 39 def update
39 40 if @group.update(group_params)
40 41 redirect_to @group, notice: 'Group was successfully updated.'
41 42 else
42 43 render :edit
43 44 end
44 45 end
45 46
46 47 # DELETE /groups/1
47 48 def destroy
48 49 @group.destroy
49 50 redirect_to groups_url, notice: 'Group was successfully destroyed.'
50 51 end
51 52
53 + def toggle
54 + @group.enabled = @group.enabled? ? false : true
55 + @group.save
56 + end
57 +
52 58 def remove_user
53 59 user = User.find(params[:user_id])
54 60 @group.users.delete(user)
55 61 redirect_to group_path(@group), flash: {success: "User #{user.login} was removed from the group #{@group.name}"}
56 62 end
57 63
58 64 def remove_all_user
59 65 @group.users.clear
60 66 redirect_to group_path(@group), alert: 'All users removed'
61 67 end
62 68
63 69 def remove_all_problem
64 70 @group.problems.clear
65 71 redirect_to group_path(@group), alert: 'All problems removed'
66 72 end
67 73
68 74 def add_user
69 75 user = User.find(params[:user_id])
70 76 begin
71 77 @group.users << user
72 78 redirect_to group_path(@group), flash: { success: "User #{user.login} was add to the group #{@group.name}"}
73 79 rescue => e
74 80 redirect_to group_path(@group), alert: e.message
75 81 end
76 82 end
77 83
78 84 def remove_problem
79 85 problem = Problem.find(params[:problem_id])
80 86 @group.problems.delete(problem)
81 87 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was removed from the group #{@group.name}" }
82 88 end
83 89
84 90 def add_problem
85 91 problem = Problem.find(params[:problem_id])
86 92 begin
87 93 @group.problems << problem
88 94 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was add to the group #{@group.name}" }
89 95 rescue => e
90 96 redirect_to group_path(@group), alert: e.message
91 97 end
92 98 end
93 99
94 100 private
95 101 # Use callbacks to share common setup or constraints between actions.
96 102 def set_group
97 103 @group = Group.find(params[:id])
98 104 end
99 105
100 106 # Only allow a trusted parameter "white list" through.
101 107 def group_params
102 - params.require(:group).permit(:name, :description)
108 + params.require(:group).permit(:name, :description, :enabled)
103 109 end
104 110 end
@@ -143,97 +143,97
143 143 case_num = params[:num].to_i
144 144 out_filename = output_filename(@user.login,
145 145 @submission.problem.name,
146 146 @submission.id,
147 147 case_num)
148 148 if !FileTest.exists?(out_filename)
149 149 flash[:notice] = 'Output not found.'
150 150 redirect_to :action => 'list' and return
151 151 end
152 152
153 153 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
154 154 response.headers['Content-Type'] = "application/force-download"
155 155 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
156 156 response.headers["X-Sendfile"] = out_filename
157 157 response.headers['Content-length'] = File.size(out_filename)
158 158 render :nothing => true
159 159 else
160 160 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
161 161 end
162 162 end
163 163
164 164 def error
165 165 @user = User.find(session[:user_id])
166 166 end
167 167
168 168 # announcement refreshing and hiding methods
169 169
170 170 def announcements
171 171 if params.has_key? 'recent'
172 172 prepare_announcements(params[:recent])
173 173 else
174 174 prepare_announcements
175 175 end
176 176 render(:partial => 'announcement',
177 177 :collection => @announcements,
178 178 :locals => {:announcement_effect => true})
179 179 end
180 180
181 181 def confirm_contest_start
182 182 user = User.find(session[:user_id])
183 183 if request.method == 'POST'
184 184 user.update_start_time
185 185 redirect_to :action => 'list'
186 186 else
187 187 @contests = user.contests
188 188 @user = user
189 189 end
190 190 end
191 -
191 +
192 192 protected
193 193
194 194 def prepare_announcements(recent=nil)
195 195 if GraderConfiguration.show_tasks_to?(@user)
196 196 @announcements = Announcement.published(true)
197 197 else
198 198 @announcements = Announcement.published
199 199 end
200 200 if recent!=nil
201 201 recent_id = recent.to_i
202 202 @announcements = @announcements.find_all { |a| a.id > recent_id }
203 203 end
204 204 end
205 205
206 206 def prepare_list_information
207 207 @user = User.find(session[:user_id])
208 208 if not GraderConfiguration.multicontests?
209 209 @problems = @user.available_problems
210 210 else
211 211 @contest_problems = @user.available_problems_group_by_contests
212 212 @problems = @user.available_problems
213 213 end
214 214 @prob_submissions = {}
215 215 @problems.each do |p|
216 216 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
217 217 if sub!=nil
218 218 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
219 219 else
220 220 @prob_submissions[p.id] = { :count => 0, :submission => nil }
221 221 end
222 222 end
223 223 prepare_announcements
224 224 end
225 225
226 226 def check_viewability
227 227 @user = User.find(session[:user_id])
228 228 if (!GraderConfiguration.show_tasks_to?(@user)) and
229 229 ((action_name=='submission') or (action_name=='submit'))
230 230 redirect_to :action => 'list' and return
231 231 end
232 232 end
233 233
234 234 def prepare_grading_result(submission)
235 235 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
236 236 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
237 237 else
238 238 # guess task info from problem.full_score
239 239 cases = submission.problem.full_score / 10
@@ -68,98 +68,99
68 68 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
69 69 end
70 70 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
71 71
72 72 if GraderConfiguration['system.user_setting_enabled']
73 73 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
74 74 end
75 75 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
76 76
77 77 menu_items.html_safe
78 78 end
79 79
80 80 def append_to(option,label, controller, action)
81 81 option << ' ' if option!=''
82 82 option << link_to_unless_current(label,
83 83 :controller => controller,
84 84 :action => action)
85 85 end
86 86
87 87 def format_short_time(time)
88 88 now = Time.zone.now
89 89 st = ''
90 90 if (time.yday != now.yday) or (time.year != now.year)
91 91 st = time.strftime("%d/%m/%y ")
92 92 end
93 93 st + time.strftime("%X")
94 94 end
95 95
96 96 def format_short_duration(duration)
97 97 return '' if duration==nil
98 98 d = duration.to_f
99 99 return Time.at(d).gmtime.strftime("%X")
100 100 end
101 101
102 102 def format_full_time_ago(time)
103 103 st = time_ago_in_words(time) + ' ago (' + format_short_time(time) + ')'
104 104 end
105 105
106 106 def read_textfile(fname,max_size=2048)
107 107 begin
108 108 File.open(fname).read(max_size)
109 109 rescue
110 110 nil
111 111 end
112 112 end
113 113
114 114 def toggle_button(on,toggle_url,id, option={})
115 115 btn_size = option[:size] || 'btn-xs'
116 + btn_block = option[:block] || 'btn-block'
116 117 link_to (on ? "Yes" : "No"), toggle_url,
117 - {class: "btn btn-block #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
118 + {class: "btn #{btn_block} #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
118 119 id: id,
119 120 data: {remote: true, method: 'get'}}
120 121 end
121 122
122 123 def get_ace_mode(language)
123 124 # return ace mode string from Language
124 125
125 126 case language.pretty_name
126 127 when 'Pascal'
127 128 'ace/mode/pascal'
128 129 when 'C++','C'
129 130 'ace/mode/c_cpp'
130 131 when 'Ruby'
131 132 'ace/mode/ruby'
132 133 when 'Python'
133 134 'ace/mode/python'
134 135 when 'Java'
135 136 'ace/mode/java'
136 137 else
137 138 'ace/mode/c_cpp'
138 139 end
139 140 end
140 141
141 142
142 143 def user_title_bar(user)
143 144 header = ''
144 145 time_left = ''
145 146
146 147 #
147 148 # if the contest is over
148 149 if GraderConfiguration.time_limit_mode?
149 150 if user.contest_finished?
150 151 header = <<CONTEST_OVER
151 152 <tr><td colspan="2" align="center">
152 153 <span class="contest-over-msg">THE CONTEST IS OVER</span>
153 154 </td></tr>
154 155 CONTEST_OVER
155 156 end
156 157 if !user.contest_started?
157 158 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
158 159 else
159 160 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
160 161 " #{format_short_duration(user.contest_time_left)}"
161 162 end
162 163 end
163 164
164 165 #
165 166 # if the contest is in the anaysis mode
@@ -228,119 +228,122
228 228 available_problems.each {|p| pin[p.id] = true}
229 229 end
230 230 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
231 231 contest_problems << {
232 232 :contest => nil,
233 233 :problems => other_avaiable_problems
234 234 }
235 235 return contest_problems
236 236 end
237 237
238 238 def solve_all_available_problems?
239 239 available_problems.each do |p|
240 240 u = self
241 241 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
242 242 return false if !p or !sub or sub.points < p.full_score
243 243 end
244 244 return true
245 245 end
246 246
247 247 #get a list of available problem
248 248 def available_problems
249 249 # first, we check if this is normal mode
250 250 if not GraderConfiguration.multicontests?
251 251
252 252 #if this is a normal mode
253 253 #we show problem based on problem_group, if the config said so
254 254 if GraderConfiguration.use_problem_group?
255 255 return available_problems_in_group
256 256 else
257 257 return Problem.available_problems
258 258 end
259 259 else
260 260 #this is multi contest mode
261 261 contest_problems = []
262 262 pin = {}
263 263 contests.enabled.each do |contest|
264 264 contest.problems.available.each do |problem|
265 265 if not pin.has_key? problem.id
266 266 contest_problems << problem
267 267 end
268 268 pin[problem.id] = true
269 269 end
270 270 end
271 271 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
272 272 return contest_problems + other_avaiable_problems
273 273 end
274 274 end
275 275
276 + # new feature, get list of available problem in all enabled group that the user belongs to
276 277 def available_problems_in_group
277 278 problem = []
278 - self.groups.each do |group|
279 + self.groups.where(enabled: true).each do |group|
279 280 group.problems.where(available: true).each { |p| problem << p }
280 281 end
281 282 problem.uniq!
282 283 if problem
283 284 problem.sort! do |a,b|
284 285 case
285 286 when a.date_added < b.date_added
286 287 1
287 288 when a.date_added > b.date_added
288 289 -1
289 290 else
290 291 a.name <=> b.name
291 292 end
292 293 end
293 294 return problem
294 295 else
295 296 return []
296 297 end
297 298 end
298 299
300 + #check if the user has the right to view that problem
301 + #this also consider group based problem policy
299 302 def can_view_problem?(problem)
300 303 return true if admin?
301 304 return available_problems.include? problem
302 305 end
303 306
304 307 def self.clear_last_login
305 308 User.update_all(:last_ip => nil)
306 309 end
307 310
308 311 protected
309 312 def encrypt_new_password
310 313 return if password.blank?
311 314 self.salt = (10+rand(90)).to_s
312 315 self.hashed_password = User.encrypt(self.password,self.salt)
313 316 end
314 317
315 318 def assign_default_site
316 319 # have to catch error when migrating (because self.site is not available).
317 320 begin
318 321 if self.site==nil
319 322 self.site = Site.find_by_name('default')
320 323 if self.site==nil
321 324 self.site = Site.find(1) # when 'default has be renamed'
322 325 end
323 326 end
324 327 rescue
325 328 end
326 329 end
327 330
328 331 def assign_default_contest
329 332 # have to catch error when migrating (because self.site is not available).
330 333 begin
331 334 if self.contests.length == 0
332 335 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
333 336 if default_contest
334 337 self.contests = [default_contest]
335 338 end
336 339 end
337 340 rescue
338 341 end
339 342 end
340 343
341 344 def password_required?
342 345 self.hashed_password.blank? || !self.password.blank?
343 346 end
344 347
345 348 def self.encrypt(string,salt)
346 349 Digest::SHA1.hexdigest(salt + string)
@@ -1,26 +1,26
1 1
2 2 %tr
3 3 %td{:align => "center"}
4 4 = submission.number
5 5 %td.text-right
6 6 = link_to "##{submission.id}", submission_path(submission.id)
7 7 %td
8 8 = l submission.submitted_at, format: :long
9 9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
10 10 %td
11 11 = submission.source_filename
12 12 = " (#{submission.language.pretty_name}) "
13 - = link_to('[load]',{:action => 'source', :id => submission.id})
13 + = link_to '[load]', download_submission_path(submission)
14 14 %td
15 15 - if submission.graded_at
16 16 = "Graded at #{format_short_time(submission.graded_at)}."
17 17 %br/
18 18 = "Score: #{(submission.points*100/submission.problem.full_score).to_i} " if GraderConfiguration['ui.show_score']
19 19 = " ["
20 20 %tt
21 21 = submission.grader_comment
22 22 = "]"
23 23 %td
24 24 = render :partial => 'compiler_message', :locals => {:compiler_message => submission.compiler_message }
25 25 %td
26 26 = link_to 'Edit', edit_submission_path(submission.id), class: 'btn btn-success'
@@ -1,16 +1,27
1 1 = form_for @group do |f|
2 2 - if @group.errors.any?
3 3 #error_explanation
4 4 %h2= "#{pluralize(@group.errors.count, "error")} prohibited this group from being saved:"
5 5 %ul
6 6 - @group.errors.full_messages.each do |msg|
7 7 %li= msg
8 -
9 - .form-group.field
10 - = f.label :name
11 - = f.text_field :name, class: 'form-control'
12 - .form-group.field
13 - = f.label :description
14 - = f.text_field :description, class: 'form-control'
15 - .form-group.actions
16 - = f.submit 'Save', class: 'btn btn-primary'
8 + .row
9 + .col-md-6
10 + .form-group.field
11 + = f.label :name
12 + = f.text_field :name, class: 'form-control'
13 + .row
14 + .col-md-6
15 + .form-group.field
16 + = f.label :description
17 + = f.text_field :description, class: 'form-control'
18 + .row
19 + .col-md-6
20 + .checkbox
21 + = f.label :enabled do
22 + = f.check_box :enabled
23 + Enabled
24 + .row
25 + .col-md-6
26 + .form-group.actions
27 + = f.submit 'Save', class: 'btn btn-primary'
@@ -1,22 +1,24
1 1 %h1 Groups
2 2
3 3 %p
4 4 = link_to 'New Group', new_group_path, class: 'btn btn-primary'
5 5 %table.table.table-hover
6 6 %thead
7 7 %tr
8 8 %th Name
9 9 %th Description
10 + %th Enabled?
10 11 %th
11 12 %th
12 13
13 14 %tbody
14 15 - @groups.each do |group|
15 - %tr
16 + %tr{:class => "#{(group.enabled?) ? "success" : "danger"}", id: "group-#{group.id}"}
16 17 %td= group.name
17 18 %td= group.description
19 + %td= toggle_button(group.enabled?, toggle_group_path(group), "group-enabled-#{group.id}", size: ' ', block: ' ')
18 20 %td= link_to 'View', group, class: 'btn btn-default'
19 21 %td= link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger'
20 22
21 23 %br
22 24
@@ -9,135 +9,135
9 9
10 10 resources :contests
11 11 resources :sites
12 12 resources :test
13 13
14 14 resources :messages do
15 15 member do
16 16 get 'hide'
17 17 post 'reply'
18 18 end
19 19 collection do
20 20 get 'console'
21 21 get 'list_all'
22 22 end
23 23 end
24 24
25 25 resources :announcements do
26 26 member do
27 27 get 'toggle','toggle_front'
28 28 end
29 29 end
30 30
31 31 resources :problems do
32 32 member do
33 33 get 'toggle'
34 34 get 'toggle_test'
35 35 get 'toggle_view_testcase'
36 36 get 'stat'
37 37 end
38 38 collection do
39 39 get 'turn_all_off'
40 40 get 'turn_all_on'
41 41 get 'import'
42 42 get 'manage'
43 43 get 'quick_create'
44 44 post 'do_manage'
45 45 post 'do_import'
46 46 end
47 47 end
48 48
49 49 resources :groups do
50 50 member do
51 51 post 'add_user', to: 'groups#add_user', as: 'add_user'
52 52 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
53 53 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
54 54 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
55 55 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
56 56 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
57 + get 'toggle'
57 58 end
58 59 collection do
59 60
60 61 end
61 62 end
62 63
63 64 resources :testcases, only: [] do
64 65 member do
65 66 get 'download_input'
66 67 get 'download_sol'
67 68 end
68 69 collection do
69 70 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
70 71 end
71 72 end
72 73
73 74 resources :grader_configuration, controller: 'configurations' do
74 75 collection do
75 76 get 'set_exam_right(/:value)', action: 'set_exam_right', as: 'set_exam_right'
76 77 end
77 78 end
78 79
79 80 resources :users do
80 81 member do
81 82 get 'toggle_activate', 'toggle_enable'
82 83 get 'stat'
83 84 end
84 85 collection do
85 86 get 'profile'
86 87 post 'chg_passwd'
87 88 end
88 89 end
89 90
90 91 resources :submissions do
91 92 member do
92 93 get 'download'
93 94 get 'compiler_msg'
94 95 get 'rejudge'
95 - get 'source'
96 96 end
97 97 collection do
98 98 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
99 99 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
100 100 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
101 101 end
102 102 end
103 103
104 104
105 105 #user admin
106 106 resources :user_admin do
107 107 collection do
108 108 match 'bulk_manage', via: [:get, :post]
109 109 get 'bulk_mail'
110 110 get 'user_stat'
111 111 get 'import'
112 112 get 'new_list'
113 113 get 'admin'
114 114 get 'active'
115 115 get 'mass_mailing'
116 116 get 'revoke_admin'
117 117 post 'grant_admin'
118 118 match 'create_from_list', via: [:get, :post]
119 119 match 'random_all_passwords', via: [:get, :post]
120 120 end
121 121 member do
122 122 get 'clear_last_ip'
123 123 end
124 124 end
125 125
126 126 resources :contest_management, only: [:index] do
127 127 collection do
128 128 get 'user_stat'
129 129 get 'clear_stat'
130 130 get 'clear_all_stat'
131 131 get 'change_contest_mode'
132 132 end
133 133 end
134 134
135 135 #get 'user_admin', to: 'user_admin#index'
136 136 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
137 137 #post 'user_admin', to: 'user_admin#create'
138 138 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
139 139
140 140 #singular resource
141 141 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
142 142 #report
143 143 resource :report, only: [], controller: 'report' do
@@ -1,130 +1,131
1 1 # This file is auto-generated from the current state of the database. Instead
2 2 # of editing this file, please use the migrations feature of Active Record to
3 3 # incrementally modify your database, and then regenerate this schema definition.
4 4 #
5 5 # Note that this schema.rb definition is the authoritative source for your
6 6 # database schema. If you need to create the application database on another
7 7 # system, you should be using db:schema:load, not running all the migrations
8 8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 9 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 10 #
11 11 # It's strongly recommended that you check this file into your version control system.
12 12
13 - ActiveRecord::Schema.define(version: 2018_06_12_102327) do
13 + ActiveRecord::Schema.define(version: 2020_08_13_083020) do
14 14
15 15 create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
16 16 t.string "author"
17 17 t.text "body"
18 18 t.boolean "published"
19 19 t.datetime "created_at"
20 20 t.datetime "updated_at"
21 21 t.boolean "frontpage", default: false
22 22 t.boolean "contest_only", default: false
23 23 t.string "title"
24 24 t.string "notes"
25 25 end
26 26
27 27 create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
28 28 t.string "title"
29 29 t.boolean "enabled"
30 30 t.datetime "created_at"
31 31 t.datetime "updated_at"
32 32 t.string "name"
33 33 end
34 34
35 35 create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
36 36 t.integer "contest_id"
37 37 t.integer "problem_id"
38 38 end
39 39
40 40 create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
41 41 t.integer "contest_id"
42 42 t.integer "user_id"
43 43 end
44 44
45 45 create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
46 46 t.string "name"
47 47 t.datetime "created_at"
48 48 t.datetime "updated_at"
49 49 end
50 50
51 51 create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
52 52 t.text "body"
53 53 t.boolean "markdowned"
54 54 t.datetime "created_at"
55 55 t.datetime "updated_at"
56 56 end
57 57
58 58 create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
59 59 t.string "key"
60 60 t.string "value_type"
61 61 t.string "value"
62 62 t.datetime "created_at"
63 63 t.datetime "updated_at"
64 64 t.text "description"
65 65 end
66 66
67 67 create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
68 68 t.string "host"
69 69 t.integer "pid"
70 70 t.string "mode"
71 71 t.boolean "active"
72 72 t.datetime "created_at"
73 73 t.datetime "updated_at"
74 74 t.integer "task_id"
75 75 t.string "task_type"
76 76 t.boolean "terminated"
77 77 t.index ["host", "pid"], name: "index_grader_processes_on_host_and_pid"
78 78 end
79 79
80 80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
81 81 t.string "name"
82 82 t.string "description"
83 + t.boolean "enabled", default: true
83 84 end
84 85
85 86 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
86 87 t.integer "problem_id", null: false
87 88 t.integer "group_id", null: false
88 89 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
89 90 end
90 91
91 92 create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
92 93 t.integer "group_id", null: false
93 94 t.integer "user_id", null: false
94 95 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
95 96 end
96 97
97 98 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
98 99 t.integer "user_id"
99 100 t.string "ip_address"
100 101 t.datetime "created_at"
101 102 t.datetime "updated_at"
102 103 t.string "status"
103 104 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
104 105 end
105 106
106 107 create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
107 108 t.string "name", limit: 10
108 109 t.string "pretty_name"
109 110 t.string "ext", limit: 10
110 111 t.string "common_ext"
111 112 end
112 113
113 114 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
114 115 t.integer "user_id"
115 116 t.string "ip_address"
116 117 t.datetime "created_at"
117 118 t.datetime "updated_at"
118 119 end
119 120
120 121 create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
121 122 t.integer "sender_id"
122 123 t.integer "receiver_id"
123 124 t.integer "replying_message_id"
124 125 t.text "body"
125 126 t.boolean "replied"
126 127 t.datetime "created_at"
127 128 t.datetime "updated_at"
128 129 end
129 130
130 131 create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
You need to be logged in to leave comments. Login now