Description:
live editor using cloud9 ace for problem
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r564:484b31caab29 - - 16 files changed: 121 inserted, 1 deleted

@@ -0,0 +1,10
1 + # Place all the behaviors and hooks related to the matching controller here.
2 + # All this logic will automatically be available in application.js.
3 + # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
4 +
5 +
6 + $ ->
7 + $("#live_submit").on "click", (event) ->
8 + h = $("#editor_text")
9 + e = ace.edit("editor")
10 + h.val(e.getValue())
@@ -0,0 +1,12
1 + // Place all the styles related to the sources controller here.
2 + // They will automatically be included in application.css.
3 + // You can use Sass (SCSS) here: http://sass-lang.com/
4 +
5 + #editor {
6 + position: absolute;
7 + top: 0;
8 + right: 0;
9 + bottom: 0;
10 + left: 0;
11 + }
12 +
@@ -0,0 +1,7
1 + class SourcesController < ApplicationController
2 + before_filter :authenticate, :except => [:index, :login]
3 +
4 + def direct_edit
5 + @problem = Problem.find_by_id(params[:pid])
6 + end
7 + end
@@ -0,0 +1,2
1 + module SourcesHelper
2 + end
@@ -0,0 +1,21
1 + %h1 Live submit
2 + = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form-inline') do
3 + = hidden_field_tag 'editor_text'
4 + = hidden_field_tag 'submission[problem_id]', @problem.id
5 + .form-group
6 + = label_tag "Task:"
7 + = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true
8 +
9 + .form-group
10 + = label_tag 'Language'
11 + = select_tag 'language_id', options_from_collection_for_select(Language.all, 'id', 'pretty_name',"C++"), class: 'form-control', style: "width: 100px"
12 + .form-group
13 + = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit'
14 +
15 + %br
16 +
17 + .container
18 + .row
19 + .col-md-12
20 + %div#editor{style: 'height: 400px'}
21 + Hahaha
@@ -0,0 +1,12
1 + require 'spec_helper'
2 +
3 + describe SourcesController do
4 +
5 + describe "GET 'direct_edit'" do
6 + it "returns http success" do
7 + get 'direct_edit'
8 + response.should be_success
9 + end
10 + end
11 +
12 + end
@@ -0,0 +1,15
1 + require 'spec_helper'
2 +
3 + # Specs in this file have access to a helper object that includes
4 + # the SourcesHelper. For example:
5 + #
6 + # describe SourcesHelper do
7 + # describe "string concat" do
8 + # it "concats two strings with spaces" do
9 + # expect(helper.concat_strings("this","that")).to eq("this that")
10 + # end
11 + # end
12 + # end
13 + describe SourcesHelper do
14 + pending "add some examples to (or delete) #{__FILE__}"
15 + end
@@ -0,0 +1,5
1 + require 'spec_helper'
2 +
3 + describe "sources/direct_edit.html.haml" do
4 + pending "add some examples to (or delete) #{__FILE__}"
5 + end
@@ -1,72 +1,75
1 source 'https://rubygems.org'
1 source 'https://rubygems.org'
2
2
3 gem 'rails', '3.2.21'
3 gem 'rails', '3.2.21'
4
4
5 gem 'select2-rails'
5 gem 'select2-rails'
6
6
7 # Bundle edge Rails instead:
7 # Bundle edge Rails instead:
8 # gem 'rails', :git => 'git://github.com/rails/rails.git'
8 # gem 'rails', :git => 'git://github.com/rails/rails.git'
9
9
10 gem 'mysql2'
10 gem 'mysql2'
11
11
12 # Gems used only for assets and not required
12 # Gems used only for assets and not required
13 # in production environments by default.
13 # in production environments by default.
14 group :assets do
14 group :assets do
15 gem 'sass-rails', '~> 3.2.6'
15 gem 'sass-rails', '~> 3.2.6'
16 gem 'coffee-rails', '~> 3.2.2'
16 gem 'coffee-rails', '~> 3.2.2'
17
17
18 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
18 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
19 # gem 'therubyracer', :platforms => :ruby
19 # gem 'therubyracer', :platforms => :ruby
20
20
21 gem 'uglifier'
21 gem 'uglifier'
22 end
22 end
23
23
24 gem 'prototype-rails'
24 gem 'prototype-rails'
25
25
26 # To use ActiveModel has_secure_password
26 # To use ActiveModel has_secure_password
27 # gem 'bcrypt-ruby', '~> 3.0.0'
27 # gem 'bcrypt-ruby', '~> 3.0.0'
28
28
29 # To use Jbuilder templates for JSON
29 # To use Jbuilder templates for JSON
30 # gem 'jbuilder'
30 # gem 'jbuilder'
31
31
32 # Use unicorn as the app server
32 # Use unicorn as the app server
33 # gem 'unicorn'
33 # gem 'unicorn'
34
34
35 # Deploy with Capistrano
35 # Deploy with Capistrano
36 # gem 'capistrano'
36 # gem 'capistrano'
37
37
38 # To use debugger
38 # To use debugger
39 # gem 'debugger'
39 # gem 'debugger'
40 #
40 #
41
41
42 #in-place editor
42 #in-place editor
43 gem 'best_in_place', '~> 3.0.1'
43 gem 'best_in_place', '~> 3.0.1'
44
44
45 # jquery addition
45 # jquery addition
46 gem 'jquery-rails'
46 gem 'jquery-rails'
47 gem 'jquery-ui-sass-rails'
47 gem 'jquery-ui-sass-rails'
48 gem 'jquery-timepicker-addon-rails'
48 gem 'jquery-timepicker-addon-rails'
49 gem 'jquery-tablesorter'
49 gem 'jquery-tablesorter'
50
50
51 #syntax highlighter
51 #syntax highlighter
52 gem 'rouge'
52 gem 'rouge'
53
53
54 #add bootstrap
54 #add bootstrap
55 gem 'bootstrap-sass', '~> 3.2.0'
55 gem 'bootstrap-sass', '~> 3.2.0'
56 gem 'bootstrap-switch-rails'
56 gem 'bootstrap-switch-rails'
57 gem 'bootstrap-toggle-rails'
57 gem 'bootstrap-toggle-rails'
58 gem 'autoprefixer-rails'
58 gem 'autoprefixer-rails'
59
59
60 + gem 'ace-rails-ap'
61 +
60
62
61 gem 'haml'
63 gem 'haml'
64 + gem 'haml-rails'
62 gem 'mail'
65 gem 'mail'
63 gem 'rdiscount'
66 gem 'rdiscount'
64 gem 'test-unit'
67 gem 'test-unit'
65 gem 'will_paginate', '~> 3.0.7'
68 gem 'will_paginate', '~> 3.0.7'
66 gem 'dynamic_form'
69 gem 'dynamic_form'
67 gem 'in_place_editing'
70 gem 'in_place_editing'
68 gem 'verification', :git => 'https://github.com/sikachu/verification.git'
71 gem 'verification', :git => 'https://github.com/sikachu/verification.git'
69
72
70 group :test, :development do
73 group :test, :development do
71 gem 'rspec-rails', '~> 2.99.0'
74 gem 'rspec-rails', '~> 2.99.0'
72 end
75 end
@@ -1,189 +1,197
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 + ace-rails-ap (4.0.2)
12 actionmailer (3.2.21)
13 actionmailer (3.2.21)
13 actionpack (= 3.2.21)
14 actionpack (= 3.2.21)
14 mail (~> 2.5.4)
15 mail (~> 2.5.4)
15 actionpack (3.2.21)
16 actionpack (3.2.21)
16 activemodel (= 3.2.21)
17 activemodel (= 3.2.21)
17 activesupport (= 3.2.21)
18 activesupport (= 3.2.21)
18 builder (~> 3.0.0)
19 builder (~> 3.0.0)
19 erubis (~> 2.7.0)
20 erubis (~> 2.7.0)
20 journey (~> 1.0.4)
21 journey (~> 1.0.4)
21 rack (~> 1.4.5)
22 rack (~> 1.4.5)
22 rack-cache (~> 1.2)
23 rack-cache (~> 1.2)
23 rack-test (~> 0.6.1)
24 rack-test (~> 0.6.1)
24 sprockets (~> 2.2.1)
25 sprockets (~> 2.2.1)
25 activemodel (3.2.21)
26 activemodel (3.2.21)
26 activesupport (= 3.2.21)
27 activesupport (= 3.2.21)
27 builder (~> 3.0.0)
28 builder (~> 3.0.0)
28 activerecord (3.2.21)
29 activerecord (3.2.21)
29 activemodel (= 3.2.21)
30 activemodel (= 3.2.21)
30 activesupport (= 3.2.21)
31 activesupport (= 3.2.21)
31 arel (~> 3.0.2)
32 arel (~> 3.0.2)
32 tzinfo (~> 0.3.29)
33 tzinfo (~> 0.3.29)
33 activeresource (3.2.21)
34 activeresource (3.2.21)
34 activemodel (= 3.2.21)
35 activemodel (= 3.2.21)
35 activesupport (= 3.2.21)
36 activesupport (= 3.2.21)
36 activesupport (3.2.21)
37 activesupport (3.2.21)
37 i18n (~> 0.6, >= 0.6.4)
38 i18n (~> 0.6, >= 0.6.4)
38 multi_json (~> 1.0)
39 multi_json (~> 1.0)
39 arel (3.0.3)
40 arel (3.0.3)
40 autoprefixer-rails (6.0.3)
41 autoprefixer-rails (6.0.3)
41 execjs
42 execjs
42 json
43 json
43 best_in_place (3.0.3)
44 best_in_place (3.0.3)
44 actionpack (>= 3.2)
45 actionpack (>= 3.2)
45 railties (>= 3.2)
46 railties (>= 3.2)
46 bootstrap-sass (3.2.0.2)
47 bootstrap-sass (3.2.0.2)
47 sass (~> 3.2)
48 sass (~> 3.2)
48 bootstrap-switch-rails (3.3.3)
49 bootstrap-switch-rails (3.3.3)
49 bootstrap-toggle-rails (2.2.1.0)
50 bootstrap-toggle-rails (2.2.1.0)
50 builder (3.0.4)
51 builder (3.0.4)
51 coffee-rails (3.2.2)
52 coffee-rails (3.2.2)
52 coffee-script (>= 2.2.0)
53 coffee-script (>= 2.2.0)
53 railties (~> 3.2.0)
54 railties (~> 3.2.0)
54 coffee-script (2.3.0)
55 coffee-script (2.3.0)
55 coffee-script-source
56 coffee-script-source
56 execjs
57 execjs
57 coffee-script-source (1.9.0)
58 coffee-script-source (1.9.0)
58 diff-lcs (1.2.5)
59 diff-lcs (1.2.5)
59 dynamic_form (1.1.4)
60 dynamic_form (1.1.4)
60 erubis (2.7.0)
61 erubis (2.7.0)
61 execjs (2.3.0)
62 execjs (2.3.0)
62 haml (4.0.6)
63 haml (4.0.6)
63 tilt
64 tilt
65 + haml-rails (0.4)
66 + actionpack (>= 3.1, < 4.1)
67 + activesupport (>= 3.1, < 4.1)
68 + haml (>= 3.1, < 4.1)
69 + railties (>= 3.1, < 4.1)
64 hike (1.2.3)
70 hike (1.2.3)
65 i18n (0.7.0)
71 i18n (0.7.0)
66 in_place_editing (1.2.0)
72 in_place_editing (1.2.0)
67 journey (1.0.4)
73 journey (1.0.4)
68 jquery-rails (3.1.2)
74 jquery-rails (3.1.2)
69 railties (>= 3.0, < 5.0)
75 railties (>= 3.0, < 5.0)
70 thor (>= 0.14, < 2.0)
76 thor (>= 0.14, < 2.0)
71 jquery-tablesorter (1.13.4)
77 jquery-tablesorter (1.13.4)
72 railties (>= 3.1, < 5)
78 railties (>= 3.1, < 5)
73 jquery-timepicker-addon-rails (1.4.1)
79 jquery-timepicker-addon-rails (1.4.1)
74 railties (>= 3.1)
80 railties (>= 3.1)
75 jquery-ui-rails (4.0.3)
81 jquery-ui-rails (4.0.3)
76 jquery-rails
82 jquery-rails
77 railties (>= 3.1.0)
83 railties (>= 3.1.0)
78 jquery-ui-sass-rails (4.0.3.0)
84 jquery-ui-sass-rails (4.0.3.0)
79 jquery-rails
85 jquery-rails
80 jquery-ui-rails (= 4.0.3)
86 jquery-ui-rails (= 4.0.3)
81 railties (>= 3.1.0)
87 railties (>= 3.1.0)
82 json (1.8.2)
88 json (1.8.2)
83 mail (2.5.4)
89 mail (2.5.4)
84 mime-types (~> 1.16)
90 mime-types (~> 1.16)
85 treetop (~> 1.4.8)
91 treetop (~> 1.4.8)
86 mime-types (1.25.1)
92 mime-types (1.25.1)
87 multi_json (1.10.1)
93 multi_json (1.10.1)
88 mysql2 (0.3.20)
94 mysql2 (0.3.20)
89 polyglot (0.3.5)
95 polyglot (0.3.5)
90 power_assert (0.2.2)
96 power_assert (0.2.2)
91 prototype-rails (3.2.1)
97 prototype-rails (3.2.1)
92 rails (~> 3.2)
98 rails (~> 3.2)
93 rack (1.4.5)
99 rack (1.4.5)
94 rack-cache (1.2)
100 rack-cache (1.2)
95 rack (>= 0.4)
101 rack (>= 0.4)
96 rack-ssl (1.3.4)
102 rack-ssl (1.3.4)
97 rack
103 rack
98 rack-test (0.6.3)
104 rack-test (0.6.3)
99 rack (>= 1.0)
105 rack (>= 1.0)
100 rails (3.2.21)
106 rails (3.2.21)
101 actionmailer (= 3.2.21)
107 actionmailer (= 3.2.21)
102 actionpack (= 3.2.21)
108 actionpack (= 3.2.21)
103 activerecord (= 3.2.21)
109 activerecord (= 3.2.21)
104 activeresource (= 3.2.21)
110 activeresource (= 3.2.21)
105 activesupport (= 3.2.21)
111 activesupport (= 3.2.21)
106 bundler (~> 1.0)
112 bundler (~> 1.0)
107 railties (= 3.2.21)
113 railties (= 3.2.21)
108 railties (3.2.21)
114 railties (3.2.21)
109 actionpack (= 3.2.21)
115 actionpack (= 3.2.21)
110 activesupport (= 3.2.21)
116 activesupport (= 3.2.21)
111 rack-ssl (~> 1.3.2)
117 rack-ssl (~> 1.3.2)
112 rake (>= 0.8.7)
118 rake (>= 0.8.7)
113 rdoc (~> 3.4)
119 rdoc (~> 3.4)
114 thor (>= 0.14.6, < 2.0)
120 thor (>= 0.14.6, < 2.0)
115 rake (10.4.2)
121 rake (10.4.2)
116 rdiscount (2.1.8)
122 rdiscount (2.1.8)
117 rdoc (3.12.2)
123 rdoc (3.12.2)
118 json (~> 1.4)
124 json (~> 1.4)
119 rouge (1.8.0)
125 rouge (1.8.0)
120 rspec-collection_matchers (1.1.2)
126 rspec-collection_matchers (1.1.2)
121 rspec-expectations (>= 2.99.0.beta1)
127 rspec-expectations (>= 2.99.0.beta1)
122 rspec-core (2.99.2)
128 rspec-core (2.99.2)
123 rspec-expectations (2.99.2)
129 rspec-expectations (2.99.2)
124 diff-lcs (>= 1.1.3, < 2.0)
130 diff-lcs (>= 1.1.3, < 2.0)
125 rspec-mocks (2.99.3)
131 rspec-mocks (2.99.3)
126 rspec-rails (2.99.0)
132 rspec-rails (2.99.0)
127 actionpack (>= 3.0)
133 actionpack (>= 3.0)
128 activemodel (>= 3.0)
134 activemodel (>= 3.0)
129 activesupport (>= 3.0)
135 activesupport (>= 3.0)
130 railties (>= 3.0)
136 railties (>= 3.0)
131 rspec-collection_matchers
137 rspec-collection_matchers
132 rspec-core (~> 2.99.0)
138 rspec-core (~> 2.99.0)
133 rspec-expectations (~> 2.99.0)
139 rspec-expectations (~> 2.99.0)
134 rspec-mocks (~> 2.99.0)
140 rspec-mocks (~> 2.99.0)
135 sass (3.4.11)
141 sass (3.4.11)
136 sass-rails (3.2.6)
142 sass-rails (3.2.6)
137 railties (~> 3.2.0)
143 railties (~> 3.2.0)
138 sass (>= 3.1.10)
144 sass (>= 3.1.10)
139 tilt (~> 1.3)
145 tilt (~> 1.3)
140 select2-rails (4.0.1)
146 select2-rails (4.0.1)
141 thor (~> 0.14)
147 thor (~> 0.14)
142 sprockets (2.2.3)
148 sprockets (2.2.3)
143 hike (~> 1.2)
149 hike (~> 1.2)
144 multi_json (~> 1.0)
150 multi_json (~> 1.0)
145 rack (~> 1.0)
151 rack (~> 1.0)
146 tilt (~> 1.1, != 1.3.0)
152 tilt (~> 1.1, != 1.3.0)
147 test-unit (3.0.9)
153 test-unit (3.0.9)
148 power_assert
154 power_assert
149 thor (0.19.1)
155 thor (0.19.1)
150 tilt (1.4.1)
156 tilt (1.4.1)
151 treetop (1.4.15)
157 treetop (1.4.15)
152 polyglot
158 polyglot
153 polyglot (>= 0.3.1)
159 polyglot (>= 0.3.1)
154 tzinfo (0.3.43)
160 tzinfo (0.3.43)
155 uglifier (2.7.0)
161 uglifier (2.7.0)
156 execjs (>= 0.3.0)
162 execjs (>= 0.3.0)
157 json (>= 1.8.0)
163 json (>= 1.8.0)
158 will_paginate (3.0.7)
164 will_paginate (3.0.7)
159
165
160 PLATFORMS
166 PLATFORMS
161 ruby
167 ruby
162
168
163 DEPENDENCIES
169 DEPENDENCIES
170 + ace-rails-ap
164 autoprefixer-rails
171 autoprefixer-rails
165 best_in_place (~> 3.0.1)
172 best_in_place (~> 3.0.1)
166 bootstrap-sass (~> 3.2.0)
173 bootstrap-sass (~> 3.2.0)
167 bootstrap-switch-rails
174 bootstrap-switch-rails
168 bootstrap-toggle-rails
175 bootstrap-toggle-rails
169 coffee-rails (~> 3.2.2)
176 coffee-rails (~> 3.2.2)
170 dynamic_form
177 dynamic_form
171 haml
178 haml
179 + haml-rails
172 in_place_editing
180 in_place_editing
173 jquery-rails
181 jquery-rails
174 jquery-tablesorter
182 jquery-tablesorter
175 jquery-timepicker-addon-rails
183 jquery-timepicker-addon-rails
176 jquery-ui-sass-rails
184 jquery-ui-sass-rails
177 mail
185 mail
178 mysql2
186 mysql2
179 prototype-rails
187 prototype-rails
180 rails (= 3.2.21)
188 rails (= 3.2.21)
181 rdiscount
189 rdiscount
182 rouge
190 rouge
183 rspec-rails (~> 2.99.0)
191 rspec-rails (~> 2.99.0)
184 sass-rails (~> 3.2.6)
192 sass-rails (~> 3.2.6)
185 select2-rails
193 select2-rails
186 test-unit
194 test-unit
187 uglifier
195 uglifier
188 verification!
196 verification!
189 will_paginate (~> 3.0.7)
197 will_paginate (~> 3.0.7)
@@ -1,28 +1,29
1 // This is a manifest file that'll be compiled into application.js, which will include all the files
1 // This is a manifest file that'll be compiled into application.js, which will include all the files
2 // listed below.
2 // listed below.
3 //
3 //
4 // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
4 // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
5 // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6 //
6 //
7 // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
7 // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 // the compiled file.
8 // the compiled file.
9 //
9 //
10 // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
10 // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11 // GO AFTER THE REQUIRES BELOW.
11 // GO AFTER THE REQUIRES BELOW.
12 //
12 //
13 //= require jquery
13 //= require jquery
14 //= require jquery_ujs
14 //= require jquery_ujs
15 //= require jquery.ui.all
15 //= require jquery.ui.all
16 //= require bootstrap-sprockets
16 //= require bootstrap-sprockets
17 //x= require bootstrap-switch
17 //x= require bootstrap-switch
18 //= require bootstrap-toggle
18 //= require bootstrap-toggle
19 //= require select2
19 //= require select2
20 //= require custom
20 //= require custom
21 + //= require ace-rails-ap
21
22
22
23
23 // since this is after blank line, it is not downloaded
24 // since this is after blank line, it is not downloaded
24 //x= require prototype
25 //x= require prototype
25 //x= require prototype_ujs
26 //x= require prototype_ujs
26 //x= require effects
27 //x= require effects
27 //x= require dragdrop
28 //x= require dragdrop
28 //x= require controls
29 //x= require controls
@@ -1,41 +1,45
1 $(document).on 'change', '.btn-file :file', ->
1 $(document).on 'change', '.btn-file :file', ->
2 input = $(this)
2 input = $(this)
3 numFiles = if input.get(0).files then input.get(0).files.length else 1
3 numFiles = if input.get(0).files then input.get(0).files.length else 1
4 label = input.val().replace(/\\/g, '/').replace(/.*\//, '')
4 label = input.val().replace(/\\/g, '/').replace(/.*\//, '')
5 input.trigger 'fileselect', [
5 input.trigger 'fileselect', [
6 numFiles
6 numFiles
7 label
7 label
8 ]
8 ]
9 return
9 return
10
10
11
11
12 # document ready
12 # document ready
13
13
14 $ ->
14 $ ->
15 $(".select2").select2()
15 $(".select2").select2()
16 #$(".bootstrap-switch").bootstrapSwitch()
16 #$(".bootstrap-switch").bootstrapSwitch()
17 $(".bootstrap-toggle").bootstrapToggle()
17 $(".bootstrap-toggle").bootstrapToggle()
18 $('.btn-file :file').on 'fileselect', (event, numFiles, label) ->
18 $('.btn-file :file').on 'fileselect', (event, numFiles, label) ->
19 input = $(this).parents('.input-group').find(':text')
19 input = $(this).parents('.input-group').find(':text')
20 log = if numFiles > 1 then numFiles + ' files selected' else label
20 log = if numFiles > 1 then numFiles + ' files selected' else label
21 if input.length
21 if input.length
22 input.val log
22 input.val log
23 else
23 else
24 if log
24 if log
25 alert log
25 alert log
26 return
26 return
27 $(".go-button").on 'click', (event) ->
27 $(".go-button").on 'click', (event) ->
28 link = $(this).attr("data-source")
28 link = $(this).attr("data-source")
29 url = $(link).val()
29 url = $(link).val()
30 if url
30 if url
31 window.location.href = url
31 window.location.href = url
32 return
32 return
33 $('.ajax-toggle').on 'click', (event) ->
33 $('.ajax-toggle').on 'click', (event) ->
34 target = $(event.target)
34 target = $(event.target)
35 target.removeClass 'btn-default'
35 target.removeClass 'btn-default'
36 target.removeClass 'btn-success'
36 target.removeClass 'btn-success'
37 target.addClass 'btn-warning'
37 target.addClass 'btn-warning'
38 target.text '...'
38 target.text '...'
39 return
39 return
40
40
41 + editor = ace.edit("editor")
42 + editor.setTheme("ace/theme/monokai")
43 + editor.getSession().setMode("ace/mode/javascript")
44 +
41 return
45 return
@@ -1,385 +1,393
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 before_filter :authenticate, :except => [:index, :login]
3 before_filter :authenticate, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
5
5
6 append_before_filter :confirm_and_update_start_time,
6 append_before_filter :confirm_and_update_start_time,
7 :except => [:index,
7 :except => [:index,
8 :login,
8 :login,
9 :confirm_contest_start]
9 :confirm_contest_start]
10
10
11 # to prevent log in box to be shown when user logged out of the
11 # to prevent log in box to be shown when user logged out of the
12 # system only in some tab
12 # system only in some tab
13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
14 :only => [:announcements]
14 :only => [:announcements]
15
15
16 before_filter :authenticate_by_ip_address, :only => [:list]
16 before_filter :authenticate_by_ip_address, :only => [:list]
17
17
18 # COMMENTED OUT: filter in each action instead
18 # COMMENTED OUT: filter in each action instead
19 # before_filter :verify_time_limit, :only => [:submit]
19 # before_filter :verify_time_limit, :only => [:submit]
20
20
21 verify :method => :post, :only => [:submit],
21 verify :method => :post, :only => [:submit],
22 :redirect_to => { :action => :index }
22 :redirect_to => { :action => :index }
23
23
24 # COMMENT OUT: only need when having high load
24 # COMMENT OUT: only need when having high load
25 # caches_action :index, :login
25 # caches_action :index, :login
26
26
27 # NOTE: This method is not actually needed, 'config/routes.rb' has
27 # NOTE: This method is not actually needed, 'config/routes.rb' has
28 # assigned action login as a default action.
28 # assigned action login as a default action.
29 def index
29 def index
30 redirect_to :action => 'login'
30 redirect_to :action => 'login'
31 end
31 end
32
32
33 def login
33 def login
34 saved_notice = flash[:notice]
34 saved_notice = flash[:notice]
35 reset_session
35 reset_session
36 flash.now[:notice] = saved_notice
36 flash.now[:notice] = saved_notice
37
37
38 # EXPERIMENT:
38 # EXPERIMENT:
39 # Hide login if in single user mode and the url does not
39 # Hide login if in single user mode and the url does not
40 # explicitly specify /login
40 # explicitly specify /login
41 #
41 #
42 # logger.info "PATH: #{request.path}"
42 # logger.info "PATH: #{request.path}"
43 # if GraderConfiguration['system.single_user_mode'] and
43 # if GraderConfiguration['system.single_user_mode'] and
44 # request.path!='/main/login'
44 # request.path!='/main/login'
45 # @hidelogin = true
45 # @hidelogin = true
46 # end
46 # end
47
47
48 @announcements = Announcement.find_for_frontpage
48 @announcements = Announcement.find_for_frontpage
49 render :action => 'login', :layout => 'empty'
49 render :action => 'login', :layout => 'empty'
50 end
50 end
51
51
52 def list
52 def list
53 prepare_list_information
53 prepare_list_information
54 end
54 end
55
55
56 def help
56 def help
57 @user = User.find(session[:user_id])
57 @user = User.find(session[:user_id])
58 end
58 end
59
59
60 def submit
60 def submit
61 user = User.find(session[:user_id])
61 user = User.find(session[:user_id])
62
62
63 @submission = Submission.new
63 @submission = Submission.new
64 @submission.problem_id = params[:submission][:problem_id]
64 @submission.problem_id = params[:submission][:problem_id]
65 @submission.user = user
65 @submission.user = user
66 @submission.language_id = 0
66 @submission.language_id = 0
67 if (params['file']) and (params['file']!='')
67 if (params['file']) and (params['file']!='')
68 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
68 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
69 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
69 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
70 @submission.source_filename = params['file'].original_filename
70 @submission.source_filename = params['file'].original_filename
71 end
71 end
72 +
73 + if (params[:editor_text])
74 + language = Language.find_by_id(params[:language_id])
75 + @submission.source = params[:editor_text]
76 + @submission.source_filename = "live_edit.#{language.ext}"
77 + @submission.language = language
78 + end
79 +
72 @submission.submitted_at = Time.new.gmtime
80 @submission.submitted_at = Time.new.gmtime
73 @submission.ip_address = request.remote_ip
81 @submission.ip_address = request.remote_ip
74
82
75 if GraderConfiguration.time_limit_mode? and user.contest_finished?
83 if GraderConfiguration.time_limit_mode? and user.contest_finished?
76 @submission.errors.add(:base,"The contest is over.")
84 @submission.errors.add(:base,"The contest is over.")
77 prepare_list_information
85 prepare_list_information
78 render :action => 'list' and return
86 render :action => 'list' and return
79 end
87 end
80
88
81 if @submission.valid?
89 if @submission.valid?
82 if @submission.save == false
90 if @submission.save == false
83 flash[:notice] = 'Error saving your submission'
91 flash[:notice] = 'Error saving your submission'
84 elsif Task.create(:submission_id => @submission.id,
92 elsif Task.create(:submission_id => @submission.id,
85 :status => Task::STATUS_INQUEUE) == false
93 :status => Task::STATUS_INQUEUE) == false
86 flash[:notice] = 'Error adding your submission to task queue'
94 flash[:notice] = 'Error adding your submission to task queue'
87 end
95 end
88 else
96 else
89 prepare_list_information
97 prepare_list_information
90 render :action => 'list' and return
98 render :action => 'list' and return
91 end
99 end
92 redirect_to :action => 'list'
100 redirect_to :action => 'list'
93 end
101 end
94
102
95 def source
103 def source
96 submission = Submission.find(params[:id])
104 submission = Submission.find(params[:id])
97 if ((submission.user_id == session[:user_id]) and
105 if ((submission.user_id == session[:user_id]) and
98 (submission.problem != nil) and
106 (submission.problem != nil) and
99 (submission.problem.available))
107 (submission.problem.available))
100 send_data(submission.source,
108 send_data(submission.source,
101 {:filename => submission.download_filename,
109 {:filename => submission.download_filename,
102 :type => 'text/plain'})
110 :type => 'text/plain'})
103 else
111 else
104 flash[:notice] = 'Error viewing source'
112 flash[:notice] = 'Error viewing source'
105 redirect_to :action => 'list'
113 redirect_to :action => 'list'
106 end
114 end
107 end
115 end
108
116
109 def compiler_msg
117 def compiler_msg
110 @submission = Submission.find(params[:id])
118 @submission = Submission.find(params[:id])
111 if @submission.user_id == session[:user_id]
119 if @submission.user_id == session[:user_id]
112 render :action => 'compiler_msg', :layout => 'empty'
120 render :action => 'compiler_msg', :layout => 'empty'
113 else
121 else
114 flash[:notice] = 'Error viewing source'
122 flash[:notice] = 'Error viewing source'
115 redirect_to :action => 'list'
123 redirect_to :action => 'list'
116 end
124 end
117 end
125 end
118
126
119 def submission
127 def submission
120 @user = User.find(session[:user_id])
128 @user = User.find(session[:user_id])
121 @problems = @user.available_problems
129 @problems = @user.available_problems
122 if params[:id]==nil
130 if params[:id]==nil
123 @problem = nil
131 @problem = nil
124 @submissions = nil
132 @submissions = nil
125 else
133 else
126 @problem = Problem.find_by_id(params[:id])
134 @problem = Problem.find_by_id(params[:id])
127 if (@problem == nil) or (not @problem.available)
135 if (@problem == nil) or (not @problem.available)
128 redirect_to :action => 'list'
136 redirect_to :action => 'list'
129 flash[:notice] = 'Error: submissions for that problem are not viewable.'
137 flash[:notice] = 'Error: submissions for that problem are not viewable.'
130 return
138 return
131 end
139 end
132 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
140 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
133 end
141 end
134 end
142 end
135
143
136 def result
144 def result
137 if !GraderConfiguration.show_grading_result
145 if !GraderConfiguration.show_grading_result
138 redirect_to :action => 'list' and return
146 redirect_to :action => 'list' and return
139 end
147 end
140 @user = User.find(session[:user_id])
148 @user = User.find(session[:user_id])
141 @submission = Submission.find(params[:id])
149 @submission = Submission.find(params[:id])
142 if @submission.user!=@user
150 if @submission.user!=@user
143 flash[:notice] = 'You are not allowed to view result of other users.'
151 flash[:notice] = 'You are not allowed to view result of other users.'
144 redirect_to :action => 'list' and return
152 redirect_to :action => 'list' and return
145 end
153 end
146 prepare_grading_result(@submission)
154 prepare_grading_result(@submission)
147 end
155 end
148
156
149 def load_output
157 def load_output
150 if !GraderConfiguration.show_grading_result or params[:num]==nil
158 if !GraderConfiguration.show_grading_result or params[:num]==nil
151 redirect_to :action => 'list' and return
159 redirect_to :action => 'list' and return
152 end
160 end
153 @user = User.find(session[:user_id])
161 @user = User.find(session[:user_id])
154 @submission = Submission.find(params[:id])
162 @submission = Submission.find(params[:id])
155 if @submission.user!=@user
163 if @submission.user!=@user
156 flash[:notice] = 'You are not allowed to view result of other users.'
164 flash[:notice] = 'You are not allowed to view result of other users.'
157 redirect_to :action => 'list' and return
165 redirect_to :action => 'list' and return
158 end
166 end
159 case_num = params[:num].to_i
167 case_num = params[:num].to_i
160 out_filename = output_filename(@user.login,
168 out_filename = output_filename(@user.login,
161 @submission.problem.name,
169 @submission.problem.name,
162 @submission.id,
170 @submission.id,
163 case_num)
171 case_num)
164 if !FileTest.exists?(out_filename)
172 if !FileTest.exists?(out_filename)
165 flash[:notice] = 'Output not found.'
173 flash[:notice] = 'Output not found.'
166 redirect_to :action => 'list' and return
174 redirect_to :action => 'list' and return
167 end
175 end
168
176
169 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
177 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
170 response.headers['Content-Type'] = "application/force-download"
178 response.headers['Content-Type'] = "application/force-download"
171 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
179 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
172 response.headers["X-Sendfile"] = out_filename
180 response.headers["X-Sendfile"] = out_filename
173 response.headers['Content-length'] = File.size(out_filename)
181 response.headers['Content-length'] = File.size(out_filename)
174 render :nothing => true
182 render :nothing => true
175 else
183 else
176 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
184 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
177 end
185 end
178 end
186 end
179
187
180 def error
188 def error
181 @user = User.find(session[:user_id])
189 @user = User.find(session[:user_id])
182 end
190 end
183
191
184 # announcement refreshing and hiding methods
192 # announcement refreshing and hiding methods
185
193
186 def announcements
194 def announcements
187 if params.has_key? 'recent'
195 if params.has_key? 'recent'
188 prepare_announcements(params[:recent])
196 prepare_announcements(params[:recent])
189 else
197 else
190 prepare_announcements
198 prepare_announcements
191 end
199 end
192 render(:partial => 'announcement',
200 render(:partial => 'announcement',
193 :collection => @announcements,
201 :collection => @announcements,
194 :locals => {:announcement_effect => true})
202 :locals => {:announcement_effect => true})
195 end
203 end
196
204
197 def confirm_contest_start
205 def confirm_contest_start
198 user = User.find(session[:user_id])
206 user = User.find(session[:user_id])
199 if request.method == 'POST'
207 if request.method == 'POST'
200 user.update_start_time
208 user.update_start_time
201 redirect_to :action => 'list'
209 redirect_to :action => 'list'
202 else
210 else
203 @contests = user.contests
211 @contests = user.contests
204 @user = user
212 @user = user
205 end
213 end
206 end
214 end
207
215
208 protected
216 protected
209
217
210 def prepare_announcements(recent=nil)
218 def prepare_announcements(recent=nil)
211 if GraderConfiguration.show_tasks_to?(@user)
219 if GraderConfiguration.show_tasks_to?(@user)
212 @announcements = Announcement.find_published(true)
220 @announcements = Announcement.find_published(true)
213 else
221 else
214 @announcements = Announcement.find_published
222 @announcements = Announcement.find_published
215 end
223 end
216 if recent!=nil
224 if recent!=nil
217 recent_id = recent.to_i
225 recent_id = recent.to_i
218 @announcements = @announcements.find_all { |a| a.id > recent_id }
226 @announcements = @announcements.find_all { |a| a.id > recent_id }
219 end
227 end
220 end
228 end
221
229
222 def prepare_list_information
230 def prepare_list_information
223 @user = User.find(session[:user_id])
231 @user = User.find(session[:user_id])
224 if not GraderConfiguration.multicontests?
232 if not GraderConfiguration.multicontests?
225 @problems = @user.available_problems
233 @problems = @user.available_problems
226 else
234 else
227 @contest_problems = @user.available_problems_group_by_contests
235 @contest_problems = @user.available_problems_group_by_contests
228 @problems = @user.available_problems
236 @problems = @user.available_problems
229 end
237 end
230 @prob_submissions = {}
238 @prob_submissions = {}
231 @problems.each do |p|
239 @problems.each do |p|
232 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
240 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
233 if sub!=nil
241 if sub!=nil
234 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
242 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
235 else
243 else
236 @prob_submissions[p.id] = { :count => 0, :submission => nil }
244 @prob_submissions[p.id] = { :count => 0, :submission => nil }
237 end
245 end
238 end
246 end
239 prepare_announcements
247 prepare_announcements
240 end
248 end
241
249
242 def check_viewability
250 def check_viewability
243 @user = User.find(session[:user_id])
251 @user = User.find(session[:user_id])
244 if (!GraderConfiguration.show_tasks_to?(@user)) and
252 if (!GraderConfiguration.show_tasks_to?(@user)) and
245 ((action_name=='submission') or (action_name=='submit'))
253 ((action_name=='submission') or (action_name=='submit'))
246 redirect_to :action => 'list' and return
254 redirect_to :action => 'list' and return
247 end
255 end
248 end
256 end
249
257
250 def prepare_grading_result(submission)
258 def prepare_grading_result(submission)
251 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
259 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
252 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
260 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
253 else
261 else
254 # guess task info from problem.full_score
262 # guess task info from problem.full_score
255 cases = submission.problem.full_score / 10
263 cases = submission.problem.full_score / 10
256 grading_info = {
264 grading_info = {
257 'testruns' => cases,
265 'testruns' => cases,
258 'testcases' => cases
266 'testcases' => cases
259 }
267 }
260 end
268 end
261 @test_runs = []
269 @test_runs = []
262 if grading_info['testruns'].is_a? Integer
270 if grading_info['testruns'].is_a? Integer
263 trun_count = grading_info['testruns']
271 trun_count = grading_info['testruns']
264 trun_count.times do |i|
272 trun_count.times do |i|
265 @test_runs << [ read_grading_result(@user.login,
273 @test_runs << [ read_grading_result(@user.login,
266 submission.problem.name,
274 submission.problem.name,
267 submission.id,
275 submission.id,
268 i+1) ]
276 i+1) ]
269 end
277 end
270 else
278 else
271 grading_info['testruns'].keys.sort.each do |num|
279 grading_info['testruns'].keys.sort.each do |num|
272 run = []
280 run = []
273 testrun = grading_info['testruns'][num]
281 testrun = grading_info['testruns'][num]
274 testrun.each do |c|
282 testrun.each do |c|
275 run << read_grading_result(@user.login,
283 run << read_grading_result(@user.login,
276 submission.problem.name,
284 submission.problem.name,
277 submission.id,
285 submission.id,
278 c)
286 c)
279 end
287 end
280 @test_runs << run
288 @test_runs << run
281 end
289 end
282 end
290 end
283 end
291 end
284
292
285 def grading_result_dir(user_name, problem_name, submission_id, case_num)
293 def grading_result_dir(user_name, problem_name, submission_id, case_num)
286 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
294 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
287 end
295 end
288
296
289 def output_filename(user_name, problem_name, submission_id, case_num)
297 def output_filename(user_name, problem_name, submission_id, case_num)
290 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
298 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
291 return "#{dir}/output.txt"
299 return "#{dir}/output.txt"
292 end
300 end
293
301
294 def read_grading_result(user_name, problem_name, submission_id, case_num)
302 def read_grading_result(user_name, problem_name, submission_id, case_num)
295 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
303 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
296 result_file_name = "#{dir}/result"
304 result_file_name = "#{dir}/result"
297 if !FileTest.exists?(result_file_name)
305 if !FileTest.exists?(result_file_name)
298 return {:num => case_num, :msg => 'program did not run'}
306 return {:num => case_num, :msg => 'program did not run'}
299 else
307 else
300 results = File.open(result_file_name).readlines
308 results = File.open(result_file_name).readlines
301 run_stat = extract_running_stat(results)
309 run_stat = extract_running_stat(results)
302 output_filename = "#{dir}/output.txt"
310 output_filename = "#{dir}/output.txt"
303 if FileTest.exists?(output_filename)
311 if FileTest.exists?(output_filename)
304 output_file = true
312 output_file = true
305 output_size = File.size(output_filename)
313 output_size = File.size(output_filename)
306 else
314 else
307 output_file = false
315 output_file = false
308 output_size = 0
316 output_size = 0
309 end
317 end
310
318
311 return {
319 return {
312 :num => case_num,
320 :num => case_num,
313 :msg => results[0],
321 :msg => results[0],
314 :run_stat => run_stat,
322 :run_stat => run_stat,
315 :output => output_file,
323 :output => output_file,
316 :output_size => output_size
324 :output_size => output_size
317 }
325 }
318 end
326 end
319 end
327 end
320
328
321 # copied from grader/script/lib/test_request_helper.rb
329 # copied from grader/script/lib/test_request_helper.rb
322 def extract_running_stat(results)
330 def extract_running_stat(results)
323 running_stat_line = results[-1]
331 running_stat_line = results[-1]
324
332
325 # extract exit status line
333 # extract exit status line
326 run_stat = ""
334 run_stat = ""
327 if !(/[Cc]orrect/.match(results[0]))
335 if !(/[Cc]orrect/.match(results[0]))
328 run_stat = results[0].chomp
336 run_stat = results[0].chomp
329 else
337 else
330 run_stat = 'Program exited normally'
338 run_stat = 'Program exited normally'
331 end
339 end
332
340
333 logger.info "Stat line: #{running_stat_line}"
341 logger.info "Stat line: #{running_stat_line}"
334
342
335 # extract running time
343 # extract running time
336 if res = /r(.*)u(.*)s/.match(running_stat_line)
344 if res = /r(.*)u(.*)s/.match(running_stat_line)
337 seconds = (res[1].to_f + res[2].to_f)
345 seconds = (res[1].to_f + res[2].to_f)
338 time_stat = "Time used: #{seconds} sec."
346 time_stat = "Time used: #{seconds} sec."
339 else
347 else
340 seconds = nil
348 seconds = nil
341 time_stat = "Time used: n/a sec."
349 time_stat = "Time used: n/a sec."
342 end
350 end
343
351
344 # extract memory usage
352 # extract memory usage
345 if res = /s(.*)m/.match(running_stat_line)
353 if res = /s(.*)m/.match(running_stat_line)
346 memory_used = res[1].to_i
354 memory_used = res[1].to_i
347 else
355 else
348 memory_used = -1
356 memory_used = -1
349 end
357 end
350
358
351 return {
359 return {
352 :msg => "#{run_stat}\n#{time_stat}",
360 :msg => "#{run_stat}\n#{time_stat}",
353 :running_time => seconds,
361 :running_time => seconds,
354 :exit_status => run_stat,
362 :exit_status => run_stat,
355 :memory_usage => memory_used
363 :memory_usage => memory_used
356 }
364 }
357 end
365 end
358
366
359 def confirm_and_update_start_time
367 def confirm_and_update_start_time
360 user = User.find(session[:user_id])
368 user = User.find(session[:user_id])
361 if (GraderConfiguration.indv_contest_mode? and
369 if (GraderConfiguration.indv_contest_mode? and
362 GraderConfiguration['contest.confirm_indv_contest_start'] and
370 GraderConfiguration['contest.confirm_indv_contest_start'] and
363 !user.contest_started?)
371 !user.contest_started?)
364 redirect_to :action => 'confirm_contest_start' and return
372 redirect_to :action => 'confirm_contest_start' and return
365 end
373 end
366 if not GraderConfiguration.analysis_mode?
374 if not GraderConfiguration.analysis_mode?
367 user.update_start_time
375 user.update_start_time
368 end
376 end
369 end
377 end
370
378
371 def reject_announcement_refresh_when_logged_out
379 def reject_announcement_refresh_when_logged_out
372 if not session[:user_id]
380 if not session[:user_id]
373 render :text => 'Access forbidden', :status => 403
381 render :text => 'Access forbidden', :status => 403
374 end
382 end
375
383
376 if GraderConfiguration.multicontests?
384 if GraderConfiguration.multicontests?
377 user = User.find(session[:user_id])
385 user = User.find(session[:user_id])
378 if user.contest_stat.forced_logout
386 if user.contest_stat.forced_logout
379 render :text => 'Access forbidden', :status => 403
387 render :text => 'Access forbidden', :status => 403
380 end
388 end
381 end
389 end
382 end
390 end
383
391
384 end
392 end
385
393
@@ -1,128 +1,132
1 class Problem < ActiveRecord::Base
1 class Problem < ActiveRecord::Base
2
2
3 belongs_to :description
3 belongs_to :description
4 has_and_belongs_to_many :contests, :uniq => true
4 has_and_belongs_to_many :contests, :uniq => true
5 has_many :test_pairs, :dependent => :delete_all
5 has_many :test_pairs, :dependent => :delete_all
6
6
7 validates_presence_of :name
7 validates_presence_of :name
8 validates_format_of :name, :with => /^\w+$/
8 validates_format_of :name, :with => /^\w+$/
9 validates_presence_of :full_name
9 validates_presence_of :full_name
10
10
11 scope :available, :conditions => {:available => true}
11 scope :available, :conditions => {:available => true}
12
12
13 DEFAULT_TIME_LIMIT = 1
13 DEFAULT_TIME_LIMIT = 1
14 DEFAULT_MEMORY_LIMIT = 32
14 DEFAULT_MEMORY_LIMIT = 32
15
15
16 def self.find_available_problems
16 def self.find_available_problems
17 Problem.available.all(:order => "date_added DESC, name ASC")
17 Problem.available.all(:order => "date_added DESC, name ASC")
18 end
18 end
19
19
20 def self.create_from_import_form_params(params, old_problem=nil)
20 def self.create_from_import_form_params(params, old_problem=nil)
21 org_problem = old_problem || Problem.new
21 org_problem = old_problem || Problem.new
22 import_params, problem = Problem.extract_params_and_check(params,
22 import_params, problem = Problem.extract_params_and_check(params,
23 org_problem)
23 org_problem)
24
24
25 if !problem.errors.empty?
25 if !problem.errors.empty?
26 return problem, 'Error importing'
26 return problem, 'Error importing'
27 end
27 end
28
28
29 problem.full_score = 100
29 problem.full_score = 100
30 problem.date_added = Time.new
30 problem.date_added = Time.new
31 problem.test_allowed = true
31 problem.test_allowed = true
32 problem.output_only = false
32 problem.output_only = false
33 problem.available = false
33 problem.available = false
34
34
35 if not problem.save
35 if not problem.save
36 return problem, 'Error importing'
36 return problem, 'Error importing'
37 end
37 end
38
38
39 import_to_db = params.has_key? :import_to_db
39 import_to_db = params.has_key? :import_to_db
40
40
41 importer = TestdataImporter.new(problem)
41 importer = TestdataImporter.new(problem)
42
42
43 if not importer.import_from_file(import_params[:file],
43 if not importer.import_from_file(import_params[:file],
44 import_params[:time_limit],
44 import_params[:time_limit],
45 import_params[:memory_limit],
45 import_params[:memory_limit],
46 import_params[:checker_name],
46 import_params[:checker_name],
47 import_to_db)
47 import_to_db)
48 problem.errors.add(:base,'Import error.')
48 problem.errors.add(:base,'Import error.')
49 end
49 end
50
50
51 return problem, importer.log_msg
51 return problem, importer.log_msg
52 end
52 end
53
53
54 def self.download_file_basedir
54 def self.download_file_basedir
55 return "#{Rails.root}/data/tasks"
55 return "#{Rails.root}/data/tasks"
56 end
56 end
57
57
58 def get_submission_stat
58 def get_submission_stat
59 result = Hash.new
59 result = Hash.new
60 #total number of submission
60 #total number of submission
61 result[:total_sub] = Submission.where(problem_id: self.id).count
61 result[:total_sub] = Submission.where(problem_id: self.id).count
62 result[:attempted_user] = Submission.where(problem_id: self.id).group_by(:user_id)
62 result[:attempted_user] = Submission.where(problem_id: self.id).group_by(:user_id)
63 end
63 end
64
64
65 + def long_name
66 + "[#{name}] #{full_name}"
67 + end
68 +
65 protected
69 protected
66
70
67 def self.to_i_or_default(st, default)
71 def self.to_i_or_default(st, default)
68 if st!=''
72 if st!=''
69 result = st.to_i
73 result = st.to_i
70 end
74 end
71 result ||= default
75 result ||= default
72 end
76 end
73
77
74 def self.to_f_or_default(st, default)
78 def self.to_f_or_default(st, default)
75 if st!=''
79 if st!=''
76 result = st.to_f
80 result = st.to_f
77 end
81 end
78 result ||= default
82 result ||= default
79 end
83 end
80
84
81 def self.extract_params_and_check(params, problem)
85 def self.extract_params_and_check(params, problem)
82 time_limit = Problem.to_f_or_default(params[:time_limit],
86 time_limit = Problem.to_f_or_default(params[:time_limit],
83 DEFAULT_TIME_LIMIT)
87 DEFAULT_TIME_LIMIT)
84 memory_limit = Problem.to_i_or_default(params[:memory_limit],
88 memory_limit = Problem.to_i_or_default(params[:memory_limit],
85 DEFAULT_MEMORY_LIMIT)
89 DEFAULT_MEMORY_LIMIT)
86
90
87 if time_limit<=0 or time_limit >60
91 if time_limit<=0 or time_limit >60
88 problem.errors.add(:base,'Time limit out of range.')
92 problem.errors.add(:base,'Time limit out of range.')
89 end
93 end
90
94
91 if memory_limit==0 and params[:memory_limit]!='0'
95 if memory_limit==0 and params[:memory_limit]!='0'
92 problem.errors.add(:base,'Memory limit format errors.')
96 problem.errors.add(:base,'Memory limit format errors.')
93 elsif memory_limit<=0 or memory_limit >512
97 elsif memory_limit<=0 or memory_limit >512
94 problem.errors.add(:base,'Memory limit out of range.')
98 problem.errors.add(:base,'Memory limit out of range.')
95 end
99 end
96
100
97 if params[:file]==nil or params[:file]==''
101 if params[:file]==nil or params[:file]==''
98 problem.errors.add(:base,'No testdata file.')
102 problem.errors.add(:base,'No testdata file.')
99 end
103 end
100
104
101 checker_name = 'text'
105 checker_name = 'text'
102 if ['text','float'].include? params[:checker]
106 if ['text','float'].include? params[:checker]
103 checker_name = params[:checker]
107 checker_name = params[:checker]
104 end
108 end
105
109
106 file = params[:file]
110 file = params[:file]
107
111
108 if !problem.errors.empty?
112 if !problem.errors.empty?
109 return nil, problem
113 return nil, problem
110 end
114 end
111
115
112 problem.name = params[:name]
116 problem.name = params[:name]
113 if params[:full_name]!=''
117 if params[:full_name]!=''
114 problem.full_name = params[:full_name]
118 problem.full_name = params[:full_name]
115 else
119 else
116 problem.full_name = params[:name]
120 problem.full_name = params[:name]
117 end
121 end
118
122
119 return [{
123 return [{
120 :time_limit => time_limit,
124 :time_limit => time_limit,
121 :memory_limit => memory_limit,
125 :memory_limit => memory_limit,
122 :file => file,
126 :file => file,
123 :checker_name => checker_name
127 :checker_name => checker_name
124 },
128 },
125 problem]
129 problem]
126 end
130 end
127
131
128 end
132 end
@@ -1,26 +1,26
1
1
2 - if submission==nil
2 - if submission==nil
3 = "-"
3 = "-"
4 - else
4 - else
5 - if submission.graded_at==nil
5 - if submission.graded_at==nil
6 =t 'main.submitted_at'
6 =t 'main.submitted_at'
7 = format_short_time(submission.submitted_at.localtime)
7 = format_short_time(submission.submitted_at.localtime)
8 - else
8 - else
9 = t 'main.graded_at'
9 = t 'main.graded_at'
10 = "#{format_short_time(submission.graded_at.localtime)}, "
10 = "#{format_short_time(submission.graded_at.localtime)}, "
11 - if GraderConfiguration['ui.show_score']
11 - if GraderConfiguration['ui.show_score']
12 = t 'main.score'
12 = t 'main.score'
13 = "#{(submission.points*100/submission.problem.full_score).to_i} "
13 = "#{(submission.points*100/submission.problem.full_score).to_i} "
14 = " ["
14 = " ["
15 %tt
15 %tt
16 = submission.grader_comment
16 = submission.grader_comment
17 = "]"
17 = "]"
18 - if GraderConfiguration.show_grading_result
18 - if GraderConfiguration.show_grading_result
19 = " | "
19 = " | "
20 = link_to '[detailed result]', :action => 'result', :id => submission.id
20 = link_to '[detailed result]', :action => 'result', :id => submission.id
21 = " | "
21 = " | "
22 = link_to("[#{t 'main.cmp_msg'}]", {:action => 'compiler_msg', :id => submission.id}, {:popup => true})
22 = link_to("[#{t 'main.cmp_msg'}]", {:action => 'compiler_msg', :id => submission.id}, {:popup => true})
23 = " | "
23 = " | "
24 = link_to("[#{t 'main.src_link'}]",{:action => 'source', :id => submission.id})
24 = link_to("[#{t 'main.src_link'}]",{:action => 'source', :id => submission.id})
25 = " | "
25 = " | "
26 - = link_to "[#{t 'main.submissions_link'}]", :action => 'submission', :id => problem_name
26 + = link_to "[#{t 'main.submissions_link'}]", :action => 'submission', :id => submission.problem.id
@@ -1,54 +1,62
1 CafeGrader::Application.routes.draw do
1 CafeGrader::Application.routes.draw do
2 + get "sources/direct_edit"
3 +
2 root :to => 'main#login'
4 root :to => 'main#login'
3
5
4
6
5 resources :contests
7 resources :contests
6
8
7 resources :sites
9 resources :sites
8
10
9 resources :announcements do
11 resources :announcements do
10 member do
12 member do
11 get 'toggle'
13 get 'toggle'
12 end
14 end
13 end
15 end
14
16
15
17
16 resources :problems do
18 resources :problems do
17 member do
19 member do
18 get 'toggle'
20 get 'toggle'
19 end
21 end
20 collection do
22 collection do
21 get 'turn_all_off'
23 get 'turn_all_off'
22 get 'turn_all_on'
24 get 'turn_all_on'
23 get 'import'
25 get 'import'
24 get 'manage'
26 get 'manage'
25 end
27 end
26 end
28 end
27
29
28 resources :grader_configuration, controller: 'configurations'
30 resources :grader_configuration, controller: 'configurations'
29
31
30 resources :users do
32 resources :users do
31 member do
33 member do
32 get 'toggle_activate', 'toggle_enable'
34 get 'toggle_activate', 'toggle_enable'
33 end
35 end
34 end
36 end
35
37
38 + #resources :sources do
39 + # collection do
40 + # end
41 + #end
42 + get 'sources/direct_edit/:pid', to: 'sources#direct_edit', as: 'direct_edit'
43 +
36
44
37 match 'tasks/view/:file.:ext' => 'tasks#view'
45 match 'tasks/view/:file.:ext' => 'tasks#view'
38 match 'tasks/download/:id/:file.:ext' => 'tasks#download'
46 match 'tasks/download/:id/:file.:ext' => 'tasks#download'
39 match 'heartbeat/:id/edit' => 'heartbeat#edit'
47 match 'heartbeat/:id/edit' => 'heartbeat#edit'
40
48
41 #main
49 #main
42 get "main/list"
50 get "main/list"
43 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
51 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
44
52
45 #report
53 #report
46 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
54 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
47 get "report/login"
55 get "report/login"
48
56
49 # See how all your routes lay out with "rake routes"
57 # See how all your routes lay out with "rake routes"
50
58
51 # This is a legacy wild controller route that's not recommended for RESTful applications.
59 # This is a legacy wild controller route that's not recommended for RESTful applications.
52 # Note: This route will make all actions in every controller accessible via GET requests.
60 # Note: This route will make all actions in every controller accessible via GET requests.
53 match ':controller(/:action(/:id))(.:format)'
61 match ':controller(/:action(/:id))(.:format)'
54 end
62 end
You need to be logged in to leave comments. Login now