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

r685:101d67319b73 - - 43 files changed: 526 inserted, 160 deleted

@@ -0,0 +1,86
1 + class GroupsController < ApplicationController
2 + before_action :set_group, only: [:show, :edit, :update, :destroy,
3 + :add_user, :remove_user,
4 + :add_problem, :remove_problem,
5 + ]
6 + before_action :authenticate, :admin_authorization
7 +
8 + # GET /groups
9 + def index
10 + @groups = Group.all
11 + end
12 +
13 + # GET /groups/1
14 + def show
15 + end
16 +
17 + # GET /groups/new
18 + def new
19 + @group = Group.new
20 + end
21 +
22 + # GET /groups/1/edit
23 + def edit
24 + end
25 +
26 + # POST /groups
27 + def create
28 + @group = Group.new(group_params)
29 +
30 + if @group.save
31 + redirect_to @group, notice: 'Group was successfully created.'
32 + else
33 + render :new
34 + end
35 + end
36 +
37 + # PATCH/PUT /groups/1
38 + def update
39 + if @group.update(group_params)
40 + redirect_to @group, notice: 'Group was successfully updated.'
41 + else
42 + render :edit
43 + end
44 + end
45 +
46 + # DELETE /groups/1
47 + def destroy
48 + @group.destroy
49 + redirect_to groups_url, notice: 'Group was successfully destroyed.'
50 + end
51 +
52 + def remove_user
53 + user = User.find(params[:user_id])
54 + @group.users.delete(user)
55 + redirect_to group_path(@group), notice: "User #{user.login} was removed from the group #{@group.name}"
56 + end
57 +
58 + def add_user
59 + user = User.find(params[:user_id])
60 + @group.users << user
61 + redirect_to group_path(@group), notice: "User #{user.login} was add to the group #{@group.name}"
62 + end
63 +
64 + def remove_problem
65 + problem = Problem.find(params[:problem_id])
66 + @group.problems.delete(problem)
67 + redirect_to group_path(@group), notice: "Problem #{problem.name} was removed from the group #{@group.name}"
68 + end
69 +
70 + def add_problem
71 + problem = Problem.find(params[:problem_id])
72 + @group.problems << problem
73 + redirect_to group_path(@group), notice: "Problem #{problem.name} was add to the group #{@group.name}"
74 + end
75 +
76 + private
77 + # Use callbacks to share common setup or constraints between actions.
78 + def set_group
79 + @group = Group.find(params[:id])
80 + end
81 +
82 + # Only allow a trusted parameter "white list" through.
83 + def group_params
84 + params.require(:group).permit(:name, :description)
85 + end
86 + end
@@ -0,0 +1,2
1 + module GroupsHelper
2 + end
@@ -0,0 +1,5
1 + class Group < ActiveRecord::Base
2 + has_and_belongs_to_many :problems
3 + has_and_belongs_to_many :users
4 + end
5 +
@@ -0,0 +1,20
1 + %h1 Editing contest
2 + = form_for(@contest) do |f|
3 + = f.error_messages
4 + %table
5 + %tr
6 + %td= f.label :name
7 + %td= f.text_field :name
8 + %tr
9 + %td= f.label :title
10 + %td= f.text_field :title
11 + %tr
12 + %td
13 + %td
14 + = f.check_box :enabled
15 + = f.label :enabled
16 + %p
17 + = f.submit 'Update'
18 + = link_to 'Show', @contest
19 + |
20 + = link_to 'Back', contests_path
@@ -0,0 +1,27
1 + %h1 Listing contests
2 + .infobox
3 + %b Go back to:
4 + [#{link_to 'contest management', :controller => 'contest_management', :action => 'index'}]
5 + %p= link_to 'New contest', new_contest_path, class: 'btn btn-success'
6 + %table.table.table-striped
7 + %tr
8 + %th Name
9 + %th Title
10 + %th Enabled
11 + %th
12 + %th
13 + %th
14 +
15 + - @contests.each do |contest|
16 + - @contest = contest
17 + %tr
18 + -#%td= in_place_editor_field :contest, :name, {}, :rows => 1
19 + -#%td= in_place_editor_field :contest, :title, {}, :rows => 1
20 + -#%td= in_place_editor_field :contest, :enabled, {}, :rows => 1
21 + %td= best_in_place @contest, :name
22 + %td= best_in_place @contest, :title
23 + %td= best_in_place @contest, :enabled
24 + %td= link_to 'Show', contest
25 + %td= link_to 'Edit', edit_contest_path(contest)
26 + %td= link_to 'Destroy', contest, :confirm => 'Are you sure?', :method => :delete
27 + %br/
@@ -0,0 +1,18
1 + %h1 New contest
2 + = form_for(@contest) do |f|
3 + = f.error_messages
4 + %p
5 + = f.label :name
6 + %br/
7 + = f.text_field :name
8 + %p
9 + = f.label :title
10 + %br/
11 + = f.text_field :title
12 + %p
13 + = f.label :enabled
14 + %br/
15 + = f.check_box :enabled
16 + %p
17 + = f.submit 'Create'
18 + = link_to 'Back', contests_path
@@ -0,0 +1,11
1 + %h1
2 + Contest: #{h @contest.title}
3 + .infobox
4 + %b Go back to:
5 + [#{link_to 'contest management', :controller => 'contest_management', :action => 'index'}]
6 + %p
7 + %b Enabled:
8 + = h @contest.enabled
9 + = link_to 'Edit', edit_contest_path(@contest)
10 + |
11 + = link_to 'Back', contests_path
@@ -0,0 +1,16
1 + = form_for @group do |f|
2 + - if @group.errors.any?
3 + #error_explanation
4 + %h2= "#{pluralize(@group.errors.count, "error")} prohibited this group from being saved:"
5 + %ul
6 + - @group.errors.full_messages.each do |msg|
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'
@@ -0,0 +1,7
1 + %h1 Editing group
2 +
3 + = render 'form'
4 +
5 + = link_to 'Show', @group
6 + \|
7 + = link_to 'Back', groups_path
@@ -0,0 +1,22
1 + %h1 Groups
2 +
3 + %p
4 + = link_to 'New Group', new_group_path, class: 'btn btn-primary'
5 + %table.table.table-hover
6 + %thead
7 + %tr
8 + %th Name
9 + %th Description
10 + %th
11 + %th
12 +
13 + %tbody
14 + - @groups.each do |group|
15 + %tr
16 + %td= group.name
17 + %td= group.description
18 + %td= link_to 'View', group, class: 'btn btn-default'
19 + %td= link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger'
20 +
21 + %br
22 +
@@ -0,0 +1,5
1 + %h1 New group
2 +
3 + = render 'form'
4 +
5 + = link_to 'Back', groups_path
@@ -0,0 +1,72
1 + %p
2 + %b Name:
3 + = @group.name
4 + %p
5 + %b Description:
6 + = @group.description
7 +
8 + %br
9 + = link_to 'Edit', edit_group_path(@group)
10 + \|
11 + = link_to 'Back', groups_path
12 +
13 + .row
14 + %h1 Group details
15 + .row
16 + .col-md-6
17 + .panel.panel-default
18 + .panel-heading
19 + .panel-title Users in this group
20 + .panel-body
21 + =form_tag add_user_group_path(@group), class: 'form-inline' do
22 + .form-group
23 + =label_tag :user_id, "User"
24 + =select_tag :user_id, options_from_collection_for_select(User.all,'id','full_name'), class: 'select2'
25 + =submit_tag "Add",class: 'btn btn-primary'
26 +
27 +
28 + %table.table.table-hover
29 + %thead
30 + %tr
31 + %th Login
32 + %th Full name
33 + %th Remark
34 + %th
35 +
36 + %tbody
37 + - @group.users.each do |user|
38 + %tr
39 + %td= user.login
40 + %td= user.full_name
41 + %td= user.remark
42 + %td= link_to 'Remove', remove_user_group_path(@group,user), :method => :delete, :data => { :confirm => "Remove #{user.full_name}?" }, class: 'btn btn-danger'
43 + .col-md-6
44 + .panel.panel-default
45 + .panel-heading
46 + .panel-title Problems
47 + .panel-body
48 +
49 + =form_tag add_problem_group_path(@group), class: 'form-inline' do
50 + .form-group
51 + =label_tag :problem_id, "Problem"
52 + =select_tag :problem_id, options_from_collection_for_select(Problem.all,'id','full_name'), class: 'select2'
53 + =submit_tag "Add",class: 'btn btn-primary'
54 +
55 +
56 + %table.table.table-hover
57 + %thead
58 + %tr
59 + %th name
60 + %th Full name
61 + %th Full score
62 + %th
63 +
64 + %tbody
65 + - @group.problems.each do |problem|
66 + %tr
67 + %td= problem.name
68 + %td= problem.full_name
69 + %td= problem.full_score
70 + %td= link_to 'Remove', remove_problem_group_path(@group,problem), :method => :delete, :data => { :confirm => "Remove #{problem.full_name}?" }, class: 'btn btn-danger'
71 +
72 +
@@ -0,0 +1,31
1 + = error_messages_for 'user'
2 + / [form:user]
3 + .form-group
4 + %label.col-md-2.control-label{for: :login} Login
5 + .col-md-4
6 + = text_field 'user', 'login', class: 'form-control'
7 + .form-group
8 + %label.col-md-2.control-label{for: :full_name} Full name
9 + .col-md-4
10 + = text_field 'user', 'full_name', class: 'form-control'
11 + .form-group
12 + %label.col-md-2.control-label{for: :password} Password
13 + .col-md-4
14 + = password_field 'user', 'password', class: 'form-control'
15 + .form-group
16 + %label.col-md-2.control-label{for: :password_confirmation} Password (confirm)
17 + .col-md-4
18 + = password_field 'user', 'password_confirmation', class: 'form-control'
19 + .form-group
20 + %label.col-md-2.control-label{for: :email} E-mail
21 + .col-md-4
22 + = email_field 'user', 'email', class: 'form-control'
23 + .form-group
24 + %label.col-md-2.control-label{for: :alias} Alias
25 + .col-md-4
26 + = text_field 'user', 'alias', class: 'form-control'
27 + .form-group
28 + %label.col-md-2.control-label{for: :remark} Remark
29 + .col-md-4
30 + = text_field 'user', 'remark', class: 'form-control'
31 + / [eoform:user]
@@ -0,0 +1,14
1 + %h1 User information
2 + - for column in User.content_columns
3 + %p
4 + %b
5 + = column.human_name
6 + \:
7 + = h @user.send(column.name)
8 + %p
9 + %strong Group
10 + \:
11 + = @user.groups.map{ |x| link_to(x.name,group_path(x)).html_safe}.join(', ').html_safe
12 + = link_to 'Edit', :action => 'edit', :id => @user
13 + |
14 + = link_to 'Back', :action => 'index'
@@ -0,0 +1,30
1 + class CreateGroups < ActiveRecord::Migration
2 +
3 + def change
4 + create_table :groups do |t|
5 + t.string :name
6 + t.string :description
7 + end
8 +
9 + create_join_table :groups, :users do |t|
10 + # t.index [:group_id, :user_id]
11 + t.index [:user_id, :group_id]
12 + end
13 +
14 + create_join_table :problems, :groups do |t|
15 + # t.index [:problem_id, :group_id]
16 + t.index [:group_id, :problem_id]
17 + end
18 +
19 + reversible do |change|
20 + change.up do
21 + GraderConfiguration.where(key: 'system.use_problem_group').first_or_create(value_type: 'boolean', value: 'false',
22 + description: 'If true, available problem to the user will be only ones associated with the group of the user');
23 + end
24 +
25 + change.down do
26 + GraderConfiguration.where(key: 'system.use_problem_group').destroy_all
27 + end
28 + end
29 + end
30 + end
@@ -0,0 +1,49
1 + require 'test_helper'
2 +
3 + class GroupsControllerTest < ActionController::TestCase
4 + setup do
5 + @group = groups(:one)
6 + end
7 +
8 + test "should get index" do
9 + get :index
10 + assert_response :success
11 + assert_not_nil assigns(:groups)
12 + end
13 +
14 + test "should get new" do
15 + get :new
16 + assert_response :success
17 + end
18 +
19 + test "should create group" do
20 + assert_difference('Group.count') do
21 + post :create, group: { description: @group.description, name: @group.name }
22 + end
23 +
24 + assert_redirected_to group_path(assigns(:group))
25 + end
26 +
27 + test "should show group" do
28 + get :show, id: @group
29 + assert_response :success
30 + end
31 +
32 + test "should get edit" do
33 + get :edit, id: @group
34 + assert_response :success
35 + end
36 +
37 + test "should update group" do
38 + patch :update, id: @group, group: { description: @group.description, name: @group.name }
39 + assert_redirected_to group_path(assigns(:group))
40 + end
41 +
42 + test "should destroy group" do
43 + assert_difference('Group.count', -1) do
44 + delete :destroy, id: @group
45 + end
46 +
47 + assert_redirected_to groups_path
48 + end
49 + end
@@ -18,91 +18,89
18 @current_user ||= User.find(session[:user_id])
18 @current_user ||= User.find(session[:user_id])
19 end
19 end
20
20
21 def admin_authorization
21 def admin_authorization
22 return false unless authenticate
22 return false unless authenticate
23 user = User.includes(:roles).find(session[:user_id])
23 user = User.includes(:roles).find(session[:user_id])
24 unless user.admin?
24 unless user.admin?
25 unauthorized_redirect
25 unauthorized_redirect
26 return false
26 return false
27 end
27 end
28 return true
28 return true
29 end
29 end
30
30
31 def authorization_by_roles(allowed_roles)
31 def authorization_by_roles(allowed_roles)
32 return false unless authenticate
32 return false unless authenticate
33 user = User.find(session[:user_id])
33 user = User.find(session[:user_id])
34 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
34 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
35 unauthorized_redirect
35 unauthorized_redirect
36 return false
36 return false
37 end
37 end
38 end
38 end
39
39
40 def testcase_authorization
40 def testcase_authorization
41 #admin always has privileged
41 #admin always has privileged
42 - puts "haha"
43 if @current_user.admin?
42 if @current_user.admin?
44 return true
43 return true
45 end
44 end
46
45
47 - puts "hehe"
48 - puts GraderConfiguration["right.view_testcase"]
49 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
46 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
50 end
47 end
51
48
52 protected
49 protected
53
50
54 def authenticate
51 def authenticate
55 unless session[:user_id]
52 unless session[:user_id]
56 flash[:notice] = 'You need to login'
53 flash[:notice] = 'You need to login'
57 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
54 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
58 flash[:notice] = 'You need to login but you cannot log in at this time'
55 flash[:notice] = 'You need to login but you cannot log in at this time'
59 end
56 end
60 redirect_to :controller => 'main', :action => 'login'
57 redirect_to :controller => 'main', :action => 'login'
61 return false
58 return false
62 end
59 end
63
60
61 +
64 # check if run in single user mode
62 # check if run in single user mode
65 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
63 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
66 - user = User.find_by_id(session[:user_id])
64 + if @current_user==nil or (not @current_user.admin?)
67 - if user==nil or (not user.admin?)
68 flash[:notice] = 'You cannot log in at this time'
65 flash[:notice] = 'You cannot log in at this time'
69 redirect_to :controller => 'main', :action => 'login'
66 redirect_to :controller => 'main', :action => 'login'
70 return false
67 return false
71 end
68 end
72 - unless user.enabled?
73 - flash[:notice] = 'Your account is disabled'
74 - redirect_to :controller => 'main', :action => 'login'
75 - return false
76 - end
77 return true
69 return true
78 end
70 end
79
71
72 + # check if the user is enabled
73 + unless @current_user.enabled? or @current_user.admin?
74 + flash[:notice] = 'Your account is disabled'
75 + redirect_to :controller => 'main', :action => 'login'
76 + return false
77 + end
78 +
80 if GraderConfiguration.multicontests?
79 if GraderConfiguration.multicontests?
81 - user = User.find(session[:user_id])
80 + return true if @current_user.admin?
82 - return true if user.admin?
83 begin
81 begin
84 - if user.contest_stat(true).forced_logout
82 + if @current_user.contest_stat(true).forced_logout
85 flash[:notice] = 'You have been automatically logged out.'
83 flash[:notice] = 'You have been automatically logged out.'
86 redirect_to :controller => 'main', :action => 'index'
84 redirect_to :controller => 'main', :action => 'index'
87 end
85 end
88 rescue
86 rescue
89 end
87 end
90 end
88 end
91 return true
89 return true
92 end
90 end
93
91
94 def authenticate_by_ip_address
92 def authenticate_by_ip_address
95 #this assume that we have already authenticate normally
93 #this assume that we have already authenticate normally
96 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
94 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
97 user = User.find(session[:user_id])
95 user = User.find(session[:user_id])
98 if (not user.admin? and user.last_ip and user.last_ip != request.remote_ip)
96 if (not user.admin? and user.last_ip and user.last_ip != request.remote_ip)
99 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
97 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
100 redirect_to :controller => 'main', :action => 'login'
98 redirect_to :controller => 'main', :action => 'login'
101 puts "CHEAT: user #{user.login} tried to login from '#{request.remote_ip}' while last ip is '#{user.last_ip}' at #{Time.zone.now}"
99 puts "CHEAT: user #{user.login} tried to login from '#{request.remote_ip}' while last ip is '#{user.last_ip}' at #{Time.zone.now}"
102 return false
100 return false
103 end
101 end
104 unless user.last_ip
102 unless user.last_ip
105 user.last_ip = request.remote_ip
103 user.last_ip = request.remote_ip
106 user.save
104 user.save
107 end
105 end
108 end
106 end
@@ -174,48 +174,53
174 @submissions.find_each do |sub|
174 @submissions.find_each do |sub|
175 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
175 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
176 @histogram[:data][d.to_i] += 1 if d < range
176 @histogram[:data][d.to_i] += 1 if d < range
177 user[sub.user_id] = [user[sub.user_id], ((sub.try(:points) || 0) >= @problem.full_score) ? 1 : 0].max
177 user[sub.user_id] = [user[sub.user_id], ((sub.try(:points) || 0) >= @problem.full_score) ? 1 : 0].max
178 end
178 end
179 @histogram[:summary][:max] = [@histogram[:data].max,1].max
179 @histogram[:summary][:max] = [@histogram[:data].max,1].max
180
180
181 @summary = { attempt: user.count, solve: 0 }
181 @summary = { attempt: user.count, solve: 0 }
182 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
182 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
183 end
183 end
184
184
185 def manage
185 def manage
186 @problems = Problem.order(date_added: :desc)
186 @problems = Problem.order(date_added: :desc)
187 end
187 end
188
188
189 def do_manage
189 def do_manage
190 if params.has_key? 'change_date_added'
190 if params.has_key? 'change_date_added'
191 change_date_added
191 change_date_added
192 elsif params.has_key? 'add_to_contest'
192 elsif params.has_key? 'add_to_contest'
193 add_to_contest
193 add_to_contest
194 elsif params.has_key? 'enable_problem'
194 elsif params.has_key? 'enable_problem'
195 set_available(true)
195 set_available(true)
196 elsif params.has_key? 'disable_problem'
196 elsif params.has_key? 'disable_problem'
197 set_available(false)
197 set_available(false)
198 + elsif params.has_key? 'add_group'
199 + group = Group.find(params[:group_id])
200 + get_problems_from_params.each do |p|
201 + group.problems << p
202 + end
198 end
203 end
199 redirect_to :action => 'manage'
204 redirect_to :action => 'manage'
200 end
205 end
201
206
202 def import
207 def import
203 @allow_test_pair_import = allow_test_pair_import?
208 @allow_test_pair_import = allow_test_pair_import?
204 end
209 end
205
210
206 def do_import
211 def do_import
207 old_problem = Problem.find_by_name(params[:name])
212 old_problem = Problem.find_by_name(params[:name])
208 if !allow_test_pair_import? and params.has_key? :import_to_db
213 if !allow_test_pair_import? and params.has_key? :import_to_db
209 params.delete :import_to_db
214 params.delete :import_to_db
210 end
215 end
211 @problem, import_log = Problem.create_from_import_form_params(params,
216 @problem, import_log = Problem.create_from_import_form_params(params,
212 old_problem)
217 old_problem)
213
218
214 if !@problem.errors.empty?
219 if !@problem.errors.empty?
215 render :action => 'import' and return
220 render :action => 'import' and return
216 end
221 end
217
222
218 if old_problem!=nil
223 if old_problem!=nil
219 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
224 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
220 end
225 end
221 @log = import_log
226 @log = import_log
@@ -207,48 +207,49
207 def import
207 def import
208 if params[:file]==''
208 if params[:file]==''
209 flash[:notice] = 'Error importing no file'
209 flash[:notice] = 'Error importing no file'
210 redirect_to :action => 'index' and return
210 redirect_to :action => 'index' and return
211 end
211 end
212 import_from_file(params[:file])
212 import_from_file(params[:file])
213 end
213 end
214
214
215 def random_all_passwords
215 def random_all_passwords
216 users = User.all
216 users = User.all
217 @prefix = params[:prefix] || ''
217 @prefix = params[:prefix] || ''
218 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
218 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
219 @changed = false
219 @changed = false
220 if request.request_method == 'POST'
220 if request.request_method == 'POST'
221 @non_admin_users.each do |user|
221 @non_admin_users.each do |user|
222 password = random_password
222 password = random_password
223 user.password = password
223 user.password = password
224 user.password_confirmation = password
224 user.password_confirmation = password
225 user.save
225 user.save
226 end
226 end
227 @changed = true
227 @changed = true
228 end
228 end
229 end
229 end
230
230
231 +
231 # contest management
232 # contest management
232
233
233 def contests
234 def contests
234 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
235 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
235 @contests = Contest.enabled
236 @contests = Contest.enabled
236 end
237 end
237
238
238 def assign_from_list
239 def assign_from_list
239 contest_id = params[:users_contest_id]
240 contest_id = params[:users_contest_id]
240 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
241 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
241 contest = Contest.find(params[:new_contest][:id])
242 contest = Contest.find(params[:new_contest][:id])
242 if !contest
243 if !contest
243 flash[:notice] = 'Error: no contest'
244 flash[:notice] = 'Error: no contest'
244 redirect_to :action => 'contests', :id =>contest_id
245 redirect_to :action => 'contests', :id =>contest_id
245 end
246 end
246
247
247 note = []
248 note = []
248 users.each do |u|
249 users.each do |u|
249 u.contests = [contest]
250 u.contests = [contest]
250 note << u.login
251 note << u.login
251 end
252 end
252 flash[:notice] = 'User(s) ' + note.join(', ') +
253 flash[:notice] = 'User(s) ' + note.join(', ') +
253 " were successfully reassigned to #{contest.title}."
254 " were successfully reassigned to #{contest.title}."
254 redirect_to :action => 'contests', :id =>contest.id
255 redirect_to :action => 'contests', :id =>contest.id
@@ -402,62 +403,68
402 end
403 end
403 end
404 end
404
405
405 flash[:notice] = 'User(s) ' + note.join(', ') +
406 flash[:notice] = 'User(s) ' + note.join(', ') +
406 ' were successfully modified. '
407 ' were successfully modified. '
407 redirect_to :action => 'mass_mailing'
408 redirect_to :action => 'mass_mailing'
408 end
409 end
409
410
410 #bulk manage
411 #bulk manage
411 def bulk_manage
412 def bulk_manage
412
413
413 begin
414 begin
414 @users = User.where('login REGEXP ?',params[:regex]) if params[:regex]
415 @users = User.where('login REGEXP ?',params[:regex]) if params[:regex]
415 @users.count if @users #i don't know why I have to call count, but if I won't exception is not raised
416 @users.count if @users #i don't know why I have to call count, but if I won't exception is not raised
416 rescue Exception
417 rescue Exception
417 flash[:error] = 'Regular Expression is malformed'
418 flash[:error] = 'Regular Expression is malformed'
418 @users = nil
419 @users = nil
419 end
420 end
420
421
421 if params[:commit]
422 if params[:commit]
422 @action = {}
423 @action = {}
423 @action[:set_enable] = params[:enabled]
424 @action[:set_enable] = params[:enabled]
424 @action[:enabled] = params[:enable] == "1"
425 @action[:enabled] = params[:enable] == "1"
425 @action[:gen_password] = params[:gen_password]
426 @action[:gen_password] = params[:gen_password]
427 + @action[:add_group] = params[:add_group]
428 + @action[:group_name] = params[:group_name]
426 end
429 end
427
430
428 if params[:commit] == "Perform"
431 if params[:commit] == "Perform"
429 if @action[:set_enable]
432 if @action[:set_enable]
430 @users.update_all(enabled: @action[:enabled])
433 @users.update_all(enabled: @action[:enabled])
431 end
434 end
432 if @action[:gen_password]
435 if @action[:gen_password]
433 @users.each do |u|
436 @users.each do |u|
434 password = random_password
437 password = random_password
435 u.password = password
438 u.password = password
436 u.password_confirmation = password
439 u.password_confirmation = password
437 u.save
440 u.save
438 end
441 end
439 end
442 end
443 + if @action[:add_group] and @action[:group_name]
444 + @group = Group.find(@action[:group_name])
445 + @users.each { |user| @group.users << user }
446 + end
440 end
447 end
441 end
448 end
442
449
443 protected
450 protected
444
451
445 def random_password(length=5)
452 def random_password(length=5)
446 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
453 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
447 newpass = ""
454 newpass = ""
448 length.times { newpass << chars[rand(chars.size-1)] }
455 length.times { newpass << chars[rand(chars.size-1)] }
449 return newpass
456 return newpass
450 end
457 end
451
458
452 def import_from_file(f)
459 def import_from_file(f)
453 data_hash = YAML.load(f)
460 data_hash = YAML.load(f)
454 @import_log = ""
461 @import_log = ""
455
462
456 country_data = data_hash[:countries]
463 country_data = data_hash[:countries]
457 site_data = data_hash[:sites]
464 site_data = data_hash[:sites]
458 user_data = data_hash[:users]
465 user_data = data_hash[:users]
459
466
460 # import country
467 # import country
461 countries = {}
468 countries = {}
462 country_data.each_pair do |id,country|
469 country_data.each_pair do |id,country|
463 c = Country.find_by_name(country[:name])
470 c = Country.find_by_name(country[:name])
@@ -1,38 +1,39
1 require 'yaml'
1 require 'yaml'
2
2
3 #
3 #
4 # This class also contains various login of the system.
4 # This class also contains various login of the system.
5 #
5 #
6 class GraderConfiguration < ActiveRecord::Base
6 class GraderConfiguration < ActiveRecord::Base
7
7
8 SYSTEM_MODE_CONF_KEY = 'system.mode'
8 SYSTEM_MODE_CONF_KEY = 'system.mode'
9 TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout'
9 TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout'
10 MULTICONTESTS_KEY = 'system.multicontests'
10 MULTICONTESTS_KEY = 'system.multicontests'
11 CONTEST_TIME_LIMIT_KEY = 'contest.time_limit'
11 CONTEST_TIME_LIMIT_KEY = 'contest.time_limit'
12 MULTIPLE_IP_LOGIN_KEY = 'right.multiple_ip_login'
12 MULTIPLE_IP_LOGIN_KEY = 'right.multiple_ip_login'
13 VIEW_TESTCASE = 'right.view_testcase'
13 VIEW_TESTCASE = 'right.view_testcase'
14 SINGLE_USER_KEY = 'system.single_user_mode'
14 SINGLE_USER_KEY = 'system.single_user_mode'
15 + SYSTEM_USE_PROBLEM_GROUP = 'system.use_problem_group'
15
16
16 cattr_accessor :config_cache
17 cattr_accessor :config_cache
17 cattr_accessor :task_grading_info_cache
18 cattr_accessor :task_grading_info_cache
18 cattr_accessor :contest_time_str
19 cattr_accessor :contest_time_str
19 cattr_accessor :contest_time
20 cattr_accessor :contest_time
20
21
21 GraderConfiguration.config_cache = nil
22 GraderConfiguration.config_cache = nil
22 GraderConfiguration.task_grading_info_cache = nil
23 GraderConfiguration.task_grading_info_cache = nil
23
24
24 def self.config_cached?
25 def self.config_cached?
25 (defined? CONFIGURATION_CACHE_ENABLED) and (CONFIGURATION_CACHE_ENABLED)
26 (defined? CONFIGURATION_CACHE_ENABLED) and (CONFIGURATION_CACHE_ENABLED)
26 end
27 end
27
28
28 def self.get(key)
29 def self.get(key)
29 if GraderConfiguration.config_cached?
30 if GraderConfiguration.config_cached?
30 if GraderConfiguration.config_cache == nil
31 if GraderConfiguration.config_cache == nil
31 self.read_config
32 self.read_config
32 end
33 end
33 return GraderConfiguration.config_cache[key]
34 return GraderConfiguration.config_cache[key]
34 else
35 else
35 return GraderConfiguration.read_one_key(key)
36 return GraderConfiguration.read_one_key(key)
36 end
37 end
37 end
38 end
38
39
@@ -98,48 +99,52
98 def self.standard_mode?
99 def self.standard_mode?
99 return get(SYSTEM_MODE_CONF_KEY) == 'standard'
100 return get(SYSTEM_MODE_CONF_KEY) == 'standard'
100 end
101 end
101
102
102 def self.contest_mode?
103 def self.contest_mode?
103 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
104 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
104 end
105 end
105
106
106 def self.indv_contest_mode?
107 def self.indv_contest_mode?
107 return get(SYSTEM_MODE_CONF_KEY) == 'indv-contest'
108 return get(SYSTEM_MODE_CONF_KEY) == 'indv-contest'
108 end
109 end
109
110
110 def self.multicontests?
111 def self.multicontests?
111 return get(MULTICONTESTS_KEY) == true
112 return get(MULTICONTESTS_KEY) == true
112 end
113 end
113
114
114 def self.time_limit_mode?
115 def self.time_limit_mode?
115 mode = get(SYSTEM_MODE_CONF_KEY)
116 mode = get(SYSTEM_MODE_CONF_KEY)
116 return ((mode == 'contest') or (mode == 'indv-contest'))
117 return ((mode == 'contest') or (mode == 'indv-contest'))
117 end
118 end
118
119
119 def self.analysis_mode?
120 def self.analysis_mode?
120 return get(SYSTEM_MODE_CONF_KEY) == 'analysis'
121 return get(SYSTEM_MODE_CONF_KEY) == 'analysis'
121 end
122 end
123 +
124 + def self.use_problem_group?
125 + return get(SYSTEM_USE_PROBLEM_GROUP)
126 + end
122
127
123 def self.contest_time_limit
128 def self.contest_time_limit
124 contest_time_str = GraderConfiguration[CONTEST_TIME_LIMIT_KEY]
129 contest_time_str = GraderConfiguration[CONTEST_TIME_LIMIT_KEY]
125
130
126 if not defined? GraderConfiguration.contest_time_str
131 if not defined? GraderConfiguration.contest_time_str
127 GraderConfiguration.contest_time_str = nil
132 GraderConfiguration.contest_time_str = nil
128 end
133 end
129
134
130 if GraderConfiguration.contest_time_str != contest_time_str
135 if GraderConfiguration.contest_time_str != contest_time_str
131 GraderConfiguration.contest_time_str = contest_time_str
136 GraderConfiguration.contest_time_str = contest_time_str
132 if tmatch = /(\d+):(\d+)/.match(contest_time_str)
137 if tmatch = /(\d+):(\d+)/.match(contest_time_str)
133 h = tmatch[1].to_i
138 h = tmatch[1].to_i
134 m = tmatch[2].to_i
139 m = tmatch[2].to_i
135
140
136 GraderConfiguration.contest_time = h.hour + m.minute
141 GraderConfiguration.contest_time = h.hour + m.minute
137 else
142 else
138 GraderConfiguration.contest_time = nil
143 GraderConfiguration.contest_time = nil
139 end
144 end
140 end
145 end
141 return GraderConfiguration.contest_time
146 return GraderConfiguration.contest_time
142 end
147 end
143
148
144 protected
149 protected
145
150
@@ -1,28 +1,29
1 class Problem < ActiveRecord::Base
1 class Problem < ActiveRecord::Base
2
2
3 belongs_to :description
3 belongs_to :description
4 has_and_belongs_to_many :contests, :uniq => true
4 has_and_belongs_to_many :contests, :uniq => true
5 + has_and_belongs_to_many :groups
5 has_many :test_pairs, :dependent => :delete_all
6 has_many :test_pairs, :dependent => :delete_all
6 has_many :testcases, :dependent => :destroy
7 has_many :testcases, :dependent => :destroy
7
8
8 validates_presence_of :name
9 validates_presence_of :name
9 validates_format_of :name, :with => /\A\w+\z/
10 validates_format_of :name, :with => /\A\w+\z/
10 validates_presence_of :full_name
11 validates_presence_of :full_name
11
12
12 scope :available, -> { where(available: true) }
13 scope :available, -> { where(available: true) }
13
14
14 DEFAULT_TIME_LIMIT = 1
15 DEFAULT_TIME_LIMIT = 1
15 DEFAULT_MEMORY_LIMIT = 32
16 DEFAULT_MEMORY_LIMIT = 32
16
17
17 def self.available_problems
18 def self.available_problems
18 available.order(date_added: :desc).order(:name)
19 available.order(date_added: :desc).order(:name)
19 #Problem.available.all(:order => "date_added DESC, name ASC")
20 #Problem.available.all(:order => "date_added DESC, name ASC")
20 end
21 end
21
22
22 def self.create_from_import_form_params(params, old_problem=nil)
23 def self.create_from_import_form_params(params, old_problem=nil)
23 org_problem = old_problem || Problem.new
24 org_problem = old_problem || Problem.new
24 import_params, problem = Problem.extract_params_and_check(params,
25 import_params, problem = Problem.extract_params_and_check(params,
25 org_problem)
26 org_problem)
26
27
27 if !problem.errors.empty?
28 if !problem.errors.empty?
28 return problem, 'Error importing'
29 return problem, 'Error importing'
@@ -1,33 +1,34
1 require 'digest/sha1'
1 require 'digest/sha1'
2 require 'net/pop'
2 require 'net/pop'
3 require 'net/https'
3 require 'net/https'
4 require 'net/http'
4 require 'net/http'
5 require 'json'
5 require 'json'
6
6
7 class User < ActiveRecord::Base
7 class User < ActiveRecord::Base
8
8
9 has_and_belongs_to_many :roles
9 has_and_belongs_to_many :roles
10 + has_and_belongs_to_many :groups
10
11
11 has_many :test_requests, -> {order(submitted_at: DESC)}
12 has_many :test_requests, -> {order(submitted_at: DESC)}
12
13
13 has_many :messages, -> { order(created_at: DESC) },
14 has_many :messages, -> { order(created_at: DESC) },
14 :class_name => "Message",
15 :class_name => "Message",
15 :foreign_key => "sender_id"
16 :foreign_key => "sender_id"
16
17
17 has_many :replied_messages, -> { order(created_at: DESC) },
18 has_many :replied_messages, -> { order(created_at: DESC) },
18 :class_name => "Message",
19 :class_name => "Message",
19 :foreign_key => "receiver_id"
20 :foreign_key => "receiver_id"
20
21
21 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
22 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
22
23
23 belongs_to :site
24 belongs_to :site
24 belongs_to :country
25 belongs_to :country
25
26
26 has_and_belongs_to_many :contests, -> { order(:name); uniq}
27 has_and_belongs_to_many :contests, -> { order(:name); uniq}
27
28
28 scope :activated_users, -> {where activated: true}
29 scope :activated_users, -> {where activated: true}
29
30
30 validates_presence_of :login
31 validates_presence_of :login
31 validates_uniqueness_of :login
32 validates_uniqueness_of :login
32 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
33 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
33 validates_length_of :login, :within => 3..30
34 validates_length_of :login, :within => 3..30
@@ -269,65 +270,77
269 :contest => contest,
270 :contest => contest,
270 :problems => available_problems
271 :problems => available_problems
271 }
272 }
272 available_problems.each {|p| pin[p.id] = true}
273 available_problems.each {|p| pin[p.id] = true}
273 end
274 end
274 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
275 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
275 contest_problems << {
276 contest_problems << {
276 :contest => nil,
277 :contest => nil,
277 :problems => other_avaiable_problems
278 :problems => other_avaiable_problems
278 }
279 }
279 return contest_problems
280 return contest_problems
280 end
281 end
281
282
282 def solve_all_available_problems?
283 def solve_all_available_problems?
283 available_problems.each do |p|
284 available_problems.each do |p|
284 u = self
285 u = self
285 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
286 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
286 return false if !p or !sub or sub.points < p.full_score
287 return false if !p or !sub or sub.points < p.full_score
287 end
288 end
288 return true
289 return true
289 end
290 end
290
291
291 def available_problems
292 def available_problems
292 if not GraderConfiguration.multicontests?
293 if not GraderConfiguration.multicontests?
293 - return Problem.available_problems
294 + if GraderConfiguration.use_problem_group?
295 + return available_problems_in_group
296 + else
297 + return Problem.available_problems
298 + end
294 else
299 else
295 contest_problems = []
300 contest_problems = []
296 pin = {}
301 pin = {}
297 contests.enabled.each do |contest|
302 contests.enabled.each do |contest|
298 contest.problems.available.each do |problem|
303 contest.problems.available.each do |problem|
299 if not pin.has_key? problem.id
304 if not pin.has_key? problem.id
300 contest_problems << problem
305 contest_problems << problem
301 end
306 end
302 pin[problem.id] = true
307 pin[problem.id] = true
303 end
308 end
304 end
309 end
305 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
310 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
306 return contest_problems + other_avaiable_problems
311 return contest_problems + other_avaiable_problems
307 end
312 end
308 end
313 end
309
314
315 + def available_problems_in_group
316 + problem = []
317 + self.groups.each do |group|
318 + group.problems.where(available: true).each { |p| problem << p }
319 + end
320 + return problem.uniq
321 + end
322 +
310 def can_view_problem?(problem)
323 def can_view_problem?(problem)
311 if not GraderConfiguration.multicontests?
324 if not GraderConfiguration.multicontests?
312 return problem.available
325 return problem.available
313 else
326 else
314 return problem_in_user_contests? problem
327 return problem_in_user_contests? problem
315 end
328 end
316 end
329 end
317
330
318 def self.clear_last_login
331 def self.clear_last_login
319 User.update_all(:last_ip => nil)
332 User.update_all(:last_ip => nil)
320 end
333 end
321
334
322 protected
335 protected
323 def encrypt_new_password
336 def encrypt_new_password
324 return if password.blank?
337 return if password.blank?
325 self.salt = (10+rand(90)).to_s
338 self.salt = (10+rand(90)).to_s
326 self.hashed_password = User.encrypt(self.password,self.salt)
339 self.hashed_password = User.encrypt(self.password,self.salt)
327 end
340 end
328
341
329 def assign_default_site
342 def assign_default_site
330 # have to catch error when migrating (because self.site is not available).
343 # have to catch error when migrating (because self.site is not available).
331 begin
344 begin
332 if self.site==nil
345 if self.site==nil
333 self.site = Site.find_by_name('default')
346 self.site = Site.find_by_name('default')
@@ -26,48 +26,49
26 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
26 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
27 / display MODE button (with countdown in contest mode)
27 / display MODE button (with countdown in contest mode)
28 - if GraderConfiguration.analysis_mode?
28 - if GraderConfiguration.analysis_mode?
29 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
29 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
30 - elsif GraderConfiguration.time_limit_mode?
30 - elsif GraderConfiguration.time_limit_mode?
31 - if @current_user.contest_finished?
31 - if @current_user.contest_finished?
32 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
32 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
33 - elsif !@current_user.contest_started?
33 - elsif !@current_user.contest_started?
34 %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started')
34 %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started')
35 - else
35 - else
36 %div.navbar-btn.btn.btn-primary#countdown asdf
36 %div.navbar-btn.btn.btn-primary#countdown asdf
37 :javascript
37 :javascript
38 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
38 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
39 / admin section
39 / admin section
40 - if (@current_user!=nil) and (session[:admin])
40 - if (@current_user!=nil) and (session[:admin])
41 / management
41 / management
42 %li.dropdown
42 %li.dropdown
43 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
43 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
44 Manage
44 Manage
45 %span.caret
45 %span.caret
46 %ul.dropdown-menu
46 %ul.dropdown-menu
47 = add_menu( 'Announcements', 'announcements', 'index')
47 = add_menu( 'Announcements', 'announcements', 'index')
48 = add_menu( 'Problems', 'problems', 'index')
48 = add_menu( 'Problems', 'problems', 'index')
49 = add_menu( 'Users', 'user_admin', 'index')
49 = add_menu( 'Users', 'user_admin', 'index')
50 + = add_menu( 'User Groups', 'groups', 'index')
50 = add_menu( 'Graders', 'graders', 'list')
51 = add_menu( 'Graders', 'graders', 'list')
51 = add_menu( 'Message ', 'messages', 'console')
52 = add_menu( 'Message ', 'messages', 'console')
52 %li.divider{role: 'separator'}
53 %li.divider{role: 'separator'}
53 = add_menu( 'System config', 'configurations', 'index')
54 = add_menu( 'System config', 'configurations', 'index')
54 %li.divider{role: 'separator'}
55 %li.divider{role: 'separator'}
55 = add_menu( 'Sites', 'sites', 'index')
56 = add_menu( 'Sites', 'sites', 'index')
56 = add_menu( 'Contests', 'contest_management', 'index')
57 = add_menu( 'Contests', 'contest_management', 'index')
57 / report
58 / report
58 %li.dropdown
59 %li.dropdown
59 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
60 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
60 Report
61 Report
61 %span.caret
62 %span.caret
62 %ul.dropdown-menu
63 %ul.dropdown-menu
63 = add_menu( 'Current Score', 'report', 'current_score')
64 = add_menu( 'Current Score', 'report', 'current_score')
64 = add_menu( 'Score Report', 'report', 'max_score')
65 = add_menu( 'Score Report', 'report', 'max_score')
65 = add_menu( 'Report', 'report', 'multiple_login')
66 = add_menu( 'Report', 'report', 'multiple_login')
66 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
67 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
67 =link_to "#{ungraded} backlogs!",
68 =link_to "#{ungraded} backlogs!",
68 grader_list_path,
69 grader_list_path,
69 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
70 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
70
71
71 %ul.nav.navbar-nav.navbar-right
72 %ul.nav.navbar-nav.navbar-right
72 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
73 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
73 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
74 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
@@ -18,68 +18,73
18 if (e.shiftKey) {
18 if (e.shiftKey) {
19 stop = parseInt($(this).attr('id').split('-')[2]);
19 stop = parseInt($(this).attr('id').split('-')[2]);
20 var orig_stop = stop
20 var orig_stop = stop
21 if (typeof start !== 'undefined') {
21 if (typeof start !== 'undefined') {
22 if (start > stop) {
22 if (start > stop) {
23 var tmp = start;
23 var tmp = start;
24 start = stop;
24 start = stop;
25 stop = tmp;
25 stop = tmp;
26 }
26 }
27 shiftclick(start,stop,$(this).is(':checked') )
27 shiftclick(start,stop,$(this).is(':checked') )
28 }
28 }
29 start = orig_stop
29 start = orig_stop
30 } else {
30 } else {
31 start = parseInt($(this).attr('id').split('-')[2]);
31 start = parseInt($(this).attr('id').split('-')[2]);
32 }
32 }
33 });
33 });
34 });
34 });
35
35
36
36
37 %h1 Manage problems
37 %h1 Manage problems
38
38
39 %p= link_to '[Back to problem list]', :action => 'list'
39 %p= link_to '[Back to problem list]', :action => 'list'
40
40
41 = form_tag :action=>'do_manage' do
41 = form_tag :action=>'do_manage' do
42 - .submitbox
42 + .submitbox.panel
43 What do you want to do to the selected problem?
43 What do you want to do to the selected problem?
44 %br/
44 %br/
45 (You can shift-click to select a range of problems)
45 (You can shift-click to select a range of problems)
46 %ul
46 %ul
47 %li
47 %li
48 Change date added to
48 Change date added to
49 = select_date Date.current, :prefix => 'date_added'
49 = select_date Date.current, :prefix => 'date_added'
50 &nbsp;&nbsp;&nbsp;
50 &nbsp;&nbsp;&nbsp;
51 = submit_tag 'Change', :name => 'change_date_added'
51 = submit_tag 'Change', :name => 'change_date_added'
52 %li
52 %li
53 Set available to
53 Set available to
54 = submit_tag 'True', :name => 'enable_problem'
54 = submit_tag 'True', :name => 'enable_problem'
55 = submit_tag 'False', :name => 'disable_problem'
55 = submit_tag 'False', :name => 'disable_problem'
56
56
57 - if GraderConfiguration.multicontests?
57 - if GraderConfiguration.multicontests?
58 %li
58 %li
59 Add to
59 Add to
60 = select("contest","id",Contest.all.collect {|c| [c.title, c.id]})
60 = select("contest","id",Contest.all.collect {|c| [c.title, c.id]})
61 = submit_tag 'Add', :name => 'add_to_contest'
61 = submit_tag 'Add', :name => 'add_to_contest'
62 + %li
63 + Add problems to group
64 + = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2'
65 + = submit_tag 'Add', name: 'add_group'
66 +
62
67
63 - %table
68 + %table.table.table-hover
64 %tr{style: "text-align: left;"}
69 %tr{style: "text-align: left;"}
65 %th= check_box_tag 'select_all'
70 %th= check_box_tag 'select_all'
66 %th Name
71 %th Name
67 %th Full name
72 %th Full name
68 %th Available
73 %th Available
69 %th Date added
74 %th Date added
70 - if GraderConfiguration.multicontests?
75 - if GraderConfiguration.multicontests?
71 %th Contests
76 %th Contests
72
77
73 - num = 0
78 - num = 0
74 - for problem in @problems
79 - for problem in @problems
75 - num += 1
80 - num += 1
76 %tr{:id => "row-prob-#{problem.id}", :name=> "prob-#{problem.id}"}
81 %tr{:id => "row-prob-#{problem.id}", :name=> "prob-#{problem.id}"}
77 %td= check_box_tag "prob-#{problem.id}-#{num}"
82 %td= check_box_tag "prob-#{problem.id}-#{num}"
78 %td= problem.name
83 %td= problem.name
79 %td= problem.full_name
84 %td= problem.full_name
80 %td= problem.available
85 %td= problem.available
81 %td= problem.date_added
86 %td= problem.date_added
82 - if GraderConfiguration.multicontests?
87 - if GraderConfiguration.multicontests?
83 %td
88 %td
84 - problem.contests.each do |contest|
89 - problem.contests.each do |contest|
85 = "(#{contest.name} [#{link_to 'x', :action => 'remove_contest', :id => problem.id, :contest_id => contest.id }])"
90 = "(#{contest.name} [#{link_to 'x', :action => 'remove_contest', :id => problem.id, :contest_id => contest.id }])"
@@ -25,48 +25,57
25 matches every user whose login ends with "21"
25 matches every user whose login ends with "21"
26 .col-md-6
26 .col-md-6
27 .panel.panel-primary
27 .panel.panel-primary
28 .panel-title.panel-heading
28 .panel-title.panel-heading
29 Action
29 Action
30 .panel-body
30 .panel-body
31 .row.form-group
31 .row.form-group
32 .col-md-6
32 .col-md-6
33 %label.checkbox-inline
33 %label.checkbox-inline
34 = check_box_tag "enabled", true, params[:enabled]
34 = check_box_tag "enabled", true, params[:enabled]
35 Change "Enabled" to
35 Change "Enabled" to
36 .col-md-3
36 .col-md-3
37 %label.radio-inline
37 %label.radio-inline
38 = radio_button_tag "enable", 1, params[:enable] == '1', id: 'enable-yes'
38 = radio_button_tag "enable", 1, params[:enable] == '1', id: 'enable-yes'
39 Yes
39 Yes
40 .col-md-3
40 .col-md-3
41 %label.radio-inline
41 %label.radio-inline
42 = radio_button_tag "enable", 0, params[:enable] == '0', id: 'enable-no'
42 = radio_button_tag "enable", 0, params[:enable] == '0', id: 'enable-no'
43 No
43 No
44 .row.form-group
44 .row.form-group
45 .col-md-6
45 .col-md-6
46 %label.checkbox-inline
46 %label.checkbox-inline
47 = check_box_tag "gen_password", true, params[:gen_password]
47 = check_box_tag "gen_password", true, params[:gen_password]
48 Generate new random password
48 Generate new random password
49 + .row.form-group
50 + .col-md-4
51 + %label.checkbox-inline
52 + = check_box_tag "add_group", true, params[:add_group]
53 + Add users to group
54 + %label.col-md-3.control-label.text-right Group name
55 + .col-md-5
56 + = select_tag "group_name", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'form-control select2'
57 +
49
58
50 .row
59 .row
51 .col-md-12
60 .col-md-12
52 = submit_tag "Preview Result", class: 'btn btn-default'
61 = submit_tag "Preview Result", class: 'btn btn-default'
53 - if @users
62 - if @users
54 .row
63 .row
55 .col-md-4
64 .col-md-4
56 - if @action
65 - if @action
57 %h2 Confirmation
66 %h2 Confirmation
58 - if @action[:set_enable]
67 - if @action[:set_enable]
59 .alert.alert-info The following users will be set #{(@action[:enabled] ? 'enable' : 'disable')}.
68 .alert.alert-info The following users will be set #{(@action[:enabled] ? 'enable' : 'disable')}.
60 - if @action[:gen_password]
69 - if @action[:gen_password]
61 .alert.alert-info The password of the following users will be randomly generated.
70 .alert.alert-info The password of the following users will be randomly generated.
62 .row
71 .row
63 .col-md-4
72 .col-md-4
64 = submit_tag "Perform", class: 'btn btn-primary'
73 = submit_tag "Perform", class: 'btn btn-primary'
65 .row
74 .row
66 .col-md-12
75 .col-md-12
67 The pattern matches #{@users.count} following users.
76 The pattern matches #{@users.count} following users.
68 %br
77 %br
69 - @users.each do |user|
78 - @users.each do |user|
70 = user.login
79 = user.login
71 = ' '
80 = ' '
72 = user.full_name
81 = user.full_name
@@ -1,11 +1,13
1 %h1 Editing user
1 %h1 Editing user
2
2
3 - = form_tag :action => 'update', :id => @user do
3 + = form_tag( {:action => 'update', :id => @user}, {class: 'form-horizontal'}) do
4 = error_messages_for 'user'
4 = error_messages_for 'user'
5 = render partial: "form"
5 = render partial: "form"
6 - = submit_tag "Edit"
6 + .form-group
7 + .col-md-offset-2.col-md-4
8 + = submit_tag "Edit", class: 'btn btn-primary'
7
9
8
10
9 = link_to 'Show', :action => 'show', :id => @user
11 = link_to 'Show', :action => 'show', :id => @user
10 |
12 |
11 = link_to 'Back', :action => 'list'
13 = link_to 'Back', :action => 'list'
@@ -8,49 +8,57
8
8
9 resources :contests
9 resources :contests
10
10
11 resources :sites
11 resources :sites
12
12
13 resources :announcements do
13 resources :announcements do
14 member do
14 member do
15 get 'toggle','toggle_front'
15 get 'toggle','toggle_front'
16 end
16 end
17 end
17 end
18
18
19 resources :problems do
19 resources :problems do
20 member do
20 member do
21 get 'toggle'
21 get 'toggle'
22 get 'toggle_test'
22 get 'toggle_test'
23 get 'toggle_view_testcase'
23 get 'toggle_view_testcase'
24 get 'stat'
24 get 'stat'
25 end
25 end
26 collection do
26 collection do
27 get 'turn_all_off'
27 get 'turn_all_off'
28 get 'turn_all_on'
28 get 'turn_all_on'
29 get 'import'
29 get 'import'
30 get 'manage'
30 get 'manage'
31 end
31 end
32 + end
32
33
34 + resources :groups do
35 + member do
36 + post 'add_user', to: 'groups#add_user', as: 'add_user'
37 + delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
38 + post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
39 + delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
40 + end
33 end
41 end
34
42
35 resources :testcases, only: [] do
43 resources :testcases, only: [] do
36 member do
44 member do
37 get 'download_input'
45 get 'download_input'
38 get 'download_sol'
46 get 'download_sol'
39 end
47 end
40 collection do
48 collection do
41 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
49 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
42 end
50 end
43 end
51 end
44
52
45 resources :grader_configuration, controller: 'configurations'
53 resources :grader_configuration, controller: 'configurations'
46
54
47 resources :users do
55 resources :users do
48 member do
56 member do
49 get 'toggle_activate', 'toggle_enable'
57 get 'toggle_activate', 'toggle_enable'
50 get 'stat'
58 get 'stat'
51 end
59 end
52 end
60 end
53
61
54 resources :submissions do
62 resources :submissions do
55 member do
63 member do
56 get 'download'
64 get 'download'
@@ -1,16 +1,16
1 class AddLanguageExt < ActiveRecord::Migration
1 class AddLanguageExt < ActiveRecord::Migration
2 def self.up
2 def self.up
3 add_column :languages, :ext, :string, :limit => 10
3 add_column :languages, :ext, :string, :limit => 10
4
4
5 Language.reset_column_information
5 Language.reset_column_information
6 - langs = Language.find(:all)
6 + langs = Language.all
7 langs.each do |l|
7 langs.each do |l|
8 l.ext = l.name
8 l.ext = l.name
9 l.save
9 l.save
10 end
10 end
11 end
11 end
12
12
13 def self.down
13 def self.down
14 remove_column :languages, :ext
14 remove_column :languages, :ext
15 end
15 end
16 end
16 end
@@ -1,17 +1,17
1 class AddStatusToTasks < ActiveRecord::Migration
1 class AddStatusToTasks < ActiveRecord::Migration
2 def self.up
2 def self.up
3 add_column :tasks, :status, :integer
3 add_column :tasks, :status, :integer
4 add_column :tasks, :updated_at, :datetime
4 add_column :tasks, :updated_at, :datetime
5
5
6 Task.reset_column_information
6 Task.reset_column_information
7 - Task.find(:all).each do |task|
7 + Task.all.each do |task|
8 task.status_complete
8 task.status_complete
9 task.save
9 task.save
10 end
10 end
11 end
11 end
12
12
13 def self.down
13 def self.down
14 remove_column :tasks, :updated_at
14 remove_column :tasks, :updated_at
15 remove_column :tasks, :status
15 remove_column :tasks, :status
16 end
16 end
17 end
17 end
@@ -1,33 +1,32
1 class AddNumberToSubmissions < ActiveRecord::Migration
1 class AddNumberToSubmissions < ActiveRecord::Migration
2 def self.up
2 def self.up
3 add_column :submissions, :number, :integer
3 add_column :submissions, :number, :integer
4
4
5 # add number field for all records
5 # add number field for all records
6 Submission.reset_column_information
6 Submission.reset_column_information
7
7
8 last_user_id = nil
8 last_user_id = nil
9 last_problem_id = nil
9 last_problem_id = nil
10 current_number = 0
10 current_number = 0
11
11
12 - Submission.find(:all,
12 + Submission.order('user_id, problem_id, submitted_at').each do |submission|
13 - :order => 'user_id, problem_id, submitted_at').each do |submission|
14 if submission.user_id==last_user_id and submission.problem_id==last_problem_id
13 if submission.user_id==last_user_id and submission.problem_id==last_problem_id
15 current_number += 1
14 current_number += 1
16 else
15 else
17 current_number = 1
16 current_number = 1
18 end
17 end
19 submission.number = current_number
18 submission.number = current_number
20 submission.save
19 submission.save
21
20
22 last_user_id = submission.user_id
21 last_user_id = submission.user_id
23 last_problem_id = submission.problem_id
22 last_problem_id = submission.problem_id
24 end
23 end
25
24
26 add_index :submissions, [:user_id, :problem_id, :number], :unique => true
25 add_index :submissions, [:user_id, :problem_id, :number], :unique => true
27 end
26 end
28
27
29 def self.down
28 def self.down
30 remove_index :submissions, :column => [:user_id, :problem_id, :number]
29 remove_index :submissions, :column => [:user_id, :problem_id, :number]
31 remove_column :submissions, :number
30 remove_column :submissions, :number
32 end
31 end
33 end
32 end
@@ -1,29 +1,29
1 class AddSiteToUserAndAddDefaultSite < ActiveRecord::Migration
1 class AddSiteToUserAndAddDefaultSite < ActiveRecord::Migration
2 def self.up
2 def self.up
3 default_site = Site.new({:name => 'default',
3 default_site = Site.new({:name => 'default',
4 :started => false})
4 :started => false})
5 default_site.save!
5 default_site.save!
6
6
7 add_column :users, :site_id, :integer
7 add_column :users, :site_id, :integer
8 User.reset_column_information
8 User.reset_column_information
9
9
10 - User.find(:all).each do |user|
10 + User.all.each do |user|
11
11
12 class << user
12 class << user
13 def valid?
13 def valid?
14 true
14 true
15 end
15 end
16 end
16 end
17
17
18 user.site_id = default_site.id
18 user.site_id = default_site.id
19 user.save
19 user.save
20 end
20 end
21 end
21 end
22
22
23 def self.down
23 def self.down
24 remove_column :users, :site_id
24 remove_column :users, :site_id
25
25
26 default_site = Site.find_by_name('default')
26 default_site = Site.find_by_name('default')
27 default_site.destroy if default_site
27 default_site.destroy if default_site
28 end
28 end
29 end
29 end
@@ -1,33 +1,33
1 class RefactorProblemBodyToDescription < ActiveRecord::Migration
1 class RefactorProblemBodyToDescription < ActiveRecord::Migration
2 def self.up
2 def self.up
3 add_column :problems, :description_id, :integer
3 add_column :problems, :description_id, :integer
4 Problem.reset_column_information
4 Problem.reset_column_information
5
5
6 - Problem.find(:all).each do |problem|
6 + Problem.all.each do |problem|
7 if problem.body!=nil
7 if problem.body!=nil
8 description = Description.new
8 description = Description.new
9 description.body = problem.body
9 description.body = problem.body
10 description.markdowned = false
10 description.markdowned = false
11 description.save
11 description.save
12 problem.description_id = description.id
12 problem.description_id = description.id
13 problem.save
13 problem.save
14 end
14 end
15 end
15 end
16
16
17 remove_column :problems, :body
17 remove_column :problems, :body
18 end
18 end
19
19
20 def self.down
20 def self.down
21 add_column :problems, :body, :text
21 add_column :problems, :body, :text
22 Problem.reset_column_information
22 Problem.reset_column_information
23
23
24 - Problem.find(:all).each do |problem|
24 + Problem.all.each do |problem|
25 if problem.description_id != nil
25 if problem.description_id != nil
26 problem.body = Description.find(problem.description_id).body
26 problem.body = Description.find(problem.description_id).body
27 problem.save
27 problem.save
28 end
28 end
29 end
29 end
30
30
31 remove_column :problems, :description_id
31 remove_column :problems, :description_id
32 end
32 end
33 end
33 end
@@ -1,15 +1,15
1 class AddTestAllowedToProblems < ActiveRecord::Migration
1 class AddTestAllowedToProblems < ActiveRecord::Migration
2 def self.up
2 def self.up
3 add_column :problems, :test_allowed, :boolean
3 add_column :problems, :test_allowed, :boolean
4 Problem.reset_column_information
4 Problem.reset_column_information
5
5
6 - Problem.find(:all).each do |problem|
6 + Problem.all.each do |problem|
7 problem.test_allowed = true
7 problem.test_allowed = true
8 problem.save
8 problem.save
9 end
9 end
10 end
10 end
11
11
12 def self.down
12 def self.down
13 remove_column :problems, :test_allowed
13 remove_column :problems, :test_allowed
14 end
14 end
15 end
15 end
@@ -1,25 +1,25
1 class AddActivatedToUsers < ActiveRecord::Migration
1 class AddActivatedToUsers < ActiveRecord::Migration
2 def self.up
2 def self.up
3 add_column :users, :activated, :boolean, :default => 0
3 add_column :users, :activated, :boolean, :default => 0
4
4
5 User.reset_column_information
5 User.reset_column_information
6
6
7 - User.find(:all).each do |user|
7 + User.all.each do |user|
8
8
9 # disable validation
9 # disable validation
10 class <<user
10 class <<user
11 def valid?
11 def valid?
12 return true
12 return true
13 end
13 end
14 end
14 end
15
15
16 user.activated = true
16 user.activated = true
17 user.save
17 user.save
18 end
18 end
19 end
19 end
20
20
21
21
22 def self.down
22 def self.down
23 remove_column :users, :activated
23 remove_column :users, :activated
24 end
24 end
25 end
25 end
@@ -1,23 +1,23
1 class AddCommonExtToLanguages < ActiveRecord::Migration
1 class AddCommonExtToLanguages < ActiveRecord::Migration
2 def self.up
2 def self.up
3 # language.common_ext is a comma-separated list of common file
3 # language.common_ext is a comma-separated list of common file
4 # extensions.
4 # extensions.
5 add_column :languages, :common_ext, :string
5 add_column :languages, :common_ext, :string
6
6
7 # updating table information
7 # updating table information
8 Language.reset_column_information
8 Language.reset_column_information
9 common_ext = {
9 common_ext = {
10 'c' => 'c',
10 'c' => 'c',
11 'cpp' => 'cpp,cc',
11 'cpp' => 'cpp,cc',
12 'pas' => 'pas'
12 'pas' => 'pas'
13 }
13 }
14 - Language.find(:all).each do |lang|
14 + Language.all.each do |lang|
15 lang.common_ext = common_ext[lang.name]
15 lang.common_ext = common_ext[lang.name]
16 lang.save
16 lang.save
17 end
17 end
18 end
18 end
19
19
20 def self.down
20 def self.down
21 remove_column :languages, :common_ext
21 remove_column :languages, :common_ext
22 end
22 end
23 end
23 end
@@ -1,38 +1,38
1 # encoding: UTF-8
1 # encoding: UTF-8
2 # This file is auto-generated from the current state of the database. Instead
2 # This file is auto-generated from the current state of the database. Instead
3 # of editing this file, please use the migrations feature of Active Record to
3 # of editing this file, please use the migrations feature of Active Record to
4 # incrementally modify your database, and then regenerate this schema definition.
4 # incrementally modify your database, and then regenerate this schema definition.
5 #
5 #
6 # Note that this schema.rb definition is the authoritative source for your
6 # Note that this schema.rb definition is the authoritative source for your
7 # database schema. If you need to create the application database on another
7 # database schema. If you need to create the application database on another
8 # system, you should be using db:schema:load, not running all the migrations
8 # system, you should be using db:schema:load, not running all the migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
11 #
11 #
12 # It's strongly recommended that you check this file into your version control system.
12 # It's strongly recommended that you check this file into your version control system.
13
13
14 - ActiveRecord::Schema.define(version: 20170427070345) do
14 + ActiveRecord::Schema.define(version: 20170911091143) do
15
15
16 create_table "announcements", force: :cascade do |t|
16 create_table "announcements", force: :cascade do |t|
17 t.string "author", limit: 255
17 t.string "author", limit: 255
18 t.text "body", limit: 16777215
18 t.text "body", limit: 16777215
19 t.boolean "published"
19 t.boolean "published"
20 t.datetime "created_at", null: false
20 t.datetime "created_at", null: false
21 t.datetime "updated_at", null: false
21 t.datetime "updated_at", null: false
22 t.boolean "frontpage", default: false
22 t.boolean "frontpage", default: false
23 t.boolean "contest_only", default: false
23 t.boolean "contest_only", default: false
24 t.string "title", limit: 255
24 t.string "title", limit: 255
25 t.string "notes", limit: 255
25 t.string "notes", limit: 255
26 end
26 end
27
27
28 create_table "contests", force: :cascade do |t|
28 create_table "contests", force: :cascade do |t|
29 t.string "title", limit: 255
29 t.string "title", limit: 255
30 t.boolean "enabled"
30 t.boolean "enabled"
31 t.datetime "created_at", null: false
31 t.datetime "created_at", null: false
32 t.datetime "updated_at", null: false
32 t.datetime "updated_at", null: false
33 t.string "name", limit: 255
33 t.string "name", limit: 255
34 end
34 end
35
35
36 create_table "contests_problems", id: false, force: :cascade do |t|
36 create_table "contests_problems", id: false, force: :cascade do |t|
37 t.integer "contest_id", limit: 4
37 t.integer "contest_id", limit: 4
38 t.integer "problem_id", limit: 4
38 t.integer "problem_id", limit: 4
@@ -58,48 +58,67
58
58
59 create_table "grader_configurations", force: :cascade do |t|
59 create_table "grader_configurations", force: :cascade do |t|
60 t.string "key", limit: 255
60 t.string "key", limit: 255
61 t.string "value_type", limit: 255
61 t.string "value_type", limit: 255
62 t.string "value", limit: 255
62 t.string "value", limit: 255
63 t.datetime "created_at", null: false
63 t.datetime "created_at", null: false
64 t.datetime "updated_at", null: false
64 t.datetime "updated_at", null: false
65 t.text "description", limit: 16777215
65 t.text "description", limit: 16777215
66 end
66 end
67
67
68 create_table "grader_processes", force: :cascade do |t|
68 create_table "grader_processes", force: :cascade do |t|
69 t.string "host", limit: 255
69 t.string "host", limit: 255
70 t.integer "pid", limit: 4
70 t.integer "pid", limit: 4
71 t.string "mode", limit: 255
71 t.string "mode", limit: 255
72 t.boolean "active"
72 t.boolean "active"
73 t.datetime "created_at", null: false
73 t.datetime "created_at", null: false
74 t.datetime "updated_at", null: false
74 t.datetime "updated_at", null: false
75 t.integer "task_id", limit: 4
75 t.integer "task_id", limit: 4
76 t.string "task_type", limit: 255
76 t.string "task_type", limit: 255
77 t.boolean "terminated"
77 t.boolean "terminated"
78 end
78 end
79
79
80 add_index "grader_processes", ["host", "pid"], name: "index_grader_processes_on_ip_and_pid", using: :btree
80 add_index "grader_processes", ["host", "pid"], name: "index_grader_processes_on_ip_and_pid", using: :btree
81
81
82 + create_table "groups", force: :cascade do |t|
83 + t.string "name", limit: 255
84 + t.string "description", limit: 255
85 + end
86 +
87 + create_table "groups_problems", id: false, force: :cascade do |t|
88 + t.integer "problem_id", limit: 4, null: false
89 + t.integer "group_id", limit: 4, null: false
90 + end
91 +
92 + add_index "groups_problems", ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id", using: :btree
93 +
94 + create_table "groups_users", id: false, force: :cascade do |t|
95 + t.integer "group_id", limit: 4, null: false
96 + t.integer "user_id", limit: 4, null: false
97 + end
98 +
99 + add_index "groups_users", ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id", using: :btree
100 +
82 create_table "heart_beats", force: :cascade do |t|
101 create_table "heart_beats", force: :cascade do |t|
83 t.integer "user_id", limit: 4
102 t.integer "user_id", limit: 4
84 t.string "ip_address", limit: 255
103 t.string "ip_address", limit: 255
85 t.datetime "created_at", null: false
104 t.datetime "created_at", null: false
86 t.datetime "updated_at", null: false
105 t.datetime "updated_at", null: false
87 t.string "status", limit: 255
106 t.string "status", limit: 255
88 end
107 end
89
108
90 add_index "heart_beats", ["updated_at"], name: "index_heart_beats_on_updated_at", using: :btree
109 add_index "heart_beats", ["updated_at"], name: "index_heart_beats_on_updated_at", using: :btree
91
110
92 create_table "languages", force: :cascade do |t|
111 create_table "languages", force: :cascade do |t|
93 t.string "name", limit: 10
112 t.string "name", limit: 10
94 t.string "pretty_name", limit: 255
113 t.string "pretty_name", limit: 255
95 t.string "ext", limit: 10
114 t.string "ext", limit: 10
96 t.string "common_ext", limit: 255
115 t.string "common_ext", limit: 255
97 end
116 end
98
117
99 create_table "logins", force: :cascade do |t|
118 create_table "logins", force: :cascade do |t|
100 t.integer "user_id", limit: 4
119 t.integer "user_id", limit: 4
101 t.string "ip_address", limit: 255
120 t.string "ip_address", limit: 255
102 t.datetime "created_at", null: false
121 t.datetime "created_at", null: false
103 t.datetime "updated_at", null: false
122 t.datetime "updated_at", null: false
104 end
123 end
105
124
@@ -142,49 +142,58
142 # before the contest ends.
142 # before the contest ends.
143 {
143 {
144 :key => 'contest.test_request.early_timeout',
144 :key => 'contest.test_request.early_timeout',
145 :value_type => 'boolean',
145 :value_type => 'boolean',
146 :default_value => 'false'
146 :default_value => 'false'
147 },
147 },
148
148
149 {
149 {
150 :key => 'system.multicontests',
150 :key => 'system.multicontests',
151 :value_type => 'boolean',
151 :value_type => 'boolean',
152 :default_value => 'false'
152 :default_value => 'false'
153 },
153 },
154
154
155 {
155 {
156 :key => 'contest.confirm_indv_contest_start',
156 :key => 'contest.confirm_indv_contest_start',
157 :value_type => 'boolean',
157 :value_type => 'boolean',
158 :default_value => 'false'
158 :default_value => 'false'
159 },
159 },
160
160
161 {
161 {
162 :key => 'contest.default_contest_name',
162 :key => 'contest.default_contest_name',
163 :value_type => 'string',
163 :value_type => 'string',
164 :default_value => 'none',
164 :default_value => 'none',
165 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
165 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
166 - }
166 + },
167 +
168 + {
169 + :key => 'system.use_problem_group',
170 + :value_type => 'boolean',
171 + :default_value => 'false',
172 + :description => "If true, available problem to the user will be only ones associated with the group of the user."
173 + },
174 +
175 +
167
176
168 ]
177 ]
169
178
170
179
171 def create_configuration_key(key,
180 def create_configuration_key(key,
172 value_type,
181 value_type,
173 default_value,
182 default_value,
174 description='')
183 description='')
175 conf = (GraderConfiguration.find_by_key(key) ||
184 conf = (GraderConfiguration.find_by_key(key) ||
176 GraderConfiguration.new(:key => key,
185 GraderConfiguration.new(:key => key,
177 :value_type => value_type,
186 :value_type => value_type,
178 :value => default_value))
187 :value => default_value))
179 conf.description = description
188 conf.description = description
180 conf.save
189 conf.save
181 end
190 end
182
191
183 def seed_config
192 def seed_config
184 CONFIGURATIONS.each do |conf|
193 CONFIGURATIONS.each do |conf|
185 if conf.has_key? :description
194 if conf.has_key? :description
186 desc = conf[:description]
195 desc = conf[:description]
187 else
196 else
188 desc = ''
197 desc = ''
189 end
198 end
190 create_configuration_key(conf[:key],
199 create_configuration_key(conf[:key],
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
You need to be logged in to leave comments. Login now