Description:
change find(:xxx) to correct syntax for rails 4
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r619:35d86016ce86 - - 26 files changed: 108 inserted, 147 deleted

@@ -1,81 +1,81
1 1 source 'https://rubygems.org'
2 2
3 - gem 'rails', '~>4.0.0'
3 + gem 'rails', '~>4.1.0'
4 4 gem 'activerecord-session_store'
5 5
6 6 gem 'select2-rails'
7 7
8 8 # Bundle edge Rails instead:
9 9 # gem 'rails', :git => 'git://github.com/rails/rails.git'
10 10
11 11 gem 'mysql2', '~> 0.3.0'
12 12
13 13 # Gems used only for assets and not required
14 14 # in production environments by default.
15 15 group :assets do
16 16 gem 'sass-rails'
17 17 gem 'coffee-rails'
18 18
19 19 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
20 20 # gem 'therubyracer', :platforms => :ruby
21 21
22 22 gem 'uglifier'
23 23 end
24 24
25 25 # gem 'prototype-rails'
26 26
27 27 # To use ActiveModel has_secure_password
28 28 # gem 'bcrypt-ruby', '~> 3.0.0'
29 29
30 30 # To use Jbuilder templates for JSON
31 31 # gem 'jbuilder'
32 32
33 33 # Use unicorn as the app server
34 34 # gem 'unicorn'
35 35
36 36 # Deploy with Capistrano
37 37 # gem 'capistrano'
38 38
39 39 # To use debugger
40 40 # gem 'debugger'
41 41 #
42 42
43 43 #in-place editor
44 44 gem 'best_in_place', '~> 3.0.1'
45 45
46 46 # jquery addition
47 47 gem 'jquery-rails'
48 48 gem 'jquery-ui-sass-rails'
49 49 gem 'jquery-timepicker-addon-rails'
50 50 gem 'jquery-tablesorter'
51 51 gem 'jquery-countdown-rails'
52 52
53 53 #syntax highlighter
54 54 gem 'rouge'
55 55
56 56 #add bootstrap
57 57 gem 'bootstrap-sass', '~> 3.2.0'
58 58 gem 'bootstrap-switch-rails'
59 59 gem 'bootstrap-toggle-rails'
60 60 gem 'autoprefixer-rails'
61 61
62 62 #bootstrap sortable
63 63 gem 'momentjs-rails'
64 64 gem 'rails_bootstrap_sortable'
65 65
66 66 #ace editor
67 67 gem 'ace-rails-ap'
68 68
69 69 gem 'haml'
70 70 gem 'haml-rails'
71 71 gem 'mail'
72 72 gem 'rdiscount'
73 73 gem 'test-unit'
74 74 gem 'will_paginate', '~> 3.0.7'
75 75 gem 'dynamic_form'
76 76 gem 'in_place_editing'
77 77 gem 'verification', :git => 'https://github.com/sikachu/verification.git'
78 78
79 79 group :test, :development do
80 80 gem 'rspec-rails', '~> 2.99.0'
81 81 end
@@ -1,212 +1,218
1 1 GIT
2 2 remote: https://github.com/sikachu/verification.git
3 3 revision: e6fe084ce16b7b5a4b1cdfca5374d125fd034a0f
4 4 specs:
5 5 verification (1.0.3)
6 6 actionpack (>= 3.0.0, < 5.0)
7 7 activesupport (>= 3.0.0, < 5.0)
8 8
9 9 GEM
10 10 remote: https://rubygems.org/
11 11 specs:
12 12 ace-rails-ap (4.1.1)
13 - actionmailer (4.0.13)
14 - actionpack (= 4.0.13)
13 + actionmailer (4.1.16)
14 + actionpack (= 4.1.16)
15 + actionview (= 4.1.16)
15 16 mail (~> 2.5, >= 2.5.4)
16 - actionpack (4.0.13)
17 - activesupport (= 4.0.13)
18 - builder (~> 3.1.0)
19 - erubis (~> 2.7.0)
17 + actionpack (4.1.16)
18 + actionview (= 4.1.16)
19 + activesupport (= 4.1.16)
20 20 rack (~> 1.5.2)
21 21 rack-test (~> 0.6.2)
22 - activemodel (4.0.13)
23 - activesupport (= 4.0.13)
24 - builder (~> 3.1.0)
25 - activerecord (4.0.13)
26 - activemodel (= 4.0.13)
27 - activerecord-deprecated_finders (~> 1.0.2)
28 - activesupport (= 4.0.13)
29 - arel (~> 4.0.0)
30 - activerecord-deprecated_finders (1.0.4)
22 + actionview (4.1.16)
23 + activesupport (= 4.1.16)
24 + builder (~> 3.1)
25 + erubis (~> 2.7.0)
26 + activemodel (4.1.16)
27 + activesupport (= 4.1.16)
28 + builder (~> 3.1)
29 + activerecord (4.1.16)
30 + activemodel (= 4.1.16)
31 + activesupport (= 4.1.16)
32 + arel (~> 5.0.0)
31 33 activerecord-session_store (1.0.0)
32 34 actionpack (>= 4.0, < 5.1)
33 35 activerecord (>= 4.0, < 5.1)
34 36 multi_json (~> 1.11, >= 1.11.2)
35 37 rack (>= 1.5.2, < 3)
36 38 railties (>= 4.0, < 5.1)
37 - activesupport (4.0.13)
39 + activesupport (4.1.16)
38 40 i18n (~> 0.6, >= 0.6.9)
39 - minitest (~> 4.2)
40 - multi_json (~> 1.3)
41 + json (~> 1.7, >= 1.7.7)
42 + minitest (~> 5.1)
41 43 thread_safe (~> 0.1)
42 - tzinfo (~> 0.3.37)
43 - arel (4.0.2)
44 - autoprefixer-rails (6.5.2)
44 + tzinfo (~> 1.1)
45 + arel (5.0.1.20140414130214)
46 + autoprefixer-rails (6.5.3.1)
45 47 execjs
46 48 best_in_place (3.0.3)
47 49 actionpack (>= 3.2)
48 50 railties (>= 3.2)
49 51 bootstrap-sass (3.2.0.2)
50 52 sass (~> 3.2)
51 53 bootstrap-switch-rails (3.3.3)
52 54 bootstrap-toggle-rails (2.2.1.0)
53 - builder (3.1.4)
55 + builder (3.2.2)
54 56 coffee-rails (4.2.1)
55 57 coffee-script (>= 2.2.0)
56 58 railties (>= 4.0.0, < 5.2.x)
57 59 coffee-script (2.4.1)
58 60 coffee-script-source
59 61 execjs
60 - coffee-script-source (1.10.0)
62 + coffee-script-source (1.11.1)
61 63 concurrent-ruby (1.0.2)
62 64 diff-lcs (1.2.5)
63 65 dynamic_form (1.1.4)
64 66 erubis (2.7.0)
65 67 execjs (2.7.0)
66 68 haml (4.0.7)
67 69 tilt
68 70 haml-rails (0.9.0)
69 71 actionpack (>= 4.0.1)
70 72 activesupport (>= 4.0.1)
71 73 haml (>= 4.0.6, < 5.0)
72 74 html2haml (>= 1.0.1)
73 75 railties (>= 4.0.1)
74 76 html2haml (2.0.0)
75 77 erubis (~> 2.7.0)
76 78 haml (~> 4.0.0)
77 79 nokogiri (~> 1.6.0)
78 80 ruby_parser (~> 3.5)
79 81 i18n (0.7.0)
80 82 in_place_editing (1.2.0)
81 83 jquery-countdown-rails (2.0.2)
82 84 jquery-rails (3.1.4)
83 85 railties (>= 3.0, < 5.0)
84 86 thor (>= 0.14, < 2.0)
85 - jquery-tablesorter (1.22.7)
87 + jquery-tablesorter (1.23.1)
86 88 railties (>= 3.2, < 6)
87 89 jquery-timepicker-addon-rails (1.4.1)
88 90 railties (>= 3.1)
89 91 jquery-ui-rails (4.0.3)
90 92 jquery-rails
91 93 railties (>= 3.1.0)
92 94 jquery-ui-sass-rails (4.0.3.0)
93 95 jquery-rails
94 96 jquery-ui-rails (= 4.0.3)
95 97 railties (>= 3.1.0)
98 + json (1.8.3)
96 99 mail (2.6.4)
97 100 mime-types (>= 1.16, < 4)
98 101 mime-types (3.1)
99 102 mime-types-data (~> 3.2015)
100 103 mime-types-data (3.2016.0521)
101 104 mini_portile2 (2.1.0)
102 - minitest (4.7.5)
105 + minitest (5.10.1)
103 106 momentjs-rails (2.15.1)
104 107 railties (>= 3.1)
105 108 multi_json (1.12.1)
106 109 mysql2 (0.3.21)
107 110 nokogiri (1.6.8.1)
108 111 mini_portile2 (~> 2.1.0)
109 - power_assert (0.3.1)
112 + power_assert (0.4.1)
110 113 rack (1.5.5)
111 114 rack-test (0.6.3)
112 115 rack (>= 1.0)
113 - rails (4.0.13)
114 - actionmailer (= 4.0.13)
115 - actionpack (= 4.0.13)
116 - activerecord (= 4.0.13)
117 - activesupport (= 4.0.13)
116 + rails (4.1.16)
117 + actionmailer (= 4.1.16)
118 + actionpack (= 4.1.16)
119 + actionview (= 4.1.16)
120 + activemodel (= 4.1.16)
121 + activerecord (= 4.1.16)
122 + activesupport (= 4.1.16)
118 123 bundler (>= 1.3.0, < 2.0)
119 - railties (= 4.0.13)
124 + railties (= 4.1.16)
120 125 sprockets-rails (~> 2.0)
121 126 rails_bootstrap_sortable (2.0.1)
122 127 momentjs-rails (>= 2.8.3)
123 - railties (4.0.13)
124 - actionpack (= 4.0.13)
125 - activesupport (= 4.0.13)
128 + railties (4.1.16)
129 + actionpack (= 4.1.16)
130 + activesupport (= 4.1.16)
126 131 rake (>= 0.8.7)
127 132 thor (>= 0.18.1, < 2.0)
128 - rake (11.3.0)
133 + rake (12.0.0)
129 134 rdiscount (2.2.0.1)
130 - rouge (2.0.6)
135 + rouge (2.0.7)
131 136 rspec-collection_matchers (1.1.2)
132 137 rspec-expectations (>= 2.99.0.beta1)
133 138 rspec-core (2.99.2)
134 139 rspec-expectations (2.99.2)
135 140 diff-lcs (>= 1.1.3, < 2.0)
136 141 rspec-mocks (2.99.4)
137 142 rspec-rails (2.99.0)
138 143 actionpack (>= 3.0)
139 144 activemodel (>= 3.0)
140 145 activesupport (>= 3.0)
141 146 railties (>= 3.0)
142 147 rspec-collection_matchers
143 148 rspec-core (~> 2.99.0)
144 149 rspec-expectations (~> 2.99.0)
145 150 rspec-mocks (~> 2.99.0)
146 151 ruby_parser (3.8.3)
147 152 sexp_processor (~> 4.1)
148 153 sass (3.4.22)
149 154 sass-rails (5.0.6)
150 155 railties (>= 4.0.0, < 6)
151 156 sass (~> 3.1)
152 157 sprockets (>= 2.8, < 4.0)
153 158 sprockets-rails (>= 2.0, < 4.0)
154 159 tilt (>= 1.1, < 3)
155 160 select2-rails (4.0.3)
156 161 thor (~> 0.14)
157 162 sexp_processor (4.7.0)
158 163 sprockets (3.7.0)
159 164 concurrent-ruby (~> 1.0)
160 165 rack (> 1, < 3)
161 166 sprockets-rails (2.3.3)
162 167 actionpack (>= 3.0)
163 168 activesupport (>= 3.0)
164 169 sprockets (>= 2.8, < 4.0)
165 - test-unit (3.2.2)
170 + test-unit (3.2.3)
166 171 power_assert
167 - thor (0.19.1)
172 + thor (0.19.4)
168 173 thread_safe (0.3.5)
169 174 tilt (2.0.5)
170 - tzinfo (0.3.52)
171 - uglifier (3.0.3)
175 + tzinfo (1.2.2)
176 + thread_safe (~> 0.1)
177 + uglifier (3.0.4)
172 178 execjs (>= 0.3.0, < 3)
173 179 will_paginate (3.0.12)
174 180
175 181 PLATFORMS
176 182 ruby
177 183
178 184 DEPENDENCIES
179 185 ace-rails-ap
180 186 activerecord-session_store
181 187 autoprefixer-rails
182 188 best_in_place (~> 3.0.1)
183 189 bootstrap-sass (~> 3.2.0)
184 190 bootstrap-switch-rails
185 191 bootstrap-toggle-rails
186 192 coffee-rails
187 193 dynamic_form
188 194 haml
189 195 haml-rails
190 196 in_place_editing
191 197 jquery-countdown-rails
192 198 jquery-rails
193 199 jquery-tablesorter
194 200 jquery-timepicker-addon-rails
195 201 jquery-ui-sass-rails
196 202 mail
197 203 momentjs-rails
198 204 mysql2 (~> 0.3.0)
199 - rails (~> 4.0.0)
205 + rails (~> 4.1.0)
200 206 rails_bootstrap_sortable
201 207 rdiscount
202 208 rouge
203 209 rspec-rails (~> 2.99.0)
204 210 sass-rails
205 211 select2-rails
206 212 test-unit
207 213 uglifier
208 214 verification!
209 215 will_paginate (~> 3.0.7)
210 216
211 217 BUNDLED WITH
212 218 1.13.6
@@ -1,107 +1,106
1 1 class AnnouncementsController < ApplicationController
2 2
3 3 before_filter :admin_authorization
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
18 17
19 18 # GET /announcements/1
20 19 # GET /announcements/1.xml
21 20 def show
22 21 @announcement = Announcement.find(params[:id])
23 22
24 23 respond_to do |format|
25 24 format.html # show.html.erb
26 25 format.xml { render :xml => @announcement }
27 26 end
28 27 end
29 28
30 29 # GET /announcements/new
31 30 # GET /announcements/new.xml
32 31 def new
33 32 @announcement = Announcement.new
34 33
35 34 respond_to do |format|
36 35 format.html # new.html.erb
37 36 format.xml { render :xml => @announcement }
38 37 end
39 38 end
40 39
41 40 # GET /announcements/1/edit
42 41 def edit
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 48 @announcement = Announcement.new(params[:announcement])
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 }
56 55 else
57 56 format.html { render :action => "new" }
58 57 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
59 58 end
60 59 end
61 60 end
62 61
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 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" }
76 75 format.js {}
77 76 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
78 77 end
79 78 end
80 79 end
81 80
82 81 def toggle
83 82 @announcement = Announcement.find(params[:id])
84 83 @announcement.update_attributes( published: !@announcement.published? )
85 84 respond_to do |format|
86 85 format.js { render partial: 'toggle_button',
87 86 locals: {button_id: "#announcement_toggle_#{@announcement.id}",button_on: @announcement.published? } }
88 87 end
89 88 end
90 89
91 90 def toggle_front
92 91 @announcement = Announcement.find(params[:id])
93 92 @announcement.update_attributes( frontpage: !@announcement.frontpage? )
94 93 respond_to do |format|
95 94 format.js { render partial: 'toggle_button',
96 95 locals: {button_id: "#announcement_toggle_front_#{@announcement.id}",button_on: @announcement.frontpage? } }
97 96 end
98 97 end
99 98
100 99 # DELETE /announcements/1
101 100 # DELETE /announcements/1.xml
102 101 def destroy
103 102 @announcement = Announcement.find(params[:id])
104 103 @announcement.destroy
105 104
106 105 respond_to do |format|
107 106 format.html { redirect_to(announcements_url) }
@@ -1,119 +1,119
1 1 class ApplicationController < ActionController::Base
2 2 protect_from_forgery
3 3
4 4 before_filter :current_user
5 5
6 6 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
7 7 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
8 8
9 9 #report and redirect for unauthorized activities
10 10 def unauthorized_redirect
11 11 flash[:notice] = 'You are not authorized to view the page you requested'
12 12 redirect_to :controller => 'main', :action => 'login'
13 13 end
14 14
15 15 # Returns the current logged-in user (if any).
16 16 def current_user
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
30 30
31 31 def authorization_by_roles(allowed_roles)
32 32 return false unless authenticate
33 33 user = User.find(session[:user_id])
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 40 protected
41 41
42 42 def authenticate
43 43 unless session[:user_id]
44 44 flash[:notice] = 'You need to login'
45 45 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
46 46 flash[:notice] = 'You need to login but you cannot log in at this time'
47 47 end
48 48 redirect_to :controller => 'main', :action => 'login'
49 49 return false
50 50 end
51 51
52 52 # check if run in single user mode
53 53 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
54 54 user = User.find_by_id(session[:user_id])
55 55 if user==nil or (not user.admin?)
56 56 flash[:notice] = 'You cannot log in at this time'
57 57 redirect_to :controller => 'main', :action => 'login'
58 58 return false
59 59 end
60 60 unless user.enabled?
61 61 flash[:notice] = 'Your account is disabled'
62 62 redirect_to :controller => 'main', :action => 'login'
63 63 return false
64 64 end
65 65 return true
66 66 end
67 67
68 68 if GraderConfiguration.multicontests?
69 69 user = User.find(session[:user_id])
70 70 return true if user.admin?
71 71 begin
72 72 if user.contest_stat(true).forced_logout
73 73 flash[:notice] = 'You have been automatically logged out.'
74 74 redirect_to :controller => 'main', :action => 'index'
75 75 end
76 76 rescue
77 77 end
78 78 end
79 79 return true
80 80 end
81 81
82 82 def authenticate_by_ip_address
83 83 #this assume that we have already authenticate normally
84 84 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
85 85 user = User.find(session[:user_id])
86 86 if (not user.admin? and user.last_ip and user.last_ip != request.remote_ip)
87 87 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
88 88 redirect_to :controller => 'main', :action => 'login'
89 89 puts "CHEAT: user #{user.login} tried to login from '#{request.remote_ip}' while last ip is '#{user.last_ip}' at #{Time.zone.now}"
90 90 return false
91 91 end
92 92 unless user.last_ip
93 93 user.last_ip = request.remote_ip
94 94 user.save
95 95 end
96 96 end
97 97 return true
98 98 end
99 99
100 100 def authorization
101 101 return false unless authenticate
102 102 user = User.find(session[:user_id])
103 103 unless user.roles.detect { |role|
104 104 role.rights.detect{ |right|
105 105 right.controller == self.class.controller_name and
106 106 (right.action == 'all' or right.action == action_name)
107 107 }
108 108 }
109 109 flash[:notice] = 'You are not authorized to view the page you requested'
110 110 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
111 111 redirect_to :controller => 'main', :action => 'login'
112 112 return false
113 113 end
114 114 end
115 115
116 116 def verify_time_limit
117 117 return true if session[:user_id]==nil
118 118 user = User.find(session[:user_id], :include => :site)
119 119 return true if user==nil or user.site == nil
@@ -1,35 +1,34
1 1 class ConfigurationsController < ApplicationController
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)
10 9 @group = GraderConfiguration.pluck("grader_configurations.key").map{ |x| x[0...(x.index('.'))] }.uniq.sort
11 10 end
12 11
13 12 def reload
14 13 GraderConfiguration.reload
15 14 redirect_to :action => 'index'
16 15 end
17 16
18 17 def update
19 18 @config = GraderConfiguration.find(params[:id])
20 19 User.clear_last_login if @config.key == GraderConfiguration::MULTIPLE_IP_LOGIN_KEY and @config.value == 'true' and params[:grader_configuration][:value] == 'false'
21 20 respond_to do |format|
22 21 if @config.update_attributes(configuration_params)
23 22 format.json { head :ok }
24 23 else
25 24 format.json { respond_with_bip(@config) }
26 25 end
27 26 end
28 27 end
29 28
30 29 private
31 30 def configuration_params
32 31 params.require(:grader_configuration).permit(:key,:value_type,:value,:description)
33 32 end
34 33
35 34 end
@@ -1,50 +1,50
1 1 class ContestManagementController < ApplicationController
2 2
3 3 before_filter :admin_authorization
4 4
5 5 def index
6 6 @num_contests = Contest.count()
7 7 end
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])
23 23 if user.contest_stat!=nil
24 24 user.contest_stat.destroy
25 25 end
26 26 redirect_to :action => 'user_stat'
27 27 end
28 28
29 29 def clear_all_stat
30 30 if not GraderConfiguration.indv_contest_mode?
31 31 redirect_to :action => 'index' and return
32 32 end
33 33
34 34 UserContestStat.delete_all()
35 35 flash[:notice] = 'All start time statistic cleared.'
36 36 redirect_to :action => 'index'
37 37 end
38 38
39 39 def change_contest_mode
40 40 if ['standard', 'contest', 'indv-contest', 'analysis'].include? params[:id]
41 41 config = GraderConfiguration.find_by_key('system.mode')
42 42 config.value = params[:id]
43 43 config.save
44 44 else
45 45 flash[:notice] = 'Wrong contest mode value'
46 46 end
47 47 redirect_to :action => 'index'
48 48 end
49 49
50 50 end
@@ -1,130 +1,128
1 1 class GradersController < ApplicationController
2 2
3 3 before_filter :admin_authorization, except: [ :submission ]
4 4 before_filter(only: [:submission]) {
5 5 #check if authenticated
6 6 return false unless authenticate
7 7
8 8 #admin always has privileged
9 9 if @current_user.admin?
10 10 return true
11 11 end
12 12
13 13 if GraderConfiguration["right.user_view_submission"] and Submission.find(params[:id]).problem.available?
14 14 return true
15 15 else
16 16 unauthorized_redirect
17 17 return false
18 18 end
19 19 }
20 20
21 21 verify :method => :post, :only => ['clear_all',
22 22 'start_exam',
23 23 'start_grading',
24 24 'stop_all',
25 25 'clear_terminated'],
26 26 :redirect_to => {:action => 'index'}
27 27
28 28 def index
29 29 redirect_to :action => 'list'
30 30 end
31 31
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])
48 46 grader_proc.destroy if grader_proc!=nil
49 47 redirect_to :action => 'list'
50 48 end
51 49
52 50 def clear_terminated
53 51 GraderProcess.find_terminated_graders.each do |p|
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
67 65 if params[:type]=='Task'
68 66 redirect_to :action => 'task', :id => params[:id]
69 67 else
70 68 redirect_to :action => 'test_request', :id => params[:id]
71 69 end
72 70 end
73 71
74 72 def test_request
75 73 @test_request = TestRequest.find(params[:id])
76 74 end
77 75
78 76 def task
79 77 @task = Task.find(params[:id])
80 78 end
81 79
82 80 def submission
83 81 @submission = Submission.find(params[:id])
84 82 formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true )
85 83 lexer = case @submission.language.name
86 84 when "c" then Rouge::Lexers::C.new
87 85 when "cpp" then Rouge::Lexers::Cpp.new
88 86 when "pas" then Rouge::Lexers::Pas.new
89 87 when "ruby" then Rouge::Lexers::Ruby.new
90 88 when "python" then Rouge::Lexers::Python.new
91 89 when "java" then Rouge::Lexers::Java.new
92 90 when "php" then Rouge::Lexers::PHP.new
93 91 end
94 92 @formatted_code = formatter.format(lexer.lex(@submission.source))
95 93 @css_style = Rouge::Themes::ThankfulEyes.render(scope: '.highlight')
96 94
97 95 user = User.find(session[:user_id])
98 96 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
99 97
100 98 end
101 99
102 100 # various grader controls
103 101
104 102 def stop
105 103 grader_proc = GraderProcess.find(params[:id])
106 104 GraderScript.stop_grader(grader_proc.pid)
107 105 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
108 106 redirect_to :action => 'list'
109 107 end
110 108
111 109 def stop_all
112 110 GraderScript.stop_graders(GraderProcess.find_running_graders +
113 111 GraderProcess.find_stalled_process)
114 112 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
115 113 redirect_to :action => 'list'
116 114 end
117 115
118 116 def start_grading
119 117 GraderScript.start_grader('grading')
120 118 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
121 119 redirect_to :action => 'list'
122 120 end
123 121
124 122 def start_exam
125 123 GraderScript.start_grader('exam')
126 124 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
127 125 redirect_to :action => 'list'
128 126 end
129 127
130 128 end
@@ -1,318 +1,318
1 1 class MainController < ApplicationController
2 2
3 3 before_filter :authenticate, :except => [:index, :login]
4 4 before_filter :check_viewability, :except => [:index, :login]
5 5
6 6 append_before_filter :confirm_and_update_start_time,
7 7 :except => [:index,
8 8 :login,
9 9 :confirm_contest_start]
10 10
11 11 # to prevent log in box to be shown when user logged out of the
12 12 # system only in some tab
13 13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
14 14 :only => [:announcements]
15 15
16 16 before_filter :authenticate_by_ip_address, :only => [:list]
17 17
18 18 # COMMENTED OUT: filter in each action instead
19 19 # before_filter :verify_time_limit, :only => [:submit]
20 20
21 21 verify :method => :post, :only => [:submit],
22 22 :redirect_to => { :action => :index }
23 23
24 24 # COMMENT OUT: only need when having high load
25 25 # caches_action :index, :login
26 26
27 27 # NOTE: This method is not actually needed, 'config/routes.rb' has
28 28 # assigned action login as a default action.
29 29 def index
30 30 redirect_to :action => 'login'
31 31 end
32 32
33 33 def login
34 34 saved_notice = flash[:notice]
35 35 reset_session
36 36 flash.now[:notice] = saved_notice
37 37
38 38 # EXPERIMENT:
39 39 # Hide login if in single user mode and the url does not
40 40 # explicitly specify /login
41 41 #
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
55 55
56 56 def help
57 57 @user = User.find(session[:user_id])
58 58 end
59 59
60 60 def submit
61 61 user = User.find(session[:user_id])
62 62
63 63 @submission = Submission.new
64 64 @submission.problem_id = params[:submission][:problem_id]
65 65 @submission.user = user
66 66 @submission.language_id = 0
67 67 if (params['file']) and (params['file']!='')
68 68 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
69 69 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
70 70 @submission.source_filename = params['file'].original_filename
71 71 end
72 72
73 73 if (params[:editor_text])
74 74 language = Language.find_by_id(params[:language_id])
75 75 @submission.source = params[:editor_text]
76 76 @submission.source_filename = "live_edit.#{language.ext}"
77 77 @submission.language = language
78 78 end
79 79
80 80 @submission.submitted_at = Time.new.gmtime
81 81 @submission.ip_address = request.remote_ip
82 82
83 83 if GraderConfiguration.time_limit_mode? and user.contest_finished?
84 84 @submission.errors.add(:base,"The contest is over.")
85 85 prepare_list_information
86 86 render :action => 'list' and return
87 87 end
88 88
89 89 if @submission.valid?
90 90 if @submission.save == false
91 91 flash[:notice] = 'Error saving your submission'
92 92 elsif Task.create(:submission_id => @submission.id,
93 93 :status => Task::STATUS_INQUEUE) == false
94 94 flash[:notice] = 'Error adding your submission to task queue'
95 95 end
96 96 else
97 97 prepare_list_information
98 98 render :action => 'list' and return
99 99 end
100 100 redirect_to :action => 'list'
101 101 end
102 102
103 103 def source
104 104 submission = Submission.find(params[:id])
105 105 if ((submission.user_id == session[:user_id]) and
106 106 (submission.problem != nil) and
107 107 (submission.problem.available))
108 108 send_data(submission.source,
109 109 {:filename => submission.download_filename,
110 110 :type => 'text/plain'})
111 111 else
112 112 flash[:notice] = 'Error viewing source'
113 113 redirect_to :action => 'list'
114 114 end
115 115 end
116 116
117 117 def compiler_msg
118 118 @submission = Submission.find(params[:id])
119 119 if @submission.user_id == session[:user_id]
120 120 render :action => 'compiler_msg', :layout => 'empty'
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 127 def submission
128 128 @user = User.find(session[:user_id])
129 129 @problems = @user.available_problems
130 130 if params[:id]==nil
131 131 @problem = nil
132 132 @submissions = nil
133 133 else
134 134 @problem = Problem.find_by_id(params[:id])
135 135 if (@problem == nil) or (not @problem.available)
136 136 redirect_to :action => 'list'
137 137 flash[:notice] = 'Error: submissions for that problem are not viewable.'
138 138 return
139 139 end
140 140 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
141 141 end
142 142 end
143 143
144 144 def result
145 145 if !GraderConfiguration.show_grading_result
146 146 redirect_to :action => 'list' and return
147 147 end
148 148 @user = User.find(session[:user_id])
149 149 @submission = Submission.find(params[:id])
150 150 if @submission.user!=@user
151 151 flash[:notice] = 'You are not allowed to view result of other users.'
152 152 redirect_to :action => 'list' and return
153 153 end
154 154 prepare_grading_result(@submission)
155 155 end
156 156
157 157 def load_output
158 158 if !GraderConfiguration.show_grading_result or params[:num]==nil
159 159 redirect_to :action => 'list' and return
160 160 end
161 161 @user = User.find(session[:user_id])
162 162 @submission = Submission.find(params[:id])
163 163 if @submission.user!=@user
164 164 flash[:notice] = 'You are not allowed to view result of other users.'
165 165 redirect_to :action => 'list' and return
166 166 end
167 167 case_num = params[:num].to_i
168 168 out_filename = output_filename(@user.login,
169 169 @submission.problem.name,
170 170 @submission.id,
171 171 case_num)
172 172 if !FileTest.exists?(out_filename)
173 173 flash[:notice] = 'Output not found.'
174 174 redirect_to :action => 'list' and return
175 175 end
176 176
177 177 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
178 178 response.headers['Content-Type'] = "application/force-download"
179 179 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
180 180 response.headers["X-Sendfile"] = out_filename
181 181 response.headers['Content-length'] = File.size(out_filename)
182 182 render :nothing => true
183 183 else
184 184 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
185 185 end
186 186 end
187 187
188 188 def error
189 189 @user = User.find(session[:user_id])
190 190 end
191 191
192 192 # announcement refreshing and hiding methods
193 193
194 194 def announcements
195 195 if params.has_key? 'recent'
196 196 prepare_announcements(params[:recent])
197 197 else
198 198 prepare_announcements
199 199 end
200 200 render(:partial => 'announcement',
201 201 :collection => @announcements,
202 202 :locals => {:announcement_effect => true})
203 203 end
204 204
205 205 def confirm_contest_start
206 206 user = User.find(session[:user_id])
207 207 if request.method == 'POST'
208 208 user.update_start_time
209 209 redirect_to :action => 'list'
210 210 else
211 211 @contests = user.contests
212 212 @user = user
213 213 end
214 214 end
215 215
216 216 protected
217 217
218 218 def prepare_announcements(recent=nil)
219 219 if GraderConfiguration.show_tasks_to?(@user)
220 - @announcements = Announcement.find_published(true)
220 + @announcements = Announcement.published(true)
221 221 else
222 - @announcements = Announcement.find_published
222 + @announcements = Announcement.published
223 223 end
224 224 if recent!=nil
225 225 recent_id = recent.to_i
226 226 @announcements = @announcements.find_all { |a| a.id > recent_id }
227 227 end
228 228 end
229 229
230 230 def prepare_list_information
231 231 @user = User.find(session[:user_id])
232 232 if not GraderConfiguration.multicontests?
233 233 @problems = @user.available_problems
234 234 else
235 235 @contest_problems = @user.available_problems_group_by_contests
236 236 @problems = @user.available_problems
237 237 end
238 238 @prob_submissions = {}
239 239 @problems.each do |p|
240 240 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
241 241 if sub!=nil
242 242 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
243 243 else
244 244 @prob_submissions[p.id] = { :count => 0, :submission => nil }
245 245 end
246 246 end
247 247 prepare_announcements
248 248 end
249 249
250 250 def check_viewability
251 251 @user = User.find(session[:user_id])
252 252 if (!GraderConfiguration.show_tasks_to?(@user)) and
253 253 ((action_name=='submission') or (action_name=='submit'))
254 254 redirect_to :action => 'list' and return
255 255 end
256 256 end
257 257
258 258 def prepare_grading_result(submission)
259 259 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
260 260 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
261 261 else
262 262 # guess task info from problem.full_score
263 263 cases = submission.problem.full_score / 10
264 264 grading_info = {
265 265 'testruns' => cases,
266 266 'testcases' => cases
267 267 }
268 268 end
269 269 @test_runs = []
270 270 if grading_info['testruns'].is_a? Integer
271 271 trun_count = grading_info['testruns']
272 272 trun_count.times do |i|
273 273 @test_runs << [ read_grading_result(@user.login,
274 274 submission.problem.name,
275 275 submission.id,
276 276 i+1) ]
277 277 end
278 278 else
279 279 grading_info['testruns'].keys.sort.each do |num|
280 280 run = []
281 281 testrun = grading_info['testruns'][num]
282 282 testrun.each do |c|
283 283 run << read_grading_result(@user.login,
284 284 submission.problem.name,
285 285 submission.id,
286 286 c)
287 287 end
288 288 @test_runs << run
289 289 end
290 290 end
291 291 end
292 292
293 293 def grading_result_dir(user_name, problem_name, submission_id, case_num)
294 294 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
295 295 end
296 296
297 297 def output_filename(user_name, problem_name, submission_id, case_num)
298 298 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
299 299 return "#{dir}/output.txt"
300 300 end
301 301
302 302 def read_grading_result(user_name, problem_name, submission_id, case_num)
303 303 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
304 304 result_file_name = "#{dir}/result"
305 305 if !FileTest.exists?(result_file_name)
306 306 return {:num => case_num, :msg => 'program did not run'}
307 307 else
308 308 results = File.open(result_file_name).readlines
309 309 run_stat = extract_running_stat(results)
310 310 output_filename = "#{dir}/output.txt"
311 311 if FileTest.exists?(output_filename)
312 312 output_file = true
313 313 output_size = File.size(output_filename)
314 314 else
315 315 output_file = false
316 316 output_size = 0
317 317 end
318 318
@@ -1,275 +1,273
1 1 class ProblemsController < ApplicationController
2 2
3 3 before_filter :authenticate, :authorization
4 4
5 5 in_place_edit_for :problem, :name
6 6 in_place_edit_for :problem, :full_name
7 7 in_place_edit_for :problem, :full_score
8 8
9 9 def index
10 - @problems = Problem.find(:all, :order => 'date_added DESC')
10 + @problems = Problem.order(date_added: :desc)
11 11 end
12 12
13 13 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
14 14 verify :method => :post, :only => [ :create, :quick_create,
15 15 :do_manage,
16 16 :do_import,
17 17 ],
18 18 :redirect_to => { :action => :index }
19 19
20 20 def show
21 21 @problem = Problem.find(params[:id])
22 22 end
23 23
24 24 def new
25 25 @problem = Problem.new
26 26 @description = nil
27 27 end
28 28
29 29 def create
30 30 @problem = Problem.new(params[:problem])
31 31 @description = Description.new(params[:description])
32 32 if @description.body!=''
33 33 if !@description.save
34 34 render :action => new and return
35 35 end
36 36 else
37 37 @description = nil
38 38 end
39 39 @problem.description = @description
40 40 if @problem.save
41 41 flash[:notice] = 'Problem was successfully created.'
42 42 redirect_to action: :index
43 43 else
44 44 render :action => 'new'
45 45 end
46 46 end
47 47
48 48 def quick_create
49 49 @problem = Problem.new(params[:problem])
50 50 @problem.full_name = @problem.name if @problem.full_name == ''
51 51 @problem.full_score = 100
52 52 @problem.available = false
53 53 @problem.test_allowed = true
54 54 @problem.output_only = false
55 55 @problem.date_added = Time.new
56 56 if @problem.save
57 57 flash[:notice] = 'Problem was successfully created.'
58 58 redirect_to action: :index
59 59 else
60 60 flash[:notice] = 'Error saving problem'
61 61 redirect_to action: :index
62 62 end
63 63 end
64 64
65 65 def edit
66 66 @problem = Problem.find(params[:id])
67 67 @description = @problem.description
68 68 end
69 69
70 70 def update
71 71 @problem = Problem.find(params[:id])
72 72 @description = @problem.description
73 73 if @description.nil? and params[:description][:body]!=''
74 74 @description = Description.new(params[:description])
75 75 if !@description.save
76 76 flash[:notice] = 'Error saving description'
77 77 render :action => 'edit' and return
78 78 end
79 79 @problem.description = @description
80 80 elsif @description
81 81 if !@description.update_attributes(params[:description])
82 82 flash[:notice] = 'Error saving description'
83 83 render :action => 'edit' and return
84 84 end
85 85 end
86 86 if params[:file] and params[:file].content_type != 'application/pdf'
87 87 flash[:notice] = 'Error: Uploaded file is not PDF'
88 88 render :action => 'edit' and return
89 89 end
90 90 if @problem.update_attributes(params[:problem])
91 91 flash[:notice] = 'Problem was successfully updated.'
92 92 unless params[:file] == nil or params[:file] == ''
93 93 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
94 94 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
95 95 if not FileTest.exists? out_dirname
96 96 Dir.mkdir out_dirname
97 97 end
98 98
99 99 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
100 100 if FileTest.exists? out_filename
101 101 File.delete out_filename
102 102 end
103 103
104 104 File.open(out_filename,"wb") do |file|
105 105 file.write(params[:file].read)
106 106 end
107 107 @problem.description_filename = "#{@problem.name}.pdf"
108 108 @problem.save
109 109 end
110 110 redirect_to :action => 'show', :id => @problem
111 111 else
112 112 render :action => 'edit'
113 113 end
114 114 end
115 115
116 116 def destroy
117 117 p = Problem.find(params[:id]).destroy
118 118 redirect_to action: :index
119 119 end
120 120
121 121 def toggle
122 122 @problem = Problem.find(params[:id])
123 123 @problem.update_attributes(available: !(@problem.available) )
124 124 respond_to do |format|
125 125 format.js { }
126 126 end
127 127 end
128 128
129 129 def toggle_test
130 130 @problem = Problem.find(params[:id])
131 131 @problem.update_attributes(test_allowed: !(@problem.test_allowed?) )
132 132 respond_to do |format|
133 133 format.js { }
134 134 end
135 135 end
136 136
137 137 def turn_all_off
138 - Problem.find(:all,
139 - :conditions => "available = 1").each do |problem|
138 + Problem.available.all.each do |problem|
140 139 problem.available = false
141 140 problem.save
142 141 end
143 142 redirect_to action: :index
144 143 end
145 144
146 145 def turn_all_on
147 - Problem.find(:all,
148 - :conditions => "available = 0").each do |problem|
146 + Problem.where.not(available: true).each do |problem|
149 147 problem.available = true
150 148 problem.save
151 149 end
152 150 redirect_to action: :index
153 151 end
154 152
155 153 def stat
156 154 @problem = Problem.find(params[:id])
157 155 unless @problem.available or session[:admin]
158 156 redirect_to :controller => 'main', :action => 'list'
159 157 return
160 158 end
161 159 @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
162 160
163 161 #stat summary
164 162 range =65
165 163 @histogram = { data: Array.new(range,0), summary: {} }
166 164 user = Hash.new(0)
167 165 @submissions.find_each do |sub|
168 166 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
169 167 @histogram[:data][d.to_i] += 1 if d < range
170 168 user[sub.user_id] = [user[sub.user_id], ((sub.try(:points) || 0) >= @problem.full_score) ? 1 : 0].max
171 169 end
172 170 @histogram[:summary][:max] = [@histogram[:data].max,1].max
173 171
174 172 @summary = { attempt: user.count, solve: 0 }
175 173 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
176 174 end
177 175
178 176 def manage
179 - @problems = Problem.find(:all, :order => 'date_added DESC')
177 + @problems = Problem.order(date_added: :desc)
180 178 end
181 179
182 180 def do_manage
183 181 if params.has_key? 'change_date_added'
184 182 change_date_added
185 183 elsif params.has_key? 'add_to_contest'
186 184 add_to_contest
187 185 elsif params.has_key? 'enable_problem'
188 186 set_available(true)
189 187 elsif params.has_key? 'disable_problem'
190 188 set_available(false)
191 189 end
192 190 redirect_to :action => 'manage'
193 191 end
194 192
195 193 def import
196 194 @allow_test_pair_import = allow_test_pair_import?
197 195 end
198 196
199 197 def do_import
200 198 old_problem = Problem.find_by_name(params[:name])
201 199 if !allow_test_pair_import? and params.has_key? :import_to_db
202 200 params.delete :import_to_db
203 201 end
204 202 @problem, import_log = Problem.create_from_import_form_params(params,
205 203 old_problem)
206 204
207 205 if !@problem.errors.empty?
208 206 render :action => 'import' and return
209 207 end
210 208
211 209 if old_problem!=nil
212 210 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
213 211 end
214 212 @log = import_log
215 213 end
216 214
217 215 def remove_contest
218 216 problem = Problem.find(params[:id])
219 217 contest = Contest.find(params[:contest_id])
220 218 if problem!=nil and contest!=nil
221 219 problem.contests.delete(contest)
222 220 end
223 221 redirect_to :action => 'manage'
224 222 end
225 223
226 224 ##################################
227 225 protected
228 226
229 227 def allow_test_pair_import?
230 228 if defined? ALLOW_TEST_PAIR_IMPORT
231 229 return ALLOW_TEST_PAIR_IMPORT
232 230 else
233 231 return false
234 232 end
235 233 end
236 234
237 235 def change_date_added
238 236 problems = get_problems_from_params
239 237 year = params[:date_added][:year].to_i
240 238 month = params[:date_added][:month].to_i
241 239 day = params[:date_added][:day].to_i
242 240 date = Date.new(year,month,day)
243 241 problems.each do |p|
244 242 p.date_added = date
245 243 p.save
246 244 end
247 245 end
248 246
249 247 def add_to_contest
250 248 problems = get_problems_from_params
251 249 contest = Contest.find(params[:contest][:id])
252 250 if contest!=nil and contest.enabled
253 251 problems.each do |p|
254 252 p.contests << contest
255 253 end
256 254 end
257 255 end
258 256
259 257 def set_available(avail)
260 258 problems = get_problems_from_params
261 259 problems.each do |p|
262 260 p.available = avail
263 261 p.save
264 262 end
265 263 end
266 264
267 265 def get_problems_from_params
268 266 problems = []
269 267 params.keys.each do |k|
270 268 if k.index('prob-')==0
271 269 name, id, order = k.split('-')
272 270 problems << Problem.find(id)
273 271 end
274 272 end
275 273 problems
@@ -1,174 +1,170
1 1 require 'csv'
2 2
3 3 class ReportController < ApplicationController
4 4
5 5 before_filter :authenticate
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)
30 26 send_data csv, filename: 'max_score.csv'
31 27 else
32 28 #render template: 'user_admin/user_stat'
33 29 render 'current_score'
34 30 end
35 31 end
36 32
37 33 def show_max_score
38 34 #process parameters
39 35 #problems
40 36 @problems = []
41 37 params[:problem_id].each do |id|
42 38 next unless id.strip != ""
43 39 pid = Problem.find_by_id(id.to_i)
44 40 @problems << pid if pid
45 41 end
46 42
47 43 #users
48 44 @users = if params[:user] == "all" then
49 - User.find(:all, :include => [:contests, :contest_stat])
45 + User.includes(:contests).includes(:contest_stat)
50 46 else
51 47 User.includes(:contests).includes(:contest_stat).where(enabled: true)
52 48 end
53 49
54 50 #set up range from param
55 51 since_id = params.fetch(:from_id, 0).to_i
56 52 until_id = params.fetch(:to_id, 0).to_i
57 53
58 54 #calculate the routine
59 55 @scorearray = calculate_max_score(@problems, @users,since_id,until_id)
60 56
61 57 #rencer accordingly
62 58 if params[:button] == 'download' then
63 59 csv = gen_csv_from_scorearray(@scorearray,@problems)
64 60 send_data csv, filename: 'max_score.csv'
65 61 else
66 62 #render template: 'user_admin/user_stat'
67 63 render 'max_score'
68 64 end
69 65
70 66 end
71 67
72 68 def score
73 69 if params[:commit] == 'download csv'
74 70 @problems = Problem.all
75 71 else
76 - @problems = Problem.find_available_problems
72 + @problems = Problem.available_problems
77 73 end
78 - @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
74 + @users = User.includes(:contests, :contest_stat).where(enabled: true)
79 75 @scorearray = Array.new
80 76 @users.each do |u|
81 77 ustat = Array.new
82 78 ustat[0] = u
83 79 @problems.each do |p|
84 80 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
85 81 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
86 82 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
87 83 else
88 84 ustat << [0,false]
89 85 end
90 86 end
91 87 @scorearray << ustat
92 88 end
93 89 if params[:commit] == 'download csv' then
94 90 csv = gen_csv_from_scorearray(@scorearray,@problems)
95 91 send_data csv, filename: 'last_score.csv'
96 92 else
97 93 render template: 'user_admin/user_stat'
98 94 end
99 95
100 96 end
101 97
102 98 def login_stat
103 99 @logins = Array.new
104 100
105 101 date_and_time = '%Y-%m-%d %H:%M'
106 102 begin
107 103 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
108 104 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
109 105 rescue
110 106 @since_time = DateTime.new(1000,1,1)
111 107 end
112 108 begin
113 109 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
114 110 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
115 111 rescue
116 112 @until_time = DateTime.new(3000,1,1)
117 113 end
118 114
119 115 User.all.each do |user|
120 116 @logins << { id: user.id,
121 117 login: user.login,
122 118 full_name: user.full_name,
123 119 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
124 120 user.id,@since_time,@until_time)
125 121 .count(:id),
126 122 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
127 123 user.id,@since_time,@until_time)
128 124 .minimum(:created_at),
129 125 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
130 126 user.id,@since_time,@until_time)
131 127 .maximum(:created_at),
132 128 ip: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
133 129 user.id,@since_time,@until_time)
134 130 .select(:ip_address).uniq
135 131
136 132 }
137 133 end
138 134 end
139 135
140 136 def submission_stat
141 137
142 138 date_and_time = '%Y-%m-%d %H:%M'
143 139 begin
144 140 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
145 141 rescue
146 142 @since_time = DateTime.new(1000,1,1)
147 143 end
148 144 begin
149 145 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
150 146 rescue
151 147 @until_time = DateTime.new(3000,1,1)
152 148 end
153 149
154 150 @submissions = {}
155 151
156 152 User.find_each do |user|
157 153 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
158 154 end
159 155
160 156 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
161 157 if @submissions[s.user_id]
162 158 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
163 159 a = Problem.find_by_id(s.problem_id)
164 160 @submissions[s.user_id][:sub][s.problem_id] =
165 161 { prob_name: (a ? a.full_name : '(NULL)'),
166 162 sub_ids: [s.id] }
167 163 else
168 164 @submissions[s.user_id][:sub][s.problem_id][:sub_ids] << s.id
169 165 end
170 166 @submissions[s.user_id][:count] += 1
171 167 end
172 168 end
173 169 end
174 170
@@ -1,67 +1,67
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
14 14
15 15 @site_select = []
16 16 @countries.each do |country|
17 17 country.sites.each do |site|
18 18 @site_select << ["#{site.name}, #{country.name}", site.id]
19 19 end
20 20 end
21 21
22 22 @default_site = Site.first if !GraderConfiguration['contest.multisites']
23 23
24 24 render :action => 'login', :layout => 'empty'
25 25 end
26 26
27 27 def index
28 28 if @site.started
29 29 render :action => 'started', :layout => 'empty'
30 30 else
31 31 render :action => 'prompt', :layout => 'empty'
32 32 end
33 33 end
34 34
35 35 def start
36 36 @site.started = true
37 37 @site.start_time = Time.new.gmtime
38 38 @site.save
39 39 redirect_to :action => 'index'
40 40 end
41 41
42 42 def logout
43 43 reset_session
44 44 redirect_to :controller => 'main', :action => 'login'
45 45 end
46 46
47 47 protected
48 48 def site_admin_authorization
49 49 if session[:site_id]==nil
50 50 redirect_to :controller => 'site', :action => 'login' and return
51 51 end
52 52 begin
53 53 @site = Site.find(session[:site_id], :include => :country)
54 54 rescue ActiveRecord::RecordNotFound
55 55 @site = nil
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 62 private
63 63 def site_params
64 64 params.require(:site).permit()
65 65 end
66 66
67 67 end
@@ -1,97 +1,97
1 1 class SitesController < ApplicationController
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
15 15
16 16 # GET /sites/1
17 17 # GET /sites/1.xml
18 18 def show
19 19 @site = Site.find(params[:id])
20 20
21 21 respond_to do |format|
22 22 format.html # show.html.erb
23 23 format.xml { render :xml => @site }
24 24 end
25 25 end
26 26
27 27 # GET /sites/new
28 28 # GET /sites/new.xml
29 29 def new
30 30 @site = Site.new
31 31
32 32 respond_to do |format|
33 33 format.html # new.html.erb
34 34 format.xml { render :xml => @site }
35 35 end
36 36 end
37 37
38 38 # GET /sites/1/edit
39 39 def edit
40 40 @site = Site.find(params[:id])
41 41 end
42 42
43 43 # POST /sites
44 44 # POST /sites.xml
45 45 def create
46 46 @site = Site.new(params[:site])
47 47 @site.clear_start_time_if_not_started
48 48
49 49 respond_to do |format|
50 50 if @site.save
51 51 flash[:notice] = 'Site was successfully created.'
52 52 format.html { redirect_to(@site) }
53 53 format.xml { render :xml => @site, :status => :created, :location => @site }
54 54 else
55 55 format.html { render :action => "new" }
56 56 format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
57 57 end
58 58 end
59 59 end
60 60
61 61 # PUT /sites/1
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 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 }
75 75 end
76 76 end
77 77 end
78 78
79 79 # DELETE /sites/1
80 80 # DELETE /sites/1.xml
81 81 def destroy
82 82 @site = Site.find(params[:id])
83 83 @site.destroy
84 84
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 91 private
92 92
93 93 def site_params
94 94 params.require(:site).permit(:name,:started,:start_time,:country_id,:password)
95 95 end
96 96
97 97 end
@@ -1,423 +1,423
1 1 require 'csv'
2 2
3 3 class UserAdminController < ApplicationController
4 4
5 5 include MailHelperMethods
6 6
7 7 before_filter :admin_authorization
8 8
9 9 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
10 10 verify :method => :post, :only => [
11 11 :create, :create_from_list,
12 12 :update,
13 13 :manage_contest,
14 14 :bulk_mail
15 15 ],
16 16 :redirect_to => { :action => :list }
17 17
18 18 def index
19 19 @user_count = User.count
20 20 if params[:page] == 'all'
21 21 @users = User.all
22 22 @paginated = false
23 23 else
24 24 @users = User.paginate :page => params[:page]
25 25 @paginated = true
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
39 39 end
40 40
41 41 def show
42 42 @user = User.find(params[:id])
43 43 end
44 44
45 45 def new
46 46 @user = User.new
47 47 end
48 48
49 49 def create
50 50 @user = User.new(params[:user])
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'
57 57 end
58 58 end
59 59
60 60 def clear_last_ip
61 61 @user = User.find(params[:id])
62 62 @user.last_ip = nil
63 63 @user.save
64 64 redirect_to action: 'index', page: params[:page]
65 65 end
66 66
67 67 def create_from_list
68 68 lines = params[:user_list]
69 69
70 70 note = []
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 77
78 78 added_random_password = false
79 79 if items.length>=3
80 80 password = items[2].chomp(" ")
81 81 user_alias = (items.length>=4) ? items[3] : login
82 82 else
83 83 password = random_password
84 84 user_alias = (items.length>=4) ? items[3] : login
85 85 added_random_password = true
86 86 end
87 87
88 88 user = User.find_by_login(login)
89 89 if (user)
90 90 user.full_name = full_name
91 91 user.password = password
92 92 else
93 93 user = User.new({:login => login,
94 94 :full_name => full_name,
95 95 :password => password,
96 96 :password_confirmation => password,
97 97 :alias => user_alias})
98 98 end
99 99 user.activated = true
100 100 user.save
101 101
102 102 if added_random_password
103 103 note << "'#{login}' (+)"
104 104 else
105 105 note << login
106 106 end
107 107 end
108 108 end
109 109 flash[:notice] = 'User(s) ' + note.join(', ') +
110 110 ' were successfully created. ' +
111 111 '( (+) - created with random passwords.)'
112 112 redirect_to :action => 'index'
113 113 end
114 114
115 115 def edit
116 116 @user = User.find(params[:id])
117 117 end
118 118
119 119 def update
120 120 @user = User.find(params[:id])
121 121 if @user.update_attributes(user_params)
122 122 flash[:notice] = 'User was successfully updated.'
123 123 redirect_to :action => 'show', :id => @user
124 124 else
125 125 render :action => 'edit'
126 126 end
127 127 end
128 128
129 129 def destroy
130 130 User.find(params[:id]).destroy
131 131 redirect_to :action => 'index'
132 132 end
133 133
134 134 def user_stat
135 135 if params[:commit] == 'download csv'
136 136 @problems = Problem.all
137 137 else
138 - @problems = Problem.find_available_problems
138 + @problems = Problem.available_problems
139 139 end
140 - @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
140 + @users = User.includes(:contests, :contest_stat).where(enabled: true)
141 141 @scorearray = Array.new
142 142 @users.each do |u|
143 143 ustat = Array.new
144 144 ustat[0] = u
145 145 @problems.each do |p|
146 146 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
147 147 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
148 148 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
149 149 else
150 150 ustat << [0,false]
151 151 end
152 152 end
153 153 @scorearray << ustat
154 154 end
155 155 if params[:commit] == 'download csv' then
156 156 csv = gen_csv_from_scorearray(@scorearray,@problems)
157 157 send_data csv, filename: 'last_score.csv'
158 158 else
159 159 render template: 'user_admin/user_stat'
160 160 end
161 161 end
162 162
163 163 def user_stat_max
164 164 if params[:commit] == 'download csv'
165 165 @problems = Problem.all
166 166 else
167 - @problems = Problem.find_available_problems
167 + @problems = Problem.available_problems
168 168 end
169 - @users = User.find(:all, :include => [:contests, :contest_stat])
169 + @users = User.includes(:contests).includes(:contest_stat).all
170 170 @scorearray = Array.new
171 171 #set up range from param
172 172 since_id = params.fetch(:since_id, 0).to_i
173 173 until_id = params.fetch(:until_id, 0).to_i
174 174 @users.each do |u|
175 175 ustat = Array.new
176 176 ustat[0] = u
177 177 @problems.each do |p|
178 178 max_points = 0
179 179 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
180 180 max_points = sub.points if sub and sub.points and (sub.points > max_points)
181 181 end
182 182 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
183 183 end
184 184 @scorearray << ustat
185 185 end
186 186
187 187 if params[:commit] == 'download csv' then
188 188 csv = gen_csv_from_scorearray(@scorearray,@problems)
189 189 send_data csv, filename: 'max_score.csv'
190 190 else
191 191 render template: 'user_admin/user_stat'
192 192 end
193 193 end
194 194
195 195 def import
196 196 if params[:file]==''
197 197 flash[:notice] = 'Error importing no file'
198 198 redirect_to :action => 'index' and return
199 199 end
200 200 import_from_file(params[:file])
201 201 end
202 202
203 203 def random_all_passwords
204 - users = User.find(:all)
204 + users = User.all
205 205 @prefix = params[:prefix] || ''
206 206 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
207 207 @changed = false
208 208 if request.request_method == 'POST'
209 209 @non_admin_users.each do |user|
210 210 password = random_password
211 211 user.password = password
212 212 user.password_confirmation = password
213 213 user.save
214 214 end
215 215 @changed = true
216 216 end
217 217 end
218 218
219 219 # contest management
220 220
221 221 def contests
222 222 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
223 223 @contests = Contest.enabled
224 224 end
225 225
226 226 def assign_from_list
227 227 contest_id = params[:users_contest_id]
228 228 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
229 229 contest = Contest.find(params[:new_contest][:id])
230 230 if !contest
231 231 flash[:notice] = 'Error: no contest'
232 232 redirect_to :action => 'contests', :id =>contest_id
233 233 end
234 234
235 235 note = []
236 236 users.each do |u|
237 237 u.contests = [contest]
238 238 note << u.login
239 239 end
240 240 flash[:notice] = 'User(s) ' + note.join(', ') +
241 241 " were successfully reassigned to #{contest.title}."
242 242 redirect_to :action => 'contests', :id =>contest.id
243 243 end
244 244
245 245 def add_to_contest
246 246 user = User.find(params[:id])
247 247 contest = Contest.find(params[:contest_id])
248 248 if user and contest
249 249 user.contests << contest
250 250 end
251 251 redirect_to :action => 'index'
252 252 end
253 253
254 254 def remove_from_contest
255 255 user = User.find(params[:id])
256 256 contest = Contest.find(params[:contest_id])
257 257 if user and contest
258 258 user.contests.delete(contest)
259 259 end
260 260 redirect_to :action => 'index'
261 261 end
262 262
263 263 def contest_management
264 264 end
265 265
266 266 def manage_contest
267 267 contest = Contest.find(params[:contest][:id])
268 268 if !contest
269 269 flash[:notice] = 'You did not choose the contest.'
270 270 redirect_to :action => 'contest_management' and return
271 271 end
272 272
273 273 operation = params[:operation]
274 274
275 275 if not ['add','remove','assign'].include? operation
276 276 flash[:notice] = 'You did not choose the operation to perform.'
277 277 redirect_to :action => 'contest_management' and return
278 278 end
279 279
280 280 lines = params[:login_list]
281 281 if !lines or lines.blank?
282 282 flash[:notice] = 'You entered an empty list.'
283 283 redirect_to :action => 'contest_management' and return
284 284 end
285 285
286 286 note = []
287 287 users = []
288 288 lines.split("\n").each do |line|
289 289 user = User.find_by_login(line.chomp)
290 290 if user
291 291 if operation=='add'
292 292 if ! user.contests.include? contest
293 293 user.contests << contest
294 294 end
295 295 elsif operation=='remove'
296 296 user.contests.delete(contest)
297 297 else
298 298 user.contests = [contest]
299 299 end
300 300
301 301 if params[:reset_timer]
302 302 user.contest_stat.forced_logout = true
303 303 user.contest_stat.reset_timer_and_save
304 304 end
305 305
306 306 if params[:notification_emails]
307 307 send_contest_update_notification_email(user, contest)
308 308 end
309 309
310 310 note << user.login
311 311 users << user
312 312 end
313 313 end
314 314
315 315 if params[:reset_timer]
316 316 logout_users(users)
317 317 end
318 318
319 319 flash[:notice] = 'User(s) ' + note.join(', ') +
320 320 ' were successfully modified. '
321 321 redirect_to :action => 'contest_management'
322 322 end
323 323
324 324 # admin management
325 325
326 326 def admin
327 - @admins = User.find(:all).find_all {|user| user.admin? }
327 + @admins = User.all.find_all {|user| user.admin? }
328 328 end
329 329
330 330 def grant_admin
331 331 login = params[:login]
332 332 user = User.find_by_login(login)
333 333 if user!=nil
334 334 admin_role = Role.find_by_name('admin')
335 335 user.roles << admin_role
336 336 else
337 337 flash[:notice] = 'Unknown user'
338 338 end
339 339 flash[:notice] = 'User added as admins'
340 340 redirect_to :action => 'admin'
341 341 end
342 342
343 343 def revoke_admin
344 344 user = User.find(params[:id])
345 345 if user==nil
346 346 flash[:notice] = 'Unknown user'
347 347 redirect_to :action => 'admin' and return
348 348 elsif user.login == 'root'
349 349 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
350 350 redirect_to :action => 'admin' and return
351 351 end
352 352
353 353 admin_role = Role.find_by_name('admin')
354 354 user.roles.delete(admin_role)
355 355 flash[:notice] = 'User permission revoked'
356 356 redirect_to :action => 'admin'
357 357 end
358 358
359 359 # mass mailing
360 360
361 361 def mass_mailing
362 362 end
363 363
364 364 def bulk_mail
365 365 lines = params[:login_list]
366 366 if !lines or lines.blank?
367 367 flash[:notice] = 'You entered an empty list.'
368 368 redirect_to :action => 'mass_mailing' and return
369 369 end
370 370
371 371 mail_subject = params[:subject]
372 372 if !mail_subject or mail_subject.blank?
373 373 flash[:notice] = 'You entered an empty mail subject.'
374 374 redirect_to :action => 'mass_mailing' and return
375 375 end
376 376
377 377 mail_body = params[:email_body]
378 378 if !mail_body or mail_body.blank?
379 379 flash[:notice] = 'You entered an empty mail body.'
380 380 redirect_to :action => 'mass_mailing' and return
381 381 end
382 382
383 383 note = []
384 384 users = []
385 385 lines.split("\n").each do |line|
386 386 user = User.find_by_login(line.chomp)
387 387 if user
388 388 send_mail(user.email, mail_subject, mail_body)
389 389 note << user.login
390 390 end
391 391 end
392 392
393 393 flash[:notice] = 'User(s) ' + note.join(', ') +
394 394 ' were successfully modified. '
395 395 redirect_to :action => 'mass_mailing'
396 396 end
397 397
398 398 protected
399 399
400 400 def random_password(length=5)
401 401 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
402 402 newpass = ""
403 403 length.times { newpass << chars[rand(chars.size-1)] }
404 404 return newpass
405 405 end
406 406
407 407 def import_from_file(f)
408 408 data_hash = YAML.load(f)
409 409 @import_log = ""
410 410
411 411 country_data = data_hash[:countries]
412 412 site_data = data_hash[:sites]
413 413 user_data = data_hash[:users]
414 414
415 415 # import country
416 416 countries = {}
417 417 country_data.each_pair do |id,country|
418 418 c = Country.find_by_name(country[:name])
419 419 if c!=nil
420 420 countries[id] = c
421 421 @import_log << "Found #{country[:name]}\n"
422 422 else
423 423 countries[id] = Country.new(:name => country[:name])
@@ -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
@@ -59,119 +59,119
59 59 return true
60 60 end
61 61
62 62 def self.show_tasks_to?(user)
63 63 if time_limit_mode?
64 64 return false if not user.contest_started?
65 65 end
66 66 return true
67 67 end
68 68
69 69 def self.show_grading_result
70 70 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
71 71 end
72 72
73 73 def self.allow_test_request(user)
74 74 mode = get(SYSTEM_MODE_CONF_KEY)
75 75 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
76 76 if (mode=='contest')
77 77 return false if ((user.site!=nil) and
78 78 ((user.site.started!=true) or
79 79 (early_timeout and (user.site.time_left < 30.minutes))))
80 80 end
81 81 return false if mode=='analysis'
82 82 return true
83 83 end
84 84
85 85 def self.task_grading_info
86 86 if GraderConfiguration.task_grading_info_cache==nil
87 87 read_grading_info
88 88 end
89 89 return GraderConfiguration.task_grading_info_cache
90 90 end
91 91
92 92 def self.standard_mode?
93 93 return get(SYSTEM_MODE_CONF_KEY) == 'standard'
94 94 end
95 95
96 96 def self.contest_mode?
97 97 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
98 98 end
99 99
100 100 def self.indv_contest_mode?
101 101 return get(SYSTEM_MODE_CONF_KEY) == 'indv-contest'
102 102 end
103 103
104 104 def self.multicontests?
105 105 return get(MULTICONTESTS_KEY) == true
106 106 end
107 107
108 108 def self.time_limit_mode?
109 109 mode = get(SYSTEM_MODE_CONF_KEY)
110 110 return ((mode == 'contest') or (mode == 'indv-contest'))
111 111 end
112 112
113 113 def self.analysis_mode?
114 114 return get(SYSTEM_MODE_CONF_KEY) == 'analysis'
115 115 end
116 116
117 117 def self.contest_time_limit
118 118 contest_time_str = GraderConfiguration[CONTEST_TIME_LIMIT_KEY]
119 119
120 120 if not defined? GraderConfiguration.contest_time_str
121 121 GraderConfiguration.contest_time_str = nil
122 122 end
123 123
124 124 if GraderConfiguration.contest_time_str != contest_time_str
125 125 GraderConfiguration.contest_time_str = contest_time_str
126 126 if tmatch = /(\d+):(\d+)/.match(contest_time_str)
127 127 h = tmatch[1].to_i
128 128 m = tmatch[2].to_i
129 129
130 130 GraderConfiguration.contest_time = h.hour + m.minute
131 131 else
132 132 GraderConfiguration.contest_time = nil
133 133 end
134 134 end
135 135 return GraderConfiguration.contest_time
136 136 end
137 137
138 138 protected
139 139
140 140 def self.convert_type(val,type)
141 141 case type
142 142 when 'string'
143 143 return val
144 144
145 145 when 'integer'
146 146 return val.to_i
147 147
148 148 when 'boolean'
149 149 return (val=='true')
150 150 end
151 151 end
152 152
153 153 def self.read_config
154 154 GraderConfiguration.config_cache = {}
155 - GraderConfiguration.find(:all).each do |conf|
155 + GraderConfiguration.all.each do |conf|
156 156 key = conf.key
157 157 val = conf.value
158 158 GraderConfiguration.config_cache[key] = GraderConfiguration.convert_type(val,conf.value_type)
159 159 end
160 160 end
161 161
162 162 def self.read_one_key(key)
163 163 conf = GraderConfiguration.find_by_key(key)
164 164 if conf
165 165 return GraderConfiguration.convert_type(conf.value,conf.value_type)
166 166 else
167 167 return nil
168 168 end
169 169 end
170 170
171 171 def self.read_grading_info
172 172 f = File.open(TASK_GRADING_INFO_FILENAME)
173 173 GraderConfiguration.task_grading_info_cache = YAML.load(f)
174 174 f.close
175 175 end
176 176
177 177 end
@@ -1,81 +1,72
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
15 11 grader.active = nil
16 12 grader.task_id = nil
17 13 grader.task_type = nil
18 14 grader.terminated = false
19 15 grader.save
20 16 else
21 17 grader = GraderProcess.create(:host => host,
22 18 :pid => pid,
23 19 :mode => mode,
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
50 41 self.task_type = task.class.to_s
51 42 else
52 43 self.task_id = nil
53 44 self.task_type = nil
54 45 end
55 46 self.save
56 47 end
57 48
58 49 def report_inactive(task=nil)
59 50 self.active = false
60 51 if task!=nil
61 52 self.task_id = task.id
62 53 self.task_type = task.class.to_s
63 54 else
64 55 self.task_id = nil
65 56 self.task_type = nil
66 57 end
67 58 self.save
68 59 end
69 60
70 61 def terminate
71 62 self.terminated = true
72 63 self.save
73 64 end
74 65
75 66 protected
76 67
77 68 def self.stalled_time()
78 69 return 1.minute
79 70 end
80 71
81 72 end
@@ -1,24 +1,24
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
14 14 def self.find_by_extension(ext)
15 15 if @@languages_by_ext.length == 0
16 16 Language.cache_ext_hash
17 17 end
18 18 if @@languages_by_ext.has_key? ext
19 19 return @@languages_by_ext[ext]
20 20 else
21 21 return nil
22 22 end
23 23 end
24 24 end
@@ -1,60 +1,58
1 1 class Message < ActiveRecord::Base
2 2
3 3 belongs_to :sender, :class_name => "User"
4 4 belongs_to :receiver, :class_name => "User"
5 5
6 6 belongs_to :replying_message, :class_name => "Message"
7 7
8 8 # commented manually do it
9 9 #
10 10 #has_many :replied_messages, {
11 11 # :class_name => "Message",
12 12 # :foreign_key => "replying_message_id"
13 13 #}
14 14 #
15 15
16 16 attr_accessor :replied_messages
17 17
18 18 def self.find_all_sent_by_user(user)
19 19 messages = user.messages
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
36 34 args.each do |collection|
37 35 collection.each do |m|
38 36 all_messages[m.id] = m
39 37 m.replied_messages = []
40 38 end
41 39 end
42 40
43 41 all_messages.each_value do |m|
44 42 rep_id = m.replying_message_id
45 43 if all_messages[rep_id]!=nil
46 44 all_messages[rep_id].add_replied_message(m)
47 45 end
48 46 end
49 47 end
50 48
51 49 def add_replied_message(m)
52 50 if @replied_messages==nil
53 51 @replied_messages = [m]
54 52 else
55 53 @replied_messages << m
56 54 end
57 55 @replied_messages
58 56 end
59 57
60 58 end
@@ -1,114 +1,115
1 1 class Problem < ActiveRecord::Base
2 2
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 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)
25 26
26 27 if !problem.errors.empty?
27 28 return problem, 'Error importing'
28 29 end
29 30
30 31 problem.full_score = 100
31 32 problem.date_added = Time.new
32 33 problem.test_allowed = true
33 34 problem.output_only = false
34 35 problem.available = false
35 36
36 37 if not problem.save
37 38 return problem, 'Error importing'
38 39 end
39 40
40 41 import_to_db = params.has_key? :import_to_db
41 42
42 43 importer = TestdataImporter.new(problem)
43 44
44 45 if not importer.import_from_file(import_params[:file],
45 46 import_params[:time_limit],
46 47 import_params[:memory_limit],
47 48 import_params[:checker_name],
48 49 import_to_db)
49 50 problem.errors.add(:base,'Import error.')
50 51 end
51 52
52 53 return problem, importer.log_msg
53 54 end
54 55
55 56 def self.download_file_basedir
56 57 return "#{Rails.root}/data/tasks"
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 64 result[:attempted_user] = Submission.where(problem_id: self.id).group_by(:user_id)
64 65 end
65 66
66 67 def long_name
67 68 "[#{name}] #{full_name}"
68 69 end
69 70
70 71 protected
71 72
72 73 def self.to_i_or_default(st, default)
73 74 if st!=''
74 75 result = st.to_i
75 76 end
76 77 result ||= default
77 78 end
78 79
79 80 def self.to_f_or_default(st, default)
80 81 if st!=''
81 82 result = st.to_f
82 83 end
83 84 result ||= default
84 85 end
85 86
86 87 def self.extract_params_and_check(params, problem)
87 88 time_limit = Problem.to_f_or_default(params[:time_limit],
88 89 DEFAULT_TIME_LIMIT)
89 90 memory_limit = Problem.to_i_or_default(params[:memory_limit],
90 91 DEFAULT_MEMORY_LIMIT)
91 92
92 93 if time_limit<=0 or time_limit >60
93 94 problem.errors.add(:base,'Time limit out of range.')
94 95 end
95 96
96 97 if memory_limit==0 and params[:memory_limit]!='0'
97 98 problem.errors.add(:base,'Memory limit format errors.')
98 99 elsif memory_limit<=0 or memory_limit >512
99 100 problem.errors.add(:base,'Memory limit out of range.')
100 101 end
101 102
102 103 if params[:file]==nil or params[:file]==''
103 104 problem.errors.add(:base,'No testdata file.')
104 105 end
105 106
106 107 checker_name = 'text'
107 108 if ['text','float'].include? params[:checker]
108 109 checker_name = params[:checker]
109 110 end
110 111
111 112 file = params[:file]
112 113
113 114 if !problem.errors.empty?
114 115 return nil, problem
@@ -1,164 +1,151
1 1 class Submission < ActiveRecord::Base
2 2
3 3 belongs_to :language
4 4 belongs_to :problem
5 5 belongs_to :user
6 6
7 7 before_validation :assign_problem
8 8 before_validation :assign_language
9 9
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 16 before_save :assign_latest_number_if_new_recond
17 17
18 18 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
19 + where("user_id = ? AND problem_id = ?",user_id,problem_id).last
24 20 end
25 21
26 22 def self.find_all_last_by_problem(problem_id)
27 23 # need to put in SQL command, maybe there's a better way
28 24 Submission.includes(:user).find_by_sql("SELECT * FROM submissions " +
29 25 "WHERE id = " +
30 26 "(SELECT MAX(id) FROM submissions AS subs " +
31 27 "WHERE subs.user_id = submissions.user_id AND " +
32 28 "problem_id = " + problem_id.to_s + " " +
33 29 "GROUP BY user_id) " +
34 30 "ORDER BY user_id")
35 31 end
36 32
37 33 def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id)
38 34 records = Submission.where(problem_id: problem_id,user_id: user_id)
39 35 records = records.where('id >= ?',since_id) if since_id > 0
40 36 records = records.where('id <= ?',until_id) if until_id > 0
41 37 records.all
42 38 end
43 39
44 40 def self.find_last_for_all_available_problems(user_id)
45 41 submissions = Array.new
46 - problems = Problem.find_available_problems
42 + problems = Problem.available_problems
47 43 problems.each do |problem|
48 44 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
49 45 submissions << sub if sub!=nil
50 46 end
51 47 submissions
52 48 end
53 49
54 50 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 - })
51 + where("user_id = ? AND problem_id = ? AND number = ?",user_id,problem_id,number).first
61 52 end
62 53
63 54 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 - })
55 + where("user_id = ? AND problem_id = ?",user_id,problem_id)
69 56 end
70 57
71 58 def download_filename
72 59 if self.problem.output_only
73 60 return self.source_filename
74 61 else
75 62 timestamp = self.submitted_at.localtime.strftime("%H%M%S")
76 63 return "#{self.problem.name}-#{timestamp}.#{self.language.ext}"
77 64 end
78 65 end
79 66
80 67 protected
81 68
82 69 def self.find_option_in_source(option, source)
83 70 if source==nil
84 71 return nil
85 72 end
86 73 i = 0
87 74 source.each_line do |s|
88 75 if s =~ option
89 76 words = s.split
90 77 return words[1]
91 78 end
92 79 i = i + 1
93 80 if i==10
94 81 return nil
95 82 end
96 83 end
97 84 return nil
98 85 end
99 86
100 87 def self.find_language_in_source(source, source_filename="")
101 88 langopt = find_option_in_source(/^LANG:/,source)
102 89 if langopt
103 90 return (Language.find_by_name(langopt) ||
104 91 Language.find_by_pretty_name(langopt))
105 92 else
106 93 if source_filename
107 94 return Language.find_by_extension(source_filename.split('.').last)
108 95 else
109 96 return nil
110 97 end
111 98 end
112 99 end
113 100
114 101 def self.find_problem_in_source(source, source_filename="")
115 102 prob_opt = find_option_in_source(/^TASK:/,source)
116 103 if problem = Problem.find_by_name(prob_opt)
117 104 return problem
118 105 else
119 106 if source_filename
120 107 return Problem.find_by_name(source_filename.split('.').first)
121 108 else
122 109 return nil
123 110 end
124 111 end
125 112 end
126 113
127 114 def assign_problem
128 115 if self.problem_id!=-1
129 116 begin
130 117 self.problem = Problem.find(self.problem_id)
131 118 rescue ActiveRecord::RecordNotFound
132 119 self.problem = nil
133 120 end
134 121 else
135 122 self.problem = Submission.find_problem_in_source(self.source,
136 123 self.source_filename)
137 124 end
138 125 end
139 126
140 127 def assign_language
141 128 self.language = Submission.find_language_in_source(self.source,
142 129 self.source_filename)
143 130 end
144 131
145 132 # validation codes
146 133 def must_specify_language
147 134 return if self.source==nil
148 135
149 136 # for output_only tasks
150 137 return if self.problem!=nil and self.problem.output_only
151 138
152 139 if self.language==nil
153 140 errors.add('source',"Cannot detect language. Did you submit a correct source file?") unless self.language!=nil
154 141 end
155 142 end
156 143
157 144 def must_have_valid_problem
158 145 return if self.source==nil
159 146 if self.problem==nil
160 147 errors.add('problem',"must be specified.")
161 148 elsif (!self.problem.available) and (self.new_record?)
162 149 errors.add('problem',"must be valid.")
163 150 end
164 151 end
@@ -1,68 +1,65
1 1 class Task < ActiveRecord::Base
2 2
3 3 belongs_to :submission
4 4
5 5 STATUS_GRADING = 0
6 6 STATUS_INQUEUE = 1
7 7 STATUS_COMPLETE = 2
8 8
9 9 def status_inqueue
10 10 self.status = Task::STATUS_INQUEUE
11 11 end
12 12
13 13 def status_inqueue!
14 14 status_inqueue
15 15 self.save
16 16 end
17 17
18 18 def status_grading
19 19 self.status = Task::STATUS_GRADING
20 20 end
21 21
22 22 def status_grading!
23 23 status_grading
24 24 self.save
25 25 end
26 26
27 27 def status_complete
28 28 self.status = Task::STATUS_COMPLETE
29 29 end
30 30
31 31 def status_complete!
32 32 status_complete
33 33 self.save
34 34 end
35 35
36 36 def status_str
37 37 case self.status
38 38 when Task::STATUS_INQUEUE
39 39 "inqueue"
40 40 when Task::STATUS_GRADING
41 41 "grading"
42 42 when Task::STATUS_COMPLETE
43 43 "complete"
44 44 end
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).where(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
61 58 rescue
62 59 task = nil
63 60
64 61 end
65 62 task
66 63 end
67 64
68 65 end
@@ -1,138 +1,136
1 1 #
2 2 # A TestRequest is a composition of submission with user's testdata.
3 3 #
4 4 # Note about TestRequest#problem: Usually, A TestRequest has to be
5 5 # associated with a problem, so that execution environment can be
6 6 # determined. However, to be more flexible, we have to ensure that
7 7 # it works as well with problem=nil. In this case, we shall provide
8 8 # a "default" execution environment for it. This can be done
9 9 # seamlessly by using TestRequest#problem_name or
10 10 # TestRequest#name_of(problem) when retrieving the name of the
11 11 # problem: #name_of would return problem.name when problem!=nil and
12 12 # it would return "default" when problem=nil, #problem_name just
13 13 # call #name_of.
14 14 #
15 15
16 16 require 'fileutils'
17 17
18 18 class TestRequest < Task
19 19 self.table_name = "test_requests"
20 20
21 21 belongs_to :user
22 22 belongs_to :problem
23 23 belongs_to :submission
24 24
25 25 validates_presence_of :submission
26 26 validate :must_have_valid_problem
27 27
28 28 def problem_name
29 29 TestRequest.name_of(self.problem)
30 30 end
31 31
32 32 def language
33 33 self.submission.language
34 34 end
35 35
36 36 def self.get_inqueue_and_change_status(status)
37 37 # since there will be only one grader grading TestRequest
38 38 # we do not need locking (hopefully)
39 39
40 - test_request = TestRequest.find(:first,
41 - :order => "created_at",
42 - :conditions => {:status=> Task::STATUS_INQUEUE})
40 + test_request = TestRequest.where(status: Task::STATUS_INQUEUE).first
43 41 if test_request!=nil
44 42 test_request.status = status
45 43 test_request.save!
46 44 end
47 45
48 46 test_request
49 47 end
50 48
51 49 # interfacing with form
52 50 def self.new_from_form_params(user,params)
53 51 test_request = TestRequest.new
54 52 test_request.user = user
55 53 begin
56 54 problem = Problem.find(params[:problem_id])
57 55 rescue ActiveRecord::RecordNotFound
58 56 problem = nil
59 57 end
60 58 test_request.problem = problem
61 59 if problem!=nil
62 60 test_request.submission =
63 61 Submission.find_by_user_problem_number(user.id,
64 62 problem.id,
65 63 params[:submission_number])
66 64 else
67 65 test_request.submission = nil
68 66 end
69 67
70 68 # checks if the user submits any input file
71 69 if params[:input_file]==nil or params[:input_file]==""
72 70 test_request.errors.add(:base,"No input submitted.")
73 71 test_request.input_file_name = nil
74 72 else
75 73 test_request.input_file_name = save_input_file(params[:input_file], user, problem)
76 74 if test_request.input_file_name == nil
77 75 test_request.errors.adds(:base,"No input submitted.")
78 76 end
79 77 if params[:additional_file]!=nil and params[:additional_file]!=""
80 78 save_additional_file(params[:additional_file],
81 79 "#{test_request.input_file_name}.files")
82 80 end
83 81 end
84 82 test_request.submitted_at = Time.new.gmtime
85 83 test_request.status_inqueue
86 84 test_request
87 85 end
88 86
89 87 protected
90 88
91 89 def self.name_of(problem)
92 90 if problem!=nil
93 91 problem.name
94 92 else
95 93 "default"
96 94 end
97 95 end
98 96
99 97 def self.random_input_file_name(user,problem)
100 98 problem_name = TestRequest.name_of(problem)
101 99 begin
102 100 tmpname = TEST_REQUEST_INPUT_FILE_DIR + "/#{user.login}/#{problem_name}/#{rand(10000)}"
103 101 end while File.exists?(tmpname)
104 102 tmpname
105 103 end
106 104
107 105 def self.save_input_file(tempfile, user, problem)
108 106 new_file_name = random_input_file_name(user,problem)
109 107 dirname = File.dirname(new_file_name)
110 108 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
111 109
112 110 # when the user did not submit any file
113 111 return nil if tempfile==""
114 112
115 113 if tempfile.instance_of?(Tempfile)
116 114 tempfile.close
117 115 FileUtils.move(tempfile.path,new_file_name)
118 116 else
119 117 File.open(new_file_name, "wb") do |f|
120 118 f.write(tempfile.read)
121 119 end
122 120 end
123 121 new_file_name
124 122 end
125 123
126 124 def self.save_additional_file(tempfile,dir)
127 125 new_file_name = "#{dir}/#{tempfile.original_filename}"
128 126 dirname = File.dirname(new_file_name)
129 127 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
130 128
131 129 # when the user did not submit any file
132 130 return nil if tempfile==""
133 131
134 132 if tempfile.instance_of?(Tempfile)
135 133 tempfile.close
136 134 FileUtils.move(tempfile.path,new_file_name)
137 135 else
138 136 File.open(new_file_name, "wb") do |f|
@@ -82,298 +82,298
82 82 end
83 83
84 84 def authenticated_by_pop3?(password)
85 85 Net::POP3.enable_ssl
86 86 pop = Net::POP3.new('pops.it.chula.ac.th')
87 87 authen = true
88 88 begin
89 89 pop.start(login, password)
90 90 pop.finish
91 91 return true
92 92 rescue
93 93 return false
94 94 end
95 95 end
96 96
97 97 def authenticated_by_cucas?(password)
98 98 url = URI.parse('https://www.cas.chula.ac.th/cas/api/?q=studentAuthenticate')
99 99 appid = '41508763e340d5858c00f8c1a0f5a2bb'
100 100 appsecret ='d9cbb5863091dbe186fded85722a1e31'
101 101 post_args = {
102 102 'appid' => appid,
103 103 'appsecret' => appsecret,
104 104 'username' => login,
105 105 'password' => password
106 106 }
107 107
108 108 #simple call
109 109 begin
110 110 http = Net::HTTP.new('www.cas.chula.ac.th', 443)
111 111 http.use_ssl = true
112 112 http.verify_mode = OpenSSL::SSL::VERIFY_NONE
113 113 result = [ ]
114 114 http.start do |http|
115 115 req = Net::HTTP::Post.new('/cas/api/?q=studentAuthenticate')
116 116 param = "appid=#{appid}&appsecret=#{appsecret}&username=#{login}&password=#{password}"
117 117 resp = http.request(req,param)
118 118 result = JSON.parse resp.body
119 119 end
120 120 return true if result["type"] == "beanStudent"
121 121 rescue => e
122 122 return false
123 123 end
124 124 return false
125 125 end
126 126
127 127 def admin?
128 128 self.roles.detect {|r| r.name == 'admin' }
129 129 end
130 130
131 131 def email_for_editing
132 132 if self.email==nil
133 133 "(unknown)"
134 134 elsif self.email==''
135 135 "(blank)"
136 136 else
137 137 self.email
138 138 end
139 139 end
140 140
141 141 def email_for_editing=(e)
142 142 self.email=e
143 143 end
144 144
145 145 def alias_for_editing
146 146 if self.alias==nil
147 147 "(unknown)"
148 148 elsif self.alias==''
149 149 "(blank)"
150 150 else
151 151 self.alias
152 152 end
153 153 end
154 154
155 155 def alias_for_editing=(e)
156 156 self.alias=e
157 157 end
158 158
159 159 def activation_key
160 160 if self.hashed_password==nil
161 161 encrypt_new_password
162 162 end
163 163 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
164 164 end
165 165
166 166 def verify_activation_key(key)
167 167 key == activation_key
168 168 end
169 169
170 170 def self.random_password(length=5)
171 171 chars = 'abcdefghjkmnopqrstuvwxyz'
172 172 password = ''
173 173 length.times { password << chars[rand(chars.length - 1)] }
174 174 password
175 175 end
176 176
177 177 def self.find_non_admin_with_prefix(prefix='')
178 - users = User.find(:all)
178 + users = User.all
179 179 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
180 180 end
181 181
182 182 # Contest information
183 183
184 184 def self.find_users_with_no_contest()
185 - users = User.find(:all)
185 + users = User.all
186 186 return users.find_all { |u| u.contests.length == 0 }
187 187 end
188 188
189 189
190 190 def contest_time_left
191 191 if GraderConfiguration.contest_mode?
192 192 return nil if site==nil
193 193 return site.time_left
194 194 elsif GraderConfiguration.indv_contest_mode?
195 195 time_limit = GraderConfiguration.contest_time_limit
196 196 if time_limit == nil
197 197 return nil
198 198 end
199 199 if contest_stat==nil or contest_stat.started_at==nil
200 200 return (Time.now.gmtime + time_limit) - Time.now.gmtime
201 201 else
202 202 finish_time = contest_stat.started_at + time_limit
203 203 current_time = Time.now.gmtime
204 204 if current_time > finish_time
205 205 return 0
206 206 else
207 207 return finish_time - current_time
208 208 end
209 209 end
210 210 else
211 211 return nil
212 212 end
213 213 end
214 214
215 215 def contest_finished?
216 216 if GraderConfiguration.contest_mode?
217 217 return false if site==nil
218 218 return site.finished?
219 219 elsif GraderConfiguration.indv_contest_mode?
220 220 return false if self.contest_stat(true)==nil
221 221 return contest_time_left == 0
222 222 else
223 223 return false
224 224 end
225 225 end
226 226
227 227 def contest_started?
228 228 if GraderConfiguration.indv_contest_mode?
229 229 stat = self.contest_stat
230 230 return ((stat != nil) and (stat.started_at != nil))
231 231 elsif GraderConfiguration.contest_mode?
232 232 return true if site==nil
233 233 return site.started
234 234 else
235 235 return true
236 236 end
237 237 end
238 238
239 239 def update_start_time
240 240 stat = self.contest_stat
241 241 if stat.nil? or stat.started_at.nil?
242 242 stat ||= UserContestStat.new(:user => self)
243 243 stat.started_at = Time.now.gmtime
244 244 stat.save
245 245 end
246 246 end
247 247
248 248 def problem_in_user_contests?(problem)
249 249 problem_contests = problem.contests.all
250 250
251 251 if problem_contests.length == 0 # this is public contest
252 252 return true
253 253 end
254 254
255 255 contests.each do |contest|
256 256 if problem_contests.find {|c| c.id == contest.id }
257 257 return true
258 258 end
259 259 end
260 260 return false
261 261 end
262 262
263 263 def available_problems_group_by_contests
264 264 contest_problems = []
265 265 pin = {}
266 266 contests.enabled.each do |contest|
267 267 available_problems = contest.problems.available
268 268 contest_problems << {
269 269 :contest => contest,
270 270 :problems => available_problems
271 271 }
272 272 available_problems.each {|p| pin[p.id] = true}
273 273 end
274 274 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
275 275 contest_problems << {
276 276 :contest => nil,
277 277 :problems => other_avaiable_problems
278 278 }
279 279 return contest_problems
280 280 end
281 281
282 282 def available_problems
283 283 if not GraderConfiguration.multicontests?
284 - return Problem.find_available_problems
284 + return Problem.available_problems
285 285 else
286 286 contest_problems = []
287 287 pin = {}
288 288 contests.enabled.each do |contest|
289 289 contest.problems.available.each do |problem|
290 290 if not pin.has_key? problem.id
291 291 contest_problems << problem
292 292 end
293 293 pin[problem.id] = true
294 294 end
295 295 end
296 296 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
297 297 return contest_problems + other_avaiable_problems
298 298 end
299 299 end
300 300
301 301 def can_view_problem?(problem)
302 302 if not GraderConfiguration.multicontests?
303 303 return problem.available
304 304 else
305 305 return problem_in_user_contests? problem
306 306 end
307 307 end
308 308
309 309 def self.clear_last_login
310 310 User.update_all(:last_ip => nil)
311 311 end
312 312
313 313 protected
314 314 def encrypt_new_password
315 315 return if password.blank?
316 316 self.salt = (10+rand(90)).to_s
317 317 self.hashed_password = User.encrypt(self.password,self.salt)
318 318 end
319 319
320 320 def assign_default_site
321 321 # have to catch error when migrating (because self.site is not available).
322 322 begin
323 323 if self.site==nil
324 324 self.site = Site.find_by_name('default')
325 325 if self.site==nil
326 326 self.site = Site.find(1) # when 'default has be renamed'
327 327 end
328 328 end
329 329 rescue
330 330 end
331 331 end
332 332
333 333 def assign_default_contest
334 334 # have to catch error when migrating (because self.site is not available).
335 335 begin
336 336 if self.contests.length == 0
337 337 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
338 338 if default_contest
339 339 self.contests = [default_contest]
340 340 end
341 341 end
342 342 rescue
343 343 end
344 344 end
345 345
346 346 def password_required?
347 347 self.hashed_password.blank? || !self.password.blank?
348 348 end
349 349
350 350 def self.encrypt(string,salt)
351 351 Digest::SHA1.hexdigest(salt + string)
352 352 end
353 353
354 354 def uniqueness_of_email_from_activated_users
355 355 user = User.activated_users.find_by_email(self.email)
356 356 if user and (user.login != self.login)
357 357 self.errors.add(:base,"Email has already been taken")
358 358 end
359 359 end
360 360
361 361 def enough_time_interval_between_same_email_registrations
362 362 return if !self.new_record?
363 363 return if self.activated
364 364 open_user = User.find_by_email(self.email,
365 365 :order => 'created_at DESC')
366 366 if open_user and open_user.created_at and
367 367 (open_user.created_at > Time.now.gmtime - 5.minutes)
368 368 self.errors.add(:base,"There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
369 369 end
370 370 end
371 371
372 372 def email_validation?
373 373 begin
374 374 return VALIDATE_USER_EMAILS
375 375 rescue
376 376 return false
377 377 end
378 378 end
379 379 end
@@ -1,34 +1,34
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 6 / %th Activated?
7 7 / %th Logged_in
8 8 / %th Contest(s)
9 9 %th Remark
10 10 - @problems.each do |p|
11 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 22 / %td= sc[i].activated
23 23 / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
24 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
31 31 %td.text-right= num_passed
32 32
33 33 :javascript
34 34 $.bootstrapSortable(true,'reversed')
@@ -1,18 +1,18
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
12 12
13 13 (1..1000).each do |i|
14 14 Task.create(:id => i,
15 15 :submission_id => i,
16 16 :status => Task::STATUS_INQUEUE)
17 17 end
18 18
@@ -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
You need to be logged in to leave comments. Login now