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

r532:e19c25c6b241 - - 13 files changed: 122 inserted, 6 deleted

@@ -0,0 +1,3
1 + class SubmissionViewLog < ActiveRecord::Base
2 + attr_accessible :submission_id, :user_id
3 + end
@@ -0,0 +1,82
1 + - content_for :header do
2 + = stylesheet_link_tag 'tablesorter-theme.cafe'
3 + = javascript_include_tag 'local_jquery'
4 +
5 + %script{:type=>"text/javascript"}
6 + $(function () {
7 + $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 + $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
9 + $('#my_table').tablesorter({widthFixed: true, widgets: ['zebra']});
10 + $('#my_table2').tablesorter({widthFixed: true, widgets: ['zebra']});
11 + $('#sub_table').tablesorter({widthFixed: true, widgets: ['zebra']});
12 + });
13 +
14 + %h1 Login status
15 +
16 + =render partial: 'report_menu'
17 +
18 +
19 + = form_tag({session: :url }) do
20 + .submitbox
21 + %table
22 + %tr
23 + %td{colspan: 6, style: 'font-weight: bold'}= 'Query login & submit in the range'
24 + %tr
25 + %td{style: 'width: 120px; font-weight: bold'}= 'Login date range'
26 + %td{align: 'right'} since:
27 + %td= text_field_tag 'since_datetime', @since_time
28 + %tr
29 + %td
30 + %td{align: 'right'} until:
31 + %td= text_field_tag 'until_datetime', @until_time
32 + %tr
33 + %td
34 + %td
35 + %td Blank mean no condition
36 + %tr
37 + %td{style: 'width: 120px; font-weight: bold'}= "ID"
38 + %td{colspan: 2}= text_field_tag 'SID', @sid, size: 40
39 + %tr
40 + %td
41 + %td
42 + %td= submit_tag 'query'
43 +
44 +
45 + %h2 Logs
46 +
47 + - if @sid
48 + %table
49 + %tbody
50 + - @sid.each do |id|
51 + - user = User.where("login = ?",id).first
52 + %tr
53 + //%td= link_to id, controller: :user, action: :profile, id: id
54 + %td= link_to id, "https://www.nattee.net/java/users/profile/#{user.id}"
55 + %td= user.full_name
56 +
57 + //%table.tablesorter-cafe#my_table
58 + %table.info
59 + %thead
60 + %tr.info-head
61 + %th Time
62 + %th Action
63 + %th IP
64 + %th login
65 + %th name
66 + %th problem
67 + %th score
68 + %tbody
69 + - if @logs
70 + - @logs.each do |l|
71 + %tr{class: cycle('info-even','info-odd')}
72 + %td= l[:submitted_at].strftime "%Y.%b.%d %H:%M:%S"
73 + //%td= l[:id] == -1 ? "LOGIN" : link_to("submit #{l[:id]}", controller: 'graders' , action: 'submission', id: l[:id])
74 + %td= l[:id] == -1 ? "LOGIN" : link_to( "submit #{l[:id]}", "https://www.nattee.net/java/graders/submission/#{l[:id]}")
75 + %td= l[:ip_address]
76 + //%td= link_to l[:login], controller: 'users', action: 'profile', id: l[:id]
77 + %td= link_to( l[:login], "https://www.nattee.net/java/users/profile/#{l.user_id}")
78 + %td= l[:full_name]
79 + %td= l[:id] == -1 ? "" : l.problem.name
80 + %td= l[:id] == -1 ? "" : l.points * 100/ l.problem.full_score
81 +
82 +
@@ -0,0 +1,10
1 + class CreateSubmissionViewLogs < ActiveRecord::Migration
2 + def change
3 + create_table :submission_view_logs do |t|
4 + t.integer :user_id
5 + t.integer :submission_id
6 +
7 + t.timestamps
8 + end
9 + end
10 + end
@@ -0,0 +1,5
1 + class AddLastIpToUser < ActiveRecord::Migration
2 + def change
3 + add_column :users, :last_ip, :string
4 + end
5 + end
@@ -0,0 +1,5
1 + require 'spec_helper'
2 +
3 + describe SubmissionViewLogs do
4 + pending "add some examples to (or delete) #{__FILE__}"
5 + end
@@ -1,175 +1,175
1 GIT
1 GIT
2 remote: https://github.com/sikachu/verification.git
2 remote: https://github.com/sikachu/verification.git
3 revision: 76eaf51b13276ecae54bd9cd115832595d2ff56d
3 revision: 76eaf51b13276ecae54bd9cd115832595d2ff56d
4 specs:
4 specs:
5 verification (1.0.3)
5 verification (1.0.3)
6 actionpack (>= 3.0.0, < 5.0)
6 actionpack (>= 3.0.0, < 5.0)
7 activesupport (>= 3.0.0, < 5.0)
7 activesupport (>= 3.0.0, < 5.0)
8
8
9 GEM
9 GEM
10 remote: https://rubygems.org/
10 remote: https://rubygems.org/
11 specs:
11 specs:
12 actionmailer (3.2.21)
12 actionmailer (3.2.21)
13 actionpack (= 3.2.21)
13 actionpack (= 3.2.21)
14 mail (~> 2.5.4)
14 mail (~> 2.5.4)
15 actionpack (3.2.21)
15 actionpack (3.2.21)
16 activemodel (= 3.2.21)
16 activemodel (= 3.2.21)
17 activesupport (= 3.2.21)
17 activesupport (= 3.2.21)
18 builder (~> 3.0.0)
18 builder (~> 3.0.0)
19 erubis (~> 2.7.0)
19 erubis (~> 2.7.0)
20 journey (~> 1.0.4)
20 journey (~> 1.0.4)
21 rack (~> 1.4.5)
21 rack (~> 1.4.5)
22 rack-cache (~> 1.2)
22 rack-cache (~> 1.2)
23 rack-test (~> 0.6.1)
23 rack-test (~> 0.6.1)
24 sprockets (~> 2.2.1)
24 sprockets (~> 2.2.1)
25 activemodel (3.2.21)
25 activemodel (3.2.21)
26 activesupport (= 3.2.21)
26 activesupport (= 3.2.21)
27 builder (~> 3.0.0)
27 builder (~> 3.0.0)
28 activerecord (3.2.21)
28 activerecord (3.2.21)
29 activemodel (= 3.2.21)
29 activemodel (= 3.2.21)
30 activesupport (= 3.2.21)
30 activesupport (= 3.2.21)
31 arel (~> 3.0.2)
31 arel (~> 3.0.2)
32 tzinfo (~> 0.3.29)
32 tzinfo (~> 0.3.29)
33 activeresource (3.2.21)
33 activeresource (3.2.21)
34 activemodel (= 3.2.21)
34 activemodel (= 3.2.21)
35 activesupport (= 3.2.21)
35 activesupport (= 3.2.21)
36 activesupport (3.2.21)
36 activesupport (3.2.21)
37 i18n (~> 0.6, >= 0.6.4)
37 i18n (~> 0.6, >= 0.6.4)
38 multi_json (~> 1.0)
38 multi_json (~> 1.0)
39 arel (3.0.3)
39 arel (3.0.3)
40 best_in_place (3.0.3)
40 best_in_place (3.0.3)
41 actionpack (>= 3.2)
41 actionpack (>= 3.2)
42 railties (>= 3.2)
42 railties (>= 3.2)
43 builder (3.0.4)
43 builder (3.0.4)
44 coffee-rails (3.2.2)
44 coffee-rails (3.2.2)
45 coffee-script (>= 2.2.0)
45 coffee-script (>= 2.2.0)
46 railties (~> 3.2.0)
46 railties (~> 3.2.0)
47 coffee-script (2.3.0)
47 coffee-script (2.3.0)
48 coffee-script-source
48 coffee-script-source
49 execjs
49 execjs
50 coffee-script-source (1.9.0)
50 coffee-script-source (1.9.0)
51 diff-lcs (1.2.5)
51 diff-lcs (1.2.5)
52 dynamic_form (1.1.4)
52 dynamic_form (1.1.4)
53 erubis (2.7.0)
53 erubis (2.7.0)
54 execjs (2.3.0)
54 execjs (2.3.0)
55 haml (4.0.6)
55 haml (4.0.6)
56 tilt
56 tilt
57 hike (1.2.3)
57 hike (1.2.3)
58 i18n (0.7.0)
58 i18n (0.7.0)
59 in_place_editing (1.2.0)
59 in_place_editing (1.2.0)
60 journey (1.0.4)
60 journey (1.0.4)
61 jquery-rails (3.1.2)
61 jquery-rails (3.1.2)
62 railties (>= 3.0, < 5.0)
62 railties (>= 3.0, < 5.0)
63 thor (>= 0.14, < 2.0)
63 thor (>= 0.14, < 2.0)
64 jquery-tablesorter (1.13.4)
64 jquery-tablesorter (1.13.4)
65 railties (>= 3.1, < 5)
65 railties (>= 3.1, < 5)
66 jquery-timepicker-addon-rails (1.4.1)
66 jquery-timepicker-addon-rails (1.4.1)
67 railties (>= 3.1)
67 railties (>= 3.1)
68 jquery-ui-rails (4.0.3)
68 jquery-ui-rails (4.0.3)
69 jquery-rails
69 jquery-rails
70 railties (>= 3.1.0)
70 railties (>= 3.1.0)
71 jquery-ui-sass-rails (4.0.3.0)
71 jquery-ui-sass-rails (4.0.3.0)
72 jquery-rails
72 jquery-rails
73 jquery-ui-rails (= 4.0.3)
73 jquery-ui-rails (= 4.0.3)
74 railties (>= 3.1.0)
74 railties (>= 3.1.0)
75 json (1.8.2)
75 json (1.8.2)
76 mail (2.5.4)
76 mail (2.5.4)
77 mime-types (~> 1.16)
77 mime-types (~> 1.16)
78 treetop (~> 1.4.8)
78 treetop (~> 1.4.8)
79 mime-types (1.25.1)
79 mime-types (1.25.1)
80 multi_json (1.10.1)
80 multi_json (1.10.1)
81 - mysql2 (0.3.19)
81 + mysql2 (0.3.20)
82 polyglot (0.3.5)
82 polyglot (0.3.5)
83 power_assert (0.2.2)
83 power_assert (0.2.2)
84 prototype-rails (3.2.1)
84 prototype-rails (3.2.1)
85 rails (~> 3.2)
85 rails (~> 3.2)
86 rack (1.4.5)
86 rack (1.4.5)
87 rack-cache (1.2)
87 rack-cache (1.2)
88 rack (>= 0.4)
88 rack (>= 0.4)
89 rack-ssl (1.3.4)
89 rack-ssl (1.3.4)
90 rack
90 rack
91 rack-test (0.6.3)
91 rack-test (0.6.3)
92 rack (>= 1.0)
92 rack (>= 1.0)
93 rails (3.2.21)
93 rails (3.2.21)
94 actionmailer (= 3.2.21)
94 actionmailer (= 3.2.21)
95 actionpack (= 3.2.21)
95 actionpack (= 3.2.21)
96 activerecord (= 3.2.21)
96 activerecord (= 3.2.21)
97 activeresource (= 3.2.21)
97 activeresource (= 3.2.21)
98 activesupport (= 3.2.21)
98 activesupport (= 3.2.21)
99 bundler (~> 1.0)
99 bundler (~> 1.0)
100 railties (= 3.2.21)
100 railties (= 3.2.21)
101 railties (3.2.21)
101 railties (3.2.21)
102 actionpack (= 3.2.21)
102 actionpack (= 3.2.21)
103 activesupport (= 3.2.21)
103 activesupport (= 3.2.21)
104 rack-ssl (~> 1.3.2)
104 rack-ssl (~> 1.3.2)
105 rake (>= 0.8.7)
105 rake (>= 0.8.7)
106 rdoc (~> 3.4)
106 rdoc (~> 3.4)
107 thor (>= 0.14.6, < 2.0)
107 thor (>= 0.14.6, < 2.0)
108 rake (10.4.2)
108 rake (10.4.2)
109 rdiscount (2.1.8)
109 rdiscount (2.1.8)
110 rdoc (3.12.2)
110 rdoc (3.12.2)
111 json (~> 1.4)
111 json (~> 1.4)
112 rouge (1.8.0)
112 rouge (1.8.0)
113 rspec-collection_matchers (1.1.2)
113 rspec-collection_matchers (1.1.2)
114 rspec-expectations (>= 2.99.0.beta1)
114 rspec-expectations (>= 2.99.0.beta1)
115 rspec-core (2.99.2)
115 rspec-core (2.99.2)
116 rspec-expectations (2.99.2)
116 rspec-expectations (2.99.2)
117 diff-lcs (>= 1.1.3, < 2.0)
117 diff-lcs (>= 1.1.3, < 2.0)
118 rspec-mocks (2.99.3)
118 rspec-mocks (2.99.3)
119 rspec-rails (2.99.0)
119 rspec-rails (2.99.0)
120 actionpack (>= 3.0)
120 actionpack (>= 3.0)
121 activemodel (>= 3.0)
121 activemodel (>= 3.0)
122 activesupport (>= 3.0)
122 activesupport (>= 3.0)
123 railties (>= 3.0)
123 railties (>= 3.0)
124 rspec-collection_matchers
124 rspec-collection_matchers
125 rspec-core (~> 2.99.0)
125 rspec-core (~> 2.99.0)
126 rspec-expectations (~> 2.99.0)
126 rspec-expectations (~> 2.99.0)
127 rspec-mocks (~> 2.99.0)
127 rspec-mocks (~> 2.99.0)
128 sass (3.4.11)
128 sass (3.4.11)
129 sass-rails (3.2.6)
129 sass-rails (3.2.6)
130 railties (~> 3.2.0)
130 railties (~> 3.2.0)
131 sass (>= 3.1.10)
131 sass (>= 3.1.10)
132 tilt (~> 1.3)
132 tilt (~> 1.3)
133 sprockets (2.2.3)
133 sprockets (2.2.3)
134 hike (~> 1.2)
134 hike (~> 1.2)
135 multi_json (~> 1.0)
135 multi_json (~> 1.0)
136 rack (~> 1.0)
136 rack (~> 1.0)
137 tilt (~> 1.1, != 1.3.0)
137 tilt (~> 1.1, != 1.3.0)
138 test-unit (3.0.9)
138 test-unit (3.0.9)
139 power_assert
139 power_assert
140 thor (0.19.1)
140 thor (0.19.1)
141 tilt (1.4.1)
141 tilt (1.4.1)
142 treetop (1.4.15)
142 treetop (1.4.15)
143 polyglot
143 polyglot
144 polyglot (>= 0.3.1)
144 polyglot (>= 0.3.1)
145 tzinfo (0.3.43)
145 tzinfo (0.3.43)
146 uglifier (2.7.0)
146 uglifier (2.7.0)
147 execjs (>= 0.3.0)
147 execjs (>= 0.3.0)
148 json (>= 1.8.0)
148 json (>= 1.8.0)
149 will_paginate (3.0.7)
149 will_paginate (3.0.7)
150
150
151 PLATFORMS
151 PLATFORMS
152 ruby
152 ruby
153
153
154 DEPENDENCIES
154 DEPENDENCIES
155 best_in_place (~> 3.0.1)
155 best_in_place (~> 3.0.1)
156 coffee-rails (~> 3.2.2)
156 coffee-rails (~> 3.2.2)
157 dynamic_form
157 dynamic_form
158 haml
158 haml
159 in_place_editing
159 in_place_editing
160 jquery-rails
160 jquery-rails
161 jquery-tablesorter
161 jquery-tablesorter
162 jquery-timepicker-addon-rails
162 jquery-timepicker-addon-rails
163 jquery-ui-sass-rails
163 jquery-ui-sass-rails
164 mail
164 mail
165 mysql2
165 mysql2
166 prototype-rails
166 prototype-rails
167 rails (= 3.2.21)
167 rails (= 3.2.21)
168 rdiscount
168 rdiscount
169 rouge
169 rouge
170 rspec-rails (~> 2.99.0)
170 rspec-rails (~> 2.99.0)
171 sass-rails (~> 3.2.6)
171 sass-rails (~> 3.2.6)
172 test-unit
172 test-unit
173 uglifier
173 uglifier
174 verification!
174 verification!
175 will_paginate (~> 3.0.7)
175 will_paginate (~> 3.0.7)
@@ -1,29 +1,29
1 class ConfigurationsController < ApplicationController
1 class ConfigurationsController < ApplicationController
2
2
3 before_filter :authenticate
3 before_filter :authenticate
4 before_filter { |controller| controller.authorization_by_roles(['admin'])}
4 before_filter { |controller| controller.authorization_by_roles(['admin'])}
5
5
6
6
7 def index
7 def index
8 @configurations = GraderConfiguration.find(:all,
8 @configurations = GraderConfiguration.find(:all,
9 :order => '`key`')
9 :order => '`key`')
10 end
10 end
11
11
12 def reload
12 def reload
13 GraderConfiguration.reload
13 GraderConfiguration.reload
14 redirect_to :action => 'index'
14 redirect_to :action => 'index'
15 end
15 end
16
16
17 def update
17 def update
18 @config = GraderConfiguration.find(params[:id])
18 @config = GraderConfiguration.find(params[:id])
19 - User.clear_last_login if @config.key = 'multiple_ip_login' and @config.value == 'true' and params[:grader_configuration][:value] == 'false'
19 + User.clear_last_login if @config.key == GraderConfiguration::MULTIPLE_IP_LOGIN_KEY and @config.value == 'true' and params[:grader_configuration][:value] == 'false'
20 respond_to do |format|
20 respond_to do |format|
21 if @config.update_attributes(params[:grader_configuration])
21 if @config.update_attributes(params[:grader_configuration])
22 format.json { head :ok }
22 format.json { head :ok }
23 else
23 else
24 format.json { respond_with_bip(@config) }
24 format.json { respond_with_bip(@config) }
25 end
25 end
26 end
26 end
27 end
27 end
28
28
29 end
29 end
@@ -1,119 +1,122
1 class GradersController < ApplicationController
1 class GradersController < ApplicationController
2
2
3 before_filter :admin_authorization, except: [ :submission ]
3 before_filter :admin_authorization, except: [ :submission ]
4 before_filter(only: [:submission]) {
4 before_filter(only: [:submission]) {
5 return false unless authenticate
5 return false unless authenticate
6
6
7 if GraderConfiguration["right.user_view_submission"]
7 if GraderConfiguration["right.user_view_submission"]
8 return true;
8 return true;
9 end
9 end
10
10
11 admin_authorization
11 admin_authorization
12 }
12 }
13
13
14 verify :method => :post, :only => ['clear_all',
14 verify :method => :post, :only => ['clear_all',
15 'start_exam',
15 'start_exam',
16 'start_grading',
16 'start_grading',
17 'stop_all',
17 'stop_all',
18 'clear_terminated'],
18 'clear_terminated'],
19 :redirect_to => {:action => 'index'}
19 :redirect_to => {:action => 'index'}
20
20
21 def index
21 def index
22 redirect_to :action => 'list'
22 redirect_to :action => 'list'
23 end
23 end
24
24
25 def list
25 def list
26 @grader_processes = GraderProcess.find_running_graders
26 @grader_processes = GraderProcess.find_running_graders
27 @stalled_processes = GraderProcess.find_stalled_process
27 @stalled_processes = GraderProcess.find_stalled_process
28
28
29 @terminated_processes = GraderProcess.find_terminated_graders
29 @terminated_processes = GraderProcess.find_terminated_graders
30
30
31 @last_task = Task.find(:first,
31 @last_task = Task.find(:first,
32 :order => 'created_at DESC')
32 :order => 'created_at DESC')
33 @last_test_request = TestRequest.find(:first,
33 @last_test_request = TestRequest.find(:first,
34 :order => 'created_at DESC')
34 :order => 'created_at DESC')
35 @submission = Submission.order("id desc").limit(20)
35 @submission = Submission.order("id desc").limit(20)
36 end
36 end
37
37
38 def clear
38 def clear
39 grader_proc = GraderProcess.find(params[:id])
39 grader_proc = GraderProcess.find(params[:id])
40 grader_proc.destroy if grader_proc!=nil
40 grader_proc.destroy if grader_proc!=nil
41 redirect_to :action => 'list'
41 redirect_to :action => 'list'
42 end
42 end
43
43
44 def clear_terminated
44 def clear_terminated
45 GraderProcess.find_terminated_graders.each do |p|
45 GraderProcess.find_terminated_graders.each do |p|
46 p.destroy
46 p.destroy
47 end
47 end
48 redirect_to :action => 'list'
48 redirect_to :action => 'list'
49 end
49 end
50
50
51 def clear_all
51 def clear_all
52 GraderProcess.find(:all).each do |p|
52 GraderProcess.find(:all).each do |p|
53 p.destroy
53 p.destroy
54 end
54 end
55 redirect_to :action => 'list'
55 redirect_to :action => 'list'
56 end
56 end
57
57
58 def view
58 def view
59 if params[:type]=='Task'
59 if params[:type]=='Task'
60 redirect_to :action => 'task', :id => params[:id]
60 redirect_to :action => 'task', :id => params[:id]
61 else
61 else
62 redirect_to :action => 'test_request', :id => params[:id]
62 redirect_to :action => 'test_request', :id => params[:id]
63 end
63 end
64 end
64 end
65
65
66 def test_request
66 def test_request
67 @test_request = TestRequest.find(params[:id])
67 @test_request = TestRequest.find(params[:id])
68 end
68 end
69
69
70 def task
70 def task
71 @task = Task.find(params[:id])
71 @task = Task.find(params[:id])
72 end
72 end
73
73
74 def submission
74 def submission
75 @submission = Submission.find(params[:id])
75 @submission = Submission.find(params[:id])
76 formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true )
76 formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true )
77 lexer = case @submission.language.name
77 lexer = case @submission.language.name
78 when "c" then Rouge::Lexers::C.new
78 when "c" then Rouge::Lexers::C.new
79 when "cpp" then Rouge::Lexers::Cpp.new
79 when "cpp" then Rouge::Lexers::Cpp.new
80 when "pas" then Rouge::Lexers::Pas.new
80 when "pas" then Rouge::Lexers::Pas.new
81 when "ruby" then Rouge::Lexers::Ruby.new
81 when "ruby" then Rouge::Lexers::Ruby.new
82 when "python" then Rouge::Lexers::Python.new
82 when "python" then Rouge::Lexers::Python.new
83 when "java" then Rouge::Lexers::Java.new
83 when "java" then Rouge::Lexers::Java.new
84 when "php" then Rouge::Lexers::PHP.new
84 when "php" then Rouge::Lexers::PHP.new
85 end
85 end
86 @formatted_code = formatter.format(lexer.lex(@submission.source))
86 @formatted_code = formatter.format(lexer.lex(@submission.source))
87 @css_style = Rouge::Themes::ThankfulEyes.render(scope: '.highlight')
87 @css_style = Rouge::Themes::ThankfulEyes.render(scope: '.highlight')
88
88
89 + user = User.find(session[:user_id])
90 + SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
91 +
89 end
92 end
90
93
91 # various grader controls
94 # various grader controls
92
95
93 def stop
96 def stop
94 grader_proc = GraderProcess.find(params[:id])
97 grader_proc = GraderProcess.find(params[:id])
95 GraderScript.stop_grader(grader_proc.pid)
98 GraderScript.stop_grader(grader_proc.pid)
96 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
99 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
97 redirect_to :action => 'list'
100 redirect_to :action => 'list'
98 end
101 end
99
102
100 def stop_all
103 def stop_all
101 GraderScript.stop_graders(GraderProcess.find_running_graders +
104 GraderScript.stop_graders(GraderProcess.find_running_graders +
102 GraderProcess.find_stalled_process)
105 GraderProcess.find_stalled_process)
103 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
106 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
104 redirect_to :action => 'list'
107 redirect_to :action => 'list'
105 end
108 end
106
109
107 def start_grading
110 def start_grading
108 GraderScript.start_grader('grading')
111 GraderScript.start_grader('grading')
109 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
112 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
110 redirect_to :action => 'list'
113 redirect_to :action => 'list'
111 end
114 end
112
115
113 def start_exam
116 def start_exam
114 GraderScript.start_grader('exam')
117 GraderScript.start_grader('exam')
115 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
118 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
116 redirect_to :action => 'list'
119 redirect_to :action => 'list'
117 end
120 end
118
121
119 end
122 end
@@ -70,193 +70,193
70
70
71 def edit
71 def edit
72 @problem = Problem.find(params[:id])
72 @problem = Problem.find(params[:id])
73 @description = @problem.description
73 @description = @problem.description
74 end
74 end
75
75
76 def update
76 def update
77 @problem = Problem.find(params[:id])
77 @problem = Problem.find(params[:id])
78 @description = @problem.description
78 @description = @problem.description
79 if @description == nil and params[:description][:body]!=''
79 if @description == nil and params[:description][:body]!=''
80 @description = Description.new(params[:description])
80 @description = Description.new(params[:description])
81 if !@description.save
81 if !@description.save
82 flash[:notice] = 'Error saving description'
82 flash[:notice] = 'Error saving description'
83 render :action => 'edit' and return
83 render :action => 'edit' and return
84 end
84 end
85 @problem.description = @description
85 @problem.description = @description
86 elsif @description!=nil
86 elsif @description!=nil
87 if !@description.update_attributes(params[:description])
87 if !@description.update_attributes(params[:description])
88 flash[:notice] = 'Error saving description'
88 flash[:notice] = 'Error saving description'
89 render :action => 'edit' and return
89 render :action => 'edit' and return
90 end
90 end
91 end
91 end
92 if params[:file] and params[:file].content_type != 'application/pdf'
92 if params[:file] and params[:file].content_type != 'application/pdf'
93 flash[:notice] = 'Error: Uploaded file is not PDF'
93 flash[:notice] = 'Error: Uploaded file is not PDF'
94 render :action => 'edit' and return
94 render :action => 'edit' and return
95 end
95 end
96 if @problem.update_attributes(params[:problem])
96 if @problem.update_attributes(params[:problem])
97 flash[:notice] = 'Problem was successfully updated.'
97 flash[:notice] = 'Problem was successfully updated.'
98 unless params[:file] == nil or params[:file] == ''
98 unless params[:file] == nil or params[:file] == ''
99 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
99 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
100 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
100 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
101 if not FileTest.exists? out_dirname
101 if not FileTest.exists? out_dirname
102 Dir.mkdir out_dirname
102 Dir.mkdir out_dirname
103 end
103 end
104
104
105 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
105 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
106 if FileTest.exists? out_filename
106 if FileTest.exists? out_filename
107 File.delete out_filename
107 File.delete out_filename
108 end
108 end
109
109
110 File.open(out_filename,"wb") do |file|
110 File.open(out_filename,"wb") do |file|
111 file.write(params[:file].read)
111 file.write(params[:file].read)
112 end
112 end
113 @problem.description_filename = "#{@problem.name}.pdf"
113 @problem.description_filename = "#{@problem.name}.pdf"
114 @problem.save
114 @problem.save
115 end
115 end
116 redirect_to :action => 'show', :id => @problem
116 redirect_to :action => 'show', :id => @problem
117 else
117 else
118 render :action => 'edit'
118 render :action => 'edit'
119 end
119 end
120 end
120 end
121
121
122 def destroy
122 def destroy
123 Problem.find(params[:id]).destroy
123 Problem.find(params[:id]).destroy
124 redirect_to :action => 'list'
124 redirect_to :action => 'list'
125 end
125 end
126
126
127 def toggle
127 def toggle
128 @problem = Problem.find(params[:id])
128 @problem = Problem.find(params[:id])
129 @problem.available = !(@problem.available)
129 @problem.available = !(@problem.available)
130 @problem.save
130 @problem.save
131 end
131 end
132
132
133 def turn_all_off
133 def turn_all_off
134 Problem.find(:all,
134 Problem.find(:all,
135 :conditions => "available = 1").each do |problem|
135 :conditions => "available = 1").each do |problem|
136 problem.available = false
136 problem.available = false
137 problem.save
137 problem.save
138 end
138 end
139 redirect_to :action => 'list'
139 redirect_to :action => 'list'
140 end
140 end
141
141
142 def turn_all_on
142 def turn_all_on
143 Problem.find(:all,
143 Problem.find(:all,
144 :conditions => "available = 0").each do |problem|
144 :conditions => "available = 0").each do |problem|
145 problem.available = true
145 problem.available = true
146 problem.save
146 problem.save
147 end
147 end
148 redirect_to :action => 'list'
148 redirect_to :action => 'list'
149 end
149 end
150
150
151 def stat
151 def stat
152 @problem = Problem.find(params[:id])
152 @problem = Problem.find(params[:id])
153 unless @problem.available or session[:admin]
153 unless @problem.available or session[:admin]
154 redirect_to :controller => 'main', :action => 'list'
154 redirect_to :controller => 'main', :action => 'list'
155 return
155 return
156 end
156 end
157 @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
157 @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
158
158
159 #stat summary
159 #stat summary
160 range =65
160 range =65
161 @histogram = { data: Array.new(range,0), summary: {} }
161 @histogram = { data: Array.new(range,0), summary: {} }
162 user = Hash.new(0)
162 user = Hash.new(0)
163 @submissions.find_each do |sub|
163 @submissions.find_each do |sub|
164 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
164 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
165 @histogram[:data][d.to_i] += 1 if d < range
165 @histogram[:data][d.to_i] += 1 if d < range
166 - user[sub.user_id] = [user[sub.user_id], (sub.try(:points) >= @problem.full_score) ? 1 : 0].max
166 + user[sub.user_id] = [user[sub.user_id], ((sub.try(:points) || 0) >= @problem.full_score) ? 1 : 0].max
167 end
167 end
168 @histogram[:summary][:max] = [@histogram[:data].max,1].max
168 @histogram[:summary][:max] = [@histogram[:data].max,1].max
169
169
170 @summary = { attempt: user.count, solve: 0 }
170 @summary = { attempt: user.count, solve: 0 }
171 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
171 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
172 end
172 end
173
173
174 def manage
174 def manage
175 @problems = Problem.find(:all, :order => 'date_added DESC')
175 @problems = Problem.find(:all, :order => 'date_added DESC')
176 end
176 end
177
177
178 def do_manage
178 def do_manage
179 if params.has_key? 'change_date_added'
179 if params.has_key? 'change_date_added'
180 change_date_added
180 change_date_added
181 elsif params.has_key? 'add_to_contest'
181 elsif params.has_key? 'add_to_contest'
182 add_to_contest
182 add_to_contest
183 elsif params.has_key? 'enable_problem'
183 elsif params.has_key? 'enable_problem'
184 set_available(true)
184 set_available(true)
185 elsif params.has_key? 'disable_problem'
185 elsif params.has_key? 'disable_problem'
186 set_available(false)
186 set_available(false)
187 end
187 end
188 redirect_to :action => 'manage'
188 redirect_to :action => 'manage'
189 end
189 end
190
190
191 def import
191 def import
192 @allow_test_pair_import = allow_test_pair_import?
192 @allow_test_pair_import = allow_test_pair_import?
193 end
193 end
194
194
195 def do_import
195 def do_import
196 old_problem = Problem.find_by_name(params[:name])
196 old_problem = Problem.find_by_name(params[:name])
197 if !allow_test_pair_import? and params.has_key? :import_to_db
197 if !allow_test_pair_import? and params.has_key? :import_to_db
198 params.delete :import_to_db
198 params.delete :import_to_db
199 end
199 end
200 @problem, import_log = Problem.create_from_import_form_params(params,
200 @problem, import_log = Problem.create_from_import_form_params(params,
201 old_problem)
201 old_problem)
202
202
203 if !@problem.errors.empty?
203 if !@problem.errors.empty?
204 render :action => 'import' and return
204 render :action => 'import' and return
205 end
205 end
206
206
207 if old_problem!=nil
207 if old_problem!=nil
208 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
208 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
209 end
209 end
210 @log = import_log
210 @log = import_log
211 end
211 end
212
212
213 def remove_contest
213 def remove_contest
214 problem = Problem.find(params[:id])
214 problem = Problem.find(params[:id])
215 contest = Contest.find(params[:contest_id])
215 contest = Contest.find(params[:contest_id])
216 if problem!=nil and contest!=nil
216 if problem!=nil and contest!=nil
217 problem.contests.delete(contest)
217 problem.contests.delete(contest)
218 end
218 end
219 redirect_to :action => 'manage'
219 redirect_to :action => 'manage'
220 end
220 end
221
221
222 ##################################
222 ##################################
223 protected
223 protected
224
224
225 def allow_test_pair_import?
225 def allow_test_pair_import?
226 if defined? ALLOW_TEST_PAIR_IMPORT
226 if defined? ALLOW_TEST_PAIR_IMPORT
227 return ALLOW_TEST_PAIR_IMPORT
227 return ALLOW_TEST_PAIR_IMPORT
228 else
228 else
229 return false
229 return false
230 end
230 end
231 end
231 end
232
232
233 def change_date_added
233 def change_date_added
234 problems = get_problems_from_params
234 problems = get_problems_from_params
235 year = params[:date_added][:year].to_i
235 year = params[:date_added][:year].to_i
236 month = params[:date_added][:month].to_i
236 month = params[:date_added][:month].to_i
237 day = params[:date_added][:day].to_i
237 day = params[:date_added][:day].to_i
238 date = Date.new(year,month,day)
238 date = Date.new(year,month,day)
239 problems.each do |p|
239 problems.each do |p|
240 p.date_added = date
240 p.date_added = date
241 p.save
241 p.save
242 end
242 end
243 end
243 end
244
244
245 def add_to_contest
245 def add_to_contest
246 problems = get_problems_from_params
246 problems = get_problems_from_params
247 contest = Contest.find(params[:contest][:id])
247 contest = Contest.find(params[:contest][:id])
248 if contest!=nil and contest.enabled
248 if contest!=nil and contest.enabled
249 problems.each do |p|
249 problems.each do |p|
250 p.contests << contest
250 p.contests << contest
251 end
251 end
252 end
252 end
253 end
253 end
254
254
255 def set_available(avail)
255 def set_available(avail)
256 problems = get_problems_from_params
256 problems = get_problems_from_params
257 problems.each do |p|
257 problems.each do |p|
258 p.available = avail
258 p.available = avail
259 p.save
259 p.save
260 end
260 end
261 end
261 end
262
262
@@ -32,164 +32,164
32
32
33 def chg_passwd
33 def chg_passwd
34 user = User.find(session[:user_id])
34 user = User.find(session[:user_id])
35 user.password = params[:passwd]
35 user.password = params[:passwd]
36 user.password_confirmation = params[:passwd_verify]
36 user.password_confirmation = params[:passwd_verify]
37 if user.save
37 if user.save
38 flash[:notice] = 'password changed'
38 flash[:notice] = 'password changed'
39 else
39 else
40 flash[:notice] = 'Error: password changing failed'
40 flash[:notice] = 'Error: password changing failed'
41 end
41 end
42 redirect_to :action => 'index'
42 redirect_to :action => 'index'
43 end
43 end
44
44
45 def new
45 def new
46 @user = User.new
46 @user = User.new
47 render :action => 'new', :layout => 'empty'
47 render :action => 'new', :layout => 'empty'
48 end
48 end
49
49
50 def register
50 def register
51 if(params[:cancel])
51 if(params[:cancel])
52 redirect_to :controller => 'main', :action => 'login'
52 redirect_to :controller => 'main', :action => 'login'
53 return
53 return
54 end
54 end
55 @user = User.new(params[:user])
55 @user = User.new(params[:user])
56 @user.password_confirmation = @user.password = User.random_password
56 @user.password_confirmation = @user.password = User.random_password
57 @user.activated = false
57 @user.activated = false
58 if (@user.valid?) and (@user.save)
58 if (@user.valid?) and (@user.save)
59 if send_confirmation_email(@user)
59 if send_confirmation_email(@user)
60 render :action => 'new_splash', :layout => 'empty'
60 render :action => 'new_splash', :layout => 'empty'
61 else
61 else
62 @admin_email = GraderConfiguration['system.admin_email']
62 @admin_email = GraderConfiguration['system.admin_email']
63 render :action => 'email_error', :layout => 'empty'
63 render :action => 'email_error', :layout => 'empty'
64 end
64 end
65 else
65 else
66 @user.errors.add(:base,"Email cannot be blank") if @user.email==''
66 @user.errors.add(:base,"Email cannot be blank") if @user.email==''
67 render :action => 'new', :layout => 'empty'
67 render :action => 'new', :layout => 'empty'
68 end
68 end
69 end
69 end
70
70
71 def confirm
71 def confirm
72 login = params[:login]
72 login = params[:login]
73 key = params[:activation]
73 key = params[:activation]
74 @user = User.find_by_login(login)
74 @user = User.find_by_login(login)
75 if (@user) and (@user.verify_activation_key(key))
75 if (@user) and (@user.verify_activation_key(key))
76 if @user.valid? # check uniquenss of email
76 if @user.valid? # check uniquenss of email
77 @user.activated = true
77 @user.activated = true
78 @user.save
78 @user.save
79 @result = :successful
79 @result = :successful
80 else
80 else
81 @result = :email_used
81 @result = :email_used
82 end
82 end
83 else
83 else
84 @result = :failed
84 @result = :failed
85 end
85 end
86 render :action => 'confirm', :layout => 'empty'
86 render :action => 'confirm', :layout => 'empty'
87 end
87 end
88
88
89 def forget
89 def forget
90 render :action => 'forget', :layout => 'empty'
90 render :action => 'forget', :layout => 'empty'
91 end
91 end
92
92
93 def retrieve_password
93 def retrieve_password
94 email = params[:email]
94 email = params[:email]
95 user = User.find_by_email(email)
95 user = User.find_by_email(email)
96 if user
96 if user
97 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
97 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
98 if last_updated_time > Time.now.gmtime - 5.minutes
98 if last_updated_time > Time.now.gmtime - 5.minutes
99 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
99 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
100 else
100 else
101 user.password = user.password_confirmation = User.random_password
101 user.password = user.password_confirmation = User.random_password
102 user.save
102 user.save
103 send_new_password_email(user)
103 send_new_password_email(user)
104 flash[:notice] = 'New password has been mailed to you.'
104 flash[:notice] = 'New password has been mailed to you.'
105 end
105 end
106 else
106 else
107 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
107 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
108 end
108 end
109 redirect_to :action => 'forget'
109 redirect_to :action => 'forget'
110 end
110 end
111
111
112 def profile
112 def profile
113 @user = User.find(params[:id])
113 @user = User.find(params[:id])
114 @submission = Submission.includes(:problem).where(user_id: params[:id])
114 @submission = Submission.includes(:problem).where(user_id: params[:id])
115
115
116 range = 120
116 range = 120
117 @histogram = { data: Array.new(range,0), summary: {} }
117 @histogram = { data: Array.new(range,0), summary: {} }
118 @summary = {count: 0, solve: 0, attempt: 0}
118 @summary = {count: 0, solve: 0, attempt: 0}
119 problem = Hash.new(0)
119 problem = Hash.new(0)
120
120
121 @submission.find_each do |sub|
121 @submission.find_each do |sub|
122 #histogram
122 #histogram
123 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
123 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
124 @histogram[:data][d.to_i] += 1 if d < range
124 @histogram[:data][d.to_i] += 1 if d < range
125
125
126 @summary[:count] += 1
126 @summary[:count] += 1
127 next unless sub.problem
127 next unless sub.problem
128 - problem[sub.problem] = [problem[sub.problem], (sub.points >= sub.problem.full_score) ? 1 : 0].max
128 + problem[sub.problem] = [problem[sub.problem], ( (sub.try(:points) || 0) >= sub.problem.full_score) ? 1 : 0].max
129 end
129 end
130
130
131 @histogram[:summary][:max] = [@histogram[:data].max,1].max
131 @histogram[:summary][:max] = [@histogram[:data].max,1].max
132 @summary[:attempt] = problem.count
132 @summary[:attempt] = problem.count
133 problem.each_value { |v| @summary[:solve] += 1 if v == 1 }
133 problem.each_value { |v| @summary[:solve] += 1 if v == 1 }
134 end
134 end
135
135
136 protected
136 protected
137
137
138 def verify_online_registration
138 def verify_online_registration
139 if !GraderConfiguration['system.online_registration']
139 if !GraderConfiguration['system.online_registration']
140 redirect_to :controller => 'main', :action => 'login'
140 redirect_to :controller => 'main', :action => 'login'
141 end
141 end
142 end
142 end
143
143
144 def send_confirmation_email(user)
144 def send_confirmation_email(user)
145 contest_name = GraderConfiguration['contest.name']
145 contest_name = GraderConfiguration['contest.name']
146 activation_url = url_for(:action => 'confirm',
146 activation_url = url_for(:action => 'confirm',
147 :login => user.login,
147 :login => user.login,
148 :activation => user.activation_key)
148 :activation => user.activation_key)
149 home_url = url_for(:controller => 'main', :action => 'index')
149 home_url = url_for(:controller => 'main', :action => 'index')
150 mail_subject = "[#{contest_name}] Confirmation"
150 mail_subject = "[#{contest_name}] Confirmation"
151 mail_body = t('registration.email_body', {
151 mail_body = t('registration.email_body', {
152 :full_name => user.full_name,
152 :full_name => user.full_name,
153 :contest_name => contest_name,
153 :contest_name => contest_name,
154 :login => user.login,
154 :login => user.login,
155 :password => user.password,
155 :password => user.password,
156 :activation_url => activation_url,
156 :activation_url => activation_url,
157 :admin_email => GraderConfiguration['system.admin_email']
157 :admin_email => GraderConfiguration['system.admin_email']
158 })
158 })
159
159
160 logger.info mail_body
160 logger.info mail_body
161
161
162 send_mail(user.email, mail_subject, mail_body)
162 send_mail(user.email, mail_subject, mail_body)
163 end
163 end
164
164
165 def send_new_password_email(user)
165 def send_new_password_email(user)
166 contest_name = GraderConfiguration['contest.name']
166 contest_name = GraderConfiguration['contest.name']
167 mail_subject = "[#{contest_name}] Password recovery"
167 mail_subject = "[#{contest_name}] Password recovery"
168 mail_body = t('registration.password_retrieval.email_body', {
168 mail_body = t('registration.password_retrieval.email_body', {
169 :full_name => user.full_name,
169 :full_name => user.full_name,
170 :contest_name => contest_name,
170 :contest_name => contest_name,
171 :login => user.login,
171 :login => user.login,
172 :password => user.password,
172 :password => user.password,
173 :admin_email => GraderConfiguration['system.admin_email']
173 :admin_email => GraderConfiguration['system.admin_email']
174 })
174 })
175
175
176 logger.info mail_body
176 logger.info mail_body
177
177
178 send_mail(user.email, mail_subject, mail_body)
178 send_mail(user.email, mail_subject, mail_body)
179 end
179 end
180
180
181 # allow viewing of regular user profile only when options allow so
181 # allow viewing of regular user profile only when options allow so
182 # only admins can view admins profile
182 # only admins can view admins profile
183 def profile_authorization
183 def profile_authorization
184 #if view admins' profile, allow only admin
184 #if view admins' profile, allow only admin
185 return false unless(params[:id])
185 return false unless(params[:id])
186 user = User.find(params[:id])
186 user = User.find(params[:id])
187 return false unless user
187 return false unless user
188 return admin_authorization if user.admin?
188 return admin_authorization if user.admin?
189 return true if GraderConfiguration["right.user_view_submission"]
189 return true if GraderConfiguration["right.user_view_submission"]
190
190
191 #finally, we allow only admin
191 #finally, we allow only admin
192 admin_authorization
192 admin_authorization
193 end
193 end
194
194
195 end
195 end
@@ -1,107 +1,108
1 require 'yaml'
1 require 'yaml'
2
2
3 #
3 #
4 # This class also contains various login of the system.
4 # This class also contains various login of the system.
5 #
5 #
6 class GraderConfiguration < ActiveRecord::Base
6 class GraderConfiguration < ActiveRecord::Base
7
7
8 SYSTEM_MODE_CONF_KEY = 'system.mode'
8 SYSTEM_MODE_CONF_KEY = 'system.mode'
9 TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout'
9 TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout'
10 MULTICONTESTS_KEY = 'system.multicontests'
10 MULTICONTESTS_KEY = 'system.multicontests'
11 CONTEST_TIME_LIMIT_KEY = 'contest.time_limit'
11 CONTEST_TIME_LIMIT_KEY = 'contest.time_limit'
12 + MULTIPLE_IP_LOGIN_KEY = 'right.multiple_ip_login'
12
13
13 cattr_accessor :config_cache
14 cattr_accessor :config_cache
14 cattr_accessor :task_grading_info_cache
15 cattr_accessor :task_grading_info_cache
15 cattr_accessor :contest_time_str
16 cattr_accessor :contest_time_str
16 cattr_accessor :contest_time
17 cattr_accessor :contest_time
17
18
18 GraderConfiguration.config_cache = nil
19 GraderConfiguration.config_cache = nil
19 GraderConfiguration.task_grading_info_cache = nil
20 GraderConfiguration.task_grading_info_cache = nil
20
21
21 def self.config_cached?
22 def self.config_cached?
22 (defined? CONFIGURATION_CACHE_ENABLED) and (CONFIGURATION_CACHE_ENABLED)
23 (defined? CONFIGURATION_CACHE_ENABLED) and (CONFIGURATION_CACHE_ENABLED)
23 end
24 end
24
25
25 def self.get(key)
26 def self.get(key)
26 if GraderConfiguration.config_cached?
27 if GraderConfiguration.config_cached?
27 if GraderConfiguration.config_cache == nil
28 if GraderConfiguration.config_cache == nil
28 self.read_config
29 self.read_config
29 end
30 end
30 return GraderConfiguration.config_cache[key]
31 return GraderConfiguration.config_cache[key]
31 else
32 else
32 return GraderConfiguration.read_one_key(key)
33 return GraderConfiguration.read_one_key(key)
33 end
34 end
34 end
35 end
35
36
36 def self.[](key)
37 def self.[](key)
37 self.get(key)
38 self.get(key)
38 end
39 end
39
40
40 def self.reload
41 def self.reload
41 self.read_config
42 self.read_config
42 end
43 end
43
44
44 def self.clear
45 def self.clear
45 GraderConfiguration.config_cache = nil
46 GraderConfiguration.config_cache = nil
46 end
47 end
47
48
48 #
49 #
49 # View decision
50 # View decision
50 #
51 #
51 def self.show_submitbox_to?(user)
52 def self.show_submitbox_to?(user)
52 mode = get(SYSTEM_MODE_CONF_KEY)
53 mode = get(SYSTEM_MODE_CONF_KEY)
53 return false if mode=='analysis'
54 return false if mode=='analysis'
54 if (mode=='contest')
55 if (mode=='contest')
55 return false if (user.site!=nil) and
56 return false if (user.site!=nil) and
56 ((user.site.started!=true) or (user.site.finished?))
57 ((user.site.started!=true) or (user.site.finished?))
57 end
58 end
58 return true
59 return true
59 end
60 end
60
61
61 def self.show_tasks_to?(user)
62 def self.show_tasks_to?(user)
62 if time_limit_mode?
63 if time_limit_mode?
63 return false if not user.contest_started?
64 return false if not user.contest_started?
64 end
65 end
65 return true
66 return true
66 end
67 end
67
68
68 def self.show_grading_result
69 def self.show_grading_result
69 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
70 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
70 end
71 end
71
72
72 def self.allow_test_request(user)
73 def self.allow_test_request(user)
73 mode = get(SYSTEM_MODE_CONF_KEY)
74 mode = get(SYSTEM_MODE_CONF_KEY)
74 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
75 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
75 if (mode=='contest')
76 if (mode=='contest')
76 return false if ((user.site!=nil) and
77 return false if ((user.site!=nil) and
77 ((user.site.started!=true) or
78 ((user.site.started!=true) or
78 (early_timeout and (user.site.time_left < 30.minutes))))
79 (early_timeout and (user.site.time_left < 30.minutes))))
79 end
80 end
80 return false if mode=='analysis'
81 return false if mode=='analysis'
81 return true
82 return true
82 end
83 end
83
84
84 def self.task_grading_info
85 def self.task_grading_info
85 if GraderConfiguration.task_grading_info_cache==nil
86 if GraderConfiguration.task_grading_info_cache==nil
86 read_grading_info
87 read_grading_info
87 end
88 end
88 return GraderConfiguration.task_grading_info_cache
89 return GraderConfiguration.task_grading_info_cache
89 end
90 end
90
91
91 def self.standard_mode?
92 def self.standard_mode?
92 return get(SYSTEM_MODE_CONF_KEY) == 'standard'
93 return get(SYSTEM_MODE_CONF_KEY) == 'standard'
93 end
94 end
94
95
95 def self.contest_mode?
96 def self.contest_mode?
96 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
97 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
97 end
98 end
98
99
99 def self.indv_contest_mode?
100 def self.indv_contest_mode?
100 return get(SYSTEM_MODE_CONF_KEY) == 'indv-contest'
101 return get(SYSTEM_MODE_CONF_KEY) == 'indv-contest'
101 end
102 end
102
103
103 def self.multicontests?
104 def self.multicontests?
104 return get(MULTICONTESTS_KEY) == true
105 return get(MULTICONTESTS_KEY) == true
105 end
106 end
106
107
107 def self.time_limit_mode?
108 def self.time_limit_mode?
@@ -1,66 +1,66
1 - content_for :header do
1 - content_for :header do
2 = javascript_include_tag 'local_jquery'
2 = javascript_include_tag 'local_jquery'
3
3
4 :javascript
4 :javascript
5 $(function () {
5 $(function () {
6 $('#submission_table').tablesorter({widgets: ['zebra']});
6 $('#submission_table').tablesorter({widgets: ['zebra']});
7 });
7 });
8
8
9 :css
9 :css
10 .fix-width {
10 .fix-width {
11 font-family: Droid Sans Mono,Consolas, monospace, mono, Courier New, Courier;
11 font-family: Droid Sans Mono,Consolas, monospace, mono, Courier New, Courier;
12 }
12 }
13
13
14 %h1= @user.full_name
14 %h1= @user.full_name
15
15
16 <b>Login:</b> #{@user.login} <br/>
16 <b>Login:</b> #{@user.login} <br/>
17 <b>Full name:</b> #{@user.full_name} <br />
17 <b>Full name:</b> #{@user.full_name} <br />
18
18
19
19
20 %h2 Problem Stat
20 %h2 Problem Stat
21 %table.info
21 %table.info
22 %thead
22 %thead
23 %tr.info-head
23 %tr.info-head
24 %th Stat
24 %th Stat
25 %th Value
25 %th Value
26 %tbody
26 %tbody
27 %tr{class: cycle('info-even','info-odd')}
27 %tr{class: cycle('info-even','info-odd')}
28 %td.info_param Submissions
28 %td.info_param Submissions
29 %td= @summary[:count]
29 %td= @summary[:count]
30 %tr{class: cycle('info-even','info-odd')}
30 %tr{class: cycle('info-even','info-odd')}
31 %td.info_param Solved/Attempted Problem
31 %td.info_param Solved/Attempted Problem
32 %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
32 %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
33
33
34 %h2 Submission History
34 %h2 Submission History
35
35
36 =render partial: 'application/bar_graph', locals: {histogram: @histogram, param: {bar_width: 7}}
36 =render partial: 'application/bar_graph', locals: {histogram: @histogram, param: {bar_width: 7}}
37
37
38
38
39 %table.tablesorter-cafe#submission_table
39 %table.tablesorter-cafe#submission_table
40 %thead
40 %thead
41 %tr
41 %tr
42 %th ID
42 %th ID
43 %th Problem code
43 %th Problem code
44 %th Problem full name
44 %th Problem full name
45 %th Language
45 %th Language
46 %th Submitted at
46 %th Submitted at
47 %th Result
47 %th Result
48 %th Score
48 %th Score
49 - if session[:admin]
49 - if session[:admin]
50 %th IP
50 %th IP
51 %tbody
51 %tbody
52 - @submission.each do |s|
52 - @submission.each do |s|
53 - next unless s.problem
53 - next unless s.problem
54 %tr
54 %tr
55 %td= link_to "#{s.id}", controller: "graders", action: "submission", id: s.id
55 %td= link_to "#{s.id}", controller: "graders", action: "submission", id: s.id
56 %td= link_to s.problem.name, controller: "problems", action: "stat", id: s.problem
56 %td= link_to s.problem.name, controller: "problems", action: "stat", id: s.problem
57 %td= s.problem.full_name
57 %td= s.problem.full_name
58 %td= s.language.pretty_name
58 %td= s.language.pretty_name
59 %td #{s.submitted_at.strftime('%Y-%m-%d %H:%M')} (#{time_ago_in_words(s.submitted_at)} ago)
59 %td #{s.submitted_at.strftime('%Y-%m-%d %H:%M')} (#{time_ago_in_words(s.submitted_at)} ago)
60 %td.fix-width= s.grader_comment
60 %td.fix-width= s.grader_comment
61 - %td= (s.points*100)/s.problem.full_score
61 + %td= ( s.try(:points) ? (s.points*100/s.problem.full_score) : '' )
62 - if session[:admin]
62 - if session[:admin]
63 %td= s.ip_address
63 %td= s.ip_address
64
64
65
65
66
66
@@ -1,250 +1,257
1 # encoding: UTF-8
1 # encoding: UTF-8
2 # This file is auto-generated from the current state of the database. Instead
2 # This file is auto-generated from the current state of the database. Instead
3 # of editing this file, please use the migrations feature of Active Record to
3 # of editing this file, please use the migrations feature of Active Record to
4 # incrementally modify your database, and then regenerate this schema definition.
4 # incrementally modify your database, and then regenerate this schema definition.
5 #
5 #
6 # Note that this schema.rb definition is the authoritative source for your
6 # Note that this schema.rb definition is the authoritative source for your
7 # database schema. If you need to create the application database on another
7 # database schema. If you need to create the application database on another
8 # system, you should be using db:schema:load, not running all the migrations
8 # system, you should be using db:schema:load, not running all the migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
11 #
11 #
12 # It's strongly recommended to check this file into your version control system.
12 # It's strongly recommended to check this file into your version control system.
13
13
14 - ActiveRecord::Schema.define(:version => 20150618085823) do
14 + ActiveRecord::Schema.define(:version => 20150827133841) do
15
15
16 create_table "announcements", :force => true do |t|
16 create_table "announcements", :force => true do |t|
17 t.string "author"
17 t.string "author"
18 t.text "body", :limit => 16777215
18 t.text "body", :limit => 16777215
19 t.boolean "published"
19 t.boolean "published"
20 t.datetime "created_at", :null => false
20 t.datetime "created_at", :null => false
21 t.datetime "updated_at", :null => false
21 t.datetime "updated_at", :null => false
22 t.boolean "frontpage", :default => false
22 t.boolean "frontpage", :default => false
23 t.boolean "contest_only", :default => false
23 t.boolean "contest_only", :default => false
24 t.string "title"
24 t.string "title"
25 t.string "notes"
25 t.string "notes"
26 end
26 end
27
27
28 create_table "contests", :force => true do |t|
28 create_table "contests", :force => true do |t|
29 t.string "title"
29 t.string "title"
30 t.boolean "enabled"
30 t.boolean "enabled"
31 t.datetime "created_at", :null => false
31 t.datetime "created_at", :null => false
32 t.datetime "updated_at", :null => false
32 t.datetime "updated_at", :null => false
33 t.string "name"
33 t.string "name"
34 end
34 end
35
35
36 create_table "contests_problems", :id => false, :force => true do |t|
36 create_table "contests_problems", :id => false, :force => true do |t|
37 t.integer "contest_id"
37 t.integer "contest_id"
38 t.integer "problem_id"
38 t.integer "problem_id"
39 end
39 end
40
40
41 create_table "contests_users", :id => false, :force => true do |t|
41 create_table "contests_users", :id => false, :force => true do |t|
42 t.integer "contest_id"
42 t.integer "contest_id"
43 t.integer "user_id"
43 t.integer "user_id"
44 end
44 end
45
45
46 create_table "countries", :force => true do |t|
46 create_table "countries", :force => true do |t|
47 t.string "name"
47 t.string "name"
48 t.datetime "created_at", :null => false
48 t.datetime "created_at", :null => false
49 t.datetime "updated_at", :null => false
49 t.datetime "updated_at", :null => false
50 end
50 end
51
51
52 create_table "descriptions", :force => true do |t|
52 create_table "descriptions", :force => true do |t|
53 t.text "body", :limit => 16777215
53 t.text "body", :limit => 16777215
54 t.boolean "markdowned"
54 t.boolean "markdowned"
55 t.datetime "created_at", :null => false
55 t.datetime "created_at", :null => false
56 t.datetime "updated_at", :null => false
56 t.datetime "updated_at", :null => false
57 end
57 end
58
58
59 create_table "grader_configurations", :force => true do |t|
59 create_table "grader_configurations", :force => true do |t|
60 t.string "key"
60 t.string "key"
61 t.string "value_type"
61 t.string "value_type"
62 t.string "value"
62 t.string "value"
63 t.datetime "created_at", :null => false
63 t.datetime "created_at", :null => false
64 t.datetime "updated_at", :null => false
64 t.datetime "updated_at", :null => false
65 t.text "description", :limit => 16777215
65 t.text "description", :limit => 16777215
66 end
66 end
67
67
68 create_table "grader_processes", :force => true do |t|
68 create_table "grader_processes", :force => true do |t|
69 t.string "host", :limit => 20
69 t.string "host", :limit => 20
70 t.integer "pid"
70 t.integer "pid"
71 t.string "mode"
71 t.string "mode"
72 t.boolean "active"
72 t.boolean "active"
73 t.datetime "created_at", :null => false
73 t.datetime "created_at", :null => false
74 t.datetime "updated_at", :null => false
74 t.datetime "updated_at", :null => false
75 t.integer "task_id"
75 t.integer "task_id"
76 t.string "task_type"
76 t.string "task_type"
77 t.boolean "terminated"
77 t.boolean "terminated"
78 end
78 end
79
79
80 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
80 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
81
81
82 create_table "languages", :force => true do |t|
82 create_table "languages", :force => true do |t|
83 t.string "name", :limit => 10
83 t.string "name", :limit => 10
84 t.string "pretty_name"
84 t.string "pretty_name"
85 t.string "ext", :limit => 10
85 t.string "ext", :limit => 10
86 t.string "common_ext"
86 t.string "common_ext"
87 end
87 end
88
88
89 create_table "logins", :force => true do |t|
89 create_table "logins", :force => true do |t|
90 t.integer "user_id"
90 t.integer "user_id"
91 t.string "ip_address"
91 t.string "ip_address"
92 t.datetime "created_at", :null => false
92 t.datetime "created_at", :null => false
93 t.datetime "updated_at", :null => false
93 t.datetime "updated_at", :null => false
94 end
94 end
95
95
96 create_table "messages", :force => true do |t|
96 create_table "messages", :force => true do |t|
97 t.integer "sender_id"
97 t.integer "sender_id"
98 t.integer "receiver_id"
98 t.integer "receiver_id"
99 t.integer "replying_message_id"
99 t.integer "replying_message_id"
100 t.text "body", :limit => 16777215
100 t.text "body", :limit => 16777215
101 t.boolean "replied"
101 t.boolean "replied"
102 t.datetime "created_at", :null => false
102 t.datetime "created_at", :null => false
103 t.datetime "updated_at", :null => false
103 t.datetime "updated_at", :null => false
104 end
104 end
105
105
106 create_table "problems", :force => true do |t|
106 create_table "problems", :force => true do |t|
107 t.string "name", :limit => 30
107 t.string "name", :limit => 30
108 t.string "full_name"
108 t.string "full_name"
109 t.integer "full_score"
109 t.integer "full_score"
110 t.date "date_added"
110 t.date "date_added"
111 t.boolean "available"
111 t.boolean "available"
112 t.string "url"
112 t.string "url"
113 t.integer "description_id"
113 t.integer "description_id"
114 t.boolean "test_allowed"
114 t.boolean "test_allowed"
115 t.boolean "output_only"
115 t.boolean "output_only"
116 t.string "description_filename"
116 t.string "description_filename"
117 end
117 end
118
118
119 create_table "rights", :force => true do |t|
119 create_table "rights", :force => true do |t|
120 t.string "name"
120 t.string "name"
121 t.string "controller"
121 t.string "controller"
122 t.string "action"
122 t.string "action"
123 end
123 end
124
124
125 create_table "rights_roles", :id => false, :force => true do |t|
125 create_table "rights_roles", :id => false, :force => true do |t|
126 t.integer "right_id"
126 t.integer "right_id"
127 t.integer "role_id"
127 t.integer "role_id"
128 end
128 end
129
129
130 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
130 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
131
131
132 create_table "roles", :force => true do |t|
132 create_table "roles", :force => true do |t|
133 t.string "name"
133 t.string "name"
134 end
134 end
135
135
136 create_table "roles_users", :id => false, :force => true do |t|
136 create_table "roles_users", :id => false, :force => true do |t|
137 t.integer "role_id"
137 t.integer "role_id"
138 t.integer "user_id"
138 t.integer "user_id"
139 end
139 end
140
140
141 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
141 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
142
142
143 create_table "sessions", :force => true do |t|
143 create_table "sessions", :force => true do |t|
144 t.string "session_id"
144 t.string "session_id"
145 t.text "data", :limit => 16777215
145 t.text "data", :limit => 16777215
146 t.datetime "updated_at"
146 t.datetime "updated_at"
147 end
147 end
148
148
149 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
149 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
150 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
150 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
151
151
152 create_table "sites", :force => true do |t|
152 create_table "sites", :force => true do |t|
153 t.string "name"
153 t.string "name"
154 t.boolean "started"
154 t.boolean "started"
155 t.datetime "start_time"
155 t.datetime "start_time"
156 t.datetime "created_at", :null => false
156 t.datetime "created_at", :null => false
157 t.datetime "updated_at", :null => false
157 t.datetime "updated_at", :null => false
158 t.integer "country_id"
158 t.integer "country_id"
159 t.string "password"
159 t.string "password"
160 end
160 end
161
161
162 + create_table "submission_view_logs", :force => true do |t|
163 + t.integer "user_id"
164 + t.integer "submission_id"
165 + t.datetime "created_at", :null => false
166 + t.datetime "updated_at", :null => false
167 + end
168 +
162 create_table "submissions", :force => true do |t|
169 create_table "submissions", :force => true do |t|
163 t.integer "user_id"
170 t.integer "user_id"
164 t.integer "problem_id"
171 t.integer "problem_id"
165 t.integer "language_id"
172 t.integer "language_id"
166 t.text "source", :limit => 16777215
173 t.text "source", :limit => 16777215
167 t.binary "binary"
174 t.binary "binary"
168 t.datetime "submitted_at"
175 t.datetime "submitted_at"
169 t.datetime "compiled_at"
176 t.datetime "compiled_at"
170 t.text "compiler_message", :limit => 16777215
177 t.text "compiler_message", :limit => 16777215
171 t.datetime "graded_at"
178 t.datetime "graded_at"
172 t.integer "points"
179 t.integer "points"
173 t.text "grader_comment", :limit => 16777215
180 t.text "grader_comment", :limit => 16777215
174 t.integer "number"
181 t.integer "number"
175 t.string "source_filename"
182 t.string "source_filename"
176 t.float "max_runtime"
183 t.float "max_runtime"
177 t.integer "peak_memory"
184 t.integer "peak_memory"
178 t.integer "effective_code_length"
185 t.integer "effective_code_length"
179 t.string "ip_address"
186 t.string "ip_address"
180 end
187 end
181
188
182 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
189 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
183 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
190 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
184
191
185 create_table "tasks", :force => true do |t|
192 create_table "tasks", :force => true do |t|
186 t.integer "submission_id"
193 t.integer "submission_id"
187 t.datetime "created_at"
194 t.datetime "created_at"
188 t.integer "status"
195 t.integer "status"
189 t.datetime "updated_at"
196 t.datetime "updated_at"
190 end
197 end
191
198
192 create_table "test_pairs", :force => true do |t|
199 create_table "test_pairs", :force => true do |t|
193 t.integer "problem_id"
200 t.integer "problem_id"
194 t.text "input", :limit => 2147483647
201 t.text "input", :limit => 2147483647
195 t.text "solution", :limit => 2147483647
202 t.text "solution", :limit => 2147483647
196 t.datetime "created_at", :null => false
203 t.datetime "created_at", :null => false
197 t.datetime "updated_at", :null => false
204 t.datetime "updated_at", :null => false
198 end
205 end
199
206
200 create_table "test_requests", :force => true do |t|
207 create_table "test_requests", :force => true do |t|
201 t.integer "user_id"
208 t.integer "user_id"
202 t.integer "problem_id"
209 t.integer "problem_id"
203 t.integer "submission_id"
210 t.integer "submission_id"
204 t.string "input_file_name"
211 t.string "input_file_name"
205 t.string "output_file_name"
212 t.string "output_file_name"
206 t.string "running_stat"
213 t.string "running_stat"
207 t.integer "status"
214 t.integer "status"
208 t.datetime "updated_at", :null => false
215 t.datetime "updated_at", :null => false
209 t.datetime "submitted_at"
216 t.datetime "submitted_at"
210 t.datetime "compiled_at"
217 t.datetime "compiled_at"
211 t.text "compiler_message", :limit => 16777215
218 t.text "compiler_message", :limit => 16777215
212 t.datetime "graded_at"
219 t.datetime "graded_at"
213 t.string "grader_comment"
220 t.string "grader_comment"
214 t.datetime "created_at", :null => false
221 t.datetime "created_at", :null => false
215 t.float "running_time"
222 t.float "running_time"
216 t.string "exit_status"
223 t.string "exit_status"
217 t.integer "memory_usage"
224 t.integer "memory_usage"
218 end
225 end
219
226
220 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
227 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
221
228
222 create_table "user_contest_stats", :force => true do |t|
229 create_table "user_contest_stats", :force => true do |t|
223 t.integer "user_id"
230 t.integer "user_id"
224 t.datetime "started_at"
231 t.datetime "started_at"
225 t.datetime "created_at", :null => false
232 t.datetime "created_at", :null => false
226 t.datetime "updated_at", :null => false
233 t.datetime "updated_at", :null => false
227 t.boolean "forced_logout"
234 t.boolean "forced_logout"
228 end
235 end
229
236
230 create_table "users", :force => true do |t|
237 create_table "users", :force => true do |t|
231 t.string "login", :limit => 50
238 t.string "login", :limit => 50
232 t.string "full_name"
239 t.string "full_name"
233 t.string "hashed_password"
240 t.string "hashed_password"
234 t.string "salt", :limit => 5
241 t.string "salt", :limit => 5
235 t.string "alias"
242 t.string "alias"
236 t.string "email"
243 t.string "email"
237 t.integer "site_id"
244 t.integer "site_id"
238 t.integer "country_id"
245 t.integer "country_id"
239 t.boolean "activated", :default => false
246 t.boolean "activated", :default => false
240 t.datetime "created_at"
247 t.datetime "created_at"
241 t.datetime "updated_at"
248 t.datetime "updated_at"
242 t.string "section"
249 t.string "section"
243 t.boolean "enabled", :default => true
250 t.boolean "enabled", :default => true
244 t.string "remark"
251 t.string "remark"
245 t.string "last_ip"
252 t.string "last_ip"
246 end
253 end
247
254
248 add_index "users", ["login"], :name => "index_users_on_login", :unique => true
255 add_index "users", ["login"], :name => "index_users_on_login", :unique => true
249
256
250 end
257 end
You need to be logged in to leave comments. Login now