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

r661:50e8e6077bb9 - - 146 files changed: 1434 inserted, 2343 deleted

@@ -0,0 +1,32
1 + class TestcasesController < ApplicationController
2 + before_action :set_testcase, only: [:download_input,:download_sol]
3 + before_action :testcase_authorization
4 +
5 + def download_input
6 + send_data @testcase.input, type: 'text/plain', filename: "#{@testcase.problem.name}.#{@testcase.num}.in"
7 + end
8 +
9 + def download_sol
10 + send_data @testcase.sol, type: 'text/plain', filename: "#{@testcase.problem.name}.#{@testcase.num}.sol"
11 + end
12 +
13 + def show_problem
14 + @problem = Problem.includes(:testcases).find(params[:problem_id])
15 + unless @current_user.admin? or @problem.view_testcase
16 + flash[:error] = 'You cannot view the testcase of this problem'
17 + redirect_to :controller => 'main', :action => 'list'
18 + end
19 + end
20 +
21 +
22 + private
23 + # Use callbacks to share common setup or constraints between actions.
24 + def set_testcase
25 + @testcase = Testcase.find(params[:id])
26 + end
27 +
28 + # Only allow a trusted parameter "white list" through.
29 + def testcase_params
30 + params[:testcase]
31 + end
32 + end
@@ -0,0 +1,2
1 + module TestcasesHelper
2 + end
@@ -0,0 +1,2
1 + = render partial: 'toggle_button',
2 + locals: {button_id: "#problem-view-testcase-#{@problem.id}",button_on: @problem.view_testcase?}
@@ -0,0 +1,4
1 + :plain
2 + $("#compiler_msg").html("#{j @submission.compiler_message}");
3 + $("#compiler").modal();
4 +
@@ -0,0 +1,2
1 + :plain
2 + $("body").prepend("<div class=\"alert alert-info\"> Submission #{@submission.id}'s task status has been changed to \"#{@task.status_str}\". It will be re-judged soon. </div>")
@@ -0,0 +1,25
1 + %h1 Test cases
2 + %h2= @problem.long_name
3 +
4 + /navbar
5 + %ul.nav.nav-pills{role: :tablist}
6 + - @problem.testcases.each.with_index do |tc,id|
7 + %li{role: :presentation, class: ('active' if id == 0)}
8 + %a{href:"#tc#{tc.id}", role: 'tab', data: {toggle: 'tab'}}= tc.num
9 +
10 + /actual data
11 + .tab-content
12 + - @problem.testcases.each.with_index do |tc,id|
13 + .tab-pane{id: "tc#{tc.id}",class: ('active' if id == 0)}
14 + .row
15 + .col-md-6
16 + %h3 Input
17 + = link_to "Download",download_input_testcase_path(tc),class: 'btn btn-info btn-sm'
18 + .col-md-6
19 + %h3 Output
20 + = link_to "Download",download_sol_testcase_path(tc),class: 'btn btn-info btn-sm'
21 + .row
22 + .col-md-6
23 + %textarea{ rows: 25,readonly: true,style: "width:100%;resize=none;overflow-y: scroll;"}= tc.input
24 + .col-md-6
25 + %textarea{ rows: 25,readonly: true,style: "width:100%;resize=none;overflow-y: scroll;"}= tc.sol
@@ -0,0 +1,77
1 + %h1 Bulk Manage User
2 +
3 + = form_tag bulk_manage_user_admin_path
4 + .row
5 + .col-md-6
6 + .panel.panel-primary
7 + .panel-title.panel-heading
8 + Filter User
9 + .panel-body
10 + Filtering users whose login match the following MySQL regex
11 + .form-group
12 + = label_tag "regex", 'Regex Pattern'
13 + = text_field_tag "regex", params[:regex], class: 'form-control'
14 + %p
15 + Example
16 + %ul
17 + %li
18 + %code root
19 + matches every user whose login contains "root"
20 + %li
21 + %code ^56
22 + matches every user whose login starts with "56"
23 + %li
24 + %code 21$
25 + matches every user whose login ends with "21"
26 + .col-md-6
27 + .panel.panel-primary
28 + .panel-title.panel-heading
29 + Action
30 + .panel-body
31 + .row.form-group
32 + .col-md-6
33 + %label.checkbox-inline
34 + = check_box_tag "enabled", true, params[:enabled]
35 + Change "Enabled" to
36 + .col-md-3
37 + %label.radio-inline
38 + = radio_button_tag "enable", 1, params[:enable] == '1', id: 'enable-yes'
39 + Yes
40 + .col-md-3
41 + %label.radio-inline
42 + = radio_button_tag "enable", 0, params[:enable] == '0', id: 'enable-no'
43 + No
44 + .row.form-group
45 + .col-md-6
46 + %label.checkbox-inline
47 + = check_box_tag "gen_password", true, params[:gen_password]
48 + Generate new random password
49 +
50 + .row
51 + .col-md-12
52 + = submit_tag "Preview Result", class: 'btn btn-default'
53 + - if @users
54 + .row
55 + .col-md-4
56 + - if @action
57 + %h2 Confirmation
58 + - if @action[:set_enable]
59 + .alert.alert-info The following users will be set #{(@action[:enabled] ? 'enable' : 'disable')}.
60 + - if @action[:gen_password]
61 + .alert.alert-info The password of the following users will be randomly generated.
62 + .row
63 + .col-md-4
64 + = submit_tag "Perform", class: 'btn btn-primary'
65 + .row
66 + .col-md-12
67 + The pattern matches #{@users.count} following users.
68 + %br
69 + - @users.each do |user|
70 + = user.login
71 + = ' '
72 + = user.full_name
73 + = ' '
74 + = "(#{user.remark})" if user.remark
75 + %br
76 +
77 +
@@ -0,0 +1,8
1 + development:
2 + secret_key_base: '444f426d08add8e2d7cbd76e2057e521e06091231eb4d5472af6ba5654ea1124ce6a636f549be6827ce09561c314181226ad840d44e4677e1077942ee0dc82bd'
3 +
4 + test:
5 + secret_key_base: 'd52f411b06a79cc9f56d92e10d27e670cf0f0c3357e7caf9018ec23091b5c452ea9266c03a5c9e37b72c358702d4d460e957f90dcc553c9fc73a98adb520e781'
6 +
7 + production:
8 + secret_key_base: '7f85485d3d652fc6336dfe3cd98917d9bd7a323b32096bf7635d26b98ccd0480816cc2d12b5c10805cecf7d8fb322104e2bda71eb60dd871c5c537e56a063038'
@@ -0,0 +1,16
1 + class AddConfigViewTest < ActiveRecord::Migration
2 + def up
3 + GraderConfiguration.create key: 'right.view_testcase', value_type: 'boolean', value:'true', description:'When true, any user can view/download test data'
4 + #uglily and dirtily and shamelessly check other config and inifialize
5 + GraderConfiguration.where(key: 'right.user_hall_of_fame').first_or_create(value_type: 'boolean', value: 'false',
6 + description: 'If true, any user can access hall of fame page.')
7 + GraderConfiguration.where(key: 'right.multiple_ip_login').first_or_create(value_type: 'boolean', value: 'false',
8 + description: 'When change from true to false, a user can login from the first IP they logged into afterward.')
9 + GraderConfiguration.where(key: 'right.user_view_submission').first_or_create(value_type: 'boolean', value: 'false',
10 + description: 'If true, any user can view submissions of every one.')
11 + end
12 +
13 + def down
14 + GraderConfiguration.where(key: 'right.view_testcase').destroy_all;
15 + end
16 + end
@@ -0,0 +1,6
1 + class ChangeTestcaseSize < ActiveRecord::Migration
2 + def change
3 + change_column :testcases, :input, :text, :limit => 4294967295
4 + change_column :testcases, :sol, :text, :limit => 4294967295
5 + end
6 + end
@@ -0,0 +1,5
1 + class AddViewTestcaseToProblem < ActiveRecord::Migration
2 + def change
3 + add_column :problems, :view_testcase, :bool
4 + end
5 + end
@@ -0,0 +1,5
1 + class AddIndexToTask < ActiveRecord::Migration
2 + def change
3 + add_index :tasks, :submission_id
4 + end
5 + end
@@ -0,0 +1,9
1 + class AddHeartBeatFull < ActiveRecord::Migration
2 + def up
3 + GraderConfiguration.create key: 'right.heartbeat_response_full', value_type: 'string', value:'RESTART', description:'Heart beat response text when user got full score (set this value to the empty string to disable this feature)'
4 + end
5 +
6 + def down
7 +
8 + end
9 + end
@@ -0,0 +1,41
1 + # Original from http://snippets.dzone.com/posts/show/4468 by MichaelBoutros
2 + #
3 + # Optimized version which uses to_yaml for content creation and checks
4 + # that models are ActiveRecord::Base models before trying to fetch
5 + # them from database.
6 + namespace :db do
7 + namespace :fixtures do
8 + desc 'Dumps all models into fixtures.'
9 + task :dump => :environment do
10 + puts "rails root = #{Rails.root}"
11 + models = Dir.glob(Rails.root.to_s + '/app/models/**.rb').map do |s|
12 + Pathname.new(s).basename.to_s.gsub(/\.rb$/,'').camelize
13 + end
14 +
15 + puts "Found models: " + models.join(', ')
16 +
17 + models.each do |m|
18 + model = m.constantize
19 + next unless model.ancestors.include?(ActiveRecord::Base)
20 +
21 + puts "Dumping model: " + m
22 + entries = model.all.order(id: :asc)
23 +
24 + increment = 1
25 +
26 + model_file = Rails.root.to_s + '/test/fixtures2/' + m.underscore.pluralize + '.yml'
27 + File.open(model_file, 'w') do |f|
28 + entries.each do |a|
29 + attrs = a.attributes
30 + attrs.delete_if{|k,v| v.blank?}
31 +
32 + output = {m + '_' + increment.to_s => attrs}
33 + f << output.to_yaml.gsub(/^--- \n/,'') + "\n"
34 +
35 + increment += 1
36 + end
37 + end
38 + end
39 + end
40 + end
41 + end
@@ -0,0 +1,50
1 + require 'test_helper'
2 +
3 + class AnnouncementsControllerTest < ActionController::TestCase
4 + setup do
5 + @announcement = announcements(:one)
6 + @request.session[:user_id] = users(:admin).id
7 + end
8 +
9 + test "should get index" do
10 + get :index
11 + assert_response :success
12 + assert_not_nil assigns(:announcements)
13 + end
14 +
15 + test "should get new" do
16 + get :new
17 + assert_response :success
18 + end
19 +
20 + test "should create announcement" do
21 + assert_difference('Announcement.count') do
22 + post :create, announcement: { author: 'aa',body: 'bb', published: true, frontpage: true, title: 'test'}
23 + end
24 +
25 + assert_redirected_to announcement_path(assigns(:announcement))
26 + end
27 +
28 + test "should show announcement" do
29 + get :show, id: @announcement
30 + assert_response :success
31 + end
32 +
33 + test "should get edit" do
34 + get :edit, id: @announcement
35 + assert_response :success
36 + end
37 +
38 + test "should update announcement" do
39 + patch :update, id: @announcement, announcement: { author: 'aa',body: 'bb', published: true, frontpage: true, title: 'test'}
40 + assert_redirected_to announcement_path(assigns(:announcement))
41 + end
42 +
43 + test "should destroy announcement" do
44 + assert_difference('Announcement.count', -1) do
45 + delete :destroy, id: @announcement
46 + end
47 +
48 + assert_redirected_to announcements_path
49 + end
50 + end
@@ -0,0 +1,7
1 + require 'test_helper'
2 +
3 + class TestcasesControllerTest < ActionController::TestCase
4 + setup do
5 + @testcase = testcases(:one)
6 + end
7 + end
@@ -0,0 +1,144
1 + GraderConfiguration_1:
2 + key: system.single_user_mode
3 + value_type: boolean
4 + value: 'false'
5 + description: Only admins can log in to the system when running under single user mode.
6 +
7 + GraderConfiguration_2:
8 + key: ui.front.title
9 + value_type: string
10 + value: Grader
11 +
12 + GraderConfiguration_3:
13 + key: ui.front.welcome_message
14 + value_type: string
15 + value: Welcome!
16 +
17 + GraderConfiguration_4:
18 + key: ui.show_score
19 + value_type: boolean
20 + value: 'true'
21 +
22 + GraderConfiguration_5:
23 + key: contest.time_limit
24 + value_type: string
25 + value: unlimited
26 + description: Time limit in format hh:mm, or "unlimited" for contests with no time
27 + limits. This config is CACHED. Restart the server before the change can take
28 + effect.
29 +
30 + GraderConfiguration_6:
31 + key: system.mode
32 + value_type: string
33 + value: standard
34 + description: Current modes are "standard", "contest", "indv-contest", and "analysis".
35 +
36 +
37 + GraderConfiguration_7:
38 + key: contest.name
39 + value_type: string
40 + value: Grader
41 + description: This name will be shown on the user header bar.
42 +
43 +
44 + GraderConfiguration_8:
45 + key: contest.multisites
46 + value_type: boolean
47 + value: 'false'
48 + description: If the server is in contest mode and this option is true, on the log
49 + in of the admin a menu for site selections is shown.
50 +
51 +
52 + GraderConfiguration_9:
53 + key: right.user_hall_of_fame
54 + value_type: boolean
55 + value: 'false'
56 + description: If true, any user can access hall of fame page.
57 +
58 +
59 + GraderConfiguration_10:
60 + key: right.multiple_ip_login
61 + value_type: boolean
62 + value: 'true'
63 + description: When change from true to false, a user can login from the first IP
64 + they logged into afterward.
65 +
66 +
67 + GraderConfiguration_11:
68 + key: right.user_view_submission
69 + value_type: boolean
70 + value: 'false'
71 + description: If true, any user can view submissions of every one.
72 +
73 +
74 + GraderConfiguration_12:
75 + key: right.bypass_agreement
76 + value_type: boolean
77 + value: 'true'
78 + description: When false, a user must accept usage agreement before login
79 +
80 +
81 + GraderConfiguration_13:
82 + key: right.heartbeat_response
83 + value_type: string
84 + value: OK
85 + description: Heart beat response text
86 +
87 +
88 + GraderConfiguration_14:
89 + key: right.view_testcase
90 + value_type: boolean
91 + value: 'false'
92 + description: When true, any user can view/download test data
93 +
94 +
95 + GraderConfiguration_15:
96 + key: system.online_registration.smtp
97 + value_type: string
98 + value: smtp.somehost.com
99 +
100 +
101 + GraderConfiguration_16:
102 + key: system.online_registration.from
103 + value_type: string
104 + value: your.email@address
105 +
106 +
107 + GraderConfiguration_17:
108 + key: system.admin_email
109 + value_type: string
110 + value: admin@admin.email
111 +
112 +
113 + GraderConfiguration_18:
114 + key: system.user_setting_enabled
115 + value_type: boolean
116 + value: 'true'
117 + description: If this option is true, users can change their settings
118 +
119 +
120 + GraderConfiguration_19:
121 + key: contest.test_request.early_timeout
122 + value_type: boolean
123 + value: 'false'
124 +
125 +
126 + GraderConfiguration_20:
127 + key: system.multicontests
128 + value_type: boolean
129 + value: 'false'
130 +
131 +
132 + GraderConfiguration_21:
133 + key: contest.confirm_indv_contest_start
134 + value_type: boolean
135 + value: 'false'
136 +
137 +
138 + GraderConfiguration_22:
139 + key: contest.default_contest_name
140 + value_type: string
141 + value: none
142 + description: New user will be assigned to this contest automatically, if it exists. Set
143 + to 'none' if there is no default contest.
144 +
@@ -0,0 +1,7
1 + require 'test_helper'
2 +
3 + class AdminTaskTest < ActionDispatch::IntegrationTest
4 + # test "the truth" do
5 + # assert true
6 + # end
7 + end
@@ -0,0 +1,40
1 + require 'test_helper'
2 +
3 + class LoginTest < ActionDispatch::IntegrationTest
4 + # test "the truth" do
5 + # assert true
6 + # end
7 +
8 + test "login with invalid information" do
9 + get root_path
10 + assert_response :success
11 + post login_login_path, login: "root", password: "hahaha"
12 + assert_redirected_to root_path
13 + end
14 +
15 + test "normal user login" do
16 + get root_path
17 + assert_response :success
18 + post login_login_path, {login: "john", password: "hello" }
19 + assert_redirected_to main_list_path
20 + end
21 +
22 + test "normal user login in single_user mode" do
23 + GraderConfiguration.find_by(key: GraderConfiguration::SINGLE_USER_KEY).update_attributes(value: 'true')
24 + GraderConfiguration.reload
25 + get root_path
26 + assert_response :success
27 + post login_login_path, {login: "john", password: "hello" }
28 + follow_redirect!
29 + assert_redirected_to root_path
30 + end
31 +
32 + test "root login in in single_user mode" do
33 + GraderConfiguration.find_by(key: GraderConfiguration::SINGLE_USER_KEY).update_attributes(value: 'true')
34 + GraderConfiguration.reload
35 + get root_path
36 + assert_response :success
37 + post login_login_path, {login: "admin", password: "admin" }
38 + assert_redirected_to main_list_path
39 + end
40 + end
@@ -22,12 +22,14
22 /public/assets
22 /public/assets
23 /public
23 /public
24
24
25 /data
25 /data
26
26
27 #ignore .orig and .swp
27 #ignore .orig and .swp
28 *.orig
28 *.orig
29 *.swp
29 *.swp
30
30
31 #ignore rvm setting file
31 #ignore rvm setting file
32 .ruby-gemset
32 .ruby-gemset
33 .ruby-version
33 .ruby-version
34 +
35 + /config/secrets.yml
@@ -1,80 +1,91
1 source 'https://rubygems.org'
1 source 'https://rubygems.org'
2
2
3 - gem 'rails', '~>3.2'
3 + #rails
4 + gem 'rails', '~>4.2.0'
5 + gem 'activerecord-session_store'
4
6
5 - gem 'select2-rails'
6
7
7 # Bundle edge Rails instead:
8 # Bundle edge Rails instead:
8 # gem 'rails', :git => 'git://github.com/rails/rails.git'
9 # gem 'rails', :git => 'git://github.com/rails/rails.git'
9
10
11 + #---------------- database ---------------------
12 + #the database
10 gem 'mysql2'
13 gem 'mysql2'
14 + #for testing
15 + gem 'sqlite3'
16 + #for dumping database into yaml
17 + gem 'yaml_db'
11
18
12 # Gems used only for assets and not required
19 # Gems used only for assets and not required
13 # in production environments by default.
20 # in production environments by default.
14 - group :assets do
21 + gem 'sass-rails'
15 - gem 'sass-rails', '~> 3.2.6'
22 + gem 'coffee-rails'
16 - gem 'coffee-rails', '~> 3.2.2'
17
23
18 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
24 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
19 # gem 'therubyracer', :platforms => :ruby
25 # gem 'therubyracer', :platforms => :ruby
20
26
21 gem 'uglifier'
27 gem 'uglifier'
22 - end
23
28
24 - gem 'prototype-rails'
29 + gem 'haml'
30 + gem 'haml-rails'
31 + # gem 'prototype-rails'
25
32
26 # To use ActiveModel has_secure_password
33 # To use ActiveModel has_secure_password
27 # gem 'bcrypt-ruby', '~> 3.0.0'
34 # gem 'bcrypt-ruby', '~> 3.0.0'
28
35
29 # To use Jbuilder templates for JSON
36 # To use Jbuilder templates for JSON
30 # gem 'jbuilder'
37 # gem 'jbuilder'
31
38
32 # Use unicorn as the app server
39 # Use unicorn as the app server
33 # gem 'unicorn'
40 # gem 'unicorn'
34
41
35 # Deploy with Capistrano
42 # Deploy with Capistrano
36 # gem 'capistrano'
43 # gem 'capistrano'
37
44
38 # To use debugger
45 # To use debugger
39 # gem 'debugger'
46 # gem 'debugger'
40 #
47 #
41
48
42 #in-place editor
49 #in-place editor
43 gem 'best_in_place', '~> 3.0.1'
50 gem 'best_in_place', '~> 3.0.1'
44
51
45 # jquery addition
52 # jquery addition
46 gem 'jquery-rails'
53 gem 'jquery-rails'
47 - gem 'jquery-ui-sass-rails'
54 + gem 'jquery-ui-rails'
48 gem 'jquery-timepicker-addon-rails'
55 gem 'jquery-timepicker-addon-rails'
49 gem 'jquery-tablesorter'
56 gem 'jquery-tablesorter'
50 gem 'jquery-countdown-rails'
57 gem 'jquery-countdown-rails'
51
58
52 #syntax highlighter
59 #syntax highlighter
53 gem 'rouge'
60 gem 'rouge'
54
61
55 #add bootstrap
62 #add bootstrap
56 gem 'bootstrap-sass', '~> 3.2.0'
63 gem 'bootstrap-sass', '~> 3.2.0'
57 gem 'bootstrap-switch-rails'
64 gem 'bootstrap-switch-rails'
58 gem 'bootstrap-toggle-rails'
65 gem 'bootstrap-toggle-rails'
59 gem 'autoprefixer-rails'
66 gem 'autoprefixer-rails'
60
67
61 #bootstrap sortable
68 #bootstrap sortable
62 gem 'momentjs-rails'
69 gem 'momentjs-rails'
63 gem 'rails_bootstrap_sortable'
70 gem 'rails_bootstrap_sortable'
64
71
72 + #----------- user interface -----------------
73 + #select 2
74 + gem 'select2-rails'
65 #ace editor
75 #ace editor
66 gem 'ace-rails-ap'
76 gem 'ace-rails-ap'
77 + #paginator
78 + gem 'will_paginate', '~> 3.0.7'
67
79
68 - gem 'haml'
69 - gem 'haml-rails'
70 gem 'mail'
80 gem 'mail'
71 gem 'rdiscount'
81 gem 'rdiscount'
72 - gem 'test-unit'
73 - gem 'will_paginate', '~> 3.0.7'
74 gem 'dynamic_form'
82 gem 'dynamic_form'
75 gem 'in_place_editing'
83 gem 'in_place_editing'
76 gem 'verification', :git => 'https://github.com/sikachu/verification.git'
84 gem 'verification', :git => 'https://github.com/sikachu/verification.git'
77
85
78 - group :test, :development do
86 +
79 - gem 'rspec-rails', '~> 2.99.0'
87 + #---------------- testiing -----------------------
80 - end
88 + gem 'minitest-reporters'
89 +
90 + #---------------- for console --------------------
91 + gem 'fuzzy-string-match'
@@ -1,208 +1,235
1 GIT
1 GIT
2 remote: https://github.com/sikachu/verification.git
2 remote: https://github.com/sikachu/verification.git
3 - revision: 76eaf51b13276ecae54bd9cd115832595d2ff56d
3 + revision: ff31697b940d7b0e2ec65f08764215c96104e76d
4 specs:
4 specs:
5 verification (1.0.3)
5 verification (1.0.3)
6 - actionpack (>= 3.0.0, < 5.0)
6 + actionpack (>= 3.0.0, < 5.1)
7 - activesupport (>= 3.0.0, < 5.0)
7 + activesupport (>= 3.0.0, < 5.1)
8
8
9 GEM
9 GEM
10 remote: https://rubygems.org/
10 remote: https://rubygems.org/
11 specs:
11 specs:
12 - ace-rails-ap (4.0.2)
12 + RubyInline (3.12.4)
13 - actionmailer (3.2.22.5)
13 + ZenTest (~> 4.3)
14 - actionpack (= 3.2.22.5)
14 + ZenTest (4.11.1)
15 - mail (~> 2.5.4)
15 + ace-rails-ap (4.1.1)
16 - actionpack (3.2.22.5)
16 + actionmailer (4.2.7.1)
17 - activemodel (= 3.2.22.5)
17 + actionpack (= 4.2.7.1)
18 - activesupport (= 3.2.22.5)
18 + actionview (= 4.2.7.1)
19 - builder (~> 3.0.0)
19 + activejob (= 4.2.7.1)
20 + mail (~> 2.5, >= 2.5.4)
21 + rails-dom-testing (~> 1.0, >= 1.0.5)
22 + actionpack (4.2.7.1)
23 + actionview (= 4.2.7.1)
24 + activesupport (= 4.2.7.1)
25 + rack (~> 1.6)
26 + rack-test (~> 0.6.2)
27 + rails-dom-testing (~> 1.0, >= 1.0.5)
28 + rails-html-sanitizer (~> 1.0, >= 1.0.2)
29 + actionview (4.2.7.1)
30 + activesupport (= 4.2.7.1)
31 + builder (~> 3.1)
20 erubis (~> 2.7.0)
32 erubis (~> 2.7.0)
21 - journey (~> 1.0.4)
33 + rails-dom-testing (~> 1.0, >= 1.0.5)
22 - rack (~> 1.4.5)
34 + rails-html-sanitizer (~> 1.0, >= 1.0.2)
23 - rack-cache (~> 1.2)
35 + activejob (4.2.7.1)
24 - rack-test (~> 0.6.1)
36 + activesupport (= 4.2.7.1)
25 - sprockets (~> 2.2.1)
37 + globalid (>= 0.3.0)
26 - activemodel (3.2.22.5)
38 + activemodel (4.2.7.1)
27 - activesupport (= 3.2.22.5)
39 + activesupport (= 4.2.7.1)
28 - builder (~> 3.0.0)
40 + builder (~> 3.1)
29 - activerecord (3.2.22.5)
41 + activerecord (4.2.7.1)
30 - activemodel (= 3.2.22.5)
42 + activemodel (= 4.2.7.1)
31 - activesupport (= 3.2.22.5)
43 + activesupport (= 4.2.7.1)
32 - arel (~> 3.0.2)
44 + arel (~> 6.0)
33 - tzinfo (~> 0.3.29)
45 + activerecord-session_store (1.0.0)
34 - activeresource (3.2.22.5)
46 + actionpack (>= 4.0, < 5.1)
35 - activemodel (= 3.2.22.5)
47 + activerecord (>= 4.0, < 5.1)
36 - activesupport (= 3.2.22.5)
48 + multi_json (~> 1.11, >= 1.11.2)
37 - activesupport (3.2.22.5)
49 + rack (>= 1.5.2, < 3)
38 - i18n (~> 0.6, >= 0.6.4)
50 + railties (>= 4.0, < 5.1)
39 - multi_json (~> 1.0)
51 + activesupport (4.2.7.1)
40 - arel (3.0.3)
52 + i18n (~> 0.7)
41 - autoprefixer-rails (6.0.3)
53 + json (~> 1.7, >= 1.7.7)
54 + minitest (~> 5.1)
55 + thread_safe (~> 0.3, >= 0.3.4)
56 + tzinfo (~> 1.1)
57 + ansi (1.5.0)
58 + arel (6.0.4)
59 + autoprefixer-rails (6.6.0)
42 execjs
60 execjs
43 - json
44 best_in_place (3.0.3)
61 best_in_place (3.0.3)
45 actionpack (>= 3.2)
62 actionpack (>= 3.2)
46 railties (>= 3.2)
63 railties (>= 3.2)
47 bootstrap-sass (3.2.0.2)
64 bootstrap-sass (3.2.0.2)
48 sass (~> 3.2)
65 sass (~> 3.2)
49 bootstrap-switch-rails (3.3.3)
66 bootstrap-switch-rails (3.3.3)
50 bootstrap-toggle-rails (2.2.1.0)
67 bootstrap-toggle-rails (2.2.1.0)
51 - builder (3.0.4)
68 + builder (3.2.2)
52 - coffee-rails (3.2.2)
69 + coffee-rails (4.2.1)
53 coffee-script (>= 2.2.0)
70 coffee-script (>= 2.2.0)
54 - railties (~> 3.2.0)
71 + railties (>= 4.0.0, < 5.2.x)
55 - coffee-script (2.3.0)
72 + coffee-script (2.4.1)
56 coffee-script-source
73 coffee-script-source
57 execjs
74 execjs
58 - coffee-script-source (1.9.0)
75 + coffee-script-source (1.12.2)
59 - diff-lcs (1.2.5)
76 + concurrent-ruby (1.0.4)
60 dynamic_form (1.1.4)
77 dynamic_form (1.1.4)
61 erubis (2.7.0)
78 erubis (2.7.0)
62 - execjs (2.3.0)
79 + execjs (2.7.0)
63 - haml (4.0.6)
80 + fuzzy-string-match (1.0.0)
81 + RubyInline (>= 3.8.6)
82 + globalid (0.3.7)
83 + activesupport (>= 4.1.0)
84 + haml (4.0.7)
64 tilt
85 tilt
65 - haml-rails (0.4)
86 + haml-rails (0.9.0)
66 - actionpack (>= 3.1, < 4.1)
87 + actionpack (>= 4.0.1)
67 - activesupport (>= 3.1, < 4.1)
88 + activesupport (>= 4.0.1)
68 - haml (>= 3.1, < 4.1)
89 + haml (>= 4.0.6, < 5.0)
69 - railties (>= 3.1, < 4.1)
90 + html2haml (>= 1.0.1)
70 - hike (1.2.3)
91 + railties (>= 4.0.1)
92 + html2haml (2.0.0)
93 + erubis (~> 2.7.0)
94 + haml (~> 4.0.0)
95 + nokogiri (~> 1.6.0)
96 + ruby_parser (~> 3.5)
71 i18n (0.7.0)
97 i18n (0.7.0)
72 in_place_editing (1.2.0)
98 in_place_editing (1.2.0)
73 - journey (1.0.4)
74 jquery-countdown-rails (2.0.2)
99 jquery-countdown-rails (2.0.2)
75 - jquery-rails (3.1.2)
100 + jquery-rails (4.2.1)
76 - railties (>= 3.0, < 5.0)
101 + rails-dom-testing (>= 1, < 3)
102 + railties (>= 4.2.0)
77 thor (>= 0.14, < 2.0)
103 thor (>= 0.14, < 2.0)
78 - jquery-tablesorter (1.13.4)
104 + jquery-tablesorter (1.23.3)
79 - railties (>= 3.1, < 5)
105 + railties (>= 3.2, < 6)
80 jquery-timepicker-addon-rails (1.4.1)
106 jquery-timepicker-addon-rails (1.4.1)
81 railties (>= 3.1)
107 railties (>= 3.1)
82 - jquery-ui-rails (4.0.3)
108 + jquery-ui-rails (6.0.1)
83 - jquery-rails
109 + railties (>= 3.2.16)
84 - railties (>= 3.1.0)
85 - jquery-ui-sass-rails (4.0.3.0)
86 - jquery-rails
87 - jquery-ui-rails (= 4.0.3)
88 - railties (>= 3.1.0)
89 json (1.8.3)
110 json (1.8.3)
90 - mail (2.5.4)
111 + loofah (2.0.3)
91 - mime-types (~> 1.16)
112 + nokogiri (>= 1.5.9)
92 - treetop (~> 1.4.8)
113 + mail (2.6.4)
93 - mime-types (1.25.1)
114 + mime-types (>= 1.16, < 4)
94 - momentjs-rails (2.11.1)
115 + mime-types (3.1)
116 + mime-types-data (~> 3.2015)
117 + mime-types-data (3.2016.0521)
118 + mini_portile2 (2.1.0)
119 + minitest (5.10.1)
120 + minitest-reporters (1.1.13)
121 + ansi
122 + builder
123 + minitest (>= 5.0)
124 + ruby-progressbar
125 + momentjs-rails (2.15.1)
95 railties (>= 3.1)
126 railties (>= 3.1)
96 multi_json (1.12.1)
127 multi_json (1.12.1)
97 - mysql2 (0.3.20)
128 + mysql2 (0.4.5)
98 - polyglot (0.3.5)
129 + nokogiri (1.6.8.1)
99 - power_assert (0.2.2)
130 + mini_portile2 (~> 2.1.0)
100 - prototype-rails (3.2.1)
131 + rack (1.6.5)
101 - rails (~> 3.2)
102 - rack (1.4.7)
103 - rack-cache (1.6.1)
104 - rack (>= 0.4)
105 - rack-ssl (1.3.4)
106 - rack
107 rack-test (0.6.3)
132 rack-test (0.6.3)
108 rack (>= 1.0)
133 rack (>= 1.0)
109 - rails (3.2.22.5)
134 + rails (4.2.7.1)
110 - actionmailer (= 3.2.22.5)
135 + actionmailer (= 4.2.7.1)
111 - actionpack (= 3.2.22.5)
136 + actionpack (= 4.2.7.1)
112 - activerecord (= 3.2.22.5)
137 + actionview (= 4.2.7.1)
113 - activeresource (= 3.2.22.5)
138 + activejob (= 4.2.7.1)
114 - activesupport (= 3.2.22.5)
139 + activemodel (= 4.2.7.1)
115 - bundler (~> 1.0)
140 + activerecord (= 4.2.7.1)
116 - railties (= 3.2.22.5)
141 + activesupport (= 4.2.7.1)
117 - rails_bootstrap_sortable (2.0.0)
142 + bundler (>= 1.3.0, < 2.0)
118 - momentjs-rails (~> 2, >= 2.8.3)
143 + railties (= 4.2.7.1)
119 - railties (3.2.22.5)
144 + sprockets-rails
120 - actionpack (= 3.2.22.5)
145 + rails-deprecated_sanitizer (1.0.3)
121 - activesupport (= 3.2.22.5)
146 + activesupport (>= 4.2.0.alpha)
122 - rack-ssl (~> 1.3.2)
147 + rails-dom-testing (1.0.8)
148 + activesupport (>= 4.2.0.beta, < 5.0)
149 + nokogiri (~> 1.6)
150 + rails-deprecated_sanitizer (>= 1.0.1)
151 + rails-html-sanitizer (1.0.3)
152 + loofah (~> 2.0)
153 + rails_bootstrap_sortable (2.0.1)
154 + momentjs-rails (>= 2.8.3)
155 + railties (4.2.7.1)
156 + actionpack (= 4.2.7.1)
157 + activesupport (= 4.2.7.1)
123 rake (>= 0.8.7)
158 rake (>= 0.8.7)
124 - rdoc (~> 3.4)
159 + thor (>= 0.18.1, < 2.0)
125 - thor (>= 0.14.6, < 2.0)
160 + rake (12.0.0)
126 - rake (11.2.2)
161 + rdiscount (2.2.0.1)
127 - rdiscount (2.1.8)
162 + rouge (2.0.7)
128 - rdoc (3.12.2)
163 + ruby-progressbar (1.8.1)
129 - json (~> 1.4)
164 + ruby_parser (3.8.3)
130 - rouge (1.8.0)
165 + sexp_processor (~> 4.1)
131 - rspec-collection_matchers (1.1.2)
166 + sass (3.4.23)
132 - rspec-expectations (>= 2.99.0.beta1)
167 + sass-rails (5.0.6)
133 - rspec-core (2.99.2)
168 + railties (>= 4.0.0, < 6)
134 - rspec-expectations (2.99.2)
169 + sass (~> 3.1)
135 - diff-lcs (>= 1.1.3, < 2.0)
170 + sprockets (>= 2.8, < 4.0)
136 - rspec-mocks (2.99.3)
171 + sprockets-rails (>= 2.0, < 4.0)
137 - rspec-rails (2.99.0)
172 + tilt (>= 1.1, < 3)
138 - actionpack (>= 3.0)
173 + select2-rails (4.0.3)
139 - activemodel (>= 3.0)
140 - activesupport (>= 3.0)
141 - railties (>= 3.0)
142 - rspec-collection_matchers
143 - rspec-core (~> 2.99.0)
144 - rspec-expectations (~> 2.99.0)
145 - rspec-mocks (~> 2.99.0)
146 - sass (3.4.11)
147 - sass-rails (3.2.6)
148 - railties (~> 3.2.0)
149 - sass (>= 3.1.10)
150 - tilt (~> 1.3)
151 - select2-rails (4.0.1)
152 thor (~> 0.14)
174 thor (~> 0.14)
153 - sprockets (2.2.3)
175 + sexp_processor (4.7.0)
154 - hike (~> 1.2)
176 + sprockets (3.7.1)
155 - multi_json (~> 1.0)
177 + concurrent-ruby (~> 1.0)
156 - rack (~> 1.0)
178 + rack (> 1, < 3)
157 - tilt (~> 1.1, != 1.3.0)
179 + sprockets-rails (3.2.0)
158 - test-unit (3.0.9)
180 + actionpack (>= 4.0)
159 - power_assert
181 + activesupport (>= 4.0)
160 - thor (0.19.1)
182 + sprockets (>= 3.0.0)
161 - tilt (1.4.1)
183 + sqlite3 (1.3.12)
162 - treetop (1.4.15)
184 + thor (0.19.4)
163 - polyglot
185 + thread_safe (0.3.5)
164 - polyglot (>= 0.3.1)
186 + tilt (2.0.5)
165 - tzinfo (0.3.51)
187 + tzinfo (1.2.2)
166 - uglifier (2.7.0)
188 + thread_safe (~> 0.1)
167 - execjs (>= 0.3.0)
189 + uglifier (3.0.4)
168 - json (>= 1.8.0)
190 + execjs (>= 0.3.0, < 3)
169 - will_paginate (3.0.7)
191 + will_paginate (3.0.12)
192 + yaml_db (0.4.2)
193 + rails (>= 3.0, < 5.1)
194 + rake (>= 0.8.7)
170
195
171 PLATFORMS
196 PLATFORMS
172 ruby
197 ruby
173
198
174 DEPENDENCIES
199 DEPENDENCIES
175 ace-rails-ap
200 ace-rails-ap
201 + activerecord-session_store
176 autoprefixer-rails
202 autoprefixer-rails
177 best_in_place (~> 3.0.1)
203 best_in_place (~> 3.0.1)
178 bootstrap-sass (~> 3.2.0)
204 bootstrap-sass (~> 3.2.0)
179 bootstrap-switch-rails
205 bootstrap-switch-rails
180 bootstrap-toggle-rails
206 bootstrap-toggle-rails
181 - coffee-rails (~> 3.2.2)
207 + coffee-rails
182 dynamic_form
208 dynamic_form
209 + fuzzy-string-match
183 haml
210 haml
184 haml-rails
211 haml-rails
185 in_place_editing
212 in_place_editing
186 jquery-countdown-rails
213 jquery-countdown-rails
187 jquery-rails
214 jquery-rails
188 jquery-tablesorter
215 jquery-tablesorter
189 jquery-timepicker-addon-rails
216 jquery-timepicker-addon-rails
190 - jquery-ui-sass-rails
217 + jquery-ui-rails
191 mail
218 mail
219 + minitest-reporters
192 momentjs-rails
220 momentjs-rails
193 mysql2
221 mysql2
194 - prototype-rails
222 + rails (~> 4.2.0)
195 - rails (~> 3.2)
196 rails_bootstrap_sortable
223 rails_bootstrap_sortable
197 rdiscount
224 rdiscount
198 rouge
225 rouge
199 - rspec-rails (~> 2.99.0)
226 + sass-rails
200 - sass-rails (~> 3.2.6)
201 select2-rails
227 select2-rails
202 - test-unit
228 + sqlite3
203 uglifier
229 uglifier
204 verification!
230 verification!
205 will_paginate (~> 3.0.7)
231 will_paginate (~> 3.0.7)
232 + yaml_db
206
233
207 BUNDLED WITH
234 BUNDLED WITH
208 - 1.12.5
235 + 1.13.6
@@ -3,42 +3,39
3 //
3 //
4 // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
4 // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
5 // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6 //
6 //
7 // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
7 // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 // the compiled file.
8 // the compiled file.
9 //
9 //
10 // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
10 // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11 // GO AFTER THE REQUIRES BELOW.
11 // GO AFTER THE REQUIRES BELOW.
12 //
12 //
13 //= require jquery
13 //= require jquery
14 //= require jquery_ujs
14 //= require jquery_ujs
15 - //= require jquery.ui.all
15 + //= require jquery-ui
16 //= require bootstrap-sprockets
16 //= require bootstrap-sprockets
17 //= require moment
17 //= require moment
18 //= require bootstrap-sortable
18 //= require bootstrap-sortable
19 //= require select2
19 //= require select2
20 //= require ace-rails-ap
20 //= require ace-rails-ap
21 //= require ace/mode-c_cpp
21 //= require ace/mode-c_cpp
22 //= require ace/mode-python
22 //= require ace/mode-python
23 //= require ace/mode-ruby
23 //= require ace/mode-ruby
24 //= require ace/mode-pascal
24 //= require ace/mode-pascal
25 //= require ace/mode-javascript
25 //= require ace/mode-javascript
26 //= require ace/mode-java
26 //= require ace/mode-java
27 //= require ace/theme-merbivore
27 //= require ace/theme-merbivore
28 //= require custom
28 //= require custom
29 //= require jquery.countdown
29 //= require jquery.countdown
30 //-------------- addition from local_jquery -----------
30 //-------------- addition from local_jquery -----------
31 - //= require jquery.ui.datepicker
32 - //= require jquery.ui.slider
33 - //= require jquery-ui-timepicker-addon
34 //= require jquery-tablesorter
31 //= require jquery-tablesorter
35 //= require best_in_place
32 //= require best_in_place
36 //= require best_in_place.jquery-ui
33 //= require best_in_place.jquery-ui
37 //= require brython
34 //= require brython
38
35
39 // since this is after blank line, it is not downloaded
36 // since this is after blank line, it is not downloaded
40 //x= require prototype
37 //x= require prototype
41 //x= require prototype_ujs
38 //x= require prototype_ujs
42 //x= require effects
39 //x= require effects
43 //x= require dragdrop
40 //x= require dragdrop
44 //x= require controls
41 //x= require controls
@@ -1,14 +1,4
1 - //= require jquery
2 - //= require jquery_ujs
3 - //= require jquery.ui.all
4 - //= require jquery.ui.datepicker
5 - //= require jquery.ui.slider
6 - //= require jquery-ui-timepicker-addon
7 - //= require jquery-tablesorter
8 - //= require best_in_place
9 - //= require best_in_place.jquery-ui
10 -
11 $(document).ready(function() {
1 $(document).ready(function() {
12 /* Activating Best In Place */
2 /* Activating Best In Place */
13 jQuery(".best_in_place").best_in_place();
3 jQuery(".best_in_place").best_in_place();
14 });
4 });
@@ -5,29 +5,29
5 * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
5 * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
6 *
6 *
7 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
7 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
8 * compiled file so the styles you add here take precedence over styles defined in any styles
8 * compiled file so the styles you add here take precedence over styles defined in any styles
9 * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
9 * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
10 * file per style scope.
10 * file per style scope.
11 *
11 *
12 * // bootstrap says that we should not do this, but @import each file instead
12 * // bootstrap says that we should not do this, but @import each file instead
13 * # *= require_tree .
13 * # *= require_tree .
14 * # *= require_self
14 * # *= require_self
15 */
15 */
16
16
17 - @import "jquery.ui.all";
17 + @import "jquery-ui";
18 - @import "jquery.ui.core";
18 + //@import "jquery.ui.core";
19 - @import "jquery.ui.theme";
19 + //@import "jquery.ui.theme";
20 - @import "jquery.ui.datepicker";
20 + //@import "jquery.ui.datepicker";
21 - @import "jquery.ui.slider";
21 + //@import "jquery.ui.slider";
22 @import "jquery-ui-timepicker-addon";
22 @import "jquery-ui-timepicker-addon";
23 @import "jquery-tablesorter/theme.metro-dark";
23 @import "jquery-tablesorter/theme.metro-dark";
24 @import "jquery.countdown";
24 @import "jquery.countdown";
25 @import "tablesorter-theme.cafe";
25 @import "tablesorter-theme.cafe";
26
26
27 //bootstrap
27 //bootstrap
28 @import "bootstrap-sprockets";
28 @import "bootstrap-sprockets";
29 @import "bootstrap";
29 @import "bootstrap";
30 @import "select2";
30 @import "select2";
31 @import "select2-bootstrap";
31 @import "select2-bootstrap";
32
32
33 //@import bootstrap3-switch
33 //@import bootstrap3-switch
@@ -1,23 +1,22
1 class AnnouncementsController < ApplicationController
1 class AnnouncementsController < ApplicationController
2
2
3 before_filter :admin_authorization
3 before_filter :admin_authorization
4
4
5 in_place_edit_for :announcement, :published
5 in_place_edit_for :announcement, :published
6
6
7 # GET /announcements
7 # GET /announcements
8 # GET /announcements.xml
8 # GET /announcements.xml
9 def index
9 def index
10 - @announcements = Announcement.find(:all,
10 + @announcements = Announcement.order(created_at: :desc)
11 - :order => "created_at DESC")
12
11
13 respond_to do |format|
12 respond_to do |format|
14 format.html # index.html.erb
13 format.html # index.html.erb
15 format.xml { render :xml => @announcements }
14 format.xml { render :xml => @announcements }
16 end
15 end
17 end
16 end
18
17
19 # GET /announcements/1
18 # GET /announcements/1
20 # GET /announcements/1.xml
19 # GET /announcements/1.xml
21 def show
20 def show
22 @announcement = Announcement.find(params[:id])
21 @announcement = Announcement.find(params[:id])
23
22
@@ -37,45 +36,45
37 format.xml { render :xml => @announcement }
36 format.xml { render :xml => @announcement }
38 end
37 end
39 end
38 end
40
39
41 # GET /announcements/1/edit
40 # GET /announcements/1/edit
42 def edit
41 def edit
43 @announcement = Announcement.find(params[:id])
42 @announcement = Announcement.find(params[:id])
44 end
43 end
45
44
46 # POST /announcements
45 # POST /announcements
47 # POST /announcements.xml
46 # POST /announcements.xml
48 def create
47 def create
49 - @announcement = Announcement.new(params[:announcement])
48 + @announcement = Announcement.new(announcement_params)
50
49
51 respond_to do |format|
50 respond_to do |format|
52 if @announcement.save
51 if @announcement.save
53 flash[:notice] = 'Announcement was successfully created.'
52 flash[:notice] = 'Announcement was successfully created.'
54 format.html { redirect_to(@announcement) }
53 format.html { redirect_to(@announcement) }
55 format.xml { render :xml => @announcement, :status => :created, :location => @announcement }
54 format.xml { render :xml => @announcement, :status => :created, :location => @announcement }
56 else
55 else
57 format.html { render :action => "new" }
56 format.html { render :action => "new" }
58 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
57 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
59 end
58 end
60 end
59 end
61 end
60 end
62
61
63 # PUT /announcements/1
62 # PUT /announcements/1
64 # PUT /announcements/1.xml
63 # PUT /announcements/1.xml
65 def update
64 def update
66 @announcement = Announcement.find(params[:id])
65 @announcement = Announcement.find(params[:id])
67
66
68 respond_to do |format|
67 respond_to do |format|
69 - if @announcement.update_attributes(params[:announcement])
68 + if @announcement.update_attributes(announcement_params)
70 flash[:notice] = 'Announcement was successfully updated.'
69 flash[:notice] = 'Announcement was successfully updated.'
71 format.html { redirect_to(@announcement) }
70 format.html { redirect_to(@announcement) }
72 format.js {}
71 format.js {}
73 format.xml { head :ok }
72 format.xml { head :ok }
74 else
73 else
75 format.html { render :action => "edit" }
74 format.html { render :action => "edit" }
76 format.js {}
75 format.js {}
77 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
76 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
78 end
77 end
79 end
78 end
80 end
79 end
81
80
@@ -99,13 +98,19
99
98
100 # DELETE /announcements/1
99 # DELETE /announcements/1
101 # DELETE /announcements/1.xml
100 # DELETE /announcements/1.xml
102 def destroy
101 def destroy
103 @announcement = Announcement.find(params[:id])
102 @announcement = Announcement.find(params[:id])
104 @announcement.destroy
103 @announcement.destroy
105
104
106 respond_to do |format|
105 respond_to do |format|
107 format.html { redirect_to(announcements_url) }
106 format.html { redirect_to(announcements_url) }
108 format.xml { head :ok }
107 format.xml { head :ok }
109 end
108 end
110 end
109 end
110 +
111 + private
112 +
113 + def announcement_params
114 + params.require(:announcement).permit(:author, :body, :published, :frontpage, :contest_only, :title)
111 end
115 end
116 + end
@@ -11,41 +11,53
11 flash[:notice] = 'You are not authorized to view the page you requested'
11 flash[:notice] = 'You are not authorized to view the page you requested'
12 redirect_to :controller => 'main', :action => 'login'
12 redirect_to :controller => 'main', :action => 'login'
13 end
13 end
14
14
15 # Returns the current logged-in user (if any).
15 # Returns the current logged-in user (if any).
16 def current_user
16 def current_user
17 return nil unless session[:user_id]
17 return nil unless session[:user_id]
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.find(session[:user_id], :include => ['roles'])
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
41 + #admin always has privileged
42 + puts "haha"
43 + if @current_user.admin?
44 + return true
45 + end
46 +
47 + puts "hehe"
48 + puts GraderConfiguration["right.view_testcase"]
49 + unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
50 + end
51 +
40 protected
52 protected
41
53
42 def authenticate
54 def authenticate
43 unless session[:user_id]
55 unless session[:user_id]
44 flash[:notice] = 'You need to login'
56 flash[:notice] = 'You need to login'
45 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
57 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
46 flash[:notice] = 'You need to login but you cannot log in at this time'
58 flash[:notice] = 'You need to login but you cannot log in at this time'
47 end
59 end
48 redirect_to :controller => 'main', :action => 'login'
60 redirect_to :controller => 'main', :action => 'login'
49 return false
61 return false
50 end
62 end
51
63
@@ -1,29 +1,34
1 class ConfigurationsController < ApplicationController
1 class ConfigurationsController < ApplicationController
2
2
3 before_filter :authenticate
3 before_filter :authenticate
4 before_filter { |controller| controller.authorization_by_roles(['admin'])}
4 before_filter { |controller| controller.authorization_by_roles(['admin'])}
5
5
6
6
7 def index
7 def index
8 - @configurations = GraderConfiguration.find(:all,
8 + @configurations = GraderConfiguration.order(:key)
9 - :order => '`key`')
9 + @group = GraderConfiguration.pluck("grader_configurations.key").map{ |x| x[0...(x.index('.'))] }.uniq.sort
10 end
10 end
11
11
12 def reload
12 def reload
13 GraderConfiguration.reload
13 GraderConfiguration.reload
14 redirect_to :action => 'index'
14 redirect_to :action => 'index'
15 end
15 end
16
16
17 def update
17 def update
18 @config = GraderConfiguration.find(params[:id])
18 @config = GraderConfiguration.find(params[:id])
19 User.clear_last_login if @config.key == GraderConfiguration::MULTIPLE_IP_LOGIN_KEY and @config.value == 'true' and params[:grader_configuration][:value] == 'false'
19 User.clear_last_login if @config.key == GraderConfiguration::MULTIPLE_IP_LOGIN_KEY and @config.value == 'true' and params[:grader_configuration][:value] == 'false'
20 respond_to do |format|
20 respond_to do |format|
21 - if @config.update_attributes(params[:grader_configuration])
21 + if @config.update_attributes(configuration_params)
22 format.json { head :ok }
22 format.json { head :ok }
23 else
23 else
24 format.json { respond_with_bip(@config) }
24 format.json { respond_with_bip(@config) }
25 end
25 end
26 end
26 end
27 end
27 end
28
28
29 + private
30 + def configuration_params
31 + params.require(:grader_configuration).permit(:key,:value_type,:value,:description)
29 end
32 end
33 +
34 + end
@@ -2,27 +2,27
2
2
3 before_filter :admin_authorization
3 before_filter :admin_authorization
4
4
5 def index
5 def index
6 @num_contests = Contest.count()
6 @num_contests = Contest.count()
7 end
7 end
8
8
9 def user_stat
9 def user_stat
10 if not GraderConfiguration.indv_contest_mode?
10 if not GraderConfiguration.indv_contest_mode?
11 redirect_to :action => 'index' and return
11 redirect_to :action => 'index' and return
12 end
12 end
13
13
14 - @users = User.find(:all)
14 + @users = User.all
15 @start_times = {}
15 @start_times = {}
16 - UserContestStat.find(:all).each do |stat|
16 + UserContestStat.all.each do |stat|
17 @start_times[stat.user_id] = stat.started_at
17 @start_times[stat.user_id] = stat.started_at
18 end
18 end
19 end
19 end
20
20
21 def clear_stat
21 def clear_stat
22 user = User.find(params[:id])
22 user = User.find(params[:id])
23 if user.contest_stat!=nil
23 if user.contest_stat!=nil
24 user.contest_stat.destroy
24 user.contest_stat.destroy
25 end
25 end
26 redirect_to :action => 'user_stat'
26 redirect_to :action => 'user_stat'
27 end
27 end
28
28
@@ -57,36 +57,42
57 format.html { render :action => "new" }
57 format.html { render :action => "new" }
58 format.xml { render :xml => @contest.errors, :status => :unprocessable_entity }
58 format.xml { render :xml => @contest.errors, :status => :unprocessable_entity }
59 end
59 end
60 end
60 end
61 end
61 end
62
62
63 # PUT /contests/1
63 # PUT /contests/1
64 # PUT /contests/1.xml
64 # PUT /contests/1.xml
65 def update
65 def update
66 @contest = Contest.find(params[:id])
66 @contest = Contest.find(params[:id])
67
67
68 respond_to do |format|
68 respond_to do |format|
69 - if @contest.update_attributes(params[:contest])
69 + if @contest.update_attributes(contests_params)
70 flash[:notice] = 'Contest was successfully updated.'
70 flash[:notice] = 'Contest was successfully updated.'
71 format.html { redirect_to(@contest) }
71 format.html { redirect_to(@contest) }
72 format.xml { head :ok }
72 format.xml { head :ok }
73 else
73 else
74 format.html { render :action => "edit" }
74 format.html { render :action => "edit" }
75 format.xml { render :xml => @contest.errors, :status => :unprocessable_entity }
75 format.xml { render :xml => @contest.errors, :status => :unprocessable_entity }
76 end
76 end
77 end
77 end
78 end
78 end
79
79
80 # DELETE /contests/1
80 # DELETE /contests/1
81 # DELETE /contests/1.xml
81 # DELETE /contests/1.xml
82 def destroy
82 def destroy
83 @contest = Contest.find(params[:id])
83 @contest = Contest.find(params[:id])
84 @contest.destroy
84 @contest.destroy
85
85
86 respond_to do |format|
86 respond_to do |format|
87 format.html { redirect_to(contests_url) }
87 format.html { redirect_to(contests_url) }
88 format.xml { head :ok }
88 format.xml { head :ok }
89 end
89 end
90 end
90 end
91
91
92 + private
93 +
94 + def contests_params
95 + params.require(:contest).permit(:title,:enabled,:name)
92 end
96 end
97 +
98 + end
@@ -26,47 +26,45
26 :redirect_to => {:action => 'index'}
26 :redirect_to => {:action => 'index'}
27
27
28 def index
28 def index
29 redirect_to :action => 'list'
29 redirect_to :action => 'list'
30 end
30 end
31
31
32 def list
32 def list
33 @grader_processes = GraderProcess.find_running_graders
33 @grader_processes = GraderProcess.find_running_graders
34 @stalled_processes = GraderProcess.find_stalled_process
34 @stalled_processes = GraderProcess.find_stalled_process
35
35
36 @terminated_processes = GraderProcess.find_terminated_graders
36 @terminated_processes = GraderProcess.find_terminated_graders
37
37
38 - @last_task = Task.find(:first,
38 + @last_task = Task.last
39 - :order => 'created_at DESC')
39 + @last_test_request = TestRequest.last
40 - @last_test_request = TestRequest.find(:first,
41 - :order => 'created_at DESC')
42 @submission = Submission.order("id desc").limit(20)
40 @submission = Submission.order("id desc").limit(20)
43 @backlog_submission = Submission.where('graded_at is null')
41 @backlog_submission = Submission.where('graded_at is null')
44 end
42 end
45
43
46 def clear
44 def clear
47 grader_proc = GraderProcess.find(params[:id])
45 grader_proc = GraderProcess.find(params[:id])
48 grader_proc.destroy if grader_proc!=nil
46 grader_proc.destroy if grader_proc!=nil
49 redirect_to :action => 'list'
47 redirect_to :action => 'list'
50 end
48 end
51
49
52 def clear_terminated
50 def clear_terminated
53 GraderProcess.find_terminated_graders.each do |p|
51 GraderProcess.find_terminated_graders.each do |p|
54 p.destroy
52 p.destroy
55 end
53 end
56 redirect_to :action => 'list'
54 redirect_to :action => 'list'
57 end
55 end
58
56
59 def clear_all
57 def clear_all
60 - GraderProcess.find(:all).each do |p|
58 + GraderProcess.all.each do |p|
61 p.destroy
59 p.destroy
62 end
60 end
63 redirect_to :action => 'list'
61 redirect_to :action => 'list'
64 end
62 end
65
63
66 def view
64 def view
67 if params[:type]=='Task'
65 if params[:type]=='Task'
68 redirect_to :action => 'task', :id => params[:id]
66 redirect_to :action => 'task', :id => params[:id]
69 else
67 else
70 redirect_to :action => 'test_request', :id => params[:id]
68 redirect_to :action => 'test_request', :id => params[:id]
71 end
69 end
72 end
70 end
@@ -1,31 +1,46
1 class HeartbeatController < ApplicationController
1 class HeartbeatController < ApplicationController
2 before_filter :admin_authorization, :only => ['index']
2 before_filter :admin_authorization, :only => ['index']
3
3
4 def edit
4 def edit
5 - @user = User.find_by_login(params[:id])
5 + #@user = User.find_by_login(params[:id])
6 - unless @user
6 + #unless @user
7 - render text: "LOGIN_NOT_FOUND"
7 + # render text: "LOGIN_NOT_FOUND"
8 - return
8 + # return
9 - end
9 + #end
10
10
11 #hb = HeartBeat.where(user_id: @user.id, ip_address: request.remote_ip).first
11 #hb = HeartBeat.where(user_id: @user.id, ip_address: request.remote_ip).first
12 #puts "status = #{params[:status]}"
12 #puts "status = #{params[:status]}"
13 #if hb
13 #if hb
14 # if params[:status]
14 # if params[:status]
15 # hb.status = params[:status]
15 # hb.status = params[:status]
16 # hb.save
16 # hb.save
17 # end
17 # end
18 # hb.touch
18 # hb.touch
19 #else
19 #else
20 # HeartBeat.creae(user_id: @user.id, ip_address: request.remote_ip)
20 # HeartBeat.creae(user_id: @user.id, ip_address: request.remote_ip)
21 #end
21 #end
22 - HeartBeat.create(user_id: @user.id, ip_address: request.remote_ip, status: params[:status])
22 + #HeartBeat.create(user_id: @user.id, ip_address: request.remote_ip, status: params[:status])
23 +
24 + res = GraderConfiguration['right.heartbeat_response']
25 + res.strip! if res
26 + full = GraderConfiguration['right.heartbeat_response_full']
27 + full.strip! if full
23
28
29 + if full and full != ''
30 + l = Login.where(ip_address: request.remote_ip).last
31 + @user = l.user
32 + if @user.solve_all_available_problems?
33 + render text: (full || 'OK')
34 + else
35 + render text: (res || 'OK')
36 + end
37 + else
24 render text: (GraderConfiguration['right.heartbeat_response'] || 'OK')
38 render text: (GraderConfiguration['right.heartbeat_response'] || 'OK')
25 end
39 end
40 + end
26
41
27 def index
42 def index
28 @hb = HeartBeat.where("updated_at >= ?",Time.zone.now-2.hours).includes(:user).order(:user_id).all
43 @hb = HeartBeat.where("updated_at >= ?",Time.zone.now-2.hours).includes(:user).order(:user_id).all
29 @num = HeartBeat.where("updated_at >= ?",Time.zone.now-5.minutes).count(:user_id,distinct: true)
44 @num = HeartBeat.where("updated_at >= ?",Time.zone.now-5.minutes).count(:user_id,distinct: true)
30 end
45 end
31 end
46 end
@@ -36,25 +36,25
36 flash.now[:notice] = saved_notice
36 flash.now[:notice] = saved_notice
37
37
38 # EXPERIMENT:
38 # EXPERIMENT:
39 # Hide login if in single user mode and the url does not
39 # Hide login if in single user mode and the url does not
40 # explicitly specify /login
40 # explicitly specify /login
41 #
41 #
42 # logger.info "PATH: #{request.path}"
42 # logger.info "PATH: #{request.path}"
43 # if GraderConfiguration['system.single_user_mode'] and
43 # if GraderConfiguration['system.single_user_mode'] and
44 # request.path!='/main/login'
44 # request.path!='/main/login'
45 # @hidelogin = true
45 # @hidelogin = true
46 # end
46 # end
47
47
48 - @announcements = Announcement.find_for_frontpage
48 + @announcements = Announcement.frontpage
49 render :action => 'login', :layout => 'empty'
49 render :action => 'login', :layout => 'empty'
50 end
50 end
51
51
52 def list
52 def list
53 prepare_list_information
53 prepare_list_information
54 end
54 end
55
55
56 def help
56 def help
57 @user = User.find(session[:user_id])
57 @user = User.find(session[:user_id])
58 end
58 end
59
59
60 def submit
60 def submit
@@ -115,41 +115,24
115 end
115 end
116
116
117 def compiler_msg
117 def compiler_msg
118 @submission = Submission.find(params[:id])
118 @submission = Submission.find(params[:id])
119 if @submission.user_id == session[:user_id]
119 if @submission.user_id == session[:user_id]
120 render :action => 'compiler_msg', :layout => 'empty'
120 render :action => 'compiler_msg', :layout => 'empty'
121 else
121 else
122 flash[:notice] = 'Error viewing source'
122 flash[:notice] = 'Error viewing source'
123 redirect_to :action => 'list'
123 redirect_to :action => 'list'
124 end
124 end
125 end
125 end
126
126
127 - def submission
128 - @user = User.find(session[:user_id])
129 - @problems = @user.available_problems
130 - if params[:id]==nil
131 - @problem = nil
132 - @submissions = nil
133 - else
134 - @problem = Problem.find_by_id(params[:id])
135 - if (@problem == nil) or (not @problem.available)
136 - redirect_to :action => 'list'
137 - flash[:notice] = 'Error: submissions for that problem are not viewable.'
138 - return
139 - end
140 - @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
141 - end
142 - end
143 -
144 def result
127 def result
145 if !GraderConfiguration.show_grading_result
128 if !GraderConfiguration.show_grading_result
146 redirect_to :action => 'list' and return
129 redirect_to :action => 'list' and return
147 end
130 end
148 @user = User.find(session[:user_id])
131 @user = User.find(session[:user_id])
149 @submission = Submission.find(params[:id])
132 @submission = Submission.find(params[:id])
150 if @submission.user!=@user
133 if @submission.user!=@user
151 flash[:notice] = 'You are not allowed to view result of other users.'
134 flash[:notice] = 'You are not allowed to view result of other users.'
152 redirect_to :action => 'list' and return
135 redirect_to :action => 'list' and return
153 end
136 end
154 prepare_grading_result(@submission)
137 prepare_grading_result(@submission)
155 end
138 end
@@ -208,27 +191,27
208 user.update_start_time
191 user.update_start_time
209 redirect_to :action => 'list'
192 redirect_to :action => 'list'
210 else
193 else
211 @contests = user.contests
194 @contests = user.contests
212 @user = user
195 @user = user
213 end
196 end
214 end
197 end
215
198
216 protected
199 protected
217
200
218 def prepare_announcements(recent=nil)
201 def prepare_announcements(recent=nil)
219 if GraderConfiguration.show_tasks_to?(@user)
202 if GraderConfiguration.show_tasks_to?(@user)
220 - @announcements = Announcement.find_published(true)
203 + @announcements = Announcement.published(true)
221 else
204 else
222 - @announcements = Announcement.find_published
205 + @announcements = Announcement.published
223 end
206 end
224 if recent!=nil
207 if recent!=nil
225 recent_id = recent.to_i
208 recent_id = recent.to_i
226 @announcements = @announcements.find_all { |a| a.id > recent_id }
209 @announcements = @announcements.find_all { |a| a.id > recent_id }
227 end
210 end
228 end
211 end
229
212
230 def prepare_list_information
213 def prepare_list_information
231 @user = User.find(session[:user_id])
214 @user = User.find(session[:user_id])
232 if not GraderConfiguration.multicontests?
215 if not GraderConfiguration.multicontests?
233 @problems = @user.available_problems
216 @problems = @user.available_problems
234 else
217 else
@@ -1,61 +1,62
1 class ProblemsController < ApplicationController
1 class ProblemsController < ApplicationController
2
2
3 - before_filter :authenticate, :authorization
3 + before_action :authenticate, :authorization
4 + before_action :testcase_authorization, only: [:show_testcase]
4
5
5 in_place_edit_for :problem, :name
6 in_place_edit_for :problem, :name
6 in_place_edit_for :problem, :full_name
7 in_place_edit_for :problem, :full_name
7 in_place_edit_for :problem, :full_score
8 in_place_edit_for :problem, :full_score
8
9
9 def index
10 def index
10 - @problems = Problem.find(:all, :order => 'date_added DESC')
11 + @problems = Problem.order(date_added: :desc)
11 end
12 end
12
13
13 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
14 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
14 verify :method => :post, :only => [ :create, :quick_create,
15 verify :method => :post, :only => [ :create, :quick_create,
15 :do_manage,
16 :do_manage,
16 :do_import,
17 :do_import,
17 ],
18 ],
18 :redirect_to => { :action => :index }
19 :redirect_to => { :action => :index }
19
20
20 def show
21 def show
21 @problem = Problem.find(params[:id])
22 @problem = Problem.find(params[:id])
22 end
23 end
23
24
24 def new
25 def new
25 @problem = Problem.new
26 @problem = Problem.new
26 @description = nil
27 @description = nil
27 end
28 end
28
29
29 def create
30 def create
30 - @problem = Problem.new(params[:problem])
31 + @problem = Problem.new(problem_params)
31 @description = Description.new(params[:description])
32 @description = Description.new(params[:description])
32 if @description.body!=''
33 if @description.body!=''
33 if !@description.save
34 if !@description.save
34 render :action => new and return
35 render :action => new and return
35 end
36 end
36 else
37 else
37 @description = nil
38 @description = nil
38 end
39 end
39 @problem.description = @description
40 @problem.description = @description
40 if @problem.save
41 if @problem.save
41 flash[:notice] = 'Problem was successfully created.'
42 flash[:notice] = 'Problem was successfully created.'
42 redirect_to action: :index
43 redirect_to action: :index
43 else
44 else
44 render :action => 'new'
45 render :action => 'new'
45 end
46 end
46 end
47 end
47
48
48 def quick_create
49 def quick_create
49 - @problem = Problem.new(params[:problem])
50 + @problem = Problem.new(problem_params)
50 @problem.full_name = @problem.name if @problem.full_name == ''
51 @problem.full_name = @problem.name if @problem.full_name == ''
51 @problem.full_score = 100
52 @problem.full_score = 100
52 @problem.available = false
53 @problem.available = false
53 @problem.test_allowed = true
54 @problem.test_allowed = true
54 @problem.output_only = false
55 @problem.output_only = false
55 @problem.date_added = Time.new
56 @problem.date_added = Time.new
56 if @problem.save
57 if @problem.save
57 flash[:notice] = 'Problem was successfully created.'
58 flash[:notice] = 'Problem was successfully created.'
58 redirect_to action: :index
59 redirect_to action: :index
59 else
60 else
60 flash[:notice] = 'Error saving problem'
61 flash[:notice] = 'Error saving problem'
61 redirect_to action: :index
62 redirect_to action: :index
@@ -78,25 +79,25
78 end
79 end
79 @problem.description = @description
80 @problem.description = @description
80 elsif @description
81 elsif @description
81 if !@description.update_attributes(params[:description])
82 if !@description.update_attributes(params[:description])
82 flash[:notice] = 'Error saving description'
83 flash[:notice] = 'Error saving description'
83 render :action => 'edit' and return
84 render :action => 'edit' and return
84 end
85 end
85 end
86 end
86 if params[:file] and params[:file].content_type != 'application/pdf'
87 if params[:file] and params[:file].content_type != 'application/pdf'
87 flash[:notice] = 'Error: Uploaded file is not PDF'
88 flash[:notice] = 'Error: Uploaded file is not PDF'
88 render :action => 'edit' and return
89 render :action => 'edit' and return
89 end
90 end
90 - if @problem.update_attributes(params[:problem])
91 + if @problem.update_attributes(problem_params)
91 flash[:notice] = 'Problem was successfully updated.'
92 flash[:notice] = 'Problem was successfully updated.'
92 unless params[:file] == nil or params[:file] == ''
93 unless params[:file] == nil or params[:file] == ''
93 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
94 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
94 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
95 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
95 if not FileTest.exists? out_dirname
96 if not FileTest.exists? out_dirname
96 Dir.mkdir out_dirname
97 Dir.mkdir out_dirname
97 end
98 end
98
99
99 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
100 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
100 if FileTest.exists? out_filename
101 if FileTest.exists? out_filename
101 File.delete out_filename
102 File.delete out_filename
102 end
103 end
@@ -125,36 +126,42
125 format.js { }
126 format.js { }
126 end
127 end
127 end
128 end
128
129
129 def toggle_test
130 def toggle_test
130 @problem = Problem.find(params[:id])
131 @problem = Problem.find(params[:id])
131 @problem.update_attributes(test_allowed: !(@problem.test_allowed?) )
132 @problem.update_attributes(test_allowed: !(@problem.test_allowed?) )
132 respond_to do |format|
133 respond_to do |format|
133 format.js { }
134 format.js { }
134 end
135 end
135 end
136 end
136
137
138 + def toggle_view_testcase
139 + @problem = Problem.find(params[:id])
140 + @problem.update_attributes(view_testcase: !(@problem.view_testcase?) )
141 + respond_to do |format|
142 + format.js { }
143 + end
144 + end
145 +
137 def turn_all_off
146 def turn_all_off
138 - Problem.find(:all,
147 + Problem.available.all.each do |problem|
139 - :conditions => "available = 1").each do |problem|
140 problem.available = false
148 problem.available = false
141 problem.save
149 problem.save
142 end
150 end
143 redirect_to action: :index
151 redirect_to action: :index
144 end
152 end
145
153
146 def turn_all_on
154 def turn_all_on
147 - Problem.find(:all,
155 + Problem.where.not(available: true).each do |problem|
148 - :conditions => "available = 0").each do |problem|
149 problem.available = true
156 problem.available = true
150 problem.save
157 problem.save
151 end
158 end
152 redirect_to action: :index
159 redirect_to action: :index
153 end
160 end
154
161
155 def stat
162 def stat
156 @problem = Problem.find(params[:id])
163 @problem = Problem.find(params[:id])
157 unless @problem.available or session[:admin]
164 unless @problem.available or session[:admin]
158 redirect_to :controller => 'main', :action => 'list'
165 redirect_to :controller => 'main', :action => 'list'
159 return
166 return
160 end
167 end
@@ -167,25 +174,25
167 @submissions.find_each do |sub|
174 @submissions.find_each do |sub|
168 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
169 @histogram[:data][d.to_i] += 1 if d < range
176 @histogram[:data][d.to_i] += 1 if d < range
170 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
171 end
178 end
172 @histogram[:summary][:max] = [@histogram[:data].max,1].max
179 @histogram[:summary][:max] = [@histogram[:data].max,1].max
173
180
174 @summary = { attempt: user.count, solve: 0 }
181 @summary = { attempt: user.count, solve: 0 }
175 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
182 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
176 end
183 end
177
184
178 def manage
185 def manage
179 - @problems = Problem.find(:all, :order => 'date_added DESC')
186 + @problems = Problem.order(date_added: :desc)
180 end
187 end
181
188
182 def do_manage
189 def do_manage
183 if params.has_key? 'change_date_added'
190 if params.has_key? 'change_date_added'
184 change_date_added
191 change_date_added
185 elsif params.has_key? 'add_to_contest'
192 elsif params.has_key? 'add_to_contest'
186 add_to_contest
193 add_to_contest
187 elsif params.has_key? 'enable_problem'
194 elsif params.has_key? 'enable_problem'
188 set_available(true)
195 set_available(true)
189 elsif params.has_key? 'disable_problem'
196 elsif params.has_key? 'disable_problem'
190 set_available(false)
197 set_available(false)
191 end
198 end
@@ -269,13 +276,19
269 params.keys.each do |k|
276 params.keys.each do |k|
270 if k.index('prob-')==0
277 if k.index('prob-')==0
271 name, id, order = k.split('-')
278 name, id, order = k.split('-')
272 problems << Problem.find(id)
279 problems << Problem.find(id)
273 end
280 end
274 end
281 end
275 problems
282 problems
276 end
283 end
277
284
278 def get_problems_stat
285 def get_problems_stat
279 end
286 end
280
287
288 + private
289 +
290 + def problem_params
291 + params.require(:problem).permit(:name, :full_name, :full_score, :date_added, :available, :test_allowed,:output_only, :url, :description)
281 end
292 end
293 +
294 + end
@@ -1,90 +1,88
1 require 'csv'
1 require 'csv'
2
2
3 class ReportController < ApplicationController
3 class ReportController < ApplicationController
4
4
5 before_filter :authenticate
5 before_filter :authenticate
6
6
7 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize, :show_max_score]
7 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize, :show_max_score]
8
8
9 before_filter(only: [:problem_hof]) { |c|
9 before_filter(only: [:problem_hof]) { |c|
10 return false unless authenticate
10 return false unless authenticate
11
11
12 - if GraderConfiguration["right.user_view_submission"]
12 + admin_authorization unless GraderConfiguration["right.user_view_submission"]
13 - return true;
14 - end
15 -
16 - admin_authorization
17 }
13 }
18
14
19 def max_score
15 def max_score
20 end
16 end
21
17
22 def current_score
18 def current_score
23 - @problems = Problem.find_available_problems
19 + @problems = Problem.available_problems
24 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
20 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
25 @scorearray = calculate_max_score(@problems, @users,0,0,true)
21 @scorearray = calculate_max_score(@problems, @users,0,0,true)
26
22
27 #rencer accordingly
23 #rencer accordingly
28 if params[:button] == 'download' then
24 if params[:button] == 'download' then
29 csv = gen_csv_from_scorearray(@scorearray,@problems)
25 csv = gen_csv_from_scorearray(@scorearray,@problems)
30 send_data csv, filename: 'max_score.csv'
26 send_data csv, filename: 'max_score.csv'
31 else
27 else
32 #render template: 'user_admin/user_stat'
28 #render template: 'user_admin/user_stat'
33 render 'current_score'
29 render 'current_score'
34 end
30 end
35 end
31 end
36
32
37 def show_max_score
33 def show_max_score
38 #process parameters
34 #process parameters
39 #problems
35 #problems
40 @problems = []
36 @problems = []
37 + if params[:problem_id]
41 params[:problem_id].each do |id|
38 params[:problem_id].each do |id|
42 next unless id.strip != ""
39 next unless id.strip != ""
43 pid = Problem.find_by_id(id.to_i)
40 pid = Problem.find_by_id(id.to_i)
44 @problems << pid if pid
41 @problems << pid if pid
45 end
42 end
43 + end
46
44
47 #users
45 #users
48 @users = if params[:user] == "all" then
46 @users = if params[:user] == "all" then
49 - User.find(:all, :include => [:contests, :contest_stat])
47 + User.includes(:contests).includes(:contest_stat)
50 else
48 else
51 User.includes(:contests).includes(:contest_stat).where(enabled: true)
49 User.includes(:contests).includes(:contest_stat).where(enabled: true)
52 end
50 end
53
51
54 #set up range from param
52 #set up range from param
55 - since_id = params.fetch(:min_id, 0).to_i
53 + @since_id = params.fetch(:from_id, 0).to_i
56 - until_id = params.fetch(:max_id, 0).to_i
54 + @until_id = params.fetch(:to_id, 0).to_i
57
55
58 #calculate the routine
56 #calculate the routine
59 - @scorearray = calculate_max_score(@problems, @users,since_id,until_id)
57 + @scorearray = calculate_max_score(@problems, @users, @since_id, @until_id)
60
58
61 #rencer accordingly
59 #rencer accordingly
62 if params[:button] == 'download' then
60 if params[:button] == 'download' then
63 csv = gen_csv_from_scorearray(@scorearray,@problems)
61 csv = gen_csv_from_scorearray(@scorearray,@problems)
64 send_data csv, filename: 'max_score.csv'
62 send_data csv, filename: 'max_score.csv'
65 else
63 else
66 #render template: 'user_admin/user_stat'
64 #render template: 'user_admin/user_stat'
67 render 'max_score'
65 render 'max_score'
68 end
66 end
69
67
70 end
68 end
71
69
72 def score
70 def score
73 if params[:commit] == 'download csv'
71 if params[:commit] == 'download csv'
74 @problems = Problem.all
72 @problems = Problem.all
75 else
73 else
76 - @problems = Problem.find_available_problems
74 + @problems = Problem.available_problems
77 end
75 end
78 - @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
76 + @users = User.includes(:contests, :contest_stat).where(enabled: true)
79 @scorearray = Array.new
77 @scorearray = Array.new
80 @users.each do |u|
78 @users.each do |u|
81 ustat = Array.new
79 ustat = Array.new
82 ustat[0] = u
80 ustat[0] = u
83 @problems.each do |p|
81 @problems.each do |p|
84 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
82 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
85 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
83 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
86 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
84 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
87 else
85 else
88 ustat << [0,false]
86 ustat << [0,false]
89 end
87 end
90 end
88 end
@@ -1,19 +1,19
1 class SiteController < ApplicationController
1 class SiteController < ApplicationController
2
2
3 before_filter :site_admin_authorization, :except => 'login'
3 before_filter :site_admin_authorization, :except => 'login'
4
4
5 def login
5 def login
6 # Site administrator login
6 # Site administrator login
7 - @countries = Country.find(:all, :include => :sites)
7 + @countries = Country.includes(:sites).all
8 @country_select = @countries.collect { |c| [c.name, c.id] }
8 @country_select = @countries.collect { |c| [c.name, c.id] }
9
9
10 @country_select_with_all = [['Any',0]]
10 @country_select_with_all = [['Any',0]]
11 @countries.each do |country|
11 @countries.each do |country|
12 @country_select_with_all << [country.name, country.id]
12 @country_select_with_all << [country.name, country.id]
13 end
13 end
14
14
15 @site_select = []
15 @site_select = []
16 @countries.each do |country|
16 @countries.each do |country|
17 country.sites.each do |site|
17 country.sites.each do |site|
18 @site_select << ["#{site.name}, #{country.name}", site.id]
18 @site_select << ["#{site.name}, #{country.name}", site.id]
19 end
19 end
@@ -50,13 +50,18
50 redirect_to :controller => 'site', :action => 'login' and return
50 redirect_to :controller => 'site', :action => 'login' and return
51 end
51 end
52 begin
52 begin
53 @site = Site.find(session[:site_id], :include => :country)
53 @site = Site.find(session[:site_id], :include => :country)
54 rescue ActiveRecord::RecordNotFound
54 rescue ActiveRecord::RecordNotFound
55 @site = nil
55 @site = nil
56 end
56 end
57 if @site==nil
57 if @site==nil
58 redirect_to :controller => 'site', :action => 'login' and return
58 redirect_to :controller => 'site', :action => 'login' and return
59 end
59 end
60 end
60 end
61
61
62 + private
63 + def site_params
64 + params.require(:site).permit()
62 end
65 end
66 +
67 + end
@@ -1,20 +1,20
1 class SitesController < ApplicationController
1 class SitesController < ApplicationController
2
2
3 before_filter :admin_authorization
3 before_filter :admin_authorization
4
4
5 # GET /sites
5 # GET /sites
6 # GET /sites.xml
6 # GET /sites.xml
7 def index
7 def index
8 - @sites = Site.find(:all, :order => 'country_id')
8 + @sites = Site.order(:country_id)
9
9
10 respond_to do |format|
10 respond_to do |format|
11 format.html # index.html.erb
11 format.html # index.html.erb
12 format.xml { render :xml => @sites }
12 format.xml { render :xml => @sites }
13 end
13 end
14 end
14 end
15
15
16 # GET /sites/1
16 # GET /sites/1
17 # GET /sites/1.xml
17 # GET /sites/1.xml
18 def show
18 def show
19 @site = Site.find(params[:id])
19 @site = Site.find(params[:id])
20
20
@@ -56,36 +56,42
56 format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
56 format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
57 end
57 end
58 end
58 end
59 end
59 end
60
60
61 # PUT /sites/1
61 # PUT /sites/1
62 # PUT /sites/1.xml
62 # PUT /sites/1.xml
63 def update
63 def update
64 @site = Site.find(params[:id])
64 @site = Site.find(params[:id])
65 @site.clear_start_time_if_not_started
65 @site.clear_start_time_if_not_started
66
66
67 respond_to do |format|
67 respond_to do |format|
68 - if @site.update_attributes(params[:site])
68 + if @site.update_attributes(site_params)
69 flash[:notice] = 'Site was successfully updated.'
69 flash[:notice] = 'Site was successfully updated.'
70 format.html { redirect_to(@site) }
70 format.html { redirect_to(@site) }
71 format.xml { head :ok }
71 format.xml { head :ok }
72 else
72 else
73 format.html { render :action => "edit" }
73 format.html { render :action => "edit" }
74 format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
74 format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
75 end
75 end
76 end
76 end
77 end
77 end
78
78
79 # DELETE /sites/1
79 # DELETE /sites/1
80 # DELETE /sites/1.xml
80 # DELETE /sites/1.xml
81 def destroy
81 def destroy
82 @site = Site.find(params[:id])
82 @site = Site.find(params[:id])
83 @site.destroy
83 @site.destroy
84
84
85 respond_to do |format|
85 respond_to do |format|
86 format.html { redirect_to(sites_url) }
86 format.html { redirect_to(sites_url) }
87 format.xml { head :ok }
87 format.xml { head :ok }
88 end
88 end
89 end
89 end
90
90
91 + private
92 +
93 + def site_params
94 + params.require(:site).permit(:name,:started,:start_time,:country_id,:password)
91 end
95 end
96 +
97 + end
@@ -1,45 +1,60
1 class SubmissionsController < ApplicationController
1 class SubmissionsController < ApplicationController
2 - before_filter :authenticate
2 + before_action :authenticate
3 - before_filter :submission_authorization, only: [:show, :direct_edit_submission]
3 + before_action :submission_authorization, only: [:show, :direct_edit_submission, :download, :edit]
4 + before_action :admin_authorization, only: [:rejudge]
4
5
5 # GET /submissions
6 # GET /submissions
6 # GET /submissions.json
7 # GET /submissions.json
7 # Show problem selection and user's submission of that problem
8 # Show problem selection and user's submission of that problem
8 def index
9 def index
9 @user = @current_user
10 @user = @current_user
10 @problems = @user.available_problems
11 @problems = @user.available_problems
11
12
12 if params[:problem_id]==nil
13 if params[:problem_id]==nil
13 @problem = nil
14 @problem = nil
14 @submissions = nil
15 @submissions = nil
15 else
16 else
16 @problem = Problem.find_by_id(params[:problem_id])
17 @problem = Problem.find_by_id(params[:problem_id])
17 if (@problem == nil) or (not @problem.available)
18 if (@problem == nil) or (not @problem.available)
18 redirect_to main_list_path
19 redirect_to main_list_path
19 flash[:notice] = 'Error: submissions for that problem are not viewable.'
20 flash[:notice] = 'Error: submissions for that problem are not viewable.'
20 return
21 return
21 end
22 end
22 - @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
23 + @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
23 end
24 end
24 end
25 end
25
26
26 # GET /submissions/1
27 # GET /submissions/1
27 # GET /submissions/1.json
28 # GET /submissions/1.json
28 def show
29 def show
29 @submission = Submission.find(params[:id])
30 @submission = Submission.find(params[:id])
30
31
31 #log the viewing
32 #log the viewing
32 user = User.find(session[:user_id])
33 user = User.find(session[:user_id])
33 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
34 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
35 +
36 + @task = @submission.task
37 + end
38 +
39 + def download
40 + @submission = Submission.find(params[:id])
41 + send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'})
42 + end
43 +
44 + def compiler_msg
45 + @submission = Submission.find(params[:id])
46 + respond_to do |format|
47 + format.js
48 + end
34 end
49 end
35
50
36 #on-site new submission on specific problem
51 #on-site new submission on specific problem
37 def direct_edit_problem
52 def direct_edit_problem
38 @problem = Problem.find(params[:problem_id])
53 @problem = Problem.find(params[:problem_id])
39 @source = ''
54 @source = ''
40 render 'edit'
55 render 'edit'
41 end
56 end
42
57
43 # GET /submissions/1/edit
58 # GET /submissions/1/edit
44 def edit
59 def edit
45 @submission = Submission.find(params[:id])
60 @submission = Submission.find(params[:id])
@@ -51,87 +66,43
51
66
52 def get_latest_submission_status
67 def get_latest_submission_status
53 @problem = Problem.find(params[:pid])
68 @problem = Problem.find(params[:pid])
54 @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
69 @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
55 puts User.find(params[:uid]).login
70 puts User.find(params[:uid]).login
56 puts Problem.find(params[:pid]).name
71 puts Problem.find(params[:pid]).name
57 puts 'nil' unless @submission
72 puts 'nil' unless @submission
58 respond_to do |format|
73 respond_to do |format|
59 format.js
74 format.js
60 end
75 end
61 end
76 end
62
77
63 - # # GET /submissions/new
78 + # GET /submissions/:id/rejudge
64 - # # GET /submissions/new.json
79 + def rejudge
65 - # def new
80 + @submission = Submission.find(params[:id])
66 - # @submission = Submission.new
81 + @task = @submission.task
67 - #
82 + @task.status_inqueue! if @task
68 - # respond_to do |format|
83 + respond_to do |format|
69 - # format.html # new.html.erb
84 + format.js
70 - # format.json { render json: @submission }
85 + end
71 - # end
86 + end
72 - # end
73 - #
74 - #
75 - # # POST /submissions
76 - # # POST /submissions.json
77 - # def create
78 - # @submission = Submission.new(params[:submission])
79 - #
80 - # respond_to do |format|
81 - # if @submission.save
82 - # format.html { redirect_to @submission, notice: 'Submission was successfully created.' }
83 - # format.json { render json: @submission, status: :created, location: @submission }
84 - # else
85 - # format.html { render action: "new" }
86 - # format.json { render json: @submission.errors, status: :unprocessable_entity }
87 - # end
88 - # end
89 - # end
90 - #
91 - # # PUT /submissions/1
92 - # # PUT /submissions/1.json
93 - # def update
94 - # @submission = Submission.find(params[:id])
95 - #
96 - # respond_to do |format|
97 - # if @submission.update_attributes(params[:submission])
98 - # format.html { redirect_to @submission, notice: 'Submission was successfully updated.' }
99 - # format.json { head :no_content }
100 - # else
101 - # format.html { render action: "edit" }
102 - # format.json { render json: @submission.errors, status: :unprocessable_entity }
103 - # end
104 - # end
105 - # end
106 - #
107 - # # DELETE /submissions/1
108 - # # DELETE /submissions/1.json
109 - # def destroy
110 - # @submission = Submission.find(params[:id])
111 - # @submission.destroy
112 - #
113 - # respond_to do |format|
114 - # format.html { redirect_to submissions_url }
115 - # format.json { head :no_content }
116 - # end
117 - # end
118
87
119 protected
88 protected
89 +
120 def submission_authorization
90 def submission_authorization
121 #admin always has privileged
91 #admin always has privileged
122 if @current_user.admin?
92 if @current_user.admin?
123 return true
93 return true
124 end
94 end
125
95
126 sub = Submission.find(params[:id])
96 sub = Submission.find(params[:id])
127 if sub.problem.available?
97 if sub.problem.available?
128 puts "sub = #{sub.user.id}, current = #{@current_user.id}"
98 puts "sub = #{sub.user.id}, current = #{@current_user.id}"
129 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
99 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
130 end
100 end
131
101
132 #default to NO
102 #default to NO
133 unauthorized_redirect
103 unauthorized_redirect
134 return false
104 return false
135 end
105 end
136
106
107 +
137 end
108 end
@@ -20,43 +20,43
20 if params[:page] == 'all'
20 if params[:page] == 'all'
21 @users = User.all
21 @users = User.all
22 @paginated = false
22 @paginated = false
23 else
23 else
24 @users = User.paginate :page => params[:page]
24 @users = User.paginate :page => params[:page]
25 @paginated = true
25 @paginated = true
26 end
26 end
27 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
27 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
28 @contests = Contest.enabled
28 @contests = Contest.enabled
29 end
29 end
30
30
31 def active
31 def active
32 - sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
32 + sessions = ActiveRecord::SessionStore::Session.where("updated_at >= ?", 60.minutes.ago)
33 @users = []
33 @users = []
34 sessions.each do |session|
34 sessions.each do |session|
35 if session.data[:user_id]
35 if session.data[:user_id]
36 @users << User.find(session.data[:user_id])
36 @users << User.find(session.data[:user_id])
37 end
37 end
38 end
38 end
39 end
39 end
40
40
41 def show
41 def show
42 @user = User.find(params[:id])
42 @user = User.find(params[:id])
43 end
43 end
44
44
45 def new
45 def new
46 @user = User.new
46 @user = User.new
47 end
47 end
48
48
49 def create
49 def create
50 - @user = User.new(params[:user])
50 + @user = User.new(user_params)
51 @user.activated = true
51 @user.activated = true
52 if @user.save
52 if @user.save
53 flash[:notice] = 'User was successfully created.'
53 flash[:notice] = 'User was successfully created.'
54 redirect_to :action => 'index'
54 redirect_to :action => 'index'
55 else
55 else
56 render :action => 'new'
56 render :action => 'new'
57 end
57 end
58 end
58 end
59
59
60 def clear_last_ip
60 def clear_last_ip
61 @user = User.find(params[:id])
61 @user = User.find(params[:id])
62 @user.last_ip = nil
62 @user.last_ip = nil
@@ -65,88 +65,100
65 end
65 end
66
66
67 def create_from_list
67 def create_from_list
68 lines = params[:user_list]
68 lines = params[:user_list]
69
69
70 note = []
70 note = []
71
71
72 lines.split("\n").each do |line|
72 lines.split("\n").each do |line|
73 items = line.chomp.split(',')
73 items = line.chomp.split(',')
74 if items.length>=2
74 if items.length>=2
75 login = items[0]
75 login = items[0]
76 full_name = items[1]
76 full_name = items[1]
77 + remark =''
78 + user_alias = ''
77
79
78 added_random_password = false
80 added_random_password = false
79 - if items.length>=3
81 + if items.length >= 3 and items[2].chomp(" ").length > 0;
80 password = items[2].chomp(" ")
82 password = items[2].chomp(" ")
81 - user_alias = (items.length>=4) ? items[3] : login
82 else
83 else
83 password = random_password
84 password = random_password
84 - user_alias = (items.length>=4) ? items[3] : login
85 + add_random_password=true;
85 - added_random_password = true
86 + end
87 +
88 + if items.length>= 4 and items[3].chomp(" ").length > 0;
89 + user_alias = items[3].chomp(" ")
90 + else
91 + user_alias = login
92 + end
93 +
94 + if items.length>=5
95 + remark = items[4].strip;
86 end
96 end
87
97
88 user = User.find_by_login(login)
98 user = User.find_by_login(login)
89 if (user)
99 if (user)
90 user.full_name = full_name
100 user.full_name = full_name
91 user.password = password
101 user.password = password
102 + user.remark = remark
92 else
103 else
93 user = User.new({:login => login,
104 user = User.new({:login => login,
94 :full_name => full_name,
105 :full_name => full_name,
95 :password => password,
106 :password => password,
96 :password_confirmation => password,
107 :password_confirmation => password,
97 - :alias => user_alias})
108 + :alias => user_alias,
109 + :remark => remark})
98 end
110 end
99 user.activated = true
111 user.activated = true
100 user.save
112 user.save
101
113
102 if added_random_password
114 if added_random_password
103 note << "'#{login}' (+)"
115 note << "'#{login}' (+)"
104 else
116 else
105 note << login
117 note << login
106 end
118 end
107 end
119 end
108 end
120 end
109 - flash[:notice] = 'User(s) ' + note.join(', ') +
121 + flash[:success] = 'User(s) ' + note.join(', ') +
110 ' were successfully created. ' +
122 ' were successfully created. ' +
111 '( (+) - created with random passwords.)'
123 '( (+) - created with random passwords.)'
112 redirect_to :action => 'index'
124 redirect_to :action => 'index'
113 end
125 end
114
126
115 def edit
127 def edit
116 @user = User.find(params[:id])
128 @user = User.find(params[:id])
117 end
129 end
118
130
119 def update
131 def update
120 @user = User.find(params[:id])
132 @user = User.find(params[:id])
121 - if @user.update_attributes(params[:user])
133 + if @user.update_attributes(user_params)
122 flash[:notice] = 'User was successfully updated.'
134 flash[:notice] = 'User was successfully updated.'
123 redirect_to :action => 'show', :id => @user
135 redirect_to :action => 'show', :id => @user
124 else
136 else
125 render :action => 'edit'
137 render :action => 'edit'
126 end
138 end
127 end
139 end
128
140
129 def destroy
141 def destroy
130 User.find(params[:id]).destroy
142 User.find(params[:id]).destroy
131 redirect_to :action => 'index'
143 redirect_to :action => 'index'
132 end
144 end
133
145
134 def user_stat
146 def user_stat
135 if params[:commit] == 'download csv'
147 if params[:commit] == 'download csv'
136 @problems = Problem.all
148 @problems = Problem.all
137 else
149 else
138 - @problems = Problem.find_available_problems
150 + @problems = Problem.available_problems
139 end
151 end
140 - @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
152 + @users = User.includes(:contests, :contest_stat).where(enabled: true)
141 @scorearray = Array.new
153 @scorearray = Array.new
142 @users.each do |u|
154 @users.each do |u|
143 ustat = Array.new
155 ustat = Array.new
144 ustat[0] = u
156 ustat[0] = u
145 @problems.each do |p|
157 @problems.each do |p|
146 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
158 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
147 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
159 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
148 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
160 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
149 else
161 else
150 ustat << [0,false]
162 ustat << [0,false]
151 end
163 end
152 end
164 end
@@ -155,27 +167,27
155 if params[:commit] == 'download csv' then
167 if params[:commit] == 'download csv' then
156 csv = gen_csv_from_scorearray(@scorearray,@problems)
168 csv = gen_csv_from_scorearray(@scorearray,@problems)
157 send_data csv, filename: 'last_score.csv'
169 send_data csv, filename: 'last_score.csv'
158 else
170 else
159 render template: 'user_admin/user_stat'
171 render template: 'user_admin/user_stat'
160 end
172 end
161 end
173 end
162
174
163 def user_stat_max
175 def user_stat_max
164 if params[:commit] == 'download csv'
176 if params[:commit] == 'download csv'
165 @problems = Problem.all
177 @problems = Problem.all
166 else
178 else
167 - @problems = Problem.find_available_problems
179 + @problems = Problem.available_problems
168 end
180 end
169 - @users = User.find(:all, :include => [:contests, :contest_stat])
181 + @users = User.includes(:contests).includes(:contest_stat).all
170 @scorearray = Array.new
182 @scorearray = Array.new
171 #set up range from param
183 #set up range from param
172 since_id = params.fetch(:since_id, 0).to_i
184 since_id = params.fetch(:since_id, 0).to_i
173 until_id = params.fetch(:until_id, 0).to_i
185 until_id = params.fetch(:until_id, 0).to_i
174 @users.each do |u|
186 @users.each do |u|
175 ustat = Array.new
187 ustat = Array.new
176 ustat[0] = u
188 ustat[0] = u
177 @problems.each do |p|
189 @problems.each do |p|
178 max_points = 0
190 max_points = 0
179 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
191 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
180 max_points = sub.points if sub and sub.points and (sub.points > max_points)
192 max_points = sub.points if sub and sub.points and (sub.points > max_points)
181 end
193 end
@@ -192,25 +204,25
192 end
204 end
193 end
205 end
194
206
195 def import
207 def import
196 if params[:file]==''
208 if params[:file]==''
197 flash[:notice] = 'Error importing no file'
209 flash[:notice] = 'Error importing no file'
198 redirect_to :action => 'index' and return
210 redirect_to :action => 'index' and return
199 end
211 end
200 import_from_file(params[:file])
212 import_from_file(params[:file])
201 end
213 end
202
214
203 def random_all_passwords
215 def random_all_passwords
204 - users = User.find(:all)
216 + users = User.all
205 @prefix = params[:prefix] || ''
217 @prefix = params[:prefix] || ''
206 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
218 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
207 @changed = false
219 @changed = false
208 if request.request_method == 'POST'
220 if request.request_method == 'POST'
209 @non_admin_users.each do |user|
221 @non_admin_users.each do |user|
210 password = random_password
222 password = random_password
211 user.password = password
223 user.password = password
212 user.password_confirmation = password
224 user.password_confirmation = password
213 user.save
225 user.save
214 end
226 end
215 @changed = true
227 @changed = true
216 end
228 end
@@ -315,25 +327,25
315 if params[:reset_timer]
327 if params[:reset_timer]
316 logout_users(users)
328 logout_users(users)
317 end
329 end
318
330
319 flash[:notice] = 'User(s) ' + note.join(', ') +
331 flash[:notice] = 'User(s) ' + note.join(', ') +
320 ' were successfully modified. '
332 ' were successfully modified. '
321 redirect_to :action => 'contest_management'
333 redirect_to :action => 'contest_management'
322 end
334 end
323
335
324 # admin management
336 # admin management
325
337
326 def admin
338 def admin
327 - @admins = User.find(:all).find_all {|user| user.admin? }
339 + @admins = User.all.find_all {|user| user.admin? }
328 end
340 end
329
341
330 def grant_admin
342 def grant_admin
331 login = params[:login]
343 login = params[:login]
332 user = User.find_by_login(login)
344 user = User.find_by_login(login)
333 if user!=nil
345 if user!=nil
334 admin_role = Role.find_by_name('admin')
346 admin_role = Role.find_by_name('admin')
335 user.roles << admin_role
347 user.roles << admin_role
336 else
348 else
337 flash[:notice] = 'Unknown user'
349 flash[:notice] = 'Unknown user'
338 end
350 end
339 flash[:notice] = 'User added as admins'
351 flash[:notice] = 'User added as admins'
@@ -386,24 +398,57
386 user = User.find_by_login(line.chomp)
398 user = User.find_by_login(line.chomp)
387 if user
399 if user
388 send_mail(user.email, mail_subject, mail_body)
400 send_mail(user.email, mail_subject, mail_body)
389 note << user.login
401 note << user.login
390 end
402 end
391 end
403 end
392
404
393 flash[:notice] = 'User(s) ' + note.join(', ') +
405 flash[:notice] = 'User(s) ' + note.join(', ') +
394 ' were successfully modified. '
406 ' were successfully modified. '
395 redirect_to :action => 'mass_mailing'
407 redirect_to :action => 'mass_mailing'
396 end
408 end
397
409
410 + #bulk manage
411 + def bulk_manage
412 +
413 + begin
414 + @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 + rescue Exception
417 + flash[:error] = 'Regular Expression is malformed'
418 + @users = nil
419 + end
420 +
421 + if params[:commit]
422 + @action = {}
423 + @action[:set_enable] = params[:enabled]
424 + @action[:enabled] = params[:enable] == "1"
425 + @action[:gen_password] = params[:gen_password]
426 + end
427 +
428 + if params[:commit] == "Perform"
429 + if @action[:set_enable]
430 + @users.update_all(enabled: @action[:enabled])
431 + end
432 + if @action[:gen_password]
433 + @users.each do |u|
434 + password = random_password
435 + u.password = password
436 + u.password_confirmation = password
437 + u.save
438 + end
439 + end
440 + end
441 + end
442 +
398 protected
443 protected
399
444
400 def random_password(length=5)
445 def random_password(length=5)
401 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
446 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
402 newpass = ""
447 newpass = ""
403 length.times { newpass << chars[rand(chars.size-1)] }
448 length.times { newpass << chars[rand(chars.size-1)] }
404 return newpass
449 return newpass
405 end
450 end
406
451
407 def import_from_file(f)
452 def import_from_file(f)
408 data_hash = YAML.load(f)
453 data_hash = YAML.load(f)
409 @import_log = ""
454 @import_log = ""
@@ -512,27 +557,32
512 problem.each { |p| header << p.name }
557 problem.each { |p| header << p.name }
513 header += ['Total','Passed']
558 header += ['Total','Passed']
514 csv << header
559 csv << header
515 #add data
560 #add data
516 scorearray.each do |sc|
561 scorearray.each do |sc|
517 total = num_passed = 0
562 total = num_passed = 0
518 row = Array.new
563 row = Array.new
519 sc.each_index do |i|
564 sc.each_index do |i|
520 if i == 0
565 if i == 0
521 row << sc[i].login
566 row << sc[i].login
522 row << sc[i].full_name
567 row << sc[i].full_name
523 row << sc[i].activated
568 row << sc[i].activated
524 - row << (sc[i].try(:contest_stat).try(:started_at).nil? 'no' : 'yes')
569 + row << (sc[i].try(:contest_stat).try(:started_at).nil? ? 'no' : 'yes')
525 row << sc[i].contests.collect {|c| c.name}.join(', ')
570 row << sc[i].contests.collect {|c| c.name}.join(', ')
526 else
571 else
527 row << sc[i][0]
572 row << sc[i][0]
528 total += sc[i][0]
573 total += sc[i][0]
529 num_passed += 1 if sc[i][1]
574 num_passed += 1 if sc[i][1]
530 end
575 end
531 end
576 end
532 row << total
577 row << total
533 row << num_passed
578 row << num_passed
534 csv << row
579 csv << row
535 end
580 end
536 end
581 end
537 end
582 end
583 +
584 + private
585 + def user_params
586 + params.require(:user).permit(:login,:password,:password_confirmation,:email, :alias, :full_name,:remark)
538 end
587 end
588 + end
@@ -43,25 +43,25
43 end
43 end
44
44
45 def new
45 def new
46 @user = User.new
46 @user = User.new
47 render :action => 'new', :layout => 'empty'
47 render :action => 'new', :layout => 'empty'
48 end
48 end
49
49
50 def register
50 def register
51 if(params[:cancel])
51 if(params[:cancel])
52 redirect_to :controller => 'main', :action => 'login'
52 redirect_to :controller => 'main', :action => 'login'
53 return
53 return
54 end
54 end
55 - @user = User.new(params[:user])
55 + @user = User.new(user_params)
56 @user.password_confirmation = @user.password = User.random_password
56 @user.password_confirmation = @user.password = User.random_password
57 @user.activated = false
57 @user.activated = false
58 if (@user.valid?) and (@user.save)
58 if (@user.valid?) and (@user.save)
59 if send_confirmation_email(@user)
59 if send_confirmation_email(@user)
60 render :action => 'new_splash', :layout => 'empty'
60 render :action => 'new_splash', :layout => 'empty'
61 else
61 else
62 @admin_email = GraderConfiguration['system.admin_email']
62 @admin_email = GraderConfiguration['system.admin_email']
63 render :action => 'email_error', :layout => 'empty'
63 render :action => 'email_error', :layout => 'empty'
64 end
64 end
65 else
65 else
66 @user.errors.add(:base,"Email cannot be blank") if @user.email==''
66 @user.errors.add(:base,"Email cannot be blank") if @user.email==''
67 render :action => 'new', :layout => 'empty'
67 render :action => 'new', :layout => 'empty'
@@ -201,14 +201,18
201 def profile_authorization
201 def profile_authorization
202 #if view admins' profile, allow only admin
202 #if view admins' profile, allow only admin
203 return false unless(params[:id])
203 return false unless(params[:id])
204 user = User.find(params[:id])
204 user = User.find(params[:id])
205 return false unless user
205 return false unless user
206 return admin_authorization if user.admin?
206 return admin_authorization if user.admin?
207 return true if GraderConfiguration["right.user_view_submission"]
207 return true if GraderConfiguration["right.user_view_submission"]
208
208
209 #finally, we allow only admin
209 #finally, we allow only admin
210 admin_authorization
210 admin_authorization
211 end
211 end
212
212
213 + private
214 + def user_params
215 + params.require(:user).permit(:login, :full_name, :email)
216 + end
213
217
214 end
218 end
@@ -187,13 +187,35
187 </tr>
187 </tr>
188 </table>
188 </table>
189 </div>
189 </div>
190 TITLEBAR
190 TITLEBAR
191 result.html_safe
191 result.html_safe
192 end
192 end
193
193
194 def markdown(text)
194 def markdown(text)
195 markdown = RDiscount.new(text)
195 markdown = RDiscount.new(text)
196 markdown.to_html.html_safe
196 markdown.to_html.html_safe
197 end
197 end
198
198
199 +
200 + BOOTSTRAP_FLASH_MSG = {
201 + success: 'alert-success',
202 + error: 'alert-danger',
203 + alert: 'alert-block',
204 + notice: 'alert-info'
205 + }
206 +
207 + def bootstrap_class_for(flash_type)
208 + BOOTSTRAP_FLASH_MSG.fetch(flash_type.to_sym, flash_type.to_s)
199 end
209 end
210 +
211 + def flash_messages
212 + flash.each do |msg_type, message|
213 + concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} fade in") do
214 + concat content_tag(:button, 'x', class: "close", data: { dismiss: 'alert' })
215 + concat message
216 + end)
217 + end
218 + nil
219 + end
220 +
221 + end
@@ -1,21 +1,15
1 class Announcement < ActiveRecord::Base
1 class Announcement < ActiveRecord::Base
2
2
3 - def self.find_published(contest_started=false)
3 + def self.published(contest_started=false)
4 if contest_started
4 if contest_started
5 - Announcement.find(:all,
5 + where(published: true).where(frontpage: false).order(created_at: :desc)
6 - :conditions => "(published = 1) AND (frontpage = 0)",
7 - :order => "created_at DESC")
8 else
6 else
9 - Announcement.find(:all,
7 + where(published: true).where(frontpage: false).where(contest_only: false).order(created_at: :desc)
10 - :conditions => "(published = 1) AND (frontpage = 0) AND (contest_only = 0)",
11 - :order => "created_at DESC")
12 end
8 end
13 end
9 end
14
10
15 - def self.find_for_frontpage
11 + def self.frontpage
16 - Announcement.find(:all,
12 + where(published: 1).where(frontpage: 1).order(created_at: :desc)
17 - :conditions => "(published = 1) AND (frontpage = 1)",
18 - :order => "created_at DESC")
19 end
13 end
20
14
21 end
15 end
@@ -1,8 +1,8
1 class Contest < ActiveRecord::Base
1 class Contest < ActiveRecord::Base
2
2
3 has_and_belongs_to_many :users
3 has_and_belongs_to_many :users
4 has_and_belongs_to_many :problems
4 has_and_belongs_to_many :problems
5
5
6 - scope :enabled, :conditions => {:enabled => true}
6 + scope :enabled, -> { where(enabled: true) }
7
7
8 end
8 end
@@ -1,24 +1,26
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'
14 + SINGLE_USER_KEY = 'system.single_user_mode'
13
15
14 cattr_accessor :config_cache
16 cattr_accessor :config_cache
15 cattr_accessor :task_grading_info_cache
17 cattr_accessor :task_grading_info_cache
16 cattr_accessor :contest_time_str
18 cattr_accessor :contest_time_str
17 cattr_accessor :contest_time
19 cattr_accessor :contest_time
18
20
19 GraderConfiguration.config_cache = nil
21 GraderConfiguration.config_cache = nil
20 GraderConfiguration.task_grading_info_cache = nil
22 GraderConfiguration.task_grading_info_cache = nil
21
23
22 def self.config_cached?
24 def self.config_cached?
23 (defined? CONFIGURATION_CACHE_ENABLED) and (CONFIGURATION_CACHE_ENABLED)
25 (defined? CONFIGURATION_CACHE_ENABLED) and (CONFIGURATION_CACHE_ENABLED)
24 end
26 end
@@ -61,24 +63,28
61
63
62 def self.show_tasks_to?(user)
64 def self.show_tasks_to?(user)
63 if time_limit_mode?
65 if time_limit_mode?
64 return false if not user.contest_started?
66 return false if not user.contest_started?
65 end
67 end
66 return true
68 return true
67 end
69 end
68
70
69 def self.show_grading_result
71 def self.show_grading_result
70 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
72 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
71 end
73 end
72
74
75 + def self.show_testcase
76 + return get(VIEW_TESTCASE)
77 + end
78 +
73 def self.allow_test_request(user)
79 def self.allow_test_request(user)
74 mode = get(SYSTEM_MODE_CONF_KEY)
80 mode = get(SYSTEM_MODE_CONF_KEY)
75 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
81 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
76 if (mode=='contest')
82 if (mode=='contest')
77 return false if ((user.site!=nil) and
83 return false if ((user.site!=nil) and
78 ((user.site.started!=true) or
84 ((user.site.started!=true) or
79 (early_timeout and (user.site.time_left < 30.minutes))))
85 (early_timeout and (user.site.time_left < 30.minutes))))
80 end
86 end
81 return false if mode=='analysis'
87 return false if mode=='analysis'
82 return true
88 return true
83 end
89 end
84
90
@@ -143,25 +149,25
143 return val
149 return val
144
150
145 when 'integer'
151 when 'integer'
146 return val.to_i
152 return val.to_i
147
153
148 when 'boolean'
154 when 'boolean'
149 return (val=='true')
155 return (val=='true')
150 end
156 end
151 end
157 end
152
158
153 def self.read_config
159 def self.read_config
154 GraderConfiguration.config_cache = {}
160 GraderConfiguration.config_cache = {}
155 - GraderConfiguration.find(:all).each do |conf|
161 + GraderConfiguration.all.each do |conf|
156 key = conf.key
162 key = conf.key
157 val = conf.value
163 val = conf.value
158 GraderConfiguration.config_cache[key] = GraderConfiguration.convert_type(val,conf.value_type)
164 GraderConfiguration.config_cache[key] = GraderConfiguration.convert_type(val,conf.value_type)
159 end
165 end
160 end
166 end
161
167
162 def self.read_one_key(key)
168 def self.read_one_key(key)
163 conf = GraderConfiguration.find_by_key(key)
169 conf = GraderConfiguration.find_by_key(key)
164 if conf
170 if conf
165 return GraderConfiguration.convert_type(conf.value,conf.value_type)
171 return GraderConfiguration.convert_type(conf.value,conf.value_type)
166 else
172 else
167 return nil
173 return nil
@@ -1,55 +1,46
1 class GraderProcess < ActiveRecord::Base
1 class GraderProcess < ActiveRecord::Base
2
2
3 def self.find_by_host_and_pid(host,pid)
3 def self.find_by_host_and_pid(host,pid)
4 - return GraderProcess.find(:first,
4 + return GraderProcess.where(host:host).where(pid: pid).first
5 - :conditions => {
6 - :host => host,
7 - :pid => pid
8 - })
9 end
5 end
10
6
11 def self.register(host,pid,mode)
7 def self.register(host,pid,mode)
12 grader = GraderProcess.find_by_host_and_pid(host,pid)
8 grader = GraderProcess.find_by_host_and_pid(host,pid)
13 if grader
9 if grader
14 grader.mode = mode
10 grader.mode = mode
15 grader.active = nil
11 grader.active = nil
16 grader.task_id = nil
12 grader.task_id = nil
17 grader.task_type = nil
13 grader.task_type = nil
18 grader.terminated = false
14 grader.terminated = false
19 grader.save
15 grader.save
20 else
16 else
21 grader = GraderProcess.create(:host => host,
17 grader = GraderProcess.create(:host => host,
22 :pid => pid,
18 :pid => pid,
23 :mode => mode,
19 :mode => mode,
24 :terminated => false)
20 :terminated => false)
25 end
21 end
26 grader
22 grader
27 end
23 end
28
24
29 def self.find_running_graders
25 def self.find_running_graders
30 - GraderProcess.find(:all,
26 + where(terminated: false)
31 - :conditions => {:terminated => 0})
32 end
27 end
33
28
34 def self.find_terminated_graders
29 def self.find_terminated_graders
35 - GraderProcess.find(:all,
30 + where(terminated: true)
36 - :conditions => "`terminated`")
37 end
31 end
38
32
39 def self.find_stalled_process
33 def self.find_stalled_process
40 - GraderProcess.find(:all,
34 + where(terminated: false).where(active: true).where("updated_at < ?",Time.now.gmtime - GraderProcess.stalled_time)
41 - :conditions => ["(`terminated` = 0) AND active AND " +
42 - "(updated_at < ?)",
43 - Time.now.gmtime - GraderProcess.stalled_time])
44 end
35 end
45
36
46 def report_active(task=nil)
37 def report_active(task=nil)
47 self.active = true
38 self.active = true
48 if task!=nil
39 if task!=nil
49 self.task_id = task.id
40 self.task_id = task.id
50 self.task_type = task.class.to_s
41 self.task_type = task.class.to_s
51 else
42 else
52 self.task_id = nil
43 self.task_id = nil
53 self.task_type = nil
44 self.task_type = nil
54 end
45 end
55 self.save
46 self.save
@@ -1,19 +1,19
1 class Language < ActiveRecord::Base
1 class Language < ActiveRecord::Base
2
2
3 @@languages_by_ext = {}
3 @@languages_by_ext = {}
4
4
5 def self.cache_ext_hash
5 def self.cache_ext_hash
6 @@languages_by_ext = {}
6 @@languages_by_ext = {}
7 - Language.find(:all).each do |language|
7 + Language.all.each do |language|
8 language.common_ext.split(',').each do |ext|
8 language.common_ext.split(',').each do |ext|
9 @@languages_by_ext[ext] = language
9 @@languages_by_ext[ext] = language
10 end
10 end
11 end
11 end
12 end
12 end
13
13
14 def self.find_by_extension(ext)
14 def self.find_by_extension(ext)
15 if @@languages_by_ext.length == 0
15 if @@languages_by_ext.length == 0
16 Language.cache_ext_hash
16 Language.cache_ext_hash
17 end
17 end
18 if @@languages_by_ext.has_key? ext
18 if @@languages_by_ext.has_key? ext
19 return @@languages_by_ext[ext]
19 return @@languages_by_ext[ext]
@@ -1,5 +1,4
1 class Login < ActiveRecord::Base
1 class Login < ActiveRecord::Base
2 belongs_to :user
2 belongs_to :user
3
3
4 - attr_accessible :ip_address, :logged_in_at, :user_id
5 end
4 end
@@ -14,28 +14,26
14 #
14 #
15
15
16 attr_accessor :replied_messages
16 attr_accessor :replied_messages
17
17
18 def self.find_all_sent_by_user(user)
18 def self.find_all_sent_by_user(user)
19 messages = user.messages
19 messages = user.messages
20 replied_messages = user.replied_messages
20 replied_messages = user.replied_messages
21 Message.build_replying_message_hierarchy messages, replied_messages
21 Message.build_replying_message_hierarchy messages, replied_messages
22 return messages
22 return messages
23 end
23 end
24
24
25 def self.find_all_system_unreplied_messages
25 def self.find_all_system_unreplied_messages
26 - self.find(:all,
26 + where('ISNULL(receiver_id) ' +
27 - :conditions => 'ISNULL(receiver_id) ' +
27 + 'AND (ISNULL(replied) OR replied=0)')
28 - 'AND (ISNULL(replied) OR replied=0)',
29 - :order => 'created_at')
30 end
28 end
31
29
32 def self.build_replying_message_hierarchy(*args)
30 def self.build_replying_message_hierarchy(*args)
33 # manually build replies hierarchy (to improve efficiency)
31 # manually build replies hierarchy (to improve efficiency)
34 all_messages = {}
32 all_messages = {}
35
33
36 args.each do |collection|
34 args.each do |collection|
37 collection.each do |m|
35 collection.each do |m|
38 all_messages[m.id] = m
36 all_messages[m.id] = m
39 m.replied_messages = []
37 m.replied_messages = []
40 end
38 end
41 end
39 end
@@ -1,30 +1,31
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_many :test_pairs, :dependent => :delete_all
5 has_many :test_pairs, :dependent => :delete_all
6 has_many :testcases, :dependent => :destroy
6 has_many :testcases, :dependent => :destroy
7
7
8 validates_presence_of :name
8 validates_presence_of :name
9 - validates_format_of :name, :with => /^\w+$/
9 + validates_format_of :name, :with => /\A\w+\z/
10 validates_presence_of :full_name
10 validates_presence_of :full_name
11
11
12 - scope :available, :conditions => {:available => true}
12 + scope :available, -> { where(available: true) }
13
13
14 DEFAULT_TIME_LIMIT = 1
14 DEFAULT_TIME_LIMIT = 1
15 DEFAULT_MEMORY_LIMIT = 32
15 DEFAULT_MEMORY_LIMIT = 32
16
16
17 - def self.find_available_problems
17 + def self.available_problems
18 - Problem.available.all(:order => "date_added DESC, name ASC")
18 + available.order(date_added: :desc).order(:name)
19 + #Problem.available.all(:order => "date_added DESC, name ASC")
19 end
20 end
20
21
21 def self.create_from_import_form_params(params, old_problem=nil)
22 def self.create_from_import_form_params(params, old_problem=nil)
22 org_problem = old_problem || Problem.new
23 org_problem = old_problem || Problem.new
23 import_params, problem = Problem.extract_params_and_check(params,
24 import_params, problem = Problem.extract_params_and_check(params,
24 org_problem)
25 org_problem)
25
26
26 if !problem.errors.empty?
27 if !problem.errors.empty?
27 return problem, 'Error importing'
28 return problem, 'Error importing'
28 end
29 end
29
30
30 problem.full_score = 100
31 problem.full_score = 100
@@ -51,25 +52,27
51
52
52 return problem, importer.log_msg
53 return problem, importer.log_msg
53 end
54 end
54
55
55 def self.download_file_basedir
56 def self.download_file_basedir
56 return "#{Rails.root}/data/tasks"
57 return "#{Rails.root}/data/tasks"
57 end
58 end
58
59
59 def get_submission_stat
60 def get_submission_stat
60 result = Hash.new
61 result = Hash.new
61 #total number of submission
62 #total number of submission
62 result[:total_sub] = Submission.where(problem_id: self.id).count
63 result[:total_sub] = Submission.where(problem_id: self.id).count
63 - result[:attempted_user] = Submission.where(problem_id: self.id).group_by(:user_id)
64 + result[:attempted_user] = Submission.where(problem_id: self.id).group(:user_id)
65 + result[:pass] = Submission.where(problem_id: self.id).where("points >= ?",self.full_score).count
66 + return result
64 end
67 end
65
68
66 def long_name
69 def long_name
67 "[#{name}] #{full_name}"
70 "[#{name}] #{full_name}"
68 end
71 end
69
72
70 protected
73 protected
71
74
72 def self.to_i_or_default(st, default)
75 def self.to_i_or_default(st, default)
73 if st!=''
76 if st!=''
74 result = st.to_i
77 result = st.to_i
75 end
78 end
@@ -4,77 +4,66
4 belongs_to :problem
4 belongs_to :problem
5 belongs_to :user
5 belongs_to :user
6
6
7 before_validation :assign_problem
7 before_validation :assign_problem
8 before_validation :assign_language
8 before_validation :assign_language
9
9
10 validates_presence_of :source
10 validates_presence_of :source
11 validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long'
11 validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long'
12 validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short'
12 validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short'
13 validate :must_have_valid_problem
13 validate :must_have_valid_problem
14 validate :must_specify_language
14 validate :must_specify_language
15
15
16 + has_one :task
17 +
16 before_save :assign_latest_number_if_new_recond
18 before_save :assign_latest_number_if_new_recond
17
19
18 def self.find_last_by_user_and_problem(user_id, problem_id)
20 def self.find_last_by_user_and_problem(user_id, problem_id)
19 - last_sub = find(:first,
21 + where("user_id = ? AND problem_id = ?",user_id,problem_id).last
20 - :conditions => {:user_id => user_id,
21 - :problem_id => problem_id},
22 - :order => 'number DESC')
23 - return last_sub
24 end
22 end
25
23
26 def self.find_all_last_by_problem(problem_id)
24 def self.find_all_last_by_problem(problem_id)
27 # need to put in SQL command, maybe there's a better way
25 # need to put in SQL command, maybe there's a better way
28 Submission.includes(:user).find_by_sql("SELECT * FROM submissions " +
26 Submission.includes(:user).find_by_sql("SELECT * FROM submissions " +
29 "WHERE id = " +
27 "WHERE id = " +
30 "(SELECT MAX(id) FROM submissions AS subs " +
28 "(SELECT MAX(id) FROM submissions AS subs " +
31 "WHERE subs.user_id = submissions.user_id AND " +
29 "WHERE subs.user_id = submissions.user_id AND " +
32 "problem_id = " + problem_id.to_s + " " +
30 "problem_id = " + problem_id.to_s + " " +
33 "GROUP BY user_id) " +
31 "GROUP BY user_id) " +
34 "ORDER BY user_id")
32 "ORDER BY user_id")
35 end
33 end
36
34
37 def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id)
35 def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id)
38 records = Submission.where(problem_id: problem_id,user_id: user_id)
36 records = Submission.where(problem_id: problem_id,user_id: user_id)
39 records = records.where('id >= ?',since_id) if since_id > 0
37 records = records.where('id >= ?',since_id) if since_id > 0
40 records = records.where('id <= ?',until_id) if until_id > 0
38 records = records.where('id <= ?',until_id) if until_id > 0
41 records.all
39 records.all
42 end
40 end
43
41
44 def self.find_last_for_all_available_problems(user_id)
42 def self.find_last_for_all_available_problems(user_id)
45 submissions = Array.new
43 submissions = Array.new
46 - problems = Problem.find_available_problems
44 + problems = Problem.available_problems
47 problems.each do |problem|
45 problems.each do |problem|
48 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
46 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
49 submissions << sub if sub!=nil
47 submissions << sub if sub!=nil
50 end
48 end
51 submissions
49 submissions
52 end
50 end
53
51
54 def self.find_by_user_problem_number(user_id, problem_id, number)
52 def self.find_by_user_problem_number(user_id, problem_id, number)
55 - Submission.find(:first,
53 + where("user_id = ? AND problem_id = ? AND number = ?",user_id,problem_id,number).first
56 - :conditions => {
57 - :user_id => user_id,
58 - :problem_id => problem_id,
59 - :number => number
60 - })
61 end
54 end
62
55
63 def self.find_all_by_user_problem(user_id, problem_id)
56 def self.find_all_by_user_problem(user_id, problem_id)
64 - Submission.find(:all,
57 + where("user_id = ? AND problem_id = ?",user_id,problem_id)
65 - :conditions => {
66 - :user_id => user_id,
67 - :problem_id => problem_id,
68 - })
69 end
58 end
70
59
71 def download_filename
60 def download_filename
72 if self.problem.output_only
61 if self.problem.output_only
73 return self.source_filename
62 return self.source_filename
74 else
63 else
75 timestamp = self.submitted_at.localtime.strftime("%H%M%S")
64 timestamp = self.submitted_at.localtime.strftime("%H%M%S")
76 return "#{self.problem.name}-#{timestamp}.#{self.language.ext}"
65 return "#{self.problem.name}-#{timestamp}.#{self.language.ext}"
77 end
66 end
78 end
67 end
79
68
80 protected
69 protected
@@ -1,3 +1,3
1 class SubmissionViewLog < ActiveRecord::Base
1 class SubmissionViewLog < ActiveRecord::Base
2 - attr_accessible :submission_id, :user_id
2 + #attr_accessible :submission_id, :user_id
3 end
3 end
@@ -39,28 +39,25
39 "inqueue"
39 "inqueue"
40 when Task::STATUS_GRADING
40 when Task::STATUS_GRADING
41 "grading"
41 "grading"
42 when Task::STATUS_COMPLETE
42 when Task::STATUS_COMPLETE
43 "complete"
43 "complete"
44 end
44 end
45 end
45 end
46
46
47 def self.get_inqueue_and_change_status(status)
47 def self.get_inqueue_and_change_status(status)
48 task = nil
48 task = nil
49 begin
49 begin
50 Task.transaction do
50 Task.transaction do
51 - task = Task.find(:first,
51 + task = Task.where(status: Task::STATUS_INQUEUE).lock(true).first
52 - :order => "created_at",
53 - :conditions => {:status=> Task::STATUS_INQUEUE},
54 - :lock => true)
55 if task!=nil
52 if task!=nil
56 task.status = status
53 task.status = status
57 task.save!
54 task.save!
58 end
55 end
59 end
56 end
60
57
61 rescue
58 rescue
62 task = nil
59 task = nil
63
60
64 end
61 end
65 task
62 task
66 end
63 end
@@ -7,49 +7,46
7 # it works as well with problem=nil. In this case, we shall provide
7 # it works as well with problem=nil. In this case, we shall provide
8 # a "default" execution environment for it. This can be done
8 # a "default" execution environment for it. This can be done
9 # seamlessly by using TestRequest#problem_name or
9 # seamlessly by using TestRequest#problem_name or
10 # TestRequest#name_of(problem) when retrieving the name of the
10 # TestRequest#name_of(problem) when retrieving the name of the
11 # problem: #name_of would return problem.name when problem!=nil and
11 # problem: #name_of would return problem.name when problem!=nil and
12 # it would return "default" when problem=nil, #problem_name just
12 # it would return "default" when problem=nil, #problem_name just
13 # call #name_of.
13 # call #name_of.
14 #
14 #
15
15
16 require 'fileutils'
16 require 'fileutils'
17
17
18 class TestRequest < Task
18 class TestRequest < Task
19 -
19 + self.table_name = "test_requests"
20 - set_table_name "test_requests"
21
20
22 belongs_to :user
21 belongs_to :user
23 belongs_to :problem
22 belongs_to :problem
24 belongs_to :submission
23 belongs_to :submission
25
24
26 validates_presence_of :submission
25 validates_presence_of :submission
27 validate :must_have_valid_problem
26 validate :must_have_valid_problem
28
27
29 def problem_name
28 def problem_name
30 TestRequest.name_of(self.problem)
29 TestRequest.name_of(self.problem)
31 end
30 end
32
31
33 def language
32 def language
34 self.submission.language
33 self.submission.language
35 end
34 end
36
35
37 def self.get_inqueue_and_change_status(status)
36 def self.get_inqueue_and_change_status(status)
38 # since there will be only one grader grading TestRequest
37 # since there will be only one grader grading TestRequest
39 # we do not need locking (hopefully)
38 # we do not need locking (hopefully)
40
39
41 - test_request = TestRequest.find(:first,
40 + test_request = TestRequest.where(status: Task::STATUS_INQUEUE).first
42 - :order => "created_at",
43 - :conditions => {:status=> Task::STATUS_INQUEUE})
44 if test_request!=nil
41 if test_request!=nil
45 test_request.status = status
42 test_request.status = status
46 test_request.save!
43 test_request.save!
47 end
44 end
48
45
49 test_request
46 test_request
50 end
47 end
51
48
52 # interfacing with form
49 # interfacing with form
53 def self.new_from_form_params(user,params)
50 def self.new_from_form_params(user,params)
54 test_request = TestRequest.new
51 test_request = TestRequest.new
55 test_request.user = user
52 test_request.user = user
@@ -1,4 +1,4
1 class Testcase < ActiveRecord::Base
1 class Testcase < ActiveRecord::Base
2 belongs_to :problem
2 belongs_to :problem
3 - attr_accessible :group, :input, :num, :score, :sol
3 + #attr_accessible :group, :input, :num, :score, :sol
4 end
4 end
@@ -1,46 +1,44
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
10
11 - has_many :test_requests, :order => "submitted_at DESC"
11 + has_many :test_requests, -> {order(submitted_at: DESC)}
12
12
13 - has_many :messages,
13 + has_many :messages, -> { order(created_at: DESC) },
14 :class_name => "Message",
14 :class_name => "Message",
15 - :foreign_key => "sender_id",
15 + :foreign_key => "sender_id"
16 - :order => 'created_at DESC'
17
16
18 - has_many :replied_messages,
17 + has_many :replied_messages, -> { order(created_at: DESC) },
19 :class_name => "Message",
18 :class_name => "Message",
20 - :foreign_key => "receiver_id",
19 + :foreign_key => "receiver_id"
21 - :order => 'created_at DESC'
22
20
23 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
21 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
24
22
25 belongs_to :site
23 belongs_to :site
26 belongs_to :country
24 belongs_to :country
27
25
28 - has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
26 + has_and_belongs_to_many :contests, -> { order(:name); uniq}
29
27
30 - scope :activated_users, :conditions => {:activated => true}
28 + scope :activated_users, -> {where activated: true}
31
29
32 validates_presence_of :login
30 validates_presence_of :login
33 validates_uniqueness_of :login
31 validates_uniqueness_of :login
34 - validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
32 + validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
35 validates_length_of :login, :within => 3..30
33 validates_length_of :login, :within => 3..30
36
34
37 validates_presence_of :full_name
35 validates_presence_of :full_name
38 validates_length_of :full_name, :minimum => 1
36 validates_length_of :full_name, :minimum => 1
39
37
40 validates_presence_of :password, :if => :password_required?
38 validates_presence_of :password, :if => :password_required?
41 validates_length_of :password, :within => 4..20, :if => :password_required?
39 validates_length_of :password, :within => 4..20, :if => :password_required?
42 validates_confirmation_of :password, :if => :password_required?
40 validates_confirmation_of :password, :if => :password_required?
43
41
44 validates_format_of :email,
42 validates_format_of :email,
45 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
43 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
46 :if => :email_validation?
44 :if => :email_validation?
@@ -120,32 +118,32
120 def verify_activation_key(key)
118 def verify_activation_key(key)
121 key == activation_key
119 key == activation_key
122 end
120 end
123
121
124 def self.random_password(length=5)
122 def self.random_password(length=5)
125 chars = 'abcdefghjkmnopqrstuvwxyz'
123 chars = 'abcdefghjkmnopqrstuvwxyz'
126 password = ''
124 password = ''
127 length.times { password << chars[rand(chars.length - 1)] }
125 length.times { password << chars[rand(chars.length - 1)] }
128 password
126 password
129 end
127 end
130
128
131 def self.find_non_admin_with_prefix(prefix='')
129 def self.find_non_admin_with_prefix(prefix='')
132 - users = User.find(:all)
130 + users = User.all
133 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
131 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
134 end
132 end
135
133
136 # Contest information
134 # Contest information
137
135
138 def self.find_users_with_no_contest()
136 def self.find_users_with_no_contest()
139 - users = User.find(:all)
137 + users = User.all
140 return users.find_all { |u| u.contests.length == 0 }
138 return users.find_all { |u| u.contests.length == 0 }
141 end
139 end
142
140
143
141
144 def contest_time_left
142 def contest_time_left
145 if GraderConfiguration.contest_mode?
143 if GraderConfiguration.contest_mode?
146 return nil if site==nil
144 return nil if site==nil
147 return site.time_left
145 return site.time_left
148 elsif GraderConfiguration.indv_contest_mode?
146 elsif GraderConfiguration.indv_contest_mode?
149 time_limit = GraderConfiguration.contest_time_limit
147 time_limit = GraderConfiguration.contest_time_limit
150 if time_limit == nil
148 if time_limit == nil
151 return nil
149 return nil
@@ -224,27 +222,36
224 :problems => available_problems
222 :problems => available_problems
225 }
223 }
226 available_problems.each {|p| pin[p.id] = true}
224 available_problems.each {|p| pin[p.id] = true}
227 end
225 end
228 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
226 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
229 contest_problems << {
227 contest_problems << {
230 :contest => nil,
228 :contest => nil,
231 :problems => other_avaiable_problems
229 :problems => other_avaiable_problems
232 }
230 }
233 return contest_problems
231 return contest_problems
234 end
232 end
235
233
234 + def solve_all_available_problems?
235 + available_problems.each do |p|
236 + u = self
237 + sub = Submission.find_last_by_user_and_problem(u.id,p.id)
238 + return false if !p or !sub or sub.points < p.full_score
239 + end
240 + return true
241 + end
242 +
236 def available_problems
243 def available_problems
237 if not GraderConfiguration.multicontests?
244 if not GraderConfiguration.multicontests?
238 - return Problem.find_available_problems
245 + return Problem.available_problems
239 else
246 else
240 contest_problems = []
247 contest_problems = []
241 pin = {}
248 pin = {}
242 contests.enabled.each do |contest|
249 contests.enabled.each do |contest|
243 contest.problems.available.each do |problem|
250 contest.problems.available.each do |problem|
244 if not pin.has_key? problem.id
251 if not pin.has_key? problem.id
245 contest_problems << problem
252 contest_problems << problem
246 end
253 end
247 pin[problem.id] = true
254 pin[problem.id] = true
248 end
255 end
249 end
256 end
250 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
257 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
@@ -1,17 +1,17
1
1
2 %tr
2 %tr
3 %td{:align => "center"}
3 %td{:align => "center"}
4 - = submission_counter+1
4 + = submission.number
5 - %td{:align => "center"}
5 + %td.text-right
6 = link_to "##{submission.id}", submission_path(submission.id)
6 = link_to "##{submission.id}", submission_path(submission.id)
7 %td
7 %td
8 = l submission.submitted_at, format: :long
8 = l submission.submitted_at, format: :long
9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
10 %td
10 %td
11 = submission.source_filename
11 = submission.source_filename
12 = " (#{submission.language.pretty_name}) "
12 = " (#{submission.language.pretty_name}) "
13 = link_to('[load]',{:action => 'source', :id => submission.id})
13 = link_to('[load]',{:action => 'source', :id => submission.id})
14 %td
14 %td
15 - if submission.graded_at
15 - if submission.graded_at
16 = "Graded at #{format_short_time(submission.graded_at)}."
16 = "Graded at #{format_short_time(submission.graded_at)}."
17 %br/
17 %br/
@@ -1,26 +1,26
1
1
2 - if submission.nil?
2 - if submission.nil?
3 = "-"
3 = "-"
4 - else
4 - else
5 - - if submission.graded_at.nil?
5 + - unless submission.graded_at
6 = t 'main.submitted_at'
6 = t 'main.submitted_at'
7 = format_short_time(submission.submitted_at.localtime)
7 = format_short_time(submission.submitted_at.localtime)
8 - else
8 - else
9 - = t 'main.graded_at'
9 + %strong= t 'main.graded_at'
10 - = "#{format_short_time(submission.graded_at.localtime)}, "
10 + = "#{format_short_time(submission.graded_at.localtime)} "
11 + %br
11 - if GraderConfiguration['ui.show_score']
12 - if GraderConfiguration['ui.show_score']
12 - = t 'main.score'
13 + %strong=t 'main.score'
13 = "#{(submission.points*100/submission.problem.full_score).to_i} "
14 = "#{(submission.points*100/submission.problem.full_score).to_i} "
14 = " ["
15 = " ["
15 %tt
16 %tt
16 = submission.grader_comment
17 = submission.grader_comment
17 = "]"
18 = "]"
19 + %br
20 + %strong View:
18 - if GraderConfiguration.show_grading_result
21 - if GraderConfiguration.show_grading_result
19 - = " | "
20 = link_to '[detailed result]', :action => 'result', :id => submission.id
22 = link_to '[detailed result]', :action => 'result', :id => submission.id
21 - = " | "
23 + = link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'}
22 - = link_to("[#{t 'main.cmp_msg'}]", {:action => 'compiler_msg', :id => submission.id}, {:popup => true})
24 + = link_to "#{t 'main.src_link'}", download_submission_path(submission.id), class: 'btn btn-xs btn-info'
23 - = " | "
25 + = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info'
24 - = link_to("[#{t 'main.src_link'}]",{:action => 'source', :id => submission.id})
26 +
25 - //= " | "
26 - //= link_to "[#{t 'main.submissions_link'}]", main_submission_path(submission.problem.id)
@@ -1,26 +1,29
1 /- content_for :header do
1 /- content_for :header do
2 / = javascript_include_tag 'local_jquery'
2 / = javascript_include_tag 'local_jquery'
3
3
4 %h1 System configuration
4 %h1 System configuration
5
5
6 - %table.info
6 + - @group.each do |g|
7 - %tr.info-head
7 + %h2= g
8 - %th Key
8 + %table.table.table-striped
9 - %th Type
9 + %thead
10 - %th Value
10 + %th{style: 'width: 25%'} Key
11 + %th{style: 'width: 10%'}Type
12 + %th{style: 'width: 15%'} Value
11 %th Description
13 %th Description
12 - @configurations.each do |conf|
14 - @configurations.each do |conf|
15 + - next if conf.key[0...(conf.key.index('.'))] != g
13 - @grader_configuration = conf
16 - @grader_configuration = conf
14 - %tr{:class => cycle("info-odd", "info-even")}
17 + %tr
15 %td
18 %td
16 /= in_place_editor_field :grader_configuration, :key, {}, :rows=>1
19 /= in_place_editor_field :grader_configuration, :key, {}, :rows=>1
17 = @grader_configuration.key
20 = @grader_configuration.key
18 %td
21 %td
19 /= in_place_editor_field :grader_configuration, :value_type, {}, :rows=>1
22 /= in_place_editor_field :grader_configuration, :value_type, {}, :rows=>1
20 = @grader_configuration.value_type
23 = @grader_configuration.value_type
21 %td
24 %td
22 = best_in_place @grader_configuration, :value, ok_button: "ok", cancel_button: "cancel"
25 = best_in_place @grader_configuration, :value, ok_button: "ok", cancel_button: "cancel"
23 %td= conf.description
26 %td= conf.description
24
27
25 - if GraderConfiguration.config_cached?
28 - if GraderConfiguration.config_cached?
26 %br/
29 %br/
@@ -45,38 +45,38
45 %table.table.table-striped.table-condensed
45 %table.table.table-striped.table-condensed
46 %thead
46 %thead
47 %th ID
47 %th ID
48 %th User
48 %th User
49 %th Problem
49 %th Problem
50 %th Submitted
50 %th Submitted
51 %th Graded
51 %th Graded
52 %th Result
52 %th Result
53 %tbody
53 %tbody
54 - @submission.each do |sub|
54 - @submission.each do |sub|
55 %tr.inactive
55 %tr.inactive
56 %td= link_to sub.id, submission_path(sub.id)
56 %td= link_to sub.id, submission_path(sub.id)
57 - %td= ("" unless sub.user) || link_to sub.try(:user).try(:full_name), stat_user_path(sub.user.id)
57 + %td= ("" unless sub.user) || link_to(sub.try(:user).try(:full_name), stat_user_path(sub.user.id))
58 - %td= ("" unless sub.problem) || link_to sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.id)
58 + %td= ("" unless sub.problem) || link_to(sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.id))
59 %td= "#{time_ago_in_words(sub.submitted_at)} ago"
59 %td= "#{time_ago_in_words(sub.submitted_at)} ago"
60 %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " "
60 %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " "
61 %td= sub.grader_comment
61 %td= sub.grader_comment
62 %h2 Ungraded submission
62 %h2 Ungraded submission
63 %table.table.table-striped.table-condensed
63 %table.table.table-striped.table-condensed
64 %thead
64 %thead
65 %th ID
65 %th ID
66 %th User
66 %th User
67 %th Problem
67 %th Problem
68 %th Submitted
68 %th Submitted
69 %th Graded
69 %th Graded
70 %th Result
70 %th Result
71 %tbody
71 %tbody
72 - @backlog_submission.each do |sub|
72 - @backlog_submission.each do |sub|
73 %tr.inactive
73 %tr.inactive
74 %td= link_to sub.id, submission_path(sub.id)
74 %td= link_to sub.id, submission_path(sub.id)
75 - %td= ("" unless sub.user) || link_to sub.try(:user).try(:full_name), stat_user_path(sub.user.id)
75 + %td= ("" unless sub.user) || link_to( sub.try(:user).try(:full_name), stat_user_path(sub.user.id))
76 - %td= ("" unless sub.problem) || link_to sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.id)
76 + %td= ("" unless sub.problem) || link_to( sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.id))
77 %td= "#{time_ago_in_words(sub.submitted_at)} ago"
77 %td= "#{time_ago_in_words(sub.submitted_at)} ago"
78 %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " "
78 %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " "
79 %td= sub.grader_comment
79 %td= sub.grader_comment
80
80
81
81
82
82
@@ -1,67 +1,76
1 %header.navbar.navbar-default.navbar-fixed-top
1 %header.navbar.navbar-default.navbar-fixed-top
2 %nav
2 %nav
3 .container-fluid
3 .container-fluid
4 .navbar-header
4 .navbar-header
5 + %button.navbar-toggle.collapsed{ data: {toggle: 'collapse', target: '#navbar-collapse'} }
6 + %span.sr-only Togggle Navigation
7 + %span.icon-bar
8 + %span.icon-bar
9 + %span.icon-bar
5 %a.navbar-brand{href: main_list_path}
10 %a.navbar-brand{href: main_list_path}
6 %span.glyphicon.glyphicon-home
11 %span.glyphicon.glyphicon-home
7 MAIN
12 MAIN
8 - .collapse.navbar-collapse
13 + .collapse.navbar-collapse#navbar-collapse
9 %ul.nav.navbar-nav
14 %ul.nav.navbar-nav
15 + / submission
10 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
16 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
11 - //= add_menu("#{I18n.t 'menu.tasks'}", 'tasks', 'list')
12 %li.dropdown
17 %li.dropdown
13 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
18 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
14 = "#{I18n.t 'menu.submissions'}"
19 = "#{I18n.t 'menu.submissions'}"
15 %span.caret
20 %span.caret
16 %ul.dropdown-menu
21 %ul.dropdown-menu
17 - = add_menu("View", 'main', 'submission')
22 + = add_menu("View", 'submissions', 'index')
18 = add_menu("Self Test", 'test', 'index')
23 = add_menu("Self Test", 'test', 'index')
24 + / hall of fame
19 - if GraderConfiguration['right.user_hall_of_fame']
25 - if GraderConfiguration['right.user_hall_of_fame']
20 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
26 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
21 / display MODE button (with countdown in contest mode)
27 / display MODE button (with countdown in contest mode)
22 - if GraderConfiguration.analysis_mode?
28 - if GraderConfiguration.analysis_mode?
23 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
29 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
24 - elsif GraderConfiguration.time_limit_mode?
30 - elsif GraderConfiguration.time_limit_mode?
25 - if @current_user.contest_finished?
31 - if @current_user.contest_finished?
26 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
32 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
27 - elsif !@current_user.contest_started?
33 - elsif !@current_user.contest_started?
28 %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')
29 - else
35 - else
30 %div.navbar-btn.btn.btn-primary#countdown asdf
36 %div.navbar-btn.btn.btn-primary#countdown asdf
31 :javascript
37 :javascript
32 $("#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}'});
33 / admin section
39 / admin section
34 - if (@current_user!=nil) and (session[:admin])
40 - if (@current_user!=nil) and (session[:admin])
41 + / management
35 %li.dropdown
42 %li.dropdown
36 %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"}
37 Manage
44 Manage
38 %span.caret
45 %span.caret
39 %ul.dropdown-menu
46 %ul.dropdown-menu
40 = add_menu( 'Announcements', 'announcements', 'index')
47 = add_menu( 'Announcements', 'announcements', 'index')
41 = add_menu( 'Problems', 'problems', 'index')
48 = add_menu( 'Problems', 'problems', 'index')
42 = add_menu( 'Users', 'user_admin', 'index')
49 = add_menu( 'Users', 'user_admin', 'index')
43 = add_menu( 'Graders', 'graders', 'list')
50 = add_menu( 'Graders', 'graders', 'list')
44 = add_menu( 'Message ', 'messages', 'console')
51 = add_menu( 'Message ', 'messages', 'console')
45 %li.divider{role: 'separator'}
52 %li.divider{role: 'separator'}
46 = add_menu( 'System config', 'configurations', 'index')
53 = add_menu( 'System config', 'configurations', 'index')
47 %li.divider{role: 'separator'}
54 %li.divider{role: 'separator'}
48 = add_menu( 'Sites', 'sites', 'index')
55 = add_menu( 'Sites', 'sites', 'index')
49 = add_menu( 'Contests', 'contest_management', 'index')
56 = add_menu( 'Contests', 'contest_management', 'index')
57 + / report
50 %li.dropdown
58 %li.dropdown
51 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
59 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
52 Report
60 Report
53 %span.caret
61 %span.caret
54 %ul.dropdown-menu
62 %ul.dropdown-menu
55 - = add_menu( 'Results', 'report', 'current_score')
63 + = add_menu( 'Current Score', 'report', 'current_score')
64 + = add_menu( 'Score Report', 'report', 'max_score')
56 = add_menu( 'Report', 'report', 'multiple_login')
65 = add_menu( 'Report', 'report', 'multiple_login')
57 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
66 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
58 =link_to "#{ungraded} backlogs!",
67 =link_to "#{ungraded} backlogs!",
59 grader_list_path,
68 grader_list_path,
60 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
69 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
61
70
62 %ul.nav.navbar-nav.navbar-right
71 %ul.nav.navbar-nav.navbar-right
63 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
72 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
64 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
73 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
65 - if GraderConfiguration['system.user_setting_enabled']
74 - if GraderConfiguration['system.user_setting_enabled']
66 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog')}".html_safe, 'users', 'index', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
75 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog')}".html_safe, 'users', 'index', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
67 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
76 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
@@ -2,14 +2,15
2 %html
2 %html
3 %head
3 %head
4 %title= GraderConfiguration['contest.name']
4 %title= GraderConfiguration['contest.name']
5 = stylesheet_link_tag "application", params[:controller], :media => "all"
5 = stylesheet_link_tag "application", params[:controller], :media => "all"
6 = javascript_include_tag "application", params[:controller]
6 = javascript_include_tag "application", params[:controller]
7 = csrf_meta_tags
7 = csrf_meta_tags
8 = content_for :header
8 = content_for :header
9 = yield :head
9 = yield :head
10
10
11 %body
11 %body
12 = render 'layouts/header'
12 = render 'layouts/header'
13
13
14 - = content_tag(:p,flash[:notice],class: 'alert alert-success') if flash[:notice]!=nil
14 + /= content_tag(:p,flash[:notice],class: 'alert alert-success') if flash[:notice]!=nil
15 + = flash_messages
15 = yield
16 = yield
@@ -3,25 +3,25
3
3
4 - if !@hidelogin
4 - if !@hidelogin
5 =t 'login.message'
5 =t 'login.message'
6 %br/
6 %br/
7 %br/
7 %br/
8
8
9 - if flash[:notice]
9 - if flash[:notice]
10 %hr/
10 %hr/
11 %b= flash[:notice]
11 %b= flash[:notice]
12 %hr/
12 %hr/
13
13
14 %div{ :style => "border: solid 1px gray; padding: 4px; background: #eeeeff;"}
14 %div{ :style => "border: solid 1px gray; padding: 4px; background: #eeeeff;"}
15 - = form_tag :controller => 'login', :action => 'login' do
15 + = form_tag login_login_path do
16 %table
16 %table
17 %tr
17 %tr
18 %td{:align => "right"}
18 %td{:align => "right"}
19 ="#{t 'login_label'}:"
19 ="#{t 'login_label'}:"
20 %td= text_field_tag 'login'
20 %td= text_field_tag 'login'
21 %tr
21 %tr
22 %td{:align => "right"}
22 %td{:align => "right"}
23 ="#{t 'password_label'}:"
23 ="#{t 'password_label'}:"
24 %td= password_field_tag
24 %td= password_field_tag
25 - unless GraderConfiguration['right.bypass_agreement']
25 - unless GraderConfiguration['right.bypass_agreement']
26 %tr
26 %tr
27 %td{:align => "right"}= check_box_tag 'accept_agree'
27 %td{:align => "right"}= check_box_tag 'accept_agree'
@@ -1,17 +1,21
1 %tr
1 %tr
2 %td
2 %td
3 + - if @current_user and @current_user.admin?
4 + = link_to problem.name, stat_problem_path(problem)
5 + - else
3 = "#{problem.name}"
6 = "#{problem.name}"
4 %td
7 %td
5 = "#{problem.full_name}"
8 = "#{problem.full_name}"
9 +
6 %br
10 %br
7 = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, problem
11 = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, problem
8 %td
12 %td
9 = @prob_submissions[problem.id][:count]
13 = @prob_submissions[problem.id][:count]
10 = link_to "[subs]", main_submission_path(problem.id)
14 = link_to "[subs]", main_submission_path(problem.id)
11 %td
15 %td
12 = render :partial => 'submission_short',
16 = render :partial => 'submission_short',
13 :locals => {:submission => @prob_submissions[problem.id][:submission], :problem_name => problem.name, :problem_id => problem.id }
17 :locals => {:submission => @prob_submissions[problem.id][:submission], :problem_name => problem.name, :problem_id => problem.id }
14 %td
18 %td
15 - if @prob_submissions[problem.id][:submission]
19 - if @prob_submissions[problem.id][:submission]
16 = link_to 'Edit', edit_submission_path(@prob_submissions[problem.id][:submission]), class: 'btn btn-success'
20 = link_to 'Edit', edit_submission_path(@prob_submissions[problem.id][:submission]), class: 'btn btn-success'
17 - else
21 - else
@@ -1,20 +1,20
1 = form_tag({:action => 'submit'}, :multipart => true, class: 'form') do
1 = form_tag({:action => 'submit'}, :multipart => true, class: 'form') do
2 - if @submission and @submission.errors.any?
2 - if @submission and @submission.errors.any?
3 #error_explanation
3 #error_explanation
4 .alert.alert-danger
4 .alert.alert-danger
5 %h3= "#{pluralize(@submission.errors.count, "error")} prohibited this user from being saved:"
5 %h3= "#{pluralize(@submission.errors.count, "error")} prohibited this user from being saved:"
6 %ul
6 %ul
7 - @submission.errors.full_messages.each do |msg|
7 - @submission.errors.full_messages.each do |msg|
8 %li= msg
8 %li= msg
9 .form-group
9 .form-group
10 = label_tag :submission, 'Problem:'
10 = label_tag :submission, 'Problem:'
11 - = select 'submission', 'problem_id', [[(t 'main.specified_in_header'),'-1']] + @problems.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}, {:selected => '-1'}, { class: 'select2 form-control' }
11 + = select 'submission', 'problem_id', [[(t 'main.specified_in_header'),'-1']] + @problems.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}, {:selected => '-1'}, { class: 'select2 form-control', style: "width: 100%" }
12 .form-group
12 .form-group
13 = label_tag :file, 'File:'
13 = label_tag :file, 'File:'
14 .input-group
14 .input-group
15 %span.input-group-btn
15 %span.input-group-btn
16 %span.btn.btn-default.btn-file
16 %span.btn.btn-default.btn-file
17 Browse
17 Browse
18 = file_field_tag 'file'
18 = file_field_tag 'file'
19 = text_field_tag '' , nil, {readonly: true, class: 'form-control'}
19 = text_field_tag '' , nil, {readonly: true, class: 'form-control'}
20 = submit_tag 'Submit', class: 'btn btn-default'
20 = submit_tag 'Submit', class: 'btn btn-default'
@@ -1,26 +1,29
1
1
2 - if submission.nil?
2 - if submission.nil?
3 = "-"
3 = "-"
4 - else
4 - else
5 - unless submission.graded_at
5 - unless submission.graded_at
6 =t 'main.submitted_at'
6 = t 'main.submitted_at'
7 = format_short_time(submission.submitted_at.localtime)
7 = format_short_time(submission.submitted_at.localtime)
8 - else
8 - else
9 %strong= t 'main.graded_at'
9 %strong= t 'main.graded_at'
10 = "#{format_short_time(submission.graded_at.localtime)} "
10 = "#{format_short_time(submission.graded_at.localtime)} "
11 %br
11 %br
12 - if GraderConfiguration['ui.show_score']
12 - if GraderConfiguration['ui.show_score']
13 - =t 'main.score'
13 + %strong=t 'main.score'
14 = "#{(submission.points*100/submission.problem.full_score).to_i} "
14 = "#{(submission.points*100/submission.problem.full_score).to_i} "
15 = " ["
15 = " ["
16 %tt
16 %tt
17 = submission.grader_comment
17 = submission.grader_comment
18 = "]"
18 = "]"
19 %br
19 %br
20 %strong View:
20 %strong View:
21 - if GraderConfiguration.show_grading_result
21 - if GraderConfiguration.show_grading_result
22 = link_to '[detailed result]', :action => 'result', :id => submission.id
22 = link_to '[detailed result]', :action => 'result', :id => submission.id
23 - = link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'}
23 + /= link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'}
24 + = link_to "#{t 'main.cmp_msg'}", compiler_msg_submission_path(submission.id), {popup: true,remote: true,class: 'btn btn-xs btn-info'}
24 = link_to "#{t 'main.src_link'}",{:action => 'source', :id => submission.id}, class: 'btn btn-xs btn-info'
25 = link_to "#{t 'main.src_link'}",{:action => 'source', :id => submission.id}, class: 'btn btn-xs btn-info'
25 = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info'
26 = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info'
27 + - if GraderConfiguration.show_testcase
28 + = link_to "testcases", show_problem_testcases_path(problem_id), class: 'btn btn-xs btn-info'
26
29
@@ -34,19 +34,31
34 %table.info
34 %table.info
35 %tr.info-head
35 %tr.info-head
36 %th Task name
36 %th Task name
37 %th Full name
37 %th Full name
38 %th # of sub(s)
38 %th # of sub(s)
39 %th Results
39 %th Results
40 %th
40 %th
41 = render :partial => 'problem', :collection => cp[:problems]
41 = render :partial => 'problem', :collection => cp[:problems]
42 .col-md-5
42 .col-md-5
43 .panel.panel-info
43 .panel.panel-info
44 .panel-heading
44 .panel-heading
45 Announcement
45 Announcement
46 + = link_to 'Manage', announcements_path, class: 'btn btn-xs btn-default'
46 %ul.list-group
47 %ul.list-group
47 = render :partial => 'announcement', :collection => @announcements
48 = render :partial => 'announcement', :collection => @announcements
48
49
49 %script{:type => 'text/javascript'}
50 %script{:type => 'text/javascript'}
50 = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';"
51 = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';"
51 Announcement.registerRefreshEventTimer();
52 Announcement.registerRefreshEventTimer();
52
53
54 + .modal.fade#compiler{tabindex: -1,role: 'dialog'}
55 + .modal-dialog.modal-lg{role:'document'}
56 + .modal-content
57 + .modal-header
58 + %button.close{type: 'button', data: {dismissed: :modal}, aria: {label: 'close'}}
59 + %span{aria: {hidden: 'true'}, data: {dismiss: 'modal'}} &times;
60 + %h4 Compiler message
61 + .modal-body
62 + %pre#compiler_msg
63 + .modal-footer
64 + %button.btn.btn-default{type: 'button', data: {dismiss: 'modal'}} Close
@@ -17,34 +17,38
17 = text_field 'problem', 'full_name'
17 = text_field 'problem', 'full_name'
18 = submit_tag "Create"
18 = submit_tag "Create"
19 %table.table.table-condense.table-hover
19 %table.table.table-condense.table-hover
20 %thead
20 %thead
21 %th Name
21 %th Name
22 %th Full name
22 %th Full name
23 %th.text-right Full score
23 %th.text-right Full score
24 %th Date added
24 %th Date added
25 %th.text-center
25 %th.text-center
26 Avail?
26 Avail?
27 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
27 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
28 %th.text-center
28 %th.text-center
29 + View Data?
30 + %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user view the testcase of this problem?' } [?]
31 + %th.text-center
29 Test?
32 Test?
30 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
33 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
31 - if GraderConfiguration.multicontests?
34 - if GraderConfiguration.multicontests?
32 %th Contests
35 %th Contests
33 - for problem in @problems
36 - for problem in @problems
34 %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
37 %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
35 - @problem=problem
38 - @problem=problem
36 %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1
39 %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1
37 %td= problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
40 %td= problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
38 %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1
41 %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1
39 %td= problem.date_added
42 %td= problem.date_added
40 %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}")
43 %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}")
44 + %td= toggle_button(@problem.view_testcase?, toggle_view_testcase_problem_path(@problem), "problem-view-testcase-#{@problem.id}")
41 %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}")
45 %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}")
42 - if GraderConfiguration.multicontests?
46 - if GraderConfiguration.multicontests?
43 %td
47 %td
44 = problem.contests.collect { |c| c.name }.join(', ')
48 = problem.contests.collect { |c| c.name }.join(', ')
45 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
49 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
46 %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
50 %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
47 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block'
51 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block'
48 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
52 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
49 %br/
53 %br/
50 = link_to '[New problem]', :action => 'new'
54 = link_to '[New problem]', :action => 'new'
@@ -12,13 +12,13
12 <%= markdown(@problem.description.body) %>
12 <%= markdown(@problem.description.body) %>
13 <% else %>
13 <% else %>
14 <pre>
14 <pre>
15 <%= @problem.description.body %>
15 <%= @problem.description.body %>
16 </pre>
16 </pre>
17 <% end %>
17 <% end %>
18 <% else %>
18 <% else %>
19 (not available)
19 (not available)
20 <% end %>
20 <% end %>
21 </p>
21 </p>
22
22
23 <%= link_to 'Edit', :action => 'edit', :id => @problem %> |
23 <%= link_to 'Edit', :action => 'edit', :id => @problem %> |
24 - <%= link_to 'Back', :action => 'list' %>
24 + <%= link_to 'Back', problems_path %>
@@ -1,34 +1,34
1 %table.table.sortable.table-striped.table-bordered.table-condensed
1 %table.table.sortable.table-striped.table-bordered.table-condensed
2 %thead
2 %thead
3 %tr
3 %tr
4 %th Login
4 %th Login
5 %th Name
5 %th Name
6 - %th Activated?
6 + / %th Activated?
7 - %th Logged_in
7 + / %th Logged_in
8 - %th Contest(s)
8 + / %th Contest(s)
9 %th Remark
9 %th Remark
10 - @problems.each do |p|
10 - @problems.each do |p|
11 - %th.text-right= p.name
11 + %th.text-right= p.name.gsub('_',' ')
12 %th.text-right Total
12 %th.text-right Total
13 %th.text-right Passed
13 %th.text-right Passed
14 %tbody
14 %tbody
15 - @scorearray.each do |sc|
15 - @scorearray.each do |sc|
16 %tr
16 %tr
17 - total,num_passed = 0,0
17 - total,num_passed = 0,0
18 - sc.each_index do |i|
18 - sc.each_index do |i|
19 - if i == 0
19 - if i == 0
20 - %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
20 + %td= link_to sc[i].login, stat_user_path(sc[i])
21 %td= sc[i].full_name
21 %td= sc[i].full_name
22 - %td= sc[i].activated
22 + / %td= sc[i].activated
23 - %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
23 + / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
24 - %td= sc[i].contests.collect {|c| c.name}.join(', ')
24 + / %td= sc[i].contests.collect {|c| c.name}.join(', ')
25 %td= sc[i].remark
25 %td= sc[i].remark
26 - else
26 - else
27 %td.text-right= sc[i][0]
27 %td.text-right= sc[i][0]
28 - total += sc[i][0]
28 - total += sc[i][0]
29 - num_passed += 1 if sc[i][1]
29 - num_passed += 1 if sc[i][1]
30 %td.text-right= total
30 %td.text-right= total
31 %td.text-right= num_passed
31 %td.text-right= num_passed
32
32
33 :javascript
33 :javascript
34 $.bootstrapSortable(true,'reversed')
34 $.bootstrapSortable(true,'reversed')
@@ -35,68 +35,68
35 %th
35 %th
36 %tbody
36 %tbody
37 %tr
37 %tr
38 %td.info_param Submissions
38 %td.info_param Submissions
39 %td= @summary[:count]
39 %td= @summary[:count]
40 %tr
40 %tr
41 %td.info_param Solved/Attempted User
41 %td.info_param Solved/Attempted User
42 %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
42 %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
43 - if @best
43 - if @best
44 %tr
44 %tr
45 %td.info_param Best Runtime
45 %td.info_param Best Runtime
46 %td
46 %td
47 - by #{link_to @best[:runtime][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
47 + by #{link_to @best[:runtime][:user], stat_user_path(@best[:runtime][:user_id])}
48 %br
48 %br
49 using <span class="text-success">#{@best[:runtime][:lang]}</span>
49 using <span class="text-success">#{@best[:runtime][:lang]}</span>
50 %br
50 %br
51 with <span class="text-success">#{@best[:runtime][:value] * 1000} milliseconds</span>
51 with <span class="text-success">#{@best[:runtime][:value] * 1000} milliseconds</span>
52 %br
52 %br
53 at submission
53 at submission
54 = link_to "#" + @best[:runtime][:sub_id].to_s, submission_path(@best[:runtime][:sub_id])
54 = link_to "#" + @best[:runtime][:sub_id].to_s, submission_path(@best[:runtime][:sub_id])
55
55
56 %tr
56 %tr
57 %td.info_param
57 %td.info_param
58 Best Memory Usage
58 Best Memory Usage
59 %sup{ id: "xmem_remark",
59 %sup{ id: "xmem_remark",
60 style: "position:relative; color: blue;",
60 style: "position:relative; color: blue;",
61 data: {toggle: 'tooltip', placement: 'top', animation: 'false', delay: 20},
61 data: {toggle: 'tooltip', placement: 'top', animation: 'false', delay: 20},
62 title: "This counts only for submission with 100% score. Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)"}
62 title: "This counts only for submission with 100% score. Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)"}
63 [?]
63 [?]
64 %td
64 %td
65 - by #{link_to @best[:memory][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
65 + by #{link_to @best[:memory][:user], stat_user_path(@best[:memory][:user_id])}
66 %br
66 %br
67 using <span class="text-success">#{@best[:memory][:lang]}</span>
67 using <span class="text-success">#{@best[:memory][:lang]}</span>
68 %br
68 %br
69 with <span class="text-success">#{number_with_delimiter(@best[:memory][:value])} kbytes </span>
69 with <span class="text-success">#{number_with_delimiter(@best[:memory][:value])} kbytes </span>
70 %br
70 %br
71 at submission
71 at submission
72 = link_to "#" + @best[:memory][:sub_id].to_s, submission_path(@best[:memory][:sub_id])
72 = link_to "#" + @best[:memory][:sub_id].to_s, submission_path(@best[:memory][:sub_id])
73
73
74 %tr
74 %tr
75 %td.info_param Shortest Code
75 %td.info_param Shortest Code
76 %td
76 %td
77 - by #{link_to @best[:length][:user], controller:'users', action:'profile', id:@best[:length][:user_id]}
77 + by #{link_to @best[:length][:user], stat_user_path(@best[:length][:user_id])}
78 %br
78 %br
79 using <span class="text-success">#{@best[:length][:lang]}</span>
79 using <span class="text-success">#{@best[:length][:lang]}</span>
80 %br
80 %br
81 with <span class="text-success">#{@best[:length][:value]} bytes</span>
81 with <span class="text-success">#{@best[:length][:value]} bytes</span>
82 %br
82 %br
83 at submission
83 at submission
84 = link_to "#" + @best[:length][:sub_id].to_s, submission_path(@best[:length][:sub_id])
84 = link_to "#" + @best[:length][:sub_id].to_s, submission_path(@best[:length][:sub_id])
85
85
86 %tr
86 %tr
87 %td.info_param First solver
87 %td.info_param First solver
88 %td
88 %td
89 - if @best[:first][:user] != '(NULL)'
89 - if @best[:first][:user] != '(NULL)'
90 - #{link_to @best[:first][:user], controller:'users', action:'profile', id:@best[:first][:user_id]} is the first solver
90 + #{link_to @best[:first][:user], stat_user_path(@best[:first][:user_id])} is the first solver
91 %br
91 %br
92 using <span class="text-success">#{@best[:first][:lang]}</span>
92 using <span class="text-success">#{@best[:first][:lang]}</span>
93 %br
93 %br
94 on <span class="text-success">#{@best[:first][:value]}</span>
94 on <span class="text-success">#{@best[:first][:value]}</span>
95 %br
95 %br
96 at submission
96 at submission
97 = link_to "#" + @best[:first][:sub_id].to_s, submission_path( @best[:first][:sub_id])
97 = link_to "#" + @best[:first][:sub_id].to_s, submission_path( @best[:first][:sub_id])
98 - else
98 - else
99 no first solver
99 no first solver
100 .col-md-8
100 .col-md-8
101 - if @best
101 - if @best
102 %h2 By Language
102 %h2 By Language
@@ -104,33 +104,33
104 %thead
104 %thead
105 %tr
105 %tr
106 %th Language
106 %th Language
107 %th Best runtime (ms)
107 %th Best runtime (ms)
108 %th Best memory (kbytes)
108 %th Best memory (kbytes)
109 %th Shortest Code (bytes)
109 %th Shortest Code (bytes)
110 %th First solver
110 %th First solver
111 %tbody
111 %tbody
112 - @by_lang.each do |lang,value|
112 - @by_lang.each do |lang,value|
113 %tr
113 %tr
114 %td= lang
114 %td= lang
115 %td
115 %td
116 - = link_to value[:runtime][:user], controller: 'users', action: 'profile', id: value[:runtime][:user_id]
116 + = link_to value[:runtime][:user], stat_user_path(value[:runtime][:user_id])
117 %br
117 %br
118 = "#{(value[:runtime][:value] * 1000).to_i} @"
118 = "#{(value[:runtime][:value] * 1000).to_i} @"
119 = link_to "#" + value[:runtime][:sub_id].to_s, submission_path( value[:runtime][:sub_id])
119 = link_to "#" + value[:runtime][:sub_id].to_s, submission_path( value[:runtime][:sub_id])
120 %td
120 %td
121 - = link_to value[:memory][:user], controller: 'users', action: 'profile', id: value[:memory][:user_id]
121 + = link_to value[:memory][:user], stat_user_path( value[:memory][:user_id])
122 %br
122 %br
123 = "#{number_with_delimiter(value[:memory][:value])} @"
123 = "#{number_with_delimiter(value[:memory][:value])} @"
124 = link_to "#" + value[:memory][:sub_id].to_s, submission_path(value[:memory][:sub_id])
124 = link_to "#" + value[:memory][:sub_id].to_s, submission_path(value[:memory][:sub_id])
125 %td
125 %td
126 - = link_to value[:length][:user], controller: 'users', action: 'profile', id: value[:length][:user_id]
126 + = link_to value[:length][:user], stat_user_path(value[:length][:user_id])
127 %br
127 %br
128 = "#{value[:length][:value]} @"
128 = "#{value[:length][:value]} @"
129 = link_to "#" + value[:length][:sub_id].to_s, submission_path(value[:length][:sub_id])
129 = link_to "#" + value[:length][:sub_id].to_s, submission_path(value[:length][:sub_id])
130 %td
130 %td
131 - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong...
131 - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong...
132 - = link_to value[:first][:user], controller: 'users', action: 'profile', id: value[:first][:user_id]
132 + = link_to value[:first][:user], stat_user_path(value[:first][:user_id])
133 %br
133 %br
134 = "#{value[:first][:value]} @"
134 = "#{value[:first][:value]} @"
135 = link_to "#" + value[:first][:sub_id].to_s, submission_path( value[:first][:sub_id])
135 = link_to "#" + value[:first][:sub_id].to_s, submission_path( value[:first][:sub_id])
136
136
@@ -13,28 +13,28
13 = select_tag 'problem_id[]',
13 = select_tag 'problem_id[]',
14 options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]},params[:problem_id]),
14 options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]},params[:problem_id]),
15 { class: 'select2 form-control', multiple: "true" }
15 { class: 'select2 form-control', multiple: "true" }
16 .col-md-4
16 .col-md-4
17 .panel.panel-primary
17 .panel.panel-primary
18 .panel-heading
18 .panel-heading
19 Submission range
19 Submission range
20 .panel-body
20 .panel-body
21 %p
21 %p
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
23 .form-group
23 .form-group
24 = label_tag :from, "Min"
24 = label_tag :from, "Min"
25 - = text_field_tag 'from_id', nil, class: "form-control"
25 + = text_field_tag 'from_id', @since_id, class: "form-control"
26 .form-group
26 .form-group
27 = label_tag :from, "Max"
27 = label_tag :from, "Max"
28 - = text_field_tag 'to_id', nil, class: "form-control"
28 + = text_field_tag 'to_id', @until_id, class: "form-control"
29 .col-md-4
29 .col-md-4
30 .panel.panel-primary
30 .panel.panel-primary
31 .panel-heading
31 .panel-heading
32 Users
32 Users
33 .panel-body
33 .panel-body
34 .radio
34 .radio
35 %label
35 %label
36 = radio_button_tag 'users', 'all', true
36 = radio_button_tag 'users', 'all', true
37 All users
37 All users
38 .radio
38 .radio
39 %label
39 %label
40 = radio_button_tag 'users', 'enabled'
40 = radio_button_tag 'users', 'enabled'
@@ -1,16 +1,16
1 %h2 Live submit
1 %h2 Live submit
2 %br
2 %br
3
3
4 - %textarea#text_haha{style: "display:none"}~ @source
4 + %textarea#text_sourcecode{style: "display:none"}~ @source
5 .container
5 .container
6 .row
6 .row
7 .col-md-12
7 .col-md-12
8 .alert.alert-info
8 .alert.alert-info
9 Write your code in the following box, choose language, and click submit button when finished
9 Write your code in the following box, choose language, and click submit button when finished
10 .row
10 .row
11 .col-md-8
11 .col-md-8
12 %div#editor{style: 'height: 500px; border-radius: 7px; font-size: 14px;'}
12 %div#editor{style: 'height: 500px; border-radius: 7px; font-size: 14px;'}
13 .col-md-4
13 .col-md-4
14 = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form') do
14 = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form') do
15
15
16 = hidden_field_tag 'editor_text', @source
16 = hidden_field_tag 'editor_text', @source
@@ -19,37 +19,38
19 = label_tag "Task:"
19 = label_tag "Task:"
20 = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true
20 = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true
21
21
22 .form-group
22 .form-group
23 = label_tag 'Language'
23 = label_tag 'Language'
24 = select_tag 'language_id', options_from_collection_for_select(Language.all, 'id', 'pretty_name', @lang_id || Language.find_by_pretty_name("Python").id || Language.first.id), class: 'form-control select', style: "width: 100px"
24 = select_tag 'language_id', options_from_collection_for_select(Language.all, 'id', 'pretty_name', @lang_id || Language.find_by_pretty_name("Python").id || Language.first.id), class: 'form-control select', style: "width: 100px"
25 .form-group
25 .form-group
26 = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit',
26 = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit',
27 data: {confirm: "Submitting this source code for task #{@problem.long_name}?"}
27 data: {confirm: "Submitting this source code for task #{@problem.long_name}?"}
28 .panel.panel-info
28 .panel.panel-info
29 .panel-heading
29 .panel-heading
30 Latest Submission Status
30 Latest Submission Status
31 + = link_to "Refresh",get_latest_submission_status_submissions_path(@submission.user,@problem), class: "btn btn-default btn-sm", remote: true if @submission
31 .panel-body
32 .panel-body
32 - if @submission
33 - if @submission
33 = render :partial => 'submission_short',
34 = render :partial => 'submission_short',
34 - :locals => {:submission => @submission, :problem_name => @problem.name }
35 + :locals => {submission: @submission, problem_name: @problem.name, problem_id: @problem.id }
35 .row
36 .row
36 .col-md-12
37 .col-md-12
37 %h2 Console
38 %h2 Console
38 %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20}
39 %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20}
39
40
40 :javascript
41 :javascript
41 $(document).ready(function() {
42 $(document).ready(function() {
42 e = ace.edit("editor")
43 e = ace.edit("editor")
43 - e.setValue($("#text_haha").val());
44 + e.setValue($("#text_sourcecode").val());
44 e.gotoLine(1);
45 e.gotoLine(1);
45 $("#language_id").trigger('change');
46 $("#language_id").trigger('change');
46 brython();
47 brython();
47 });
48 });
48
49
49
50
50 %script#__main__{type:'text/python3'}
51 %script#__main__{type:'text/python3'}
51 :plain
52 :plain
52 import sys
53 import sys
53 import traceback
54 import traceback
54
55
55 from browser import document as doc
56 from browser import document as doc
@@ -1,2 +1,2
1 - :javascript
1 + :plain
2 $("#latest_status").html("#{j render({partial: 'submission_short', locals: {submission: @submission, problem_name: @problem.name}})}")
2 $("#latest_status").html("#{j render({partial: 'submission_short', locals: {submission: @submission, problem_name: @problem.name}})}")
@@ -9,21 +9,21
9 { selected: (@problem ? problem_submissions_url(@problem) : -1) },
9 { selected: (@problem ? problem_submissions_url(@problem) : -1) },
10 { class: 'select2 form-control'}
10 { class: 'select2 form-control'}
11 %button.btn.btn-primary.btn-sm.go-button#problem_go{data: {source: '#submission_problem_id'}} Go
11 %button.btn.btn-primary.btn-sm.go-button#problem_go{data: {source: '#submission_problem_id'}} Go
12
12
13 - if @problem!=nil
13 - if @problem!=nil
14 %h2= "Task: #{@problem.full_name} (#{@problem.name})"
14 %h2= "Task: #{@problem.full_name} (#{@problem.name})"
15
15
16 - if @submissions!=nil
16 - if @submissions!=nil
17 - if @submissions.length>0
17 - if @submissions.length>0
18 %table.table
18 %table.table
19 %thead
19 %thead
20 %th No.
20 %th No.
21 - %th #
21 + %th.text-right #
22 %th At
22 %th At
23 %th Source
23 %th Source
24 %th Result
24 %th Result
25 %th{:width => "300px"} Compiler message
25 %th{:width => "300px"} Compiler message
26 %th
26 %th
27 = render :partial => 'submission', :collection => @submissions
27 = render :partial => 'submission', :collection => @submissions
28 - else
28 - else
29 No submission
29 No submission
@@ -1,20 +1,22
1 %h1= "Submission: #{@submission.id}"
1 %h1= "Submission: #{@submission.id}"
2
2
3 %textarea#data{style: "display:none;"}
3 %textarea#data{style: "display:none;"}
4 :preserve
4 :preserve
5 #{@submission.source}
5 #{@submission.source}
6
6
7 //%div.highlight{:style => "border: 1px solid black;"}
7 //%div.highlight{:style => "border: 1px solid black;"}
8 //=@formatted_code.html_safe
8 //=@formatted_code.html_safe
9 +
10 +
9 .containter
11 .containter
10 .row
12 .row
11 .col-md-7
13 .col-md-7
12 %h2 Source Code
14 %h2 Source Code
13 .col-md-5
15 .col-md-5
14 %h2 Stat
16 %h2 Stat
15 .row
17 .row
16 .col-md-7
18 .col-md-7
17 %div#editor{ style: "font-size: 14px; height: 400px; border-radius:5px;" }
19 %div#editor{ style: "font-size: 14px; height: 400px; border-radius:5px;" }
18 :javascript
20 :javascript
19 e = ace.edit("editor")
21 e = ace.edit("editor")
20 e.setOptions({ maxLines: Infinity })
22 e.setOptions({ maxLines: Infinity })
@@ -55,35 +57,56
55 %strong Submitted
57 %strong Submitted
56 %td #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)})
58 %td #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)})
57 %tr
59 %tr
58 %td.text-right
60 %td.text-right
59 %strong Graded
61 %strong Graded
60 - if @submission.graded_at
62 - if @submission.graded_at
61 %td #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
63 %td #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
62 - else
64 - else
63 %td -
65 %td -
64 %tr
66 %tr
65 %td.text-right
67 %td.text-right
66 %strong Points
68 %strong Points
67 - %td #{@submission.points}/#{@submission.problem.full_score}
69 + %td #{@submission.points}/#{@submission.try(:problem).try(:full_score)}
68 %tr
70 %tr
69 %td.text-right
71 %td.text-right
70 %strong Comment
72 %strong Comment
71 %td #{@submission.grader_comment}
73 %td #{@submission.grader_comment}
72 %tr
74 %tr
73 %td.text-right
75 %td.text-right
74 %strong Runtime (s)
76 %strong Runtime (s)
75 %td #{@submission.max_runtime}
77 %td #{@submission.max_runtime}
76 %tr
78 %tr
77 %td.text-right
79 %td.text-right
78 %strong Memory (kb)
80 %strong Memory (kb)
79 %td #{@submission.peak_memory}
81 %td #{@submission.peak_memory}
80 %tr
82 %tr
81 %td.text-right
83 %td.text-right
82 %strong Compiler result
84 %strong Compiler result
83 %td
85 %td
84 - %pre= @submission.compiler_message
86 + %button.btn.btn-info.btn-xs{type: 'button', data: {toggle: 'modal', target: '#compiler'}}
87 + view
85 - if session[:admin]
88 - if session[:admin]
86 %tr
89 %tr
87 %td.text-right
90 %td.text-right
88 %strong IP
91 %strong IP
89 %td #{@submission.ip_address}
92 %td #{@submission.ip_address}
93 + %tr
94 + %td.text-right
95 + %strong Grading Task Status
96 + %td
97 + = @task.status_str if @task
98 + - if session[:admin]
99 + = link_to "rejudge", rejudge_submission_path, data: {remote: true}, class: 'btn btn-info btn-xs'
100 +
101 +
102 + .modal.fade#compiler{tabindex: -1,role: 'dialog'}
103 + .modal-dialog.modal-lg{role:'document'}
104 + .modal-content
105 + .modal-header
106 + %button.close{type: 'button', data: {dismissed: :modal}, aria: {label: 'close'}}
107 + %span{aria: {hidden: 'true'}, data: {dismiss: 'modal'}} &times;
108 + %h4 Compiler message
109 + .modal-body
110 + %pre#compiler_msg= @submission.compiler_message
111 + .modal-footer
112 + %button.btn.btn-default{type: 'button', data: {dismiss: 'modal'}} Close
@@ -33,24 +33,25
33 %span.input-group-btn
33 %span.input-group-btn
34 %span.btn.btn-default.btn-file
34 %span.btn.btn-default.btn-file
35 Browse
35 Browse
36 = file_field_tag 'file'
36 = file_field_tag 'file'
37 = text_field_tag '' , nil, {readonly: true, class: 'form-control'}
37 = text_field_tag '' , nil, {readonly: true, class: 'form-control'}
38 = submit_tag 'Submit', class: 'btn btn-default'
38 = submit_tag 'Submit', class: 'btn btn-default'
39
39
40
40
41 %p
41 %p
42 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
42 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
43 = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
43 = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
44 = link_to 'View administrators',{ :action => 'admin'}, { class: 'btn btn-default '}
44 = link_to 'View administrators',{ :action => 'admin'}, { class: 'btn btn-default '}
45 + = link_to 'Bulk Manage', bulk_manage_user_admin_path , { class: 'btn btn-default '}
45 = link_to 'Random passwords',{ :action => 'random_all_passwords'}, { class: 'btn btn-default '}
46 = link_to 'Random passwords',{ :action => 'random_all_passwords'}, { class: 'btn btn-default '}
46 = link_to 'View active users',{ :action => 'active'}, { class: 'btn btn-default '}
47 = link_to 'View active users',{ :action => 'active'}, { class: 'btn btn-default '}
47 = link_to 'Mass mailing',{ :action => 'mass_mailing'}, { class: 'btn btn-default '}
48 = link_to 'Mass mailing',{ :action => 'mass_mailing'}, { class: 'btn btn-default '}
48
49
49 - if GraderConfiguration.multicontests?
50 - if GraderConfiguration.multicontests?
50 %br/
51 %br/
51 %b Multi-contest:
52 %b Multi-contest:
52 = link_to '[Manage bulk users in contests]', :action => 'contest_management'
53 = link_to '[Manage bulk users in contests]', :action => 'contest_management'
53 View users in:
54 View users in:
54 - @contests.each do |contest|
55 - @contests.each do |contest|
55 = link_to "[#{contest.name}]", :action => 'contests', :id => contest.id
56 = link_to "[#{contest.name}]", :action => 'contests', :id => contest.id
56 = link_to "[no contest]", :action => 'contests', :id => 'none'
57 = link_to "[no contest]", :action => 'contests', :id => 'none'
@@ -75,25 +76,25
75 Activated
76 Activated
76 %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'User has already confirmed the email?' } [?]
77 %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'User has already confirmed the email?' } [?]
77 %th
78 %th
78 Enabled
79 Enabled
79 %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'Allow the user to login?' } [?]
80 %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'Allow the user to login?' } [?]
80 %th Last IP
81 %th Last IP
81 %th
82 %th
82 %th
83 %th
83 %th
84 %th
84 %th
85 %th
85 - for user in @users
86 - for user in @users
86 %tr
87 %tr
87 - %td= link_to user.login, controller: :users, :action => 'profile', :id => user
88 + %td= link_to user.login, stat_user_path(user)
88 %td= user.full_name
89 %td= user.full_name
89 %td= user.email
90 %td= user.email
90 %td= user.remark
91 %td= user.remark
91 %td= toggle_button(user.activated?, toggle_activate_user_path(user),"toggle_activate_user_#{user.id}")
92 %td= toggle_button(user.activated?, toggle_activate_user_path(user),"toggle_activate_user_#{user.id}")
92 %td= toggle_button(user.enabled?, toggle_enable_user_path(user),"toggle_enable_user_#{user.id}")
93 %td= toggle_button(user.enabled?, toggle_enable_user_path(user),"toggle_enable_user_#{user.id}")
93 %td= user.last_ip
94 %td= user.last_ip
94 %td= link_to 'Clear IP', {:action => 'clear_last_ip', :id => user, :page=>params[:page]}, :confirm => 'This will reset last logging in ip of the user, are you sure?', class: 'btn btn-default btn-xs btn-block'
95 %td= link_to 'Clear IP', {:action => 'clear_last_ip', :id => user, :page=>params[:page]}, :confirm => 'This will reset last logging in ip of the user, are you sure?', class: 'btn btn-default btn-xs btn-block'
95 %td= link_to 'Show', {:action => 'show', :id => user}, class: 'btn btn-default btn-xs btn-block'
96 %td= link_to 'Show', {:action => 'show', :id => user}, class: 'btn btn-default btn-xs btn-block'
96 %td= link_to 'Edit', {:action => 'edit', :id => user}, class: 'btn btn-default btn-xs btn-block'
97 %td= link_to 'Edit', {:action => 'edit', :id => user}, class: 'btn btn-default btn-xs btn-block'
97 %td= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
98 %td= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
98 %br/
99 %br/
99 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
100 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
@@ -1,8 +1,9
1 <h1>Adding list of users</h1>
1 <h1>Adding list of users</h1>
2
2
3 <%= form_tag :action => 'create_from_list' do %>
3 <%= form_tag :action => 'create_from_list' do %>
4 - <%= submit_tag 'create users' %><br/>
4 + <%= submit_tag 'create users',class: 'btn btn-success'%><br/>
5 - List of user information in this format: <tt>user_id,name(,passwd(,alias))</tt><br/>
5 + List of user information in this format: <tt>user_id,name(,passwd(,alias(,remark)))</tt><br/>
6 - Note that <tt>passwd</tt> and <tt>alias</tt> is optional.<br/>
6 + Note that <tt>passwd, alias</tt> and <tt> remark </tt>is optional.<br />
7 + When <tt>passwd</tt> or <tt>alias</tt> is empty, the original value will be used instead.<br/>
7 <%= text_area_tag 'user_list', nil, :rows => 50, :cols => 80 %>
8 <%= text_area_tag 'user_list', nil, :rows => 50, :cols => 80 %>
8 <% end %>
9 <% end %>
@@ -1,40 +1,42
1 CafeGrader::Application.configure do
1 CafeGrader::Application.configure do
2 # Settings specified here will take precedence over those in config/application.rb
2 # Settings specified here will take precedence over those in config/application.rb
3
3
4 # In the development environment your application's code is reloaded on
4 # In the development environment your application's code is reloaded on
5 # every request. This slows down response time but is perfect for development
5 # every request. This slows down response time but is perfect for development
6 # since you don't have to restart the web server when you make code changes.
6 # since you don't have to restart the web server when you make code changes.
7 config.cache_classes = false
7 config.cache_classes = false
8
8
9 - # Log error messages when you accidentally call methods on nil.
9 + # Log error messages when you accidentally call methods on nil. //DEPRICATED
10 - config.whiny_nils = true
10 + # config.whiny_nils = true // DEPRICATED
11
11
12 # Show full error reports and disable caching
12 # Show full error reports and disable caching
13 config.consider_all_requests_local = true
13 config.consider_all_requests_local = true
14 config.action_controller.perform_caching = false
14 config.action_controller.perform_caching = false
15
15
16 # Don't care if the mailer can't send
16 # Don't care if the mailer can't send
17 config.action_mailer.raise_delivery_errors = false
17 config.action_mailer.raise_delivery_errors = false
18
18
19 # Print deprecation notices to the Rails logger
19 # Print deprecation notices to the Rails logger
20 config.active_support.deprecation = :log
20 config.active_support.deprecation = :log
21
21
22 # Only use best-standards-support built into browsers
22 # Only use best-standards-support built into browsers
23 config.action_dispatch.best_standards_support = :builtin
23 config.action_dispatch.best_standards_support = :builtin
24
24
25 # Raise exception on mass assignment protection for Active Record models
25 # Raise exception on mass assignment protection for Active Record models
26 - config.active_record.mass_assignment_sanitizer = :strict
26 + # config.active_record.mass_assignment_sanitizer = :strict //DEPRICATED
27
27
28 - # Log the query plan for queries taking more than this (works
28 + # Log the query plan for queries taking more than this (works // DEPRICATED
29 - # with SQLite, MySQL, and PostgreSQL)
29 + # with SQLite, MySQL, and PostgreSQL) // DEPRICATED
30 - config.active_record.auto_explain_threshold_in_seconds = 0.5
30 + # config.active_record.auto_explain_threshold_in_seconds = 0.5 // DEPRICATED
31
31
32 # Do not compress assets
32 # Do not compress assets
33 config.assets.compress = false
33 config.assets.compress = false
34
34
35 # Expands the lines which load the assets
35 # Expands the lines which load the assets
36 config.assets.debug = true
36 config.assets.debug = true
37
37
38 # Prevents assets from rendering twice
38 # Prevents assets from rendering twice
39 - config.serve_static_assets = true
39 + config.serve_static_files = true
40 +
41 + config.eager_load = false
40 end
42 end
@@ -1,24 +1,24
1 CafeGrader::Application.configure do
1 CafeGrader::Application.configure do
2 # Settings specified here will take precedence over those in config/application.rb
2 # Settings specified here will take precedence over those in config/application.rb
3
3
4 # Code is not reloaded between requests
4 # Code is not reloaded between requests
5 config.cache_classes = true
5 config.cache_classes = true
6
6
7 # Full error reports are disabled and caching is turned on
7 # Full error reports are disabled and caching is turned on
8 config.consider_all_requests_local = false
8 config.consider_all_requests_local = false
9 config.action_controller.perform_caching = true
9 config.action_controller.perform_caching = true
10
10
11 # Disable Rails's static asset server (Apache or nginx will already do this)
11 # Disable Rails's static asset server (Apache or nginx will already do this)
12 - config.serve_static_assets = false
12 + config.serve_static_files = false
13
13
14 # Compress JavaScripts and CSS
14 # Compress JavaScripts and CSS
15 config.assets.compress = true
15 config.assets.compress = true
16
16
17 # Don't fallback to assets pipeline if a precompiled asset is missed
17 # Don't fallback to assets pipeline if a precompiled asset is missed
18 config.assets.compile = false
18 config.assets.compile = false
19
19
20 # Generate digests for assets URLs
20 # Generate digests for assets URLs
21 config.assets.digest = true
21 config.assets.digest = true
22
22
23 # Defaults to nil and saved in location specified by config.assets.prefix
23 # Defaults to nil and saved in location specified by config.assets.prefix
24 # config.assets.manifest = YOUR_PATH
24 # config.assets.manifest = YOUR_PATH
@@ -55,13 +55,15
55 # config.threadsafe!
55 # config.threadsafe!
56
56
57 # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
57 # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
58 # the I18n.default_locale when a translation can not be found)
58 # the I18n.default_locale when a translation can not be found)
59 config.i18n.fallbacks = true
59 config.i18n.fallbacks = true
60
60
61 # Send deprecation notices to registered listeners
61 # Send deprecation notices to registered listeners
62 config.active_support.deprecation = :notify
62 config.active_support.deprecation = :notify
63
63
64 # Log the query plan for queries taking more than this (works
64 # Log the query plan for queries taking more than this (works
65 # with SQLite, MySQL, and PostgreSQL)
65 # with SQLite, MySQL, and PostgreSQL)
66 # config.active_record.auto_explain_threshold_in_seconds = 0.5
66 # config.active_record.auto_explain_threshold_in_seconds = 0.5
67 +
68 + config.eager_load = true
67 end
69 end
@@ -1,37 +1,43
1 CafeGrader::Application.configure do
1 CafeGrader::Application.configure do
2 # Settings specified here will take precedence over those in config/application.rb
2 # Settings specified here will take precedence over those in config/application.rb
3
3
4 # The test environment is used exclusively to run your application's
4 # The test environment is used exclusively to run your application's
5 # test suite. You never need to work with it otherwise. Remember that
5 # test suite. You never need to work with it otherwise. Remember that
6 # your test database is "scratch space" for the test suite and is wiped
6 # your test database is "scratch space" for the test suite and is wiped
7 # and recreated between test runs. Don't rely on the data there!
7 # and recreated between test runs. Don't rely on the data there!
8 config.cache_classes = true
8 config.cache_classes = true
9
9
10 # Configure static asset server for tests with Cache-Control for performance
10 # Configure static asset server for tests with Cache-Control for performance
11 - config.serve_static_assets = true
11 + config.serve_static_files = true
12 config.static_cache_control = "public, max-age=3600"
12 config.static_cache_control = "public, max-age=3600"
13
13
14 # Log error messages when you accidentally call methods on nil
14 # Log error messages when you accidentally call methods on nil
15 config.whiny_nils = true
15 config.whiny_nils = true
16
16
17 # Show full error reports and disable caching
17 # Show full error reports and disable caching
18 config.consider_all_requests_local = true
18 config.consider_all_requests_local = true
19 config.action_controller.perform_caching = false
19 config.action_controller.perform_caching = false
20
20
21 # Raise exceptions instead of rendering exception templates
21 # Raise exceptions instead of rendering exception templates
22 config.action_dispatch.show_exceptions = false
22 config.action_dispatch.show_exceptions = false
23
23
24 # Disable request forgery protection in test environment
24 # Disable request forgery protection in test environment
25 config.action_controller.allow_forgery_protection = false
25 config.action_controller.allow_forgery_protection = false
26
26
27 # Tell Action Mailer not to deliver emails to the real world.
27 # Tell Action Mailer not to deliver emails to the real world.
28 # The :test delivery method accumulates sent emails in the
28 # The :test delivery method accumulates sent emails in the
29 # ActionMailer::Base.deliveries array.
29 # ActionMailer::Base.deliveries array.
30 config.action_mailer.delivery_method = :test
30 config.action_mailer.delivery_method = :test
31
31
32 # Raise exception on mass assignment protection for Active Record models
32 # Raise exception on mass assignment protection for Active Record models
33 - config.active_record.mass_assignment_sanitizer = :strict
33 + #config.active_record.mass_assignment_sanitizer = :strict // DEPRICATED
34
34
35 # Print deprecation notices to the stderr
35 # Print deprecation notices to the stderr
36 config.active_support.deprecation = :stderr
36 config.active_support.deprecation = :stderr
37 +
38 + config.eager_load = false
39 +
40 + #test order
41 + config.active_support.test_order = :sorted
42 +
37 end
43 end
@@ -1,6 +1,5
1 # Be sure to restart your server when you modify this file.
1 # Be sure to restart your server when you modify this file.
2
2
3 # Add new mime types for use in respond_to blocks:
3 # Add new mime types for use in respond_to blocks:
4 # Mime::Type.register "text/richtext", :rtf
4 # Mime::Type.register "text/richtext", :rtf
5 # Mime::Type.register_alias "text/html", :iphone
5 # Mime::Type.register_alias "text/html", :iphone
6 - Mime::Type.register 'application/pdf', :pdf
@@ -1,73 +1,98
1 CafeGrader::Application.routes.draw do
1 CafeGrader::Application.routes.draw do
2 get "sources/direct_edit"
2 get "sources/direct_edit"
3
3
4 root :to => 'main#login'
4 root :to => 'main#login'
5
5
6 + #logins
7 + get 'login/login', to: 'login#login'
8 +
6 resources :contests
9 resources :contests
7
10
8 resources :sites
11 resources :sites
9
12
10 resources :announcements do
13 resources :announcements do
11 member do
14 member do
12 get 'toggle','toggle_front'
15 get 'toggle','toggle_front'
13 end
16 end
14 end
17 end
15
18
16 resources :problems do
19 resources :problems do
17 member do
20 member do
18 get 'toggle'
21 get 'toggle'
19 get 'toggle_test'
22 get 'toggle_test'
23 + get 'toggle_view_testcase'
20 get 'stat'
24 get 'stat'
21 end
25 end
22 collection do
26 collection do
23 get 'turn_all_off'
27 get 'turn_all_off'
24 get 'turn_all_on'
28 get 'turn_all_on'
25 get 'import'
29 get 'import'
26 get 'manage'
30 get 'manage'
27 end
31 end
32 +
33 + end
34 +
35 + resources :testcases, only: [] do
36 + member do
37 + get 'download_input'
38 + get 'download_sol'
39 + end
40 + collection do
41 + get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
42 + end
28 end
43 end
29
44
30 resources :grader_configuration, controller: 'configurations'
45 resources :grader_configuration, controller: 'configurations'
31
46
32 resources :users do
47 resources :users do
33 member do
48 member do
34 get 'toggle_activate', 'toggle_enable'
49 get 'toggle_activate', 'toggle_enable'
35 get 'stat'
50 get 'stat'
36 end
51 end
37 end
52 end
38
53
39 resources :submissions do
54 resources :submissions do
55 + member do
56 + get 'download'
57 + get 'compiler_msg'
58 + get 'rejudge'
59 + end
40 collection do
60 collection do
41 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
61 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
42 get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
62 get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
43 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
63 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
44 end
64 end
45 end
65 end
46
66
47 - match 'tasks/view/:file.:ext' => 'tasks#view'
67 +
48 - match 'tasks/download/:id/:file.:ext' => 'tasks#download'
49 - match 'heartbeat/:id/edit' => 'heartbeat#edit'
50
68
51 #main
69 #main
52 get "main/list"
70 get "main/list"
53 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
71 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
54
72
73 + #user admin
74 + get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
75 +
55 #report
76 #report
56 get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
77 get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
57 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
78 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
58 get "report/login"
79 get "report/login"
59 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
80 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
60 post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
81 post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
61
82
83 +
84 + #
85 + get 'tasks/view/:file.:ext' => 'tasks#view'
86 + get 'tasks/download/:id/:file.:ext' => 'tasks#download'
87 + get 'heartbeat/:id/edit' => 'heartbeat#edit'
88 +
62 #grader
89 #grader
63 get 'graders/list', to: 'graders#list', as: 'grader_list'
90 get 'graders/list', to: 'graders#list', as: 'grader_list'
64
91
65
92
66 - match 'heartbeat/:id/edit' => 'heartbeat#edit'
67 -
68 # See how all your routes lay out with "rake routes"
93 # See how all your routes lay out with "rake routes"
69
94
70 # This is a legacy wild controller route that's not recommended for RESTful applications.
95 # This is a legacy wild controller route that's not recommended for RESTful applications.
71 # Note: This route will make all actions in every controller accessible via GET requests.
96 # Note: This route will make all actions in every controller accessible via GET requests.
72 - match ':controller(/:action(/:id))(.:format)'
97 + match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
73 end
98 end
@@ -1,280 +1,283
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 to 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 => 20161014091417) do
14 + ActiveRecord::Schema.define(version: 20170427070345) do
15
15
16 - create_table "announcements", :force => true do |t|
16 + create_table "announcements", force: :cascade do |t|
17 - t.string "author"
17 + t.string "author", limit: 255
18 - t.text "body"
18 + t.text "body", limit: 65535
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"
24 + t.string "title", limit: 255
25 - t.string "notes"
25 + t.string "notes", limit: 255
26 end
26 end
27
27
28 - create_table "contests", :force => true do |t|
28 + create_table "contests", force: :cascade do |t|
29 - t.string "title"
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"
33 + t.string "name", limit: 255
34 end
34 end
35
35
36 - create_table "contests_problems", :id => false, :force => true do |t|
36 + create_table "contests_problems", id: false, force: :cascade do |t|
37 - t.integer "contest_id"
37 + t.integer "contest_id", limit: 4
38 - t.integer "problem_id"
38 + t.integer "problem_id", limit: 4
39 end
39 end
40
40
41 - create_table "contests_users", :id => false, :force => true do |t|
41 + create_table "contests_users", id: false, force: :cascade do |t|
42 - t.integer "contest_id"
42 + t.integer "contest_id", limit: 4
43 - t.integer "user_id"
43 + t.integer "user_id", limit: 4
44 end
44 end
45
45
46 - create_table "countries", :force => true do |t|
46 + create_table "countries", force: :cascade do |t|
47 - t.string "name"
47 + t.string "name", limit: 255
48 - t.datetime "created_at", :null => false
48 + t.datetime "created_at", null: false
49 - t.datetime "updated_at", :null => false
49 + t.datetime "updated_at", null: false
50 end
50 end
51
51
52 - create_table "descriptions", :force => true do |t|
52 + create_table "descriptions", force: :cascade do |t|
53 - t.text "body"
53 + t.text "body", limit: 65535
54 t.boolean "markdowned"
54 t.boolean "markdowned"
55 - t.datetime "created_at", :null => false
55 + t.datetime "created_at", null: false
56 - t.datetime "updated_at", :null => false
56 + t.datetime "updated_at", null: false
57 end
57 end
58
58
59 - create_table "grader_configurations", :force => true do |t|
59 + create_table "grader_configurations", force: :cascade do |t|
60 - t.string "key"
60 + t.string "key", limit: 255
61 - t.string "value_type"
61 + t.string "value_type", limit: 255
62 - t.string "value"
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"
65 + t.text "description", limit: 65535
66 end
66 end
67
67
68 - create_table "grader_processes", :force => true do |t|
68 + create_table "grader_processes", force: :cascade do |t|
69 - t.string "host"
69 + t.string "host", limit: 255
70 - t.integer "pid"
70 + t.integer "pid", limit: 4
71 - t.string "mode"
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"
75 + t.integer "task_id", limit: 4
76 - t.string "task_type"
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"
80 + add_index "grader_processes", ["host", "pid"], name: "index_grader_processes_on_ip_and_pid", using: :btree
81
81
82 - create_table "heart_beats", :force => true do |t|
82 + create_table "heart_beats", force: :cascade do |t|
83 - t.integer "user_id"
83 + t.integer "user_id", limit: 4
84 - t.string "ip_address"
84 + t.string "ip_address", limit: 255
85 - t.datetime "created_at", :null => false
85 + t.datetime "created_at", null: false
86 - t.datetime "updated_at", :null => false
86 + t.datetime "updated_at", null: false
87 - t.string "status"
87 + t.string "status", limit: 255
88 end
88 end
89
89
90 - add_index "heart_beats", ["updated_at"], :name => "index_heart_beats_on_updated_at"
90 + add_index "heart_beats", ["updated_at"], name: "index_heart_beats_on_updated_at", using: :btree
91
91
92 - create_table "languages", :force => true do |t|
92 + create_table "languages", force: :cascade do |t|
93 - t.string "name", :limit => 10
93 + t.string "name", limit: 10
94 - t.string "pretty_name"
94 + t.string "pretty_name", limit: 255
95 - t.string "ext", :limit => 10
95 + t.string "ext", limit: 10
96 - t.string "common_ext"
96 + t.string "common_ext", limit: 255
97 end
97 end
98
98
99 - create_table "logins", :force => true do |t|
99 + create_table "logins", force: :cascade do |t|
100 - t.integer "user_id"
100 + t.integer "user_id", limit: 4
101 - t.string "ip_address"
101 + t.string "ip_address", limit: 255
102 - t.datetime "created_at", :null => false
102 + t.datetime "created_at", null: false
103 - t.datetime "updated_at", :null => false
103 + t.datetime "updated_at", null: false
104 end
104 end
105
105
106 - create_table "messages", :force => true do |t|
106 + create_table "messages", force: :cascade do |t|
107 - t.integer "sender_id"
107 + t.integer "sender_id", limit: 4
108 - t.integer "receiver_id"
108 + t.integer "receiver_id", limit: 4
109 - t.integer "replying_message_id"
109 + t.integer "replying_message_id", limit: 4
110 - t.text "body"
110 + t.text "body", limit: 65535
111 t.boolean "replied"
111 t.boolean "replied"
112 - t.datetime "created_at", :null => false
112 + t.datetime "created_at", null: false
113 - t.datetime "updated_at", :null => false
113 + t.datetime "updated_at", null: false
114 end
114 end
115
115
116 - create_table "problems", :force => true do |t|
116 + create_table "problems", force: :cascade do |t|
117 - t.string "name", :limit => 30
117 + t.string "name", limit: 30
118 - t.string "full_name"
118 + t.string "full_name", limit: 255
119 - t.integer "full_score"
119 + t.integer "full_score", limit: 4
120 t.date "date_added"
120 t.date "date_added"
121 t.boolean "available"
121 t.boolean "available"
122 - t.string "url"
122 + t.string "url", limit: 255
123 - t.integer "description_id"
123 + t.integer "description_id", limit: 4
124 t.boolean "test_allowed"
124 t.boolean "test_allowed"
125 t.boolean "output_only"
125 t.boolean "output_only"
126 - t.string "description_filename"
126 + t.string "description_filename", limit: 255
127 + t.boolean "view_testcase"
127 end
128 end
128
129
129 - create_table "rights", :force => true do |t|
130 + create_table "rights", force: :cascade do |t|
130 - t.string "name"
131 + t.string "name", limit: 255
131 - t.string "controller"
132 + t.string "controller", limit: 255
132 - t.string "action"
133 + t.string "action", limit: 255
133 end
134 end
134
135
135 - create_table "rights_roles", :id => false, :force => true do |t|
136 + create_table "rights_roles", id: false, force: :cascade do |t|
136 - t.integer "right_id"
137 + t.integer "right_id", limit: 4
137 - t.integer "role_id"
138 + t.integer "role_id", limit: 4
138 end
139 end
139
140
140 - add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
141 + add_index "rights_roles", ["role_id"], name: "index_rights_roles_on_role_id", using: :btree
141
142
142 - create_table "roles", :force => true do |t|
143 + create_table "roles", force: :cascade do |t|
143 - t.string "name"
144 + t.string "name", limit: 255
144 end
145 end
145
146
146 - create_table "roles_users", :id => false, :force => true do |t|
147 + create_table "roles_users", id: false, force: :cascade do |t|
147 - t.integer "role_id"
148 + t.integer "role_id", limit: 4
148 - t.integer "user_id"
149 + t.integer "user_id", limit: 4
149 end
150 end
150
151
151 - add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
152 + add_index "roles_users", ["user_id"], name: "index_roles_users_on_user_id", using: :btree
152
153
153 - create_table "sessions", :force => true do |t|
154 + create_table "sessions", force: :cascade do |t|
154 - t.string "session_id"
155 + t.string "session_id", limit: 255
155 - t.text "data"
156 + t.text "data", limit: 65535
156 t.datetime "updated_at"
157 t.datetime "updated_at"
157 end
158 end
158
159
159 - add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
160 + add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", using: :btree
160 - add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
161 + add_index "sessions", ["updated_at"], name: "index_sessions_on_updated_at", using: :btree
161
162
162 - create_table "sites", :force => true do |t|
163 + create_table "sites", force: :cascade do |t|
163 - t.string "name"
164 + t.string "name", limit: 255
164 t.boolean "started"
165 t.boolean "started"
165 t.datetime "start_time"
166 t.datetime "start_time"
166 - t.datetime "created_at", :null => false
167 + t.datetime "created_at", null: false
167 - t.datetime "updated_at", :null => false
168 + t.datetime "updated_at", null: false
168 - t.integer "country_id"
169 + t.integer "country_id", limit: 4
169 - t.string "password"
170 + t.string "password", limit: 255
170 end
171 end
171
172
172 - create_table "submission_view_logs", :force => true do |t|
173 + create_table "submission_view_logs", force: :cascade do |t|
173 - t.integer "user_id"
174 + t.integer "user_id", limit: 4
174 - t.integer "submission_id"
175 + t.integer "submission_id", limit: 4
175 - t.datetime "created_at", :null => false
176 + t.datetime "created_at", null: false
176 - t.datetime "updated_at", :null => false
177 + t.datetime "updated_at", null: false
177 end
178 end
178
179
179 - create_table "submissions", :force => true do |t|
180 + create_table "submissions", force: :cascade do |t|
180 - t.integer "user_id"
181 + t.integer "user_id", limit: 4
181 - t.integer "problem_id"
182 + t.integer "problem_id", limit: 4
182 - t.integer "language_id"
183 + t.integer "language_id", limit: 4
183 - t.text "source"
184 + t.text "source", limit: 65535
184 - t.binary "binary"
185 + t.binary "binary", limit: 65535
185 t.datetime "submitted_at"
186 t.datetime "submitted_at"
186 t.datetime "compiled_at"
187 t.datetime "compiled_at"
187 - t.text "compiler_message"
188 + t.text "compiler_message", limit: 65535
188 t.datetime "graded_at"
189 t.datetime "graded_at"
189 - t.integer "points"
190 + t.integer "points", limit: 4
190 - t.text "grader_comment"
191 + t.text "grader_comment", limit: 65535
191 - t.integer "number"
192 + t.integer "number", limit: 4
192 - t.string "source_filename"
193 + t.string "source_filename", limit: 255
193 - t.float "max_runtime"
194 + t.float "max_runtime", limit: 24
194 - t.integer "peak_memory"
195 + t.integer "peak_memory", limit: 4
195 - t.integer "effective_code_length"
196 + t.integer "effective_code_length", limit: 4
196 - t.string "ip_address"
197 + t.string "ip_address", limit: 255
197 end
198 end
198
199
199 - add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
200 + add_index "submissions", ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true, using: :btree
200 - add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
201 + add_index "submissions", ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id", using: :btree
201
202
202 - create_table "tasks", :force => true do |t|
203 + create_table "tasks", force: :cascade do |t|
203 - t.integer "submission_id"
204 + t.integer "submission_id", limit: 4
204 t.datetime "created_at"
205 t.datetime "created_at"
205 - t.integer "status"
206 + t.integer "status", limit: 4
206 t.datetime "updated_at"
207 t.datetime "updated_at"
207 end
208 end
208
209
209 - create_table "test_pairs", :force => true do |t|
210 + add_index "tasks", ["submission_id"], name: "index_tasks_on_submission_id", using: :btree
210 - t.integer "problem_id"
211 +
211 - t.text "input", :limit => 16777215
212 + create_table "test_pairs", force: :cascade do |t|
212 - t.text "solution", :limit => 16777215
213 + t.integer "problem_id", limit: 4
213 - t.datetime "created_at", :null => false
214 + t.text "input", limit: 16777215
214 - t.datetime "updated_at", :null => false
215 + t.text "solution", limit: 16777215
216 + t.datetime "created_at", null: false
217 + t.datetime "updated_at", null: false
215 end
218 end
216
219
217 - create_table "test_requests", :force => true do |t|
220 + create_table "test_requests", force: :cascade do |t|
218 - t.integer "user_id"
221 + t.integer "user_id", limit: 4
219 - t.integer "problem_id"
222 + t.integer "problem_id", limit: 4
220 - t.integer "submission_id"
223 + t.integer "submission_id", limit: 4
221 - t.string "input_file_name"
224 + t.string "input_file_name", limit: 255
222 - t.string "output_file_name"
225 + t.string "output_file_name", limit: 255
223 - t.string "running_stat"
226 + t.string "running_stat", limit: 255
224 - t.integer "status"
227 + t.integer "status", limit: 4
225 - t.datetime "updated_at", :null => false
228 + t.datetime "updated_at", null: false
226 t.datetime "submitted_at"
229 t.datetime "submitted_at"
227 t.datetime "compiled_at"
230 t.datetime "compiled_at"
228 - t.text "compiler_message"
231 + t.text "compiler_message", limit: 65535
229 t.datetime "graded_at"
232 t.datetime "graded_at"
230 - t.string "grader_comment"
233 + t.string "grader_comment", limit: 255
231 - t.datetime "created_at", :null => false
234 + t.datetime "created_at", null: false
232 - t.float "running_time"
235 + t.float "running_time", limit: 24
233 - t.string "exit_status"
236 + t.string "exit_status", limit: 255
234 - t.integer "memory_usage"
237 + t.integer "memory_usage", limit: 4
235 end
238 end
236
239
237 - add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
240 + add_index "test_requests", ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id", using: :btree
238
241
239 - create_table "testcases", :force => true do |t|
242 + create_table "testcases", force: :cascade do |t|
240 - t.integer "problem_id"
243 + t.integer "problem_id", limit: 4
241 - t.integer "num"
244 + t.integer "num", limit: 4
242 - t.integer "group"
245 + t.integer "group", limit: 4
243 - t.integer "score"
246 + t.integer "score", limit: 4
244 - t.text "input"
247 + t.text "input", limit: 4294967295
245 - t.text "sol"
248 + t.text "sol", limit: 4294967295
246 - t.datetime "created_at", :null => false
249 + t.datetime "created_at"
247 - t.datetime "updated_at", :null => false
250 + t.datetime "updated_at"
248 end
251 end
249
252
250 - add_index "testcases", ["problem_id"], :name => "index_testcases_on_problem_id"
253 + add_index "testcases", ["problem_id"], name: "index_testcases_on_problem_id", using: :btree
251
254
252 - create_table "user_contest_stats", :force => true do |t|
255 + create_table "user_contest_stats", force: :cascade do |t|
253 - t.integer "user_id"
256 + t.integer "user_id", limit: 4
254 t.datetime "started_at"
257 t.datetime "started_at"
255 - t.datetime "created_at", :null => false
258 + t.datetime "created_at", null: false
256 - t.datetime "updated_at", :null => false
259 + t.datetime "updated_at", null: false
257 t.boolean "forced_logout"
260 t.boolean "forced_logout"
258 end
261 end
259
262
260 - create_table "users", :force => true do |t|
263 + create_table "users", force: :cascade do |t|
261 - t.string "login", :limit => 50
264 + t.string "login", limit: 50
262 - t.string "full_name"
265 + t.string "full_name", limit: 255
263 - t.string "hashed_password"
266 + t.string "hashed_password", limit: 255
264 - t.string "salt", :limit => 5
267 + t.string "salt", limit: 5
265 - t.string "alias"
268 + t.string "alias", limit: 255
266 - t.string "email"
269 + t.string "email", limit: 255
267 - t.integer "site_id"
270 + t.integer "site_id", limit: 4
268 - t.integer "country_id"
271 + t.integer "country_id", limit: 4
269 - t.boolean "activated", :default => false
272 + t.boolean "activated", default: false
270 t.datetime "created_at"
273 t.datetime "created_at"
271 t.datetime "updated_at"
274 t.datetime "updated_at"
272 - t.boolean "enabled", :default => true
275 + t.boolean "enabled", default: true
273 - t.string "remark"
276 + t.string "remark", limit: 255
274 - t.string "last_ip"
277 + t.string "last_ip", limit: 255
275 - t.string "section"
278 + t.string "section", limit: 255
276 end
279 end
277
280
278 - add_index "users", ["login"], :name => "index_users_on_login", :unique => true
281 + add_index "users", ["login"], name: "index_users_on_login", unique: true, using: :btree
279
282
280 end
283 end
@@ -44,45 +44,73
44 :value_type => 'string',
44 :value_type => 'string',
45 :default_value => 'Grader',
45 :default_value => 'Grader',
46 :description => 'This name will be shown on the user header bar.'
46 :description => 'This name will be shown on the user header bar.'
47 },
47 },
48
48
49 {
49 {
50 :key => 'contest.multisites',
50 :key => 'contest.multisites',
51 :value_type => 'boolean',
51 :value_type => 'boolean',
52 :default_value => 'false',
52 :default_value => 'false',
53 :description => 'If the server is in contest mode and this option is true, on the log in of the admin a menu for site selections is shown.'
53 :description => 'If the server is in contest mode and this option is true, on the log in of the admin a menu for site selections is shown.'
54 },
54 },
55
55
56 + #---------------------------- right --------------------------------
56 {
57 {
57 :key => 'right.user_hall_of_fame',
58 :key => 'right.user_hall_of_fame',
58 :value_type => 'boolean',
59 :value_type => 'boolean',
59 :default_value => 'false',
60 :default_value => 'false',
60 :description => 'If true, any user can access hall of fame page.'
61 :description => 'If true, any user can access hall of fame page.'
61 },
62 },
62
63
63 {
64 {
64 :key => 'right.multiple_ip_login',
65 :key => 'right.multiple_ip_login',
65 :value_type => 'boolean',
66 :value_type => 'boolean',
66 :default_value => 'true',
67 :default_value => 'true',
67 :description => 'When change from true to false, a user can login from the first IP they logged into afterward.'
68 :description => 'When change from true to false, a user can login from the first IP they logged into afterward.'
68 },
69 },
69
70
70 {
71 {
71 :key => 'right.user_view_submission',
72 :key => 'right.user_view_submission',
72 :value_type => 'boolean',
73 :value_type => 'boolean',
73 :default_value => 'false',
74 :default_value => 'false',
74 :description => 'If true, any user can view submissions of every one.'
75 :description => 'If true, any user can view submissions of every one.'
75 },
76 },
76
77
78 + {
79 + :key => 'right.bypass_agreement',
80 + :value_type => 'boolean',
81 + :default_value => 'true',
82 + :description => 'When false, a user must accept usage agreement before login'
83 + },
84 +
85 + {
86 + :key => 'right.heartbeat_response',
87 + :value_type => 'string',
88 + :default_value => 'OK',
89 + :description => 'Heart beat response text'
90 + },
91 +
92 + {
93 + :key => 'right.heartbeat_response_full',
94 + :value_type => 'string',
95 + :default_value => 'OK',
96 + :description => 'Heart beat response text when user got full score (set this value to the empty string to disable this feature)'
97 + },
98 +
99 + {
100 + :key => 'right.view_testcase',
101 + :value_type => 'boolean',
102 + :default_value => 'false',
103 + :description => 'When true, any user can view/download test data'
104 + },
77 # If Configuration['system.online_registration'] is true, the
105 # If Configuration['system.online_registration'] is true, the
78 # system allows online registration, and will use these
106 # system allows online registration, and will use these
79 # information for sending confirmation emails.
107 # information for sending confirmation emails.
80 {
108 {
81 :key => 'system.online_registration.smtp',
109 :key => 'system.online_registration.smtp',
82 :value_type => 'string',
110 :value_type => 'string',
83 :default_value => 'smtp.somehost.com'
111 :default_value => 'smtp.somehost.com'
84 },
112 },
85
113
86 {
114 {
87 :key => 'system.online_registration.from',
115 :key => 'system.online_registration.from',
88 :value_type => 'string',
116 :value_type => 'string',
@@ -46,13 +46,28
46 cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" +
46 cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" +
47 " -t #{time_limit} -m #{memory_limit}"
47 " -t #{time_limit} -m #{memory_limit}"
48
48
49 output = `#{cmd}`
49 output = `#{cmd}`
50
50
51 Dir.chdir(cur_dir)
51 Dir.chdir(cur_dir)
52
52
53 return "import CMD: #{cmd}\n" + output
53 return "import CMD: #{cmd}\n" + output
54 end
54 end
55 return ''
55 return ''
56 end
56 end
57
57
58 + def self.call_import_testcase(problem_name)
59 + if GraderScript.grader_control_enabled?
60 + cur_dir = `pwd`.chomp
61 + Dir.chdir(GRADER_ROOT_DIR)
62 +
63 + script_name = File.join(GRADER_ROOT_DIR, "scripts/load_testcase")
64 + cmd = "#{script_name} #{problem_name}"
65 +
66 + output = `#{cmd}`
67 +
68 + Dir.chdir(cur_dir)
69 + return "Testcase import result:\n" + output
58 end
70 end
71 + end
72 +
73 + end
@@ -29,24 +29,27
29 if import_test_pairs(dirname)
29 if import_test_pairs(dirname)
30 test_pair_count = TestPair.count :conditions => "problem_id = #{@problem.id}"
30 test_pair_count = TestPair.count :conditions => "problem_id = #{@problem.id}"
31 @log_msg = "Importing test pair successful. (#{test_pair_count} test pairs imported)"
31 @log_msg = "Importing test pair successful. (#{test_pair_count} test pairs imported)"
32 else
32 else
33 @log_msg = "Importing test pair failed. (0 test pairs imported)"
33 @log_msg = "Importing test pair failed. (0 test pairs imported)"
34 end
34 end
35 end
35 end
36
36
37 @log_msg << import_problem_description(dirname)
37 @log_msg << import_problem_description(dirname)
38 @log_msg << import_problem_pdf(dirname)
38 @log_msg << import_problem_pdf(dirname)
39 @log_msg << import_full_score(dirname)
39 @log_msg << import_full_score(dirname)
40
40
41 + #import test data
42 + @log_msg << GraderScript.call_import_testcase(@problem.name)
43 +
41 return true
44 return true
42 end
45 end
43
46
44 protected
47 protected
45
48
46 def self.long_ext(filename)
49 def self.long_ext(filename)
47 i = filename.index('.')
50 i = filename.index('.')
48 len = filename.length
51 len = filename.length
49 return filename.slice(i..len)
52 return filename.slice(i..len)
50 end
53 end
51
54
52 def extract(tempfile)
55 def extract(tempfile)
@@ -1,17 +1,17
1 ENV["RAILS_ENV"] = "test"
1 ENV["RAILS_ENV"] = "test"
2 require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
2 require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
3
3
4 def clear_all_tasks
4 def clear_all_tasks
5 - Task.find(:all).each do |task|
5 + Task.all.each do |task|
6 task.destroy
6 task.destroy
7 end
7 end
8 end
8 end
9
9
10
10
11 clear_all_tasks
11 clear_all_tasks
12
12
13 (1..1000).each do |i|
13 (1..1000).each do |i|
14 Task.create(:id => i,
14 Task.create(:id => i,
15 :submission_id => i,
15 :submission_id => i,
16 :status => Task::STATUS_INQUEUE)
16 :status => Task::STATUS_INQUEUE)
17 end
17 end
@@ -1,14 +1,13
1 ENV["RAILS_ENV"] = "test"
1 ENV["RAILS_ENV"] = "test"
2 require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
2 require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
3
3
4 def clear_all_tasks
4 def clear_all_tasks
5 - Task.find(:all).each do |task|
5 + Task.all.each do |task|
6 task.destroy
6 task.destroy
7 end
7 end
8 end
8 end
9
9
10 - puts Task.find(:all,
10 + puts Task.where(status: Task::STATUS_COMPLETE).length
11 - :conditions => {:status => Task::STATUS_COMPLETE}).length
12
11
13 clear_all_tasks
12 clear_all_tasks
14
13
@@ -1,5 +1,36
1 - # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
1 + Language_1:
2 - one:
2 + name: c
3 - id: 1
3 + pretty_name: C
4 - two:
4 + ext: c
5 - id: 2
5 + common_ext: c
6 +
7 + Language_2:
8 + name: cpp
9 + pretty_name: C++
10 + ext: cpp
11 + common_ext: cpp,cc
12 +
13 + Language_3:
14 + name: pas
15 + pretty_name: Pascal
16 + ext: pas
17 + common_ext: pas
18 +
19 + Language_4:
20 + name: ruby
21 + pretty_name: Ruby
22 + ext: rb
23 + common_ext: rb
24 +
25 + Language_5:
26 + name: python
27 + pretty_name: Python
28 + ext: py
29 + common_ext: py
30 +
31 + Language_6:
32 + name: java
33 + pretty_name: Java
34 + ext: java
35 + common_ext: java
36 +
@@ -4,28 +4,28
4 User.public_class_method :encrypt
4 User.public_class_method :encrypt
5
5
6 salt = "abc"
6 salt = "abc"
7 %>
7 %>
8
8
9 john:
9 john:
10 login: john
10 login: john
11 full_name: john
11 full_name: john
12 hashed_password: <%= User.encrypt("hello",salt) %>
12 hashed_password: <%= User.encrypt("hello",salt) %>
13 salt: <%= salt %>
13 salt: <%= salt %>
14 activated: true
14 activated: true
15
15
16 - mary:
16 + admin:
17 - login: mary
17 + login: admin
18 - full_name: mary
18 + full_name: admin
19 - hashed_password: <%= User.encrypt("goodbye",salt) %>
19 + hashed_password: <%= User.encrypt("admin",salt) %>
20 salt: <%= salt %>
20 salt: <%= salt %>
21 roles: admin
21 roles: admin
22 activated: true
22 activated: true
23
23
24 james:
24 james:
25 login: james
25 login: james
26 full_name: James
26 full_name: James
27 hashed_password: <%= User.encrypt("morning",salt) %>
27 hashed_password: <%= User.encrypt("morning",salt) %>
28 salt: <%= salt %>
28 salt: <%= salt %>
29 contests: contest_a
29 contests: contest_a
30 activated: true
30 activated: true
31
31
@@ -1,16 +1,27
1 ENV["RAILS_ENV"] = "test"
1 ENV["RAILS_ENV"] = "test"
2 require File.expand_path('../../config/environment', __FILE__)
2 require File.expand_path('../../config/environment', __FILE__)
3 require 'rails/test_help'
3 require 'rails/test_help'
4
4
5 + #reporter for beautiful result
6 + require "minitest/reporters"
7 + Minitest::Reporters.use!
8 +
9 + module SignInHelper
10 + def sign_in_as(user,password)
11 + post login_login_path, {login: user, password: password }
12 + end
13 + end
14 +
5 class ActiveSupport::TestCase
15 class ActiveSupport::TestCase
16 + include SignInHelper
6 # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
17 # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
7 #
18 #
8 # Note: You'll currently still have to declare fixtures explicitly in integration tests
19 # Note: You'll currently still have to declare fixtures explicitly in integration tests
9 # -- they do not yet inherit this setting
20 # -- they do not yet inherit this setting
10 fixtures :all
21 fixtures :all
11
22
12 # Add more helper methods to be used by all tests here...
23 # Add more helper methods to be used by all tests here...
13
24
14 self.use_transactional_fixtures = true
25 self.use_transactional_fixtures = true
15 self.use_instantiated_fixtures = false
26 self.use_instantiated_fixtures = false
16 end
27 end
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
You need to be logged in to leave comments. Login now