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
@@ -28,6 +28,8
28 28 *.orig
29 29 *.swp
30 30
31 31 #ignore rvm setting file
32 32 .ruby-gemset
33 33 .ruby-version
34 +
35 + /config/secrets.yml
@@ -1,30 +1,37
1 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 8 # Bundle edge Rails instead:
8 9 # gem 'rails', :git => 'git://github.com/rails/rails.git'
9 10
11 + #---------------- database ---------------------
12 + #the database
10 13 gem 'mysql2'
14 + #for testing
15 + gem 'sqlite3'
16 + #for dumping database into yaml
17 + gem 'yaml_db'
11 18
12 19 # Gems used only for assets and not required
13 20 # in production environments by default.
14 - group :assets do
15 - gem 'sass-rails', '~> 3.2.6'
16 - gem 'coffee-rails', '~> 3.2.2'
21 + gem 'sass-rails'
22 + gem 'coffee-rails'
17 23
18 24 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
19 25 # gem 'therubyracer', :platforms => :ruby
20 26
21 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 33 # To use ActiveModel has_secure_password
27 34 # gem 'bcrypt-ruby', '~> 3.0.0'
28 35
29 36 # To use Jbuilder templates for JSON
30 37 # gem 'jbuilder'
@@ -41,13 +48,13
41 48
42 49 #in-place editor
43 50 gem 'best_in_place', '~> 3.0.1'
44 51
45 52 # jquery addition
46 53 gem 'jquery-rails'
47 - gem 'jquery-ui-sass-rails'
54 + gem 'jquery-ui-rails'
48 55 gem 'jquery-timepicker-addon-rails'
49 56 gem 'jquery-tablesorter'
50 57 gem 'jquery-countdown-rails'
51 58
52 59 #syntax highlighter
53 60 gem 'rouge'
@@ -59,22 +66,26
59 66 gem 'autoprefixer-rails'
60 67
61 68 #bootstrap sortable
62 69 gem 'momentjs-rails'
63 70 gem 'rails_bootstrap_sortable'
64 71
72 + #----------- user interface -----------------
73 + #select 2
74 + gem 'select2-rails'
65 75 #ace editor
66 76 gem 'ace-rails-ap'
77 + #paginator
78 + gem 'will_paginate', '~> 3.0.7'
67 79
68 - gem 'haml'
69 - gem 'haml-rails'
70 80 gem 'mail'
71 81 gem 'rdiscount'
72 - gem 'test-unit'
73 - gem 'will_paginate', '~> 3.0.7'
74 82 gem 'dynamic_form'
75 83 gem 'in_place_editing'
76 84 gem 'verification', :git => 'https://github.com/sikachu/verification.git'
77 85
78 - group :test, :development do
79 - gem 'rspec-rails', '~> 2.99.0'
80 - end
86 +
87 + #---------------- testiing -----------------------
88 + gem 'minitest-reporters'
89 +
90 + #---------------- for console --------------------
91 + gem 'fuzzy-string-match'
@@ -1,208 +1,235
1 1 GIT
2 2 remote: https://github.com/sikachu/verification.git
3 - revision: 76eaf51b13276ecae54bd9cd115832595d2ff56d
3 + revision: ff31697b940d7b0e2ec65f08764215c96104e76d
4 4 specs:
5 5 verification (1.0.3)
6 - actionpack (>= 3.0.0, < 5.0)
7 - activesupport (>= 3.0.0, < 5.0)
6 + actionpack (>= 3.0.0, < 5.1)
7 + activesupport (>= 3.0.0, < 5.1)
8 8
9 9 GEM
10 10 remote: https://rubygems.org/
11 11 specs:
12 - ace-rails-ap (4.0.2)
13 - actionmailer (3.2.22.5)
14 - actionpack (= 3.2.22.5)
15 - mail (~> 2.5.4)
16 - actionpack (3.2.22.5)
17 - activemodel (= 3.2.22.5)
18 - activesupport (= 3.2.22.5)
19 - builder (~> 3.0.0)
12 + RubyInline (3.12.4)
13 + ZenTest (~> 4.3)
14 + ZenTest (4.11.1)
15 + ace-rails-ap (4.1.1)
16 + actionmailer (4.2.7.1)
17 + actionpack (= 4.2.7.1)
18 + actionview (= 4.2.7.1)
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 32 erubis (~> 2.7.0)
21 - journey (~> 1.0.4)
22 - rack (~> 1.4.5)
23 - rack-cache (~> 1.2)
24 - rack-test (~> 0.6.1)
25 - sprockets (~> 2.2.1)
26 - activemodel (3.2.22.5)
27 - activesupport (= 3.2.22.5)
28 - builder (~> 3.0.0)
29 - activerecord (3.2.22.5)
30 - activemodel (= 3.2.22.5)
31 - activesupport (= 3.2.22.5)
32 - arel (~> 3.0.2)
33 - tzinfo (~> 0.3.29)
34 - activeresource (3.2.22.5)
35 - activemodel (= 3.2.22.5)
36 - activesupport (= 3.2.22.5)
37 - activesupport (3.2.22.5)
38 - i18n (~> 0.6, >= 0.6.4)
39 - multi_json (~> 1.0)
40 - arel (3.0.3)
41 - autoprefixer-rails (6.0.3)
33 + rails-dom-testing (~> 1.0, >= 1.0.5)
34 + rails-html-sanitizer (~> 1.0, >= 1.0.2)
35 + activejob (4.2.7.1)
36 + activesupport (= 4.2.7.1)
37 + globalid (>= 0.3.0)
38 + activemodel (4.2.7.1)
39 + activesupport (= 4.2.7.1)
40 + builder (~> 3.1)
41 + activerecord (4.2.7.1)
42 + activemodel (= 4.2.7.1)
43 + activesupport (= 4.2.7.1)
44 + arel (~> 6.0)
45 + activerecord-session_store (1.0.0)
46 + actionpack (>= 4.0, < 5.1)
47 + activerecord (>= 4.0, < 5.1)
48 + multi_json (~> 1.11, >= 1.11.2)
49 + rack (>= 1.5.2, < 3)
50 + railties (>= 4.0, < 5.1)
51 + activesupport (4.2.7.1)
52 + i18n (~> 0.7)
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 60 execjs
43 - json
44 61 best_in_place (3.0.3)
45 62 actionpack (>= 3.2)
46 63 railties (>= 3.2)
47 64 bootstrap-sass (3.2.0.2)
48 65 sass (~> 3.2)
49 66 bootstrap-switch-rails (3.3.3)
50 67 bootstrap-toggle-rails (2.2.1.0)
51 - builder (3.0.4)
52 - coffee-rails (3.2.2)
68 + builder (3.2.2)
69 + coffee-rails (4.2.1)
53 70 coffee-script (>= 2.2.0)
54 - railties (~> 3.2.0)
55 - coffee-script (2.3.0)
71 + railties (>= 4.0.0, < 5.2.x)
72 + coffee-script (2.4.1)
56 73 coffee-script-source
57 74 execjs
58 - coffee-script-source (1.9.0)
59 - diff-lcs (1.2.5)
75 + coffee-script-source (1.12.2)
76 + concurrent-ruby (1.0.4)
60 77 dynamic_form (1.1.4)
61 78 erubis (2.7.0)
62 - execjs (2.3.0)
63 - haml (4.0.6)
79 + execjs (2.7.0)
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 85 tilt
65 - haml-rails (0.4)
66 - actionpack (>= 3.1, < 4.1)
67 - activesupport (>= 3.1, < 4.1)
68 - haml (>= 3.1, < 4.1)
69 - railties (>= 3.1, < 4.1)
70 - hike (1.2.3)
86 + haml-rails (0.9.0)
87 + actionpack (>= 4.0.1)
88 + activesupport (>= 4.0.1)
89 + haml (>= 4.0.6, < 5.0)
90 + html2haml (>= 1.0.1)
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 97 i18n (0.7.0)
72 98 in_place_editing (1.2.0)
73 - journey (1.0.4)
74 99 jquery-countdown-rails (2.0.2)
75 - jquery-rails (3.1.2)
76 - railties (>= 3.0, < 5.0)
100 + jquery-rails (4.2.1)
101 + rails-dom-testing (>= 1, < 3)
102 + railties (>= 4.2.0)
77 103 thor (>= 0.14, < 2.0)
78 - jquery-tablesorter (1.13.4)
79 - railties (>= 3.1, < 5)
104 + jquery-tablesorter (1.23.3)
105 + railties (>= 3.2, < 6)
80 106 jquery-timepicker-addon-rails (1.4.1)
81 107 railties (>= 3.1)
82 - jquery-ui-rails (4.0.3)
83 - jquery-rails
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)
108 + jquery-ui-rails (6.0.1)
109 + railties (>= 3.2.16)
89 110 json (1.8.3)
90 - mail (2.5.4)
91 - mime-types (~> 1.16)
92 - treetop (~> 1.4.8)
93 - mime-types (1.25.1)
94 - momentjs-rails (2.11.1)
111 + loofah (2.0.3)
112 + nokogiri (>= 1.5.9)
113 + mail (2.6.4)
114 + mime-types (>= 1.16, < 4)
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 126 railties (>= 3.1)
96 127 multi_json (1.12.1)
97 - mysql2 (0.3.20)
98 - polyglot (0.3.5)
99 - power_assert (0.2.2)
100 - prototype-rails (3.2.1)
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
128 + mysql2 (0.4.5)
129 + nokogiri (1.6.8.1)
130 + mini_portile2 (~> 2.1.0)
131 + rack (1.6.5)
107 132 rack-test (0.6.3)
108 133 rack (>= 1.0)
109 - rails (3.2.22.5)
110 - actionmailer (= 3.2.22.5)
111 - actionpack (= 3.2.22.5)
112 - activerecord (= 3.2.22.5)
113 - activeresource (= 3.2.22.5)
114 - activesupport (= 3.2.22.5)
115 - bundler (~> 1.0)
116 - railties (= 3.2.22.5)
117 - rails_bootstrap_sortable (2.0.0)
118 - momentjs-rails (~> 2, >= 2.8.3)
119 - railties (3.2.22.5)
120 - actionpack (= 3.2.22.5)
121 - activesupport (= 3.2.22.5)
122 - rack-ssl (~> 1.3.2)
134 + rails (4.2.7.1)
135 + actionmailer (= 4.2.7.1)
136 + actionpack (= 4.2.7.1)
137 + actionview (= 4.2.7.1)
138 + activejob (= 4.2.7.1)
139 + activemodel (= 4.2.7.1)
140 + activerecord (= 4.2.7.1)
141 + activesupport (= 4.2.7.1)
142 + bundler (>= 1.3.0, < 2.0)
143 + railties (= 4.2.7.1)
144 + sprockets-rails
145 + rails-deprecated_sanitizer (1.0.3)
146 + activesupport (>= 4.2.0.alpha)
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 158 rake (>= 0.8.7)
124 - rdoc (~> 3.4)
125 - thor (>= 0.14.6, < 2.0)
126 - rake (11.2.2)
127 - rdiscount (2.1.8)
128 - rdoc (3.12.2)
129 - json (~> 1.4)
130 - rouge (1.8.0)
131 - rspec-collection_matchers (1.1.2)
132 - rspec-expectations (>= 2.99.0.beta1)
133 - rspec-core (2.99.2)
134 - rspec-expectations (2.99.2)
135 - diff-lcs (>= 1.1.3, < 2.0)
136 - rspec-mocks (2.99.3)
137 - rspec-rails (2.99.0)
138 - actionpack (>= 3.0)
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)
159 + thor (>= 0.18.1, < 2.0)
160 + rake (12.0.0)
161 + rdiscount (2.2.0.1)
162 + rouge (2.0.7)
163 + ruby-progressbar (1.8.1)
164 + ruby_parser (3.8.3)
165 + sexp_processor (~> 4.1)
166 + sass (3.4.23)
167 + sass-rails (5.0.6)
168 + railties (>= 4.0.0, < 6)
169 + sass (~> 3.1)
170 + sprockets (>= 2.8, < 4.0)
171 + sprockets-rails (>= 2.0, < 4.0)
172 + tilt (>= 1.1, < 3)
173 + select2-rails (4.0.3)
152 174 thor (~> 0.14)
153 - sprockets (2.2.3)
154 - hike (~> 1.2)
155 - multi_json (~> 1.0)
156 - rack (~> 1.0)
157 - tilt (~> 1.1, != 1.3.0)
158 - test-unit (3.0.9)
159 - power_assert
160 - thor (0.19.1)
161 - tilt (1.4.1)
162 - treetop (1.4.15)
163 - polyglot
164 - polyglot (>= 0.3.1)
165 - tzinfo (0.3.51)
166 - uglifier (2.7.0)
167 - execjs (>= 0.3.0)
168 - json (>= 1.8.0)
169 - will_paginate (3.0.7)
175 + sexp_processor (4.7.0)
176 + sprockets (3.7.1)
177 + concurrent-ruby (~> 1.0)
178 + rack (> 1, < 3)
179 + sprockets-rails (3.2.0)
180 + actionpack (>= 4.0)
181 + activesupport (>= 4.0)
182 + sprockets (>= 3.0.0)
183 + sqlite3 (1.3.12)
184 + thor (0.19.4)
185 + thread_safe (0.3.5)
186 + tilt (2.0.5)
187 + tzinfo (1.2.2)
188 + thread_safe (~> 0.1)
189 + uglifier (3.0.4)
190 + execjs (>= 0.3.0, < 3)
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 196 PLATFORMS
172 197 ruby
173 198
174 199 DEPENDENCIES
175 200 ace-rails-ap
201 + activerecord-session_store
176 202 autoprefixer-rails
177 203 best_in_place (~> 3.0.1)
178 204 bootstrap-sass (~> 3.2.0)
179 205 bootstrap-switch-rails
180 206 bootstrap-toggle-rails
181 - coffee-rails (~> 3.2.2)
207 + coffee-rails
182 208 dynamic_form
209 + fuzzy-string-match
183 210 haml
184 211 haml-rails
185 212 in_place_editing
186 213 jquery-countdown-rails
187 214 jquery-rails
188 215 jquery-tablesorter
189 216 jquery-timepicker-addon-rails
190 - jquery-ui-sass-rails
217 + jquery-ui-rails
191 218 mail
219 + minitest-reporters
192 220 momentjs-rails
193 221 mysql2
194 - prototype-rails
195 - rails (~> 3.2)
222 + rails (~> 4.2.0)
196 223 rails_bootstrap_sortable
197 224 rdiscount
198 225 rouge
199 - rspec-rails (~> 2.99.0)
200 - sass-rails (~> 3.2.6)
226 + sass-rails
201 227 select2-rails
202 - test-unit
228 + sqlite3
203 229 uglifier
204 230 verification!
205 231 will_paginate (~> 3.0.7)
232 + yaml_db
206 233
207 234 BUNDLED WITH
208 - 1.12.5
235 + 1.13.6
@@ -9,13 +9,13
9 9 //
10 10 // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11 11 // GO AFTER THE REQUIRES BELOW.
12 12 //
13 13 //= require jquery
14 14 //= require jquery_ujs
15 - //= require jquery.ui.all
15 + //= require jquery-ui
16 16 //= require bootstrap-sprockets
17 17 //= require moment
18 18 //= require bootstrap-sortable
19 19 //= require select2
20 20 //= require ace-rails-ap
21 21 //= require ace/mode-c_cpp
@@ -25,15 +25,12
25 25 //= require ace/mode-javascript
26 26 //= require ace/mode-java
27 27 //= require ace/theme-merbivore
28 28 //= require custom
29 29 //= require jquery.countdown
30 30 //-------------- addition from local_jquery -----------
31 - //= require jquery.ui.datepicker
32 - //= require jquery.ui.slider
33 - //= require jquery-ui-timepicker-addon
34 31 //= require jquery-tablesorter
35 32 //= require best_in_place
36 33 //= require best_in_place.jquery-ui
37 34 //= require brython
38 35
39 36 // since this is after blank line, it is not downloaded
@@ -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 1 $(document).ready(function() {
12 2 /* Activating Best In Place */
13 3 jQuery(".best_in_place").best_in_place();
14 4 });
@@ -11,17 +11,17
11 11 *
12 12 * // bootstrap says that we should not do this, but @import each file instead
13 13 * # *= require_tree .
14 14 * # *= require_self
15 15 */
16 16
17 - @import "jquery.ui.all";
18 - @import "jquery.ui.core";
19 - @import "jquery.ui.theme";
20 - @import "jquery.ui.datepicker";
21 - @import "jquery.ui.slider";
17 + @import "jquery-ui";
18 + //@import "jquery.ui.core";
19 + //@import "jquery.ui.theme";
20 + //@import "jquery.ui.datepicker";
21 + //@import "jquery.ui.slider";
22 22 @import "jquery-ui-timepicker-addon";
23 23 @import "jquery-tablesorter/theme.metro-dark";
24 24 @import "jquery.countdown";
25 25 @import "tablesorter-theme.cafe";
26 26
27 27 //bootstrap
@@ -4,14 +4,13
4 4
5 5 in_place_edit_for :announcement, :published
6 6
7 7 # GET /announcements
8 8 # GET /announcements.xml
9 9 def index
10 - @announcements = Announcement.find(:all,
11 - :order => "created_at DESC")
10 + @announcements = Announcement.order(created_at: :desc)
12 11
13 12 respond_to do |format|
14 13 format.html # index.html.erb
15 14 format.xml { render :xml => @announcements }
16 15 end
17 16 end
@@ -43,13 +42,13
43 42 @announcement = Announcement.find(params[:id])
44 43 end
45 44
46 45 # POST /announcements
47 46 # POST /announcements.xml
48 47 def create
49 - @announcement = Announcement.new(params[:announcement])
48 + @announcement = Announcement.new(announcement_params)
50 49
51 50 respond_to do |format|
52 51 if @announcement.save
53 52 flash[:notice] = 'Announcement was successfully created.'
54 53 format.html { redirect_to(@announcement) }
55 54 format.xml { render :xml => @announcement, :status => :created, :location => @announcement }
@@ -63,13 +62,13
63 62 # PUT /announcements/1
64 63 # PUT /announcements/1.xml
65 64 def update
66 65 @announcement = Announcement.find(params[:id])
67 66
68 67 respond_to do |format|
69 - if @announcement.update_attributes(params[:announcement])
68 + if @announcement.update_attributes(announcement_params)
70 69 flash[:notice] = 'Announcement was successfully updated.'
71 70 format.html { redirect_to(@announcement) }
72 71 format.js {}
73 72 format.xml { head :ok }
74 73 else
75 74 format.html { render :action => "edit" }
@@ -105,7 +104,13
105 104
106 105 respond_to do |format|
107 106 format.html { redirect_to(announcements_url) }
108 107 format.xml { head :ok }
109 108 end
110 109 end
110 +
111 + private
112 +
113 + def announcement_params
114 + params.require(:announcement).permit(:author, :body, :published, :frontpage, :contest_only, :title)
111 115 end
116 + end
@@ -17,13 +17,13
17 17 return nil unless session[:user_id]
18 18 @current_user ||= User.find(session[:user_id])
19 19 end
20 20
21 21 def admin_authorization
22 22 return false unless authenticate
23 - user = User.find(session[:user_id], :include => ['roles'])
23 + user = User.includes(:roles).find(session[:user_id])
24 24 unless user.admin?
25 25 unauthorized_redirect
26 26 return false
27 27 end
28 28 return true
29 29 end
@@ -34,12 +34,24
34 34 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
35 35 unauthorized_redirect
36 36 return false
37 37 end
38 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 52 protected
41 53
42 54 def authenticate
43 55 unless session[:user_id]
44 56 flash[:notice] = 'You need to login'
45 57 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
@@ -2,28 +2,33
2 2
3 3 before_filter :authenticate
4 4 before_filter { |controller| controller.authorization_by_roles(['admin'])}
5 5
6 6
7 7 def index
8 - @configurations = GraderConfiguration.find(:all,
9 - :order => '`key`')
8 + @configurations = GraderConfiguration.order(:key)
9 + @group = GraderConfiguration.pluck("grader_configurations.key").map{ |x| x[0...(x.index('.'))] }.uniq.sort
10 10 end
11 11
12 12 def reload
13 13 GraderConfiguration.reload
14 14 redirect_to :action => 'index'
15 15 end
16 16
17 17 def update
18 18 @config = GraderConfiguration.find(params[:id])
19 19 User.clear_last_login if @config.key == GraderConfiguration::MULTIPLE_IP_LOGIN_KEY and @config.value == 'true' and params[:grader_configuration][:value] == 'false'
20 20 respond_to do |format|
21 - if @config.update_attributes(params[:grader_configuration])
21 + if @config.update_attributes(configuration_params)
22 22 format.json { head :ok }
23 23 else
24 24 format.json { respond_with_bip(@config) }
25 25 end
26 26 end
27 27 end
28 28
29 + private
30 + def configuration_params
31 + params.require(:grader_configuration).permit(:key,:value_type,:value,:description)
29 32 end
33 +
34 + end
@@ -8,15 +8,15
8 8
9 9 def user_stat
10 10 if not GraderConfiguration.indv_contest_mode?
11 11 redirect_to :action => 'index' and return
12 12 end
13 13
14 - @users = User.find(:all)
14 + @users = User.all
15 15 @start_times = {}
16 - UserContestStat.find(:all).each do |stat|
16 + UserContestStat.all.each do |stat|
17 17 @start_times[stat.user_id] = stat.started_at
18 18 end
19 19 end
20 20
21 21 def clear_stat
22 22 user = User.find(params[:id])
@@ -63,13 +63,13
63 63 # PUT /contests/1
64 64 # PUT /contests/1.xml
65 65 def update
66 66 @contest = Contest.find(params[:id])
67 67
68 68 respond_to do |format|
69 - if @contest.update_attributes(params[:contest])
69 + if @contest.update_attributes(contests_params)
70 70 flash[:notice] = 'Contest was successfully updated.'
71 71 format.html { redirect_to(@contest) }
72 72 format.xml { head :ok }
73 73 else
74 74 format.html { render :action => "edit" }
75 75 format.xml { render :xml => @contest.errors, :status => :unprocessable_entity }
@@ -86,7 +86,13
86 86 respond_to do |format|
87 87 format.html { redirect_to(contests_url) }
88 88 format.xml { head :ok }
89 89 end
90 90 end
91 91
92 + private
93 +
94 + def contests_params
95 + params.require(:contest).permit(:title,:enabled,:name)
92 96 end
97 +
98 + end
@@ -32,16 +32,14
32 32 def list
33 33 @grader_processes = GraderProcess.find_running_graders
34 34 @stalled_processes = GraderProcess.find_stalled_process
35 35
36 36 @terminated_processes = GraderProcess.find_terminated_graders
37 37
38 - @last_task = Task.find(:first,
39 - :order => 'created_at DESC')
40 - @last_test_request = TestRequest.find(:first,
41 - :order => 'created_at DESC')
38 + @last_task = Task.last
39 + @last_test_request = TestRequest.last
42 40 @submission = Submission.order("id desc").limit(20)
43 41 @backlog_submission = Submission.where('graded_at is null')
44 42 end
45 43
46 44 def clear
47 45 grader_proc = GraderProcess.find(params[:id])
@@ -54,13 +52,13
54 52 p.destroy
55 53 end
56 54 redirect_to :action => 'list'
57 55 end
58 56
59 57 def clear_all
60 - GraderProcess.find(:all).each do |p|
58 + GraderProcess.all.each do |p|
61 59 p.destroy
62 60 end
63 61 redirect_to :action => 'list'
64 62 end
65 63
66 64 def view
@@ -1,31 +1,46
1 1 class HeartbeatController < ApplicationController
2 2 before_filter :admin_authorization, :only => ['index']
3 3
4 4 def edit
5 - @user = User.find_by_login(params[:id])
6 - unless @user
7 - render text: "LOGIN_NOT_FOUND"
8 - return
9 - end
5 + #@user = User.find_by_login(params[:id])
6 + #unless @user
7 + # render text: "LOGIN_NOT_FOUND"
8 + # return
9 + #end
10 10
11 11 #hb = HeartBeat.where(user_id: @user.id, ip_address: request.remote_ip).first
12 12 #puts "status = #{params[:status]}"
13 13 #if hb
14 14 # if params[:status]
15 15 # hb.status = params[:status]
16 16 # hb.save
17 17 # end
18 18 # hb.touch
19 19 #else
20 20 # HeartBeat.creae(user_id: @user.id, ip_address: request.remote_ip)
21 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 38 render text: (GraderConfiguration['right.heartbeat_response'] || 'OK')
25 39 end
40 + end
26 41
27 42 def index
28 43 @hb = HeartBeat.where("updated_at >= ?",Time.zone.now-2.hours).includes(:user).order(:user_id).all
29 44 @num = HeartBeat.where("updated_at >= ?",Time.zone.now-5.minutes).count(:user_id,distinct: true)
30 45 end
31 46 end
@@ -42,13 +42,13
42 42 # logger.info "PATH: #{request.path}"
43 43 # if GraderConfiguration['system.single_user_mode'] and
44 44 # request.path!='/main/login'
45 45 # @hidelogin = true
46 46 # end
47 47
48 - @announcements = Announcement.find_for_frontpage
48 + @announcements = Announcement.frontpage
49 49 render :action => 'login', :layout => 'empty'
50 50 end
51 51
52 52 def list
53 53 prepare_list_information
54 54 end
@@ -121,29 +121,12
121 121 else
122 122 flash[:notice] = 'Error viewing source'
123 123 redirect_to :action => 'list'
124 124 end
125 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 127 def result
145 128 if !GraderConfiguration.show_grading_result
146 129 redirect_to :action => 'list' and return
147 130 end
148 131 @user = User.find(session[:user_id])
149 132 @submission = Submission.find(params[:id])
@@ -214,15 +197,15
214 197 end
215 198
216 199 protected
217 200
218 201 def prepare_announcements(recent=nil)
219 202 if GraderConfiguration.show_tasks_to?(@user)
220 - @announcements = Announcement.find_published(true)
203 + @announcements = Announcement.published(true)
221 204 else
222 - @announcements = Announcement.find_published
205 + @announcements = Announcement.published
223 206 end
224 207 if recent!=nil
225 208 recent_id = recent.to_i
226 209 @announcements = @announcements.find_all { |a| a.id > recent_id }
227 210 end
228 211 end
@@ -1,16 +1,17
1 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 6 in_place_edit_for :problem, :name
6 7 in_place_edit_for :problem, :full_name
7 8 in_place_edit_for :problem, :full_score
8 9
9 10 def index
10 - @problems = Problem.find(:all, :order => 'date_added DESC')
11 + @problems = Problem.order(date_added: :desc)
11 12 end
12 13
13 14 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
14 15 verify :method => :post, :only => [ :create, :quick_create,
15 16 :do_manage,
16 17 :do_import,
@@ -24,13 +25,13
24 25 def new
25 26 @problem = Problem.new
26 27 @description = nil
27 28 end
28 29
29 30 def create
30 - @problem = Problem.new(params[:problem])
31 + @problem = Problem.new(problem_params)
31 32 @description = Description.new(params[:description])
32 33 if @description.body!=''
33 34 if !@description.save
34 35 render :action => new and return
35 36 end
36 37 else
@@ -43,13 +44,13
43 44 else
44 45 render :action => 'new'
45 46 end
46 47 end
47 48
48 49 def quick_create
49 - @problem = Problem.new(params[:problem])
50 + @problem = Problem.new(problem_params)
50 51 @problem.full_name = @problem.name if @problem.full_name == ''
51 52 @problem.full_score = 100
52 53 @problem.available = false
53 54 @problem.test_allowed = true
54 55 @problem.output_only = false
55 56 @problem.date_added = Time.new
@@ -84,13 +85,13
84 85 end
85 86 end
86 87 if params[:file] and params[:file].content_type != 'application/pdf'
87 88 flash[:notice] = 'Error: Uploaded file is not PDF'
88 89 render :action => 'edit' and return
89 90 end
90 - if @problem.update_attributes(params[:problem])
91 + if @problem.update_attributes(problem_params)
91 92 flash[:notice] = 'Problem was successfully updated.'
92 93 unless params[:file] == nil or params[:file] == ''
93 94 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
94 95 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
95 96 if not FileTest.exists? out_dirname
96 97 Dir.mkdir out_dirname
@@ -131,24 +132,30
131 132 @problem.update_attributes(test_allowed: !(@problem.test_allowed?) )
132 133 respond_to do |format|
133 134 format.js { }
134 135 end
135 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 146 def turn_all_off
138 - Problem.find(:all,
139 - :conditions => "available = 1").each do |problem|
147 + Problem.available.all.each do |problem|
140 148 problem.available = false
141 149 problem.save
142 150 end
143 151 redirect_to action: :index
144 152 end
145 153
146 154 def turn_all_on
147 - Problem.find(:all,
148 - :conditions => "available = 0").each do |problem|
155 + Problem.where.not(available: true).each do |problem|
149 156 problem.available = true
150 157 problem.save
151 158 end
152 159 redirect_to action: :index
153 160 end
154 161
@@ -173,13 +180,13
173 180
174 181 @summary = { attempt: user.count, solve: 0 }
175 182 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
176 183 end
177 184
178 185 def manage
179 - @problems = Problem.find(:all, :order => 'date_added DESC')
186 + @problems = Problem.order(date_added: :desc)
180 187 end
181 188
182 189 def do_manage
183 190 if params.has_key? 'change_date_added'
184 191 change_date_added
185 192 elsif params.has_key? 'add_to_contest'
@@ -275,7 +282,13
275 282 problems
276 283 end
277 284
278 285 def get_problems_stat
279 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 292 end
293 +
294 + end
@@ -6,24 +6,20
6 6
7 7 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize, :show_max_score]
8 8
9 9 before_filter(only: [:problem_hof]) { |c|
10 10 return false unless authenticate
11 11
12 - if GraderConfiguration["right.user_view_submission"]
13 - return true;
14 - end
15 -
16 - admin_authorization
12 + admin_authorization unless GraderConfiguration["right.user_view_submission"]
17 13 }
18 14
19 15 def max_score
20 16 end
21 17
22 18 def current_score
23 - @problems = Problem.find_available_problems
19 + @problems = Problem.available_problems
24 20 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
25 21 @scorearray = calculate_max_score(@problems, @users,0,0,true)
26 22
27 23 #rencer accordingly
28 24 if params[:button] == 'download' then
29 25 csv = gen_csv_from_scorearray(@scorearray,@problems)
@@ -35,31 +31,33
35 31 end
36 32
37 33 def show_max_score
38 34 #process parameters
39 35 #problems
40 36 @problems = []
37 + if params[:problem_id]
41 38 params[:problem_id].each do |id|
42 39 next unless id.strip != ""
43 40 pid = Problem.find_by_id(id.to_i)
44 41 @problems << pid if pid
45 42 end
43 + end
46 44
47 45 #users
48 46 @users = if params[:user] == "all" then
49 - User.find(:all, :include => [:contests, :contest_stat])
47 + User.includes(:contests).includes(:contest_stat)
50 48 else
51 49 User.includes(:contests).includes(:contest_stat).where(enabled: true)
52 50 end
53 51
54 52 #set up range from param
55 - since_id = params.fetch(:min_id, 0).to_i
56 - until_id = params.fetch(:max_id, 0).to_i
53 + @since_id = params.fetch(:from_id, 0).to_i
54 + @until_id = params.fetch(:to_id, 0).to_i
57 55
58 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 59 #rencer accordingly
62 60 if params[:button] == 'download' then
63 61 csv = gen_csv_from_scorearray(@scorearray,@problems)
64 62 send_data csv, filename: 'max_score.csv'
65 63 else
@@ -70,15 +68,15
70 68 end
71 69
72 70 def score
73 71 if params[:commit] == 'download csv'
74 72 @problems = Problem.all
75 73 else
76 - @problems = Problem.find_available_problems
74 + @problems = Problem.available_problems
77 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 77 @scorearray = Array.new
80 78 @users.each do |u|
81 79 ustat = Array.new
82 80 ustat[0] = u
83 81 @problems.each do |p|
84 82 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
@@ -1,13 +1,13
1 1 class SiteController < ApplicationController
2 2
3 3 before_filter :site_admin_authorization, :except => 'login'
4 4
5 5 def login
6 6 # Site administrator login
7 - @countries = Country.find(:all, :include => :sites)
7 + @countries = Country.includes(:sites).all
8 8 @country_select = @countries.collect { |c| [c.name, c.id] }
9 9
10 10 @country_select_with_all = [['Any',0]]
11 11 @countries.each do |country|
12 12 @country_select_with_all << [country.name, country.id]
13 13 end
@@ -56,7 +56,12
56 56 end
57 57 if @site==nil
58 58 redirect_to :controller => 'site', :action => 'login' and return
59 59 end
60 60 end
61 61
62 + private
63 + def site_params
64 + params.require(:site).permit()
62 65 end
66 +
67 + end
@@ -2,13 +2,13
2 2
3 3 before_filter :admin_authorization
4 4
5 5 # GET /sites
6 6 # GET /sites.xml
7 7 def index
8 - @sites = Site.find(:all, :order => 'country_id')
8 + @sites = Site.order(:country_id)
9 9
10 10 respond_to do |format|
11 11 format.html # index.html.erb
12 12 format.xml { render :xml => @sites }
13 13 end
14 14 end
@@ -62,13 +62,13
62 62 # PUT /sites/1.xml
63 63 def update
64 64 @site = Site.find(params[:id])
65 65 @site.clear_start_time_if_not_started
66 66
67 67 respond_to do |format|
68 - if @site.update_attributes(params[:site])
68 + if @site.update_attributes(site_params)
69 69 flash[:notice] = 'Site was successfully updated.'
70 70 format.html { redirect_to(@site) }
71 71 format.xml { head :ok }
72 72 else
73 73 format.html { render :action => "edit" }
74 74 format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
@@ -85,7 +85,13
85 85 respond_to do |format|
86 86 format.html { redirect_to(sites_url) }
87 87 format.xml { head :ok }
88 88 end
89 89 end
90 90
91 + private
92 +
93 + def site_params
94 + params.require(:site).permit(:name,:started,:start_time,:country_id,:password)
91 95 end
96 +
97 + end
@@ -1,9 +1,10
1 1 class SubmissionsController < ApplicationController
2 - before_filter :authenticate
3 - before_filter :submission_authorization, only: [:show, :direct_edit_submission]
2 + before_action :authenticate
3 + before_action :submission_authorization, only: [:show, :direct_edit_submission, :download, :edit]
4 + before_action :admin_authorization, only: [:rejudge]
4 5
5 6 # GET /submissions
6 7 # GET /submissions.json
7 8 # Show problem selection and user's submission of that problem
8 9 def index
9 10 @user = @current_user
@@ -16,24 +17,38
16 17 @problem = Problem.find_by_id(params[:problem_id])
17 18 if (@problem == nil) or (not @problem.available)
18 19 redirect_to main_list_path
19 20 flash[:notice] = 'Error: submissions for that problem are not viewable.'
20 21 return
21 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 24 end
24 25 end
25 26
26 27 # GET /submissions/1
27 28 # GET /submissions/1.json
28 29 def show
29 30 @submission = Submission.find(params[:id])
30 31
31 32 #log the viewing
32 33 user = User.find(session[:user_id])
33 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 49 end
35 50
36 51 #on-site new submission on specific problem
37 52 def direct_edit_problem
38 53 @problem = Problem.find(params[:problem_id])
39 54 @source = ''
@@ -57,69 +72,24
57 72 puts 'nil' unless @submission
58 73 respond_to do |format|
59 74 format.js
60 75 end
61 76 end
62 77
63 - # # GET /submissions/new
64 - # # GET /submissions/new.json
65 - # def new
66 - # @submission = Submission.new
67 - #
68 - # respond_to do |format|
69 - # format.html # new.html.erb
70 - # format.json { render json: @submission }
71 - # 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
78 + # GET /submissions/:id/rejudge
79 + def rejudge
80 + @submission = Submission.find(params[:id])
81 + @task = @submission.task
82 + @task.status_inqueue! if @task
83 + respond_to do |format|
84 + format.js
85 + end
86 + end
118 87
119 88 protected
89 +
120 90 def submission_authorization
121 91 #admin always has privileged
122 92 if @current_user.admin?
123 93 return true
124 94 end
125 95
@@ -131,7 +101,8
131 101
132 102 #default to NO
133 103 unauthorized_redirect
134 104 return false
135 105 end
136 106
107 +
137 108 end
@@ -26,13 +26,13
26 26 end
27 27 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
28 28 @contests = Contest.enabled
29 29 end
30 30
31 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 33 @users = []
34 34 sessions.each do |session|
35 35 if session.data[:user_id]
36 36 @users << User.find(session.data[:user_id])
37 37 end
38 38 end
@@ -44,13 +44,13
44 44
45 45 def new
46 46 @user = User.new
47 47 end
48 48
49 49 def create
50 - @user = User.new(params[:user])
50 + @user = User.new(user_params)
51 51 @user.activated = true
52 52 if @user.save
53 53 flash[:notice] = 'User was successfully created.'
54 54 redirect_to :action => 'index'
55 55 else
56 56 render :action => 'new'
@@ -71,57 +71,69
71 71
72 72 lines.split("\n").each do |line|
73 73 items = line.chomp.split(',')
74 74 if items.length>=2
75 75 login = items[0]
76 76 full_name = items[1]
77 + remark =''
78 + user_alias = ''
77 79
78 80 added_random_password = false
79 - if items.length>=3
81 + if items.length >= 3 and items[2].chomp(" ").length > 0;
80 82 password = items[2].chomp(" ")
81 - user_alias = (items.length>=4) ? items[3] : login
82 83 else
83 84 password = random_password
84 - user_alias = (items.length>=4) ? items[3] : login
85 - added_random_password = true
85 + add_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 96 end
87 97
88 98 user = User.find_by_login(login)
89 99 if (user)
90 100 user.full_name = full_name
91 101 user.password = password
102 + user.remark = remark
92 103 else
93 104 user = User.new({:login => login,
94 105 :full_name => full_name,
95 106 :password => password,
96 107 :password_confirmation => password,
97 - :alias => user_alias})
108 + :alias => user_alias,
109 + :remark => remark})
98 110 end
99 111 user.activated = true
100 112 user.save
101 113
102 114 if added_random_password
103 115 note << "'#{login}' (+)"
104 116 else
105 117 note << login
106 118 end
107 119 end
108 120 end
109 - flash[:notice] = 'User(s) ' + note.join(', ') +
121 + flash[:success] = 'User(s) ' + note.join(', ') +
110 122 ' were successfully created. ' +
111 123 '( (+) - created with random passwords.)'
112 124 redirect_to :action => 'index'
113 125 end
114 126
115 127 def edit
116 128 @user = User.find(params[:id])
117 129 end
118 130
119 131 def update
120 132 @user = User.find(params[:id])
121 - if @user.update_attributes(params[:user])
133 + if @user.update_attributes(user_params)
122 134 flash[:notice] = 'User was successfully updated.'
123 135 redirect_to :action => 'show', :id => @user
124 136 else
125 137 render :action => 'edit'
126 138 end
127 139 end
@@ -132,15 +144,15
132 144 end
133 145
134 146 def user_stat
135 147 if params[:commit] == 'download csv'
136 148 @problems = Problem.all
137 149 else
138 - @problems = Problem.find_available_problems
150 + @problems = Problem.available_problems
139 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 153 @scorearray = Array.new
142 154 @users.each do |u|
143 155 ustat = Array.new
144 156 ustat[0] = u
145 157 @problems.each do |p|
146 158 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
@@ -161,15 +173,15
161 173 end
162 174
163 175 def user_stat_max
164 176 if params[:commit] == 'download csv'
165 177 @problems = Problem.all
166 178 else
167 - @problems = Problem.find_available_problems
179 + @problems = Problem.available_problems
168 180 end
169 - @users = User.find(:all, :include => [:contests, :contest_stat])
181 + @users = User.includes(:contests).includes(:contest_stat).all
170 182 @scorearray = Array.new
171 183 #set up range from param
172 184 since_id = params.fetch(:since_id, 0).to_i
173 185 until_id = params.fetch(:until_id, 0).to_i
174 186 @users.each do |u|
175 187 ustat = Array.new
@@ -198,13 +210,13
198 210 redirect_to :action => 'index' and return
199 211 end
200 212 import_from_file(params[:file])
201 213 end
202 214
203 215 def random_all_passwords
204 - users = User.find(:all)
216 + users = User.all
205 217 @prefix = params[:prefix] || ''
206 218 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
207 219 @changed = false
208 220 if request.request_method == 'POST'
209 221 @non_admin_users.each do |user|
210 222 password = random_password
@@ -321,13 +333,13
321 333 redirect_to :action => 'contest_management'
322 334 end
323 335
324 336 # admin management
325 337
326 338 def admin
327 - @admins = User.find(:all).find_all {|user| user.admin? }
339 + @admins = User.all.find_all {|user| user.admin? }
328 340 end
329 341
330 342 def grant_admin
331 343 login = params[:login]
332 344 user = User.find_by_login(login)
333 345 if user!=nil
@@ -392,12 +404,45
392 404
393 405 flash[:notice] = 'User(s) ' + note.join(', ') +
394 406 ' were successfully modified. '
395 407 redirect_to :action => 'mass_mailing'
396 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 443 protected
399 444
400 445 def random_password(length=5)
401 446 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
402 447 newpass = ""
403 448 length.times { newpass << chars[rand(chars.size-1)] }
@@ -518,13 +563,13
518 563 row = Array.new
519 564 sc.each_index do |i|
520 565 if i == 0
521 566 row << sc[i].login
522 567 row << sc[i].full_name
523 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 570 row << sc[i].contests.collect {|c| c.name}.join(', ')
526 571 else
527 572 row << sc[i][0]
528 573 total += sc[i][0]
529 574 num_passed += 1 if sc[i][1]
530 575 end
@@ -532,7 +577,12
532 577 row << total
533 578 row << num_passed
534 579 csv << row
535 580 end
536 581 end
537 582 end
583 +
584 + private
585 + def user_params
586 + params.require(:user).permit(:login,:password,:password_confirmation,:email, :alias, :full_name,:remark)
538 587 end
588 + end
@@ -49,13 +49,13
49 49
50 50 def register
51 51 if(params[:cancel])
52 52 redirect_to :controller => 'main', :action => 'login'
53 53 return
54 54 end
55 - @user = User.new(params[:user])
55 + @user = User.new(user_params)
56 56 @user.password_confirmation = @user.password = User.random_password
57 57 @user.activated = false
58 58 if (@user.valid?) and (@user.save)
59 59 if send_confirmation_email(@user)
60 60 render :action => 'new_splash', :layout => 'empty'
61 61 else
@@ -207,8 +207,12
207 207 return true if GraderConfiguration["right.user_view_submission"]
208 208
209 209 #finally, we allow only admin
210 210 admin_authorization
211 211 end
212 212
213 + private
214 + def user_params
215 + params.require(:user).permit(:login, :full_name, :email)
216 + end
213 217
214 218 end
@@ -193,7 +193,29
193 193
194 194 def markdown(text)
195 195 markdown = RDiscount.new(text)
196 196 markdown.to_html.html_safe
197 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 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 1 class Announcement < ActiveRecord::Base
2 2
3 - def self.find_published(contest_started=false)
3 + def self.published(contest_started=false)
4 4 if contest_started
5 - Announcement.find(:all,
6 - :conditions => "(published = 1) AND (frontpage = 0)",
7 - :order => "created_at DESC")
5 + where(published: true).where(frontpage: false).order(created_at: :desc)
8 6 else
9 - Announcement.find(:all,
10 - :conditions => "(published = 1) AND (frontpage = 0) AND (contest_only = 0)",
11 - :order => "created_at DESC")
7 + where(published: true).where(frontpage: false).where(contest_only: false).order(created_at: :desc)
12 8 end
13 9 end
14 10
15 - def self.find_for_frontpage
16 - Announcement.find(:all,
17 - :conditions => "(published = 1) AND (frontpage = 1)",
18 - :order => "created_at DESC")
11 + def self.frontpage
12 + where(published: 1).where(frontpage: 1).order(created_at: :desc)
19 13 end
20 14
21 15 end
@@ -1,8 +1,8
1 1 class Contest < ActiveRecord::Base
2 2
3 3 has_and_belongs_to_many :users
4 4 has_and_belongs_to_many :problems
5 5
6 - scope :enabled, :conditions => {:enabled => true}
6 + scope :enabled, -> { where(enabled: true) }
7 7
8 8 end
@@ -7,12 +7,14
7 7
8 8 SYSTEM_MODE_CONF_KEY = 'system.mode'
9 9 TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout'
10 10 MULTICONTESTS_KEY = 'system.multicontests'
11 11 CONTEST_TIME_LIMIT_KEY = 'contest.time_limit'
12 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 16 cattr_accessor :config_cache
15 17 cattr_accessor :task_grading_info_cache
16 18 cattr_accessor :contest_time_str
17 19 cattr_accessor :contest_time
18 20
@@ -67,12 +69,16
67 69 end
68 70
69 71 def self.show_grading_result
70 72 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
71 73 end
72 74
75 + def self.show_testcase
76 + return get(VIEW_TESTCASE)
77 + end
78 +
73 79 def self.allow_test_request(user)
74 80 mode = get(SYSTEM_MODE_CONF_KEY)
75 81 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
76 82 if (mode=='contest')
77 83 return false if ((user.site!=nil) and
78 84 ((user.site.started!=true) or
@@ -149,13 +155,13
149 155 return (val=='true')
150 156 end
151 157 end
152 158
153 159 def self.read_config
154 160 GraderConfiguration.config_cache = {}
155 - GraderConfiguration.find(:all).each do |conf|
161 + GraderConfiguration.all.each do |conf|
156 162 key = conf.key
157 163 val = conf.value
158 164 GraderConfiguration.config_cache[key] = GraderConfiguration.convert_type(val,conf.value_type)
159 165 end
160 166 end
161 167
@@ -1,14 +1,10
1 1 class GraderProcess < ActiveRecord::Base
2 2
3 3 def self.find_by_host_and_pid(host,pid)
4 - return GraderProcess.find(:first,
5 - :conditions => {
6 - :host => host,
7 - :pid => pid
8 - })
4 + return GraderProcess.where(host:host).where(pid: pid).first
9 5 end
10 6
11 7 def self.register(host,pid,mode)
12 8 grader = GraderProcess.find_by_host_and_pid(host,pid)
13 9 if grader
14 10 grader.mode = mode
@@ -24,26 +20,21
24 20 :terminated => false)
25 21 end
26 22 grader
27 23 end
28 24
29 25 def self.find_running_graders
30 - GraderProcess.find(:all,
31 - :conditions => {:terminated => 0})
26 + where(terminated: false)
32 27 end
33 28
34 29 def self.find_terminated_graders
35 - GraderProcess.find(:all,
36 - :conditions => "`terminated`")
30 + where(terminated: true)
37 31 end
38 32
39 33 def self.find_stalled_process
40 - GraderProcess.find(:all,
41 - :conditions => ["(`terminated` = 0) AND active AND " +
42 - "(updated_at < ?)",
43 - Time.now.gmtime - GraderProcess.stalled_time])
34 + where(terminated: false).where(active: true).where("updated_at < ?",Time.now.gmtime - GraderProcess.stalled_time)
44 35 end
45 36
46 37 def report_active(task=nil)
47 38 self.active = true
48 39 if task!=nil
49 40 self.task_id = task.id
@@ -1,13 +1,13
1 1 class Language < ActiveRecord::Base
2 2
3 3 @@languages_by_ext = {}
4 4
5 5 def self.cache_ext_hash
6 6 @@languages_by_ext = {}
7 - Language.find(:all).each do |language|
7 + Language.all.each do |language|
8 8 language.common_ext.split(',').each do |ext|
9 9 @@languages_by_ext[ext] = language
10 10 end
11 11 end
12 12 end
13 13
@@ -1,5 +1,4
1 1 class Login < ActiveRecord::Base
2 2 belongs_to :user
3 3
4 - attr_accessible :ip_address, :logged_in_at, :user_id
5 4 end
@@ -20,16 +20,14
20 20 replied_messages = user.replied_messages
21 21 Message.build_replying_message_hierarchy messages, replied_messages
22 22 return messages
23 23 end
24 24
25 25 def self.find_all_system_unreplied_messages
26 - self.find(:all,
27 - :conditions => 'ISNULL(receiver_id) ' +
28 - 'AND (ISNULL(replied) OR replied=0)',
29 - :order => 'created_at')
26 + where('ISNULL(receiver_id) ' +
27 + 'AND (ISNULL(replied) OR replied=0)')
30 28 end
31 29
32 30 def self.build_replying_message_hierarchy(*args)
33 31 # manually build replies hierarchy (to improve efficiency)
34 32 all_messages = {}
35 33
@@ -3,22 +3,23
3 3 belongs_to :description
4 4 has_and_belongs_to_many :contests, :uniq => true
5 5 has_many :test_pairs, :dependent => :delete_all
6 6 has_many :testcases, :dependent => :destroy
7 7
8 8 validates_presence_of :name
9 - validates_format_of :name, :with => /^\w+$/
9 + validates_format_of :name, :with => /\A\w+\z/
10 10 validates_presence_of :full_name
11 11
12 - scope :available, :conditions => {:available => true}
12 + scope :available, -> { where(available: true) }
13 13
14 14 DEFAULT_TIME_LIMIT = 1
15 15 DEFAULT_MEMORY_LIMIT = 32
16 16
17 - def self.find_available_problems
18 - Problem.available.all(:order => "date_added DESC, name ASC")
17 + def self.available_problems
18 + available.order(date_added: :desc).order(:name)
19 + #Problem.available.all(:order => "date_added DESC, name ASC")
19 20 end
20 21
21 22 def self.create_from_import_form_params(params, old_problem=nil)
22 23 org_problem = old_problem || Problem.new
23 24 import_params, problem = Problem.extract_params_and_check(params,
24 25 org_problem)
@@ -57,13 +58,15
57 58 end
58 59
59 60 def get_submission_stat
60 61 result = Hash.new
61 62 #total number of submission
62 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 67 end
65 68
66 69 def long_name
67 70 "[#{name}] #{full_name}"
68 71 end
69 72
@@ -10,20 +10,18
10 10 validates_presence_of :source
11 11 validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long'
12 12 validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short'
13 13 validate :must_have_valid_problem
14 14 validate :must_specify_language
15 15
16 + has_one :task
17 +
16 18 before_save :assign_latest_number_if_new_recond
17 19
18 20 def self.find_last_by_user_and_problem(user_id, problem_id)
19 - last_sub = find(:first,
20 - :conditions => {:user_id => user_id,
21 - :problem_id => problem_id},
22 - :order => 'number DESC')
23 - return last_sub
21 + where("user_id = ? AND problem_id = ?",user_id,problem_id).last
24 22 end
25 23
26 24 def self.find_all_last_by_problem(problem_id)
27 25 # need to put in SQL command, maybe there's a better way
28 26 Submission.includes(:user).find_by_sql("SELECT * FROM submissions " +
29 27 "WHERE id = " +
@@ -40,35 +38,26
40 38 records = records.where('id <= ?',until_id) if until_id > 0
41 39 records.all
42 40 end
43 41
44 42 def self.find_last_for_all_available_problems(user_id)
45 43 submissions = Array.new
46 - problems = Problem.find_available_problems
44 + problems = Problem.available_problems
47 45 problems.each do |problem|
48 46 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
49 47 submissions << sub if sub!=nil
50 48 end
51 49 submissions
52 50 end
53 51
54 52 def self.find_by_user_problem_number(user_id, problem_id, number)
55 - Submission.find(:first,
56 - :conditions => {
57 - :user_id => user_id,
58 - :problem_id => problem_id,
59 - :number => number
60 - })
53 + where("user_id = ? AND problem_id = ? AND number = ?",user_id,problem_id,number).first
61 54 end
62 55
63 56 def self.find_all_by_user_problem(user_id, problem_id)
64 - Submission.find(:all,
65 - :conditions => {
66 - :user_id => user_id,
67 - :problem_id => problem_id,
68 - })
57 + where("user_id = ? AND problem_id = ?",user_id,problem_id)
69 58 end
70 59
71 60 def download_filename
72 61 if self.problem.output_only
73 62 return self.source_filename
74 63 else
@@ -1,3 +1,3
1 1 class SubmissionViewLog < ActiveRecord::Base
2 - attr_accessible :submission_id, :user_id
2 + #attr_accessible :submission_id, :user_id
3 3 end
@@ -45,16 +45,13
45 45 end
46 46
47 47 def self.get_inqueue_and_change_status(status)
48 48 task = nil
49 49 begin
50 50 Task.transaction do
51 - task = Task.find(:first,
52 - :order => "created_at",
53 - :conditions => {:status=> Task::STATUS_INQUEUE},
54 - :lock => true)
51 + task = Task.where(status: Task::STATUS_INQUEUE).lock(true).first
55 52 if task!=nil
56 53 task.status = status
57 54 task.save!
58 55 end
59 56 end
60 57
@@ -13,14 +13,13
13 13 # call #name_of.
14 14 #
15 15
16 16 require 'fileutils'
17 17
18 18 class TestRequest < Task
19 -
20 - set_table_name "test_requests"
19 + self.table_name = "test_requests"
21 20
22 21 belongs_to :user
23 22 belongs_to :problem
24 23 belongs_to :submission
25 24
26 25 validates_presence_of :submission
@@ -35,15 +34,13
35 34 end
36 35
37 36 def self.get_inqueue_and_change_status(status)
38 37 # since there will be only one grader grading TestRequest
39 38 # we do not need locking (hopefully)
40 39
41 - test_request = TestRequest.find(:first,
42 - :order => "created_at",
43 - :conditions => {:status=> Task::STATUS_INQUEUE})
40 + test_request = TestRequest.where(status: Task::STATUS_INQUEUE).first
44 41 if test_request!=nil
45 42 test_request.status = status
46 43 test_request.save!
47 44 end
48 45
49 46 test_request
@@ -1,4 +1,4
1 1 class Testcase < ActiveRecord::Base
2 2 belongs_to :problem
3 - attr_accessible :group, :input, :num, :score, :sol
3 + #attr_accessible :group, :input, :num, :score, :sol
4 4 end
@@ -5,36 +5,34
5 5 require 'json'
6 6
7 7 class User < ActiveRecord::Base
8 8
9 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 14 :class_name => "Message",
15 - :foreign_key => "sender_id",
16 - :order => 'created_at DESC'
15 + :foreign_key => "sender_id"
17 16
18 - has_many :replied_messages,
17 + has_many :replied_messages, -> { order(created_at: DESC) },
19 18 :class_name => "Message",
20 - :foreign_key => "receiver_id",
21 - :order => 'created_at DESC'
19 + :foreign_key => "receiver_id"
22 20
23 21 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
24 22
25 23 belongs_to :site
26 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 30 validates_presence_of :login
33 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 33 validates_length_of :login, :within => 3..30
36 34
37 35 validates_presence_of :full_name
38 36 validates_length_of :full_name, :minimum => 1
39 37
40 38 validates_presence_of :password, :if => :password_required?
@@ -126,20 +124,20
126 124 password = ''
127 125 length.times { password << chars[rand(chars.length - 1)] }
128 126 password
129 127 end
130 128
131 129 def self.find_non_admin_with_prefix(prefix='')
132 - users = User.find(:all)
130 + users = User.all
133 131 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
134 132 end
135 133
136 134 # Contest information
137 135
138 136 def self.find_users_with_no_contest()
139 - users = User.find(:all)
137 + users = User.all
140 138 return users.find_all { |u| u.contests.length == 0 }
141 139 end
142 140
143 141
144 142 def contest_time_left
145 143 if GraderConfiguration.contest_mode?
@@ -230,15 +228,24
230 228 :contest => nil,
231 229 :problems => other_avaiable_problems
232 230 }
233 231 return contest_problems
234 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 243 def available_problems
237 244 if not GraderConfiguration.multicontests?
238 - return Problem.find_available_problems
245 + return Problem.available_problems
239 246 else
240 247 contest_problems = []
241 248 pin = {}
242 249 contests.enabled.each do |contest|
243 250 contest.problems.available.each do |problem|
244 251 if not pin.has_key? problem.id
@@ -1,11 +1,11
1 1
2 2 %tr
3 3 %td{:align => "center"}
4 - = submission_counter+1
5 - %td{:align => "center"}
4 + = submission.number
5 + %td.text-right
6 6 = link_to "##{submission.id}", submission_path(submission.id)
7 7 %td
8 8 = l submission.submitted_at, format: :long
9 9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
10 10 %td
11 11 = submission.source_filename
@@ -1,26 +1,26
1 1
2 2 - if submission.nil?
3 3 = "-"
4 4 - else
5 - - if submission.graded_at.nil?
5 + - unless submission.graded_at
6 6 = t 'main.submitted_at'
7 7 = format_short_time(submission.submitted_at.localtime)
8 8 - else
9 - = t 'main.graded_at'
10 - = "#{format_short_time(submission.graded_at.localtime)}, "
9 + %strong= t 'main.graded_at'
10 + = "#{format_short_time(submission.graded_at.localtime)} "
11 + %br
11 12 - if GraderConfiguration['ui.show_score']
12 - = t 'main.score'
13 + %strong=t 'main.score'
13 14 = "#{(submission.points*100/submission.problem.full_score).to_i} "
14 15 = " ["
15 16 %tt
16 17 = submission.grader_comment
17 18 = "]"
19 + %br
20 + %strong View:
18 21 - if GraderConfiguration.show_grading_result
19 - = " | "
20 22 = link_to '[detailed result]', :action => 'result', :id => submission.id
21 - = " | "
22 - = link_to("[#{t 'main.cmp_msg'}]", {:action => 'compiler_msg', :id => submission.id}, {:popup => true})
23 - = " | "
24 - = link_to("[#{t 'main.src_link'}]",{:action => 'source', :id => submission.id})
25 - //= " | "
26 - //= link_to "[#{t 'main.submissions_link'}]", main_submission_path(submission.problem.id)
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.src_link'}", download_submission_path(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 +
@@ -1,20 +1,23
1 1 /- content_for :header do
2 2 / = javascript_include_tag 'local_jquery'
3 3
4 4 %h1 System configuration
5 5
6 - %table.info
7 - %tr.info-head
8 - %th Key
9 - %th Type
10 - %th Value
6 + - @group.each do |g|
7 + %h2= g
8 + %table.table.table-striped
9 + %thead
10 + %th{style: 'width: 25%'} Key
11 + %th{style: 'width: 10%'}Type
12 + %th{style: 'width: 15%'} Value
11 13 %th Description
12 14 - @configurations.each do |conf|
15 + - next if conf.key[0...(conf.key.index('.'))] != g
13 16 - @grader_configuration = conf
14 - %tr{:class => cycle("info-odd", "info-even")}
17 + %tr
15 18 %td
16 19 /= in_place_editor_field :grader_configuration, :key, {}, :rows=>1
17 20 = @grader_configuration.key
18 21 %td
19 22 /= in_place_editor_field :grader_configuration, :value_type, {}, :rows=>1
20 23 = @grader_configuration.value_type
@@ -51,14 +51,14
51 51 %th Graded
52 52 %th Result
53 53 %tbody
54 54 - @submission.each do |sub|
55 55 %tr.inactive
56 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)
58 - %td= ("" unless sub.problem) || link_to sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.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))
59 59 %td= "#{time_ago_in_words(sub.submitted_at)} ago"
60 60 %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " "
61 61 %td= sub.grader_comment
62 62 %h2 Ungraded submission
63 63 %table.table.table-striped.table-condensed
64 64 %thead
@@ -69,14 +69,14
69 69 %th Graded
70 70 %th Result
71 71 %tbody
72 72 - @backlog_submission.each do |sub|
73 73 %tr.inactive
74 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)
76 - %td= ("" unless sub.problem) || link_to sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.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))
77 77 %td= "#{time_ago_in_words(sub.submitted_at)} ago"
78 78 %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " "
79 79 %td= sub.grader_comment
80 80
81 81
82 82
@@ -1,24 +1,30
1 1 %header.navbar.navbar-default.navbar-fixed-top
2 2 %nav
3 3 .container-fluid
4 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 10 %a.navbar-brand{href: main_list_path}
6 11 %span.glyphicon.glyphicon-home
7 12 MAIN
8 - .collapse.navbar-collapse
13 + .collapse.navbar-collapse#navbar-collapse
9 14 %ul.nav.navbar-nav
15 + / submission
10 16 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
11 - //= add_menu("#{I18n.t 'menu.tasks'}", 'tasks', 'list')
12 17 %li.dropdown
13 18 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
14 19 = "#{I18n.t 'menu.submissions'}"
15 20 %span.caret
16 21 %ul.dropdown-menu
17 - = add_menu("View", 'main', 'submission')
22 + = add_menu("View", 'submissions', 'index')
18 23 = add_menu("Self Test", 'test', 'index')
24 + / hall of fame
19 25 - if GraderConfiguration['right.user_hall_of_fame']
20 26 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
21 27 / display MODE button (with countdown in contest mode)
22 28 - if GraderConfiguration.analysis_mode?
23 29 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
24 30 - elsif GraderConfiguration.time_limit_mode?
@@ -29,12 +35,13
29 35 - else
30 36 %div.navbar-btn.btn.btn-primary#countdown asdf
31 37 :javascript
32 38 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
33 39 / admin section
34 40 - if (@current_user!=nil) and (session[:admin])
41 + / management
35 42 %li.dropdown
36 43 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
37 44 Manage
38 45 %span.caret
39 46 %ul.dropdown-menu
40 47 = add_menu( 'Announcements', 'announcements', 'index')
@@ -44,18 +51,20
44 51 = add_menu( 'Message ', 'messages', 'console')
45 52 %li.divider{role: 'separator'}
46 53 = add_menu( 'System config', 'configurations', 'index')
47 54 %li.divider{role: 'separator'}
48 55 = add_menu( 'Sites', 'sites', 'index')
49 56 = add_menu( 'Contests', 'contest_management', 'index')
57 + / report
50 58 %li.dropdown
51 59 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
52 60 Report
53 61 %span.caret
54 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 65 = add_menu( 'Report', 'report', 'multiple_login')
57 66 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
58 67 =link_to "#{ungraded} backlogs!",
59 68 grader_list_path,
60 69 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
61 70
@@ -8,8 +8,9
8 8 = content_for :header
9 9 = yield :head
10 10
11 11 %body
12 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 16 = yield
@@ -9,13 +9,13
9 9 - if flash[:notice]
10 10 %hr/
11 11 %b= flash[:notice]
12 12 %hr/
13 13
14 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 16 %table
17 17 %tr
18 18 %td{:align => "right"}
19 19 ="#{t 'login_label'}:"
20 20 %td= text_field_tag 'login'
21 21 %tr
@@ -1,11 +1,15
1 1 %tr
2 2 %td
3 + - if @current_user and @current_user.admin?
4 + = link_to problem.name, stat_problem_path(problem)
5 + - else
3 6 = "#{problem.name}"
4 7 %td
5 8 = "#{problem.full_name}"
9 +
6 10 %br
7 11 = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, problem
8 12 %td
9 13 = @prob_submissions[problem.id][:count]
10 14 = link_to "[subs]", main_submission_path(problem.id)
11 15 %td
@@ -5,13 +5,13
5 5 %h3= "#{pluralize(@submission.errors.count, "error")} prohibited this user from being saved:"
6 6 %ul
7 7 - @submission.errors.full_messages.each do |msg|
8 8 %li= msg
9 9 .form-group
10 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 12 .form-group
13 13 = label_tag :file, 'File:'
14 14 .input-group
15 15 %span.input-group-btn
16 16 %span.btn.btn-default.btn-file
17 17 Browse
@@ -7,20 +7,23
7 7 = format_short_time(submission.submitted_at.localtime)
8 8 - else
9 9 %strong= t 'main.graded_at'
10 10 = "#{format_short_time(submission.graded_at.localtime)} "
11 11 %br
12 12 - if GraderConfiguration['ui.show_score']
13 - =t 'main.score'
13 + %strong=t 'main.score'
14 14 = "#{(submission.points*100/submission.problem.full_score).to_i} "
15 15 = " ["
16 16 %tt
17 17 = submission.grader_comment
18 18 = "]"
19 19 %br
20 20 %strong View:
21 21 - if GraderConfiguration.show_grading_result
22 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 25 = link_to "#{t 'main.src_link'}",{:action => 'source', :id => submission.id}, class: 'btn btn-xs btn-info'
25 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
@@ -40,13 +40,25
40 40 %th
41 41 = render :partial => 'problem', :collection => cp[:problems]
42 42 .col-md-5
43 43 .panel.panel-info
44 44 .panel-heading
45 45 Announcement
46 + = link_to 'Manage', announcements_path, class: 'btn btn-xs btn-default'
46 47 %ul.list-group
47 48 = render :partial => 'announcement', :collection => @announcements
48 49
49 50 %script{:type => 'text/javascript'}
50 51 = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';"
51 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
@@ -23,24 +23,28
23 23 %th.text-right Full score
24 24 %th Date added
25 25 %th.text-center
26 26 Avail?
27 27 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
28 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 32 Test?
30 33 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
31 34 - if GraderConfiguration.multicontests?
32 35 %th Contests
33 36 - for problem in @problems
34 37 %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
35 38 - @problem=problem
36 39 %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1
37 40 %td= problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
38 41 %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1
39 42 %td= problem.date_added
40 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 45 %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}")
42 46 - if GraderConfiguration.multicontests?
43 47 %td
44 48 = problem.contests.collect { |c| c.name }.join(', ')
45 49 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
46 50 %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
@@ -18,7 +18,7
18 18 <% else %>
19 19 (not available)
20 20 <% end %>
21 21 </p>
22 22
23 23 <%= link_to 'Edit', :action => 'edit', :id => @problem %> |
24 - <%= link_to 'Back', :action => 'list' %>
24 + <%= link_to 'Back', problems_path %>
@@ -1,30 +1,30
1 1 %table.table.sortable.table-striped.table-bordered.table-condensed
2 2 %thead
3 3 %tr
4 4 %th Login
5 5 %th Name
6 - %th Activated?
7 - %th Logged_in
8 - %th Contest(s)
6 + / %th Activated?
7 + / %th Logged_in
8 + / %th Contest(s)
9 9 %th Remark
10 10 - @problems.each do |p|
11 - %th.text-right= p.name
11 + %th.text-right= p.name.gsub('_',' ')
12 12 %th.text-right Total
13 13 %th.text-right Passed
14 14 %tbody
15 15 - @scorearray.each do |sc|
16 16 %tr
17 17 - total,num_passed = 0,0
18 18 - sc.each_index do |i|
19 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 21 %td= sc[i].full_name
22 - %td= sc[i].activated
23 - %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
24 - %td= sc[i].contests.collect {|c| c.name}.join(', ')
22 + / %td= sc[i].activated
23 + / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
24 + / %td= sc[i].contests.collect {|c| c.name}.join(', ')
25 25 %td= sc[i].remark
26 26 - else
27 27 %td.text-right= sc[i][0]
28 28 - total += sc[i][0]
29 29 - num_passed += 1 if sc[i][1]
30 30 %td.text-right= total
@@ -41,13 +41,13
41 41 %td.info_param Solved/Attempted User
42 42 %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
43 43 - if @best
44 44 %tr
45 45 %td.info_param Best Runtime
46 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 48 %br
49 49 using <span class="text-success">#{@best[:runtime][:lang]}</span>
50 50 %br
51 51 with <span class="text-success">#{@best[:runtime][:value] * 1000} milliseconds</span>
52 52 %br
53 53 at submission
@@ -59,38 +59,38
59 59 %sup{ id: "xmem_remark",
60 60 style: "position:relative; color: blue;",
61 61 data: {toggle: 'tooltip', placement: 'top', animation: 'false', delay: 20},
62 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 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 66 %br
67 67 using <span class="text-success">#{@best[:memory][:lang]}</span>
68 68 %br
69 69 with <span class="text-success">#{number_with_delimiter(@best[:memory][:value])} kbytes </span>
70 70 %br
71 71 at submission
72 72 = link_to "#" + @best[:memory][:sub_id].to_s, submission_path(@best[:memory][:sub_id])
73 73
74 74 %tr
75 75 %td.info_param Shortest Code
76 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 78 %br
79 79 using <span class="text-success">#{@best[:length][:lang]}</span>
80 80 %br
81 81 with <span class="text-success">#{@best[:length][:value]} bytes</span>
82 82 %br
83 83 at submission
84 84 = link_to "#" + @best[:length][:sub_id].to_s, submission_path(@best[:length][:sub_id])
85 85
86 86 %tr
87 87 %td.info_param First solver
88 88 %td
89 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 91 %br
92 92 using <span class="text-success">#{@best[:first][:lang]}</span>
93 93 %br
94 94 on <span class="text-success">#{@best[:first][:value]}</span>
95 95 %br
96 96 at submission
@@ -110,27 +110,27
110 110 %th First solver
111 111 %tbody
112 112 - @by_lang.each do |lang,value|
113 113 %tr
114 114 %td= lang
115 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 117 %br
118 118 = "#{(value[:runtime][:value] * 1000).to_i} @"
119 119 = link_to "#" + value[:runtime][:sub_id].to_s, submission_path( value[:runtime][:sub_id])
120 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 122 %br
123 123 = "#{number_with_delimiter(value[:memory][:value])} @"
124 124 = link_to "#" + value[:memory][:sub_id].to_s, submission_path(value[:memory][:sub_id])
125 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 127 %br
128 128 = "#{value[:length][:value]} @"
129 129 = link_to "#" + value[:length][:sub_id].to_s, submission_path(value[:length][:sub_id])
130 130 %td
131 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 133 %br
134 134 = "#{value[:first][:value]} @"
135 135 = link_to "#" + value[:first][:sub_id].to_s, submission_path( value[:first][:sub_id])
136 136
@@ -19,16 +19,16
19 19 Submission range
20 20 .panel-body
21 21 %p
22 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 23 .form-group
24 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 26 .form-group
27 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 29 .col-md-4
30 30 .panel.panel-primary
31 31 .panel-heading
32 32 Users
33 33 .panel-body
34 34 .radio
@@ -1,10 +1,10
1 1 %h2 Live submit
2 2 %br
3 3
4 - %textarea#text_haha{style: "display:none"}~ @source
4 + %textarea#text_sourcecode{style: "display:none"}~ @source
5 5 .container
6 6 .row
7 7 .col-md-12
8 8 .alert.alert-info
9 9 Write your code in the following box, choose language, and click submit button when finished
10 10 .row
@@ -25,25 +25,26
25 25 .form-group
26 26 = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit',
27 27 data: {confirm: "Submitting this source code for task #{@problem.long_name}?"}
28 28 .panel.panel-info
29 29 .panel-heading
30 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 32 .panel-body
32 33 - if @submission
33 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 36 .row
36 37 .col-md-12
37 38 %h2 Console
38 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 41 :javascript
41 42 $(document).ready(function() {
42 43 e = ace.edit("editor")
43 - e.setValue($("#text_haha").val());
44 + e.setValue($("#text_sourcecode").val());
44 45 e.gotoLine(1);
45 46 $("#language_id").trigger('change');
46 47 brython();
47 48 });
48 49
49 50
@@ -1,2 +1,2
1 - :javascript
1 + :plain
2 2 $("#latest_status").html("#{j render({partial: 'submission_short', locals: {submission: @submission, problem_name: @problem.name}})}")
@@ -15,13 +15,13
15 15
16 16 - if @submissions!=nil
17 17 - if @submissions.length>0
18 18 %table.table
19 19 %thead
20 20 %th No.
21 - %th #
21 + %th.text-right #
22 22 %th At
23 23 %th Source
24 24 %th Result
25 25 %th{:width => "300px"} Compiler message
26 26 %th
27 27 = render :partial => 'submission', :collection => @submissions
@@ -3,12 +3,14
3 3 %textarea#data{style: "display:none;"}
4 4 :preserve
5 5 #{@submission.source}
6 6
7 7 //%div.highlight{:style => "border: 1px solid black;"}
8 8 //=@formatted_code.html_safe
9 +
10 +
9 11 .containter
10 12 .row
11 13 .col-md-7
12 14 %h2 Source Code
13 15 .col-md-5
14 16 %h2 Stat
@@ -61,13 +63,13
61 63 %td #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
62 64 - else
63 65 %td -
64 66 %tr
65 67 %td.text-right
66 68 %strong Points
67 - %td #{@submission.points}/#{@submission.problem.full_score}
69 + %td #{@submission.points}/#{@submission.try(:problem).try(:full_score)}
68 70 %tr
69 71 %td.text-right
70 72 %strong Comment
71 73 %td #{@submission.grader_comment}
72 74 %tr
73 75 %td.text-right
@@ -78,12 +80,33
78 80 %strong Memory (kb)
79 81 %td #{@submission.peak_memory}
80 82 %tr
81 83 %td.text-right
82 84 %strong Compiler result
83 85 %td
84 - %pre= @submission.compiler_message
86 + %button.btn.btn-info.btn-xs{type: 'button', data: {toggle: 'modal', target: '#compiler'}}
87 + view
85 88 - if session[:admin]
86 89 %tr
87 90 %td.text-right
88 91 %strong IP
89 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
@@ -39,12 +39,13
39 39
40 40
41 41 %p
42 42 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
43 43 = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
44 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 46 = link_to 'Random passwords',{ :action => 'random_all_passwords'}, { class: 'btn btn-default '}
46 47 = link_to 'View active users',{ :action => 'active'}, { class: 'btn btn-default '}
47 48 = link_to 'Mass mailing',{ :action => 'mass_mailing'}, { class: 'btn btn-default '}
48 49
49 50 - if GraderConfiguration.multicontests?
50 51 %br/
@@ -81,13 +82,13
81 82 %th
82 83 %th
83 84 %th
84 85 %th
85 86 - for user in @users
86 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 89 %td= user.full_name
89 90 %td= user.email
90 91 %td= user.remark
91 92 %td= toggle_button(user.activated?, toggle_activate_user_path(user),"toggle_activate_user_#{user.id}")
92 93 %td= toggle_button(user.enabled?, toggle_enable_user_path(user),"toggle_enable_user_#{user.id}")
93 94 %td= user.last_ip
@@ -1,8 +1,9
1 1 <h1>Adding list of users</h1>
2 2
3 3 <%= form_tag :action => 'create_from_list' do %>
4 - <%= submit_tag 'create users' %><br/>
5 - List of user information in this format: <tt>user_id,name(,passwd(,alias))</tt><br/>
6 - Note that <tt>passwd</tt> and <tt>alias</tt> is optional.<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(,remark)))</tt><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 8 <%= text_area_tag 'user_list', nil, :rows => 50, :cols => 80 %>
8 9 <% end %>
@@ -3,14 +3,14
3 3
4 4 # In the development environment your application's code is reloaded on
5 5 # every request. This slows down response time but is perfect for development
6 6 # since you don't have to restart the web server when you make code changes.
7 7 config.cache_classes = false
8 8
9 - # Log error messages when you accidentally call methods on nil.
10 - config.whiny_nils = true
9 + # Log error messages when you accidentally call methods on nil. //DEPRICATED
10 + # config.whiny_nils = true // DEPRICATED
11 11
12 12 # Show full error reports and disable caching
13 13 config.consider_all_requests_local = true
14 14 config.action_controller.perform_caching = false
15 15
16 16 # Don't care if the mailer can't send
@@ -20,21 +20,23
20 20 config.active_support.deprecation = :log
21 21
22 22 # Only use best-standards-support built into browsers
23 23 config.action_dispatch.best_standards_support = :builtin
24 24
25 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
29 - # with SQLite, MySQL, and PostgreSQL)
30 - config.active_record.auto_explain_threshold_in_seconds = 0.5
28 + # Log the query plan for queries taking more than this (works // DEPRICATED
29 + # with SQLite, MySQL, and PostgreSQL) // DEPRICATED
30 + # config.active_record.auto_explain_threshold_in_seconds = 0.5 // DEPRICATED
31 31
32 32 # Do not compress assets
33 33 config.assets.compress = false
34 34
35 35 # Expands the lines which load the assets
36 36 config.assets.debug = true
37 37
38 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 42 end
@@ -6,13 +6,13
6 6
7 7 # Full error reports are disabled and caching is turned on
8 8 config.consider_all_requests_local = false
9 9 config.action_controller.perform_caching = true
10 10
11 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 14 # Compress JavaScripts and CSS
15 15 config.assets.compress = true
16 16
17 17 # Don't fallback to assets pipeline if a precompiled asset is missed
18 18 config.assets.compile = false
@@ -61,7 +61,9
61 61 # Send deprecation notices to registered listeners
62 62 config.active_support.deprecation = :notify
63 63
64 64 # Log the query plan for queries taking more than this (works
65 65 # with SQLite, MySQL, and PostgreSQL)
66 66 # config.active_record.auto_explain_threshold_in_seconds = 0.5
67 +
68 + config.eager_load = true
67 69 end
@@ -5,13 +5,13
5 5 # test suite. You never need to work with it otherwise. Remember that
6 6 # your test database is "scratch space" for the test suite and is wiped
7 7 # and recreated between test runs. Don't rely on the data there!
8 8 config.cache_classes = true
9 9
10 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 12 config.static_cache_control = "public, max-age=3600"
13 13
14 14 # Log error messages when you accidentally call methods on nil
15 15 config.whiny_nils = true
16 16
17 17 # Show full error reports and disable caching
@@ -27,11 +27,17
27 27 # Tell Action Mailer not to deliver emails to the real world.
28 28 # The :test delivery method accumulates sent emails in the
29 29 # ActionMailer::Base.deliveries array.
30 30 config.action_mailer.delivery_method = :test
31 31
32 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 35 # Print deprecation notices to the stderr
36 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 43 end
@@ -1,6 +1,5
1 1 # Be sure to restart your server when you modify this file.
2 2
3 3 # Add new mime types for use in respond_to blocks:
4 4 # Mime::Type.register "text/richtext", :rtf
5 5 # Mime::Type.register_alias "text/html", :iphone
6 - Mime::Type.register 'application/pdf', :pdf
@@ -1,11 +1,14
1 1 CafeGrader::Application.routes.draw do
2 2 get "sources/direct_edit"
3 3
4 4 root :to => 'main#login'
5 5
6 + #logins
7 + get 'login/login', to: 'login#login'
8 +
6 9 resources :contests
7 10
8 11 resources :sites
9 12
10 13 resources :announcements do
11 14 member do
@@ -14,60 +17,82
14 17 end
15 18
16 19 resources :problems do
17 20 member do
18 21 get 'toggle'
19 22 get 'toggle_test'
23 + get 'toggle_view_testcase'
20 24 get 'stat'
21 25 end
22 26 collection do
23 27 get 'turn_all_off'
24 28 get 'turn_all_on'
25 29 get 'import'
26 30 get 'manage'
27 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 43 end
29 44
30 45 resources :grader_configuration, controller: 'configurations'
31 46
32 47 resources :users do
33 48 member do
34 49 get 'toggle_activate', 'toggle_enable'
35 50 get 'stat'
36 51 end
37 52 end
38 53
39 54 resources :submissions do
55 + member do
56 + get 'download'
57 + get 'compiler_msg'
58 + get 'rejudge'
59 + end
40 60 collection do
41 61 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
42 62 get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
43 63 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
44 64 end
45 65 end
46 66
47 - match 'tasks/view/:file.:ext' => 'tasks#view'
48 - match 'tasks/download/:id/:file.:ext' => 'tasks#download'
49 - match 'heartbeat/:id/edit' => 'heartbeat#edit'
67 +
50 68
51 69 #main
52 70 get "main/list"
53 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 76 #report
56 77 get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
57 78 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
58 79 get "report/login"
59 80 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
60 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 89 #grader
63 90 get 'graders/list', to: 'graders#list', as: 'grader_list'
64 91
65 92
66 - match 'heartbeat/:id/edit' => 'heartbeat#edit'
67 -
68 93 # See how all your routes lay out with "rake routes"
69 94
70 95 # This is a legacy wild controller route that's not recommended for RESTful applications.
71 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 98 end
@@ -6,275 +6,278
6 6 # Note that this schema.rb definition is the authoritative source for your
7 7 # database schema. If you need to create the application database on another
8 8 # system, you should be using db:schema:load, not running all the migrations
9 9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 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|
17 - t.string "author"
18 - t.text "body"
16 + create_table "announcements", force: :cascade do |t|
17 + t.string "author", limit: 255
18 + t.text "body", limit: 65535
19 19 t.boolean "published"
20 - t.datetime "created_at", :null => false
21 - t.datetime "updated_at", :null => false
22 - t.boolean "frontpage", :default => false
23 - t.boolean "contest_only", :default => false
24 - t.string "title"
25 - t.string "notes"
20 + t.datetime "created_at", null: false
21 + t.datetime "updated_at", null: false
22 + t.boolean "frontpage", default: false
23 + t.boolean "contest_only", default: false
24 + t.string "title", limit: 255
25 + t.string "notes", limit: 255
26 26 end
27 27
28 - create_table "contests", :force => true do |t|
29 - t.string "title"
28 + create_table "contests", force: :cascade do |t|
29 + t.string "title", limit: 255
30 30 t.boolean "enabled"
31 - t.datetime "created_at", :null => false
32 - t.datetime "updated_at", :null => false
33 - t.string "name"
31 + t.datetime "created_at", null: false
32 + t.datetime "updated_at", null: false
33 + t.string "name", limit: 255
34 34 end
35 35
36 - create_table "contests_problems", :id => false, :force => true do |t|
37 - t.integer "contest_id"
38 - t.integer "problem_id"
36 + create_table "contests_problems", id: false, force: :cascade do |t|
37 + t.integer "contest_id", limit: 4
38 + t.integer "problem_id", limit: 4
39 39 end
40 40
41 - create_table "contests_users", :id => false, :force => true do |t|
42 - t.integer "contest_id"
43 - t.integer "user_id"
41 + create_table "contests_users", id: false, force: :cascade do |t|
42 + t.integer "contest_id", limit: 4
43 + t.integer "user_id", limit: 4
44 44 end
45 45
46 - create_table "countries", :force => true do |t|
47 - t.string "name"
48 - t.datetime "created_at", :null => false
49 - t.datetime "updated_at", :null => false
46 + create_table "countries", force: :cascade do |t|
47 + t.string "name", limit: 255
48 + t.datetime "created_at", null: false
49 + t.datetime "updated_at", null: false
50 50 end
51 51
52 - create_table "descriptions", :force => true do |t|
53 - t.text "body"
52 + create_table "descriptions", force: :cascade do |t|
53 + t.text "body", limit: 65535
54 54 t.boolean "markdowned"
55 - t.datetime "created_at", :null => false
56 - t.datetime "updated_at", :null => false
55 + t.datetime "created_at", null: false
56 + t.datetime "updated_at", null: false
57 57 end
58 58
59 - create_table "grader_configurations", :force => true do |t|
60 - t.string "key"
61 - t.string "value_type"
62 - t.string "value"
63 - t.datetime "created_at", :null => false
64 - t.datetime "updated_at", :null => false
65 - t.text "description"
59 + create_table "grader_configurations", force: :cascade do |t|
60 + t.string "key", limit: 255
61 + t.string "value_type", limit: 255
62 + t.string "value", limit: 255
63 + t.datetime "created_at", null: false
64 + t.datetime "updated_at", null: false
65 + t.text "description", limit: 65535
66 66 end
67 67
68 - create_table "grader_processes", :force => true do |t|
69 - t.string "host"
70 - t.integer "pid"
71 - t.string "mode"
68 + create_table "grader_processes", force: :cascade do |t|
69 + t.string "host", limit: 255
70 + t.integer "pid", limit: 4
71 + t.string "mode", limit: 255
72 72 t.boolean "active"
73 - t.datetime "created_at", :null => false
74 - t.datetime "updated_at", :null => false
75 - t.integer "task_id"
76 - t.string "task_type"
73 + t.datetime "created_at", null: false
74 + t.datetime "updated_at", null: false
75 + t.integer "task_id", limit: 4
76 + t.string "task_type", limit: 255
77 77 t.boolean "terminated"
78 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|
83 - t.integer "user_id"
84 - t.string "ip_address"
85 - t.datetime "created_at", :null => false
86 - t.datetime "updated_at", :null => false
87 - t.string "status"
82 + create_table "heart_beats", force: :cascade do |t|
83 + t.integer "user_id", limit: 4
84 + t.string "ip_address", limit: 255
85 + t.datetime "created_at", null: false
86 + t.datetime "updated_at", null: false
87 + t.string "status", limit: 255
88 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|
93 - t.string "name", :limit => 10
94 - t.string "pretty_name"
95 - t.string "ext", :limit => 10
96 - t.string "common_ext"
92 + create_table "languages", force: :cascade do |t|
93 + t.string "name", limit: 10
94 + t.string "pretty_name", limit: 255
95 + t.string "ext", limit: 10
96 + t.string "common_ext", limit: 255
97 97 end
98 98
99 - create_table "logins", :force => true do |t|
100 - t.integer "user_id"
101 - t.string "ip_address"
102 - t.datetime "created_at", :null => false
103 - t.datetime "updated_at", :null => false
99 + create_table "logins", force: :cascade do |t|
100 + t.integer "user_id", limit: 4
101 + t.string "ip_address", limit: 255
102 + t.datetime "created_at", null: false
103 + t.datetime "updated_at", null: false
104 104 end
105 105
106 - create_table "messages", :force => true do |t|
107 - t.integer "sender_id"
108 - t.integer "receiver_id"
109 - t.integer "replying_message_id"
110 - t.text "body"
106 + create_table "messages", force: :cascade do |t|
107 + t.integer "sender_id", limit: 4
108 + t.integer "receiver_id", limit: 4
109 + t.integer "replying_message_id", limit: 4
110 + t.text "body", limit: 65535
111 111 t.boolean "replied"
112 - t.datetime "created_at", :null => false
113 - t.datetime "updated_at", :null => false
112 + t.datetime "created_at", null: false
113 + t.datetime "updated_at", null: false
114 114 end
115 115
116 - create_table "problems", :force => true do |t|
117 - t.string "name", :limit => 30
118 - t.string "full_name"
119 - t.integer "full_score"
116 + create_table "problems", force: :cascade do |t|
117 + t.string "name", limit: 30
118 + t.string "full_name", limit: 255
119 + t.integer "full_score", limit: 4
120 120 t.date "date_added"
121 121 t.boolean "available"
122 - t.string "url"
123 - t.integer "description_id"
122 + t.string "url", limit: 255
123 + t.integer "description_id", limit: 4
124 124 t.boolean "test_allowed"
125 125 t.boolean "output_only"
126 - t.string "description_filename"
126 + t.string "description_filename", limit: 255
127 + t.boolean "view_testcase"
127 128 end
128 129
129 - create_table "rights", :force => true do |t|
130 - t.string "name"
131 - t.string "controller"
132 - t.string "action"
130 + create_table "rights", force: :cascade do |t|
131 + t.string "name", limit: 255
132 + t.string "controller", limit: 255
133 + t.string "action", limit: 255
133 134 end
134 135
135 - create_table "rights_roles", :id => false, :force => true do |t|
136 - t.integer "right_id"
137 - t.integer "role_id"
136 + create_table "rights_roles", id: false, force: :cascade do |t|
137 + t.integer "right_id", limit: 4
138 + t.integer "role_id", limit: 4
138 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 - t.string "name"
143 + create_table "roles", force: :cascade do |t|
144 + t.string "name", limit: 255
144 145 end
145 146
146 - create_table "roles_users", :id => false, :force => true do |t|
147 - t.integer "role_id"
148 - t.integer "user_id"
147 + create_table "roles_users", id: false, force: :cascade do |t|
148 + t.integer "role_id", limit: 4
149 + t.integer "user_id", limit: 4
149 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 - t.string "session_id"
155 - t.text "data"
154 + create_table "sessions", force: :cascade do |t|
155 + t.string "session_id", limit: 255
156 + t.text "data", limit: 65535
156 157 t.datetime "updated_at"
157 158 end
158 159
159 - add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
160 - add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
160 + add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", using: :btree
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 - t.string "name"
163 + create_table "sites", force: :cascade do |t|
164 + t.string "name", limit: 255
164 165 t.boolean "started"
165 166 t.datetime "start_time"
166 - t.datetime "created_at", :null => false
167 - t.datetime "updated_at", :null => false
168 - t.integer "country_id"
169 - t.string "password"
167 + t.datetime "created_at", null: false
168 + t.datetime "updated_at", null: false
169 + t.integer "country_id", limit: 4
170 + t.string "password", limit: 255
170 171 end
171 172
172 - create_table "submission_view_logs", :force => true do |t|
173 - t.integer "user_id"
174 - t.integer "submission_id"
175 - t.datetime "created_at", :null => false
176 - t.datetime "updated_at", :null => false
173 + create_table "submission_view_logs", force: :cascade do |t|
174 + t.integer "user_id", limit: 4
175 + t.integer "submission_id", limit: 4
176 + t.datetime "created_at", null: false
177 + t.datetime "updated_at", null: false
177 178 end
178 179
179 - create_table "submissions", :force => true do |t|
180 - t.integer "user_id"
181 - t.integer "problem_id"
182 - t.integer "language_id"
183 - t.text "source"
184 - t.binary "binary"
180 + create_table "submissions", force: :cascade do |t|
181 + t.integer "user_id", limit: 4
182 + t.integer "problem_id", limit: 4
183 + t.integer "language_id", limit: 4
184 + t.text "source", limit: 65535
185 + t.binary "binary", limit: 65535
185 186 t.datetime "submitted_at"
186 187 t.datetime "compiled_at"
187 - t.text "compiler_message"
188 + t.text "compiler_message", limit: 65535
188 189 t.datetime "graded_at"
189 - t.integer "points"
190 - t.text "grader_comment"
191 - t.integer "number"
192 - t.string "source_filename"
193 - t.float "max_runtime"
194 - t.integer "peak_memory"
195 - t.integer "effective_code_length"
196 - t.string "ip_address"
190 + t.integer "points", limit: 4
191 + t.text "grader_comment", limit: 65535
192 + t.integer "number", limit: 4
193 + t.string "source_filename", limit: 255
194 + t.float "max_runtime", limit: 24
195 + t.integer "peak_memory", limit: 4
196 + t.integer "effective_code_length", limit: 4
197 + t.string "ip_address", limit: 255
197 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"], :name => "index_submissions_on_user_id_and_problem_id"
200 + add_index "submissions", ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true, using: :btree
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 - t.integer "submission_id"
203 + create_table "tasks", force: :cascade do |t|
204 + t.integer "submission_id", limit: 4
204 205 t.datetime "created_at"
205 - t.integer "status"
206 + t.integer "status", limit: 4
206 207 t.datetime "updated_at"
207 208 end
208 209
209 - create_table "test_pairs", :force => true do |t|
210 - t.integer "problem_id"
211 - t.text "input", :limit => 16777215
212 - t.text "solution", :limit => 16777215
213 - t.datetime "created_at", :null => false
214 - t.datetime "updated_at", :null => false
210 + add_index "tasks", ["submission_id"], name: "index_tasks_on_submission_id", using: :btree
211 +
212 + create_table "test_pairs", force: :cascade do |t|
213 + t.integer "problem_id", limit: 4
214 + t.text "input", limit: 16777215
215 + t.text "solution", limit: 16777215
216 + t.datetime "created_at", null: false
217 + t.datetime "updated_at", null: false
215 218 end
216 219
217 - create_table "test_requests", :force => true do |t|
218 - t.integer "user_id"
219 - t.integer "problem_id"
220 - t.integer "submission_id"
221 - t.string "input_file_name"
222 - t.string "output_file_name"
223 - t.string "running_stat"
224 - t.integer "status"
225 - t.datetime "updated_at", :null => false
220 + create_table "test_requests", force: :cascade do |t|
221 + t.integer "user_id", limit: 4
222 + t.integer "problem_id", limit: 4
223 + t.integer "submission_id", limit: 4
224 + t.string "input_file_name", limit: 255
225 + t.string "output_file_name", limit: 255
226 + t.string "running_stat", limit: 255
227 + t.integer "status", limit: 4
228 + t.datetime "updated_at", null: false
226 229 t.datetime "submitted_at"
227 230 t.datetime "compiled_at"
228 - t.text "compiler_message"
231 + t.text "compiler_message", limit: 65535
229 232 t.datetime "graded_at"
230 - t.string "grader_comment"
231 - t.datetime "created_at", :null => false
232 - t.float "running_time"
233 - t.string "exit_status"
234 - t.integer "memory_usage"
233 + t.string "grader_comment", limit: 255
234 + t.datetime "created_at", null: false
235 + t.float "running_time", limit: 24
236 + t.string "exit_status", limit: 255
237 + t.integer "memory_usage", limit: 4
235 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|
240 - t.integer "problem_id"
241 - t.integer "num"
242 - t.integer "group"
243 - t.integer "score"
244 - t.text "input"
245 - t.text "sol"
246 - t.datetime "created_at", :null => false
247 - t.datetime "updated_at", :null => false
242 + create_table "testcases", force: :cascade do |t|
243 + t.integer "problem_id", limit: 4
244 + t.integer "num", limit: 4
245 + t.integer "group", limit: 4
246 + t.integer "score", limit: 4
247 + t.text "input", limit: 4294967295
248 + t.text "sol", limit: 4294967295
249 + t.datetime "created_at"
250 + t.datetime "updated_at"
248 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|
253 - t.integer "user_id"
255 + create_table "user_contest_stats", force: :cascade do |t|
256 + t.integer "user_id", limit: 4
254 257 t.datetime "started_at"
255 - t.datetime "created_at", :null => false
256 - t.datetime "updated_at", :null => false
258 + t.datetime "created_at", null: false
259 + t.datetime "updated_at", null: false
257 260 t.boolean "forced_logout"
258 261 end
259 262
260 - create_table "users", :force => true do |t|
261 - t.string "login", :limit => 50
262 - t.string "full_name"
263 - t.string "hashed_password"
264 - t.string "salt", :limit => 5
265 - t.string "alias"
266 - t.string "email"
267 - t.integer "site_id"
268 - t.integer "country_id"
269 - t.boolean "activated", :default => false
263 + create_table "users", force: :cascade do |t|
264 + t.string "login", limit: 50
265 + t.string "full_name", limit: 255
266 + t.string "hashed_password", limit: 255
267 + t.string "salt", limit: 5
268 + t.string "alias", limit: 255
269 + t.string "email", limit: 255
270 + t.integer "site_id", limit: 4
271 + t.integer "country_id", limit: 4
272 + t.boolean "activated", default: false
270 273 t.datetime "created_at"
271 274 t.datetime "updated_at"
272 - t.boolean "enabled", :default => true
273 - t.string "remark"
274 - t.string "last_ip"
275 - t.string "section"
275 + t.boolean "enabled", default: true
276 + t.string "remark", limit: 255
277 + t.string "last_ip", limit: 255
278 + t.string "section", limit: 255
276 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 283 end
@@ -50,12 +50,13
50 50 :key => 'contest.multisites',
51 51 :value_type => 'boolean',
52 52 :default_value => 'false',
53 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 58 :key => 'right.user_hall_of_fame',
58 59 :value_type => 'boolean',
59 60 :default_value => 'false',
60 61 :description => 'If true, any user can access hall of fame page.'
61 62 },
@@ -71,12 +72,39
71 72 :key => 'right.user_view_submission',
72 73 :value_type => 'boolean',
73 74 :default_value => 'false',
74 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 105 # If Configuration['system.online_registration'] is true, the
78 106 # system allows online registration, and will use these
79 107 # information for sending confirmation emails.
80 108 {
81 109 :key => 'system.online_registration.smtp',
82 110 :value_type => 'string',
@@ -52,7 +52,22
52 52
53 53 return "import CMD: #{cmd}\n" + output
54 54 end
55 55 return ''
56 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 70 end
71 + end
72 +
73 + end
@@ -35,12 +35,15
35 35 end
36 36
37 37 @log_msg << import_problem_description(dirname)
38 38 @log_msg << import_problem_pdf(dirname)
39 39 @log_msg << import_full_score(dirname)
40 40
41 + #import test data
42 + @log_msg << GraderScript.call_import_testcase(@problem.name)
43 +
41 44 return true
42 45 end
43 46
44 47 protected
45 48
46 49 def self.long_ext(filename)
@@ -1,11 +1,11
1 1 ENV["RAILS_ENV"] = "test"
2 2 require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
3 3
4 4 def clear_all_tasks
5 - Task.find(:all).each do |task|
5 + Task.all.each do |task|
6 6 task.destroy
7 7 end
8 8 end
9 9
10 10
11 11 clear_all_tasks
@@ -1,14 +1,13
1 1 ENV["RAILS_ENV"] = "test"
2 2 require File.expand_path(File.dirname(__FILE__) + "/../../config/environment")
3 3
4 4 def clear_all_tasks
5 - Task.find(:all).each do |task|
5 + Task.all.each do |task|
6 6 task.destroy
7 7 end
8 8 end
9 9
10 - puts Task.find(:all,
11 - :conditions => {:status => Task::STATUS_COMPLETE}).length
10 + puts Task.where(status: Task::STATUS_COMPLETE).length
12 11
13 12 clear_all_tasks
14 13
@@ -1,5 +1,36
1 - # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 - one:
3 - id: 1
4 - two:
5 - id: 2
1 + Language_1:
2 + name: c
3 + pretty_name: C
4 + ext: c
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 +
@@ -10,16 +10,16
10 10 login: john
11 11 full_name: john
12 12 hashed_password: <%= User.encrypt("hello",salt) %>
13 13 salt: <%= salt %>
14 14 activated: true
15 15
16 - mary:
17 - login: mary
18 - full_name: mary
19 - hashed_password: <%= User.encrypt("goodbye",salt) %>
16 + admin:
17 + login: admin
18 + full_name: admin
19 + hashed_password: <%= User.encrypt("admin",salt) %>
20 20 salt: <%= salt %>
21 21 roles: admin
22 22 activated: true
23 23
24 24 james:
25 25 login: james
@@ -1,11 +1,22
1 1 ENV["RAILS_ENV"] = "test"
2 2 require File.expand_path('../../config/environment', __FILE__)
3 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 15 class ActiveSupport::TestCase
16 + include SignInHelper
6 17 # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
7 18 #
8 19 # Note: You'll currently still have to declare fixtures explicitly in integration tests
9 20 # -- they do not yet inherit this setting
10 21 fixtures :all
11 22
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