Description:
- bootstrapize problem/edit - bootstrapize announcement/edit
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r650:72b80e42fb9b - - 5 files changed: 5 inserted, 116 deleted

@@ -1,301 +1,301
1 1 class MainController < ApplicationController
2 2
3 3 before_filter :authenticate, :except => [:index, :login]
4 4 before_filter :check_viewability, :except => [:index, :login]
5 5
6 6 append_before_filter :confirm_and_update_start_time,
7 7 :except => [:index,
8 8 :login,
9 9 :confirm_contest_start]
10 10
11 11 # to prevent log in box to be shown when user logged out of the
12 12 # system only in some tab
13 13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
14 14 :only => [:announcements]
15 15
16 16 before_filter :authenticate_by_ip_address, :only => [:list]
17 17
18 18 # COMMENTED OUT: filter in each action instead
19 19 # before_filter :verify_time_limit, :only => [:submit]
20 20
21 21 verify :method => :post, :only => [:submit],
22 22 :redirect_to => { :action => :index }
23 23
24 24 # COMMENT OUT: only need when having high load
25 25 # caches_action :index, :login
26 26
27 27 # NOTE: This method is not actually needed, 'config/routes.rb' has
28 28 # assigned action login as a default action.
29 29 def index
30 30 redirect_to :action => 'login'
31 31 end
32 32
33 33 def login
34 34 saved_notice = flash[:notice]
35 35 reset_session
36 36 flash.now[:notice] = saved_notice
37 37
38 38 # EXPERIMENT:
39 39 # Hide login if in single user mode and the url does not
40 40 # explicitly specify /login
41 41 #
42 42 # logger.info "PATH: #{request.path}"
43 43 # if GraderConfiguration['system.single_user_mode'] and
44 44 # request.path!='/main/login'
45 45 # @hidelogin = true
46 46 # end
47 47
48 48 @announcements = Announcement.frontpage
49 49 render :action => 'login', :layout => 'empty'
50 50 end
51 51
52 52 def list
53 53 prepare_list_information
54 54 end
55 55
56 56 def help
57 57 @user = User.find(session[:user_id])
58 58 end
59 59
60 60 def submit
61 61 user = User.find(session[:user_id])
62 62
63 63 @submission = Submission.new
64 64 @submission.problem_id = params[:submission][:problem_id]
65 65 @submission.user = user
66 66 @submission.language_id = 0
67 67 if (params['file']) and (params['file']!='')
68 68 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
69 69 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
70 70 @submission.source_filename = params['file'].original_filename
71 71 end
72 72
73 73 if (params[:editor_text])
74 74 language = Language.find_by_id(params[:language_id])
75 75 @submission.source = params[:editor_text]
76 76 @submission.source_filename = "live_edit.#{language.ext}"
77 77 @submission.language = language
78 78 end
79 79
80 80 @submission.submitted_at = Time.new.gmtime
81 81 @submission.ip_address = request.remote_ip
82 82
83 83 if GraderConfiguration.time_limit_mode? and user.contest_finished?
84 84 @submission.errors.add(:base,"The contest is over.")
85 85 prepare_list_information
86 86 render :action => 'list' and return
87 87 end
88 88
89 89 if @submission.valid?
90 90 if @submission.save == false
91 - flash[:notice] = 'Error saving your submission'
91 + flash[:notice] = 'Error saving your submission'
92 92 elsif Task.create(:submission_id => @submission.id,
93 93 :status => Task::STATUS_INQUEUE) == false
94 - flash[:notice] = 'Error adding your submission to task queue'
94 + flash[:notice] = 'Error adding your submission to task queue'
95 95 end
96 96 else
97 97 prepare_list_information
98 98 render :action => 'list' and return
99 99 end
100 100 redirect_to :action => 'list'
101 101 end
102 102
103 103 def source
104 104 submission = Submission.find(params[:id])
105 105 if ((submission.user_id == session[:user_id]) and
106 106 (submission.problem != nil) and
107 107 (submission.problem.available))
108 108 send_data(submission.source,
109 - {:filename => submission.download_filename,
109 + {:filename => submission.download_filename,
110 110 :type => 'text/plain'})
111 111 else
112 112 flash[:notice] = 'Error viewing source'
113 113 redirect_to :action => 'list'
114 114 end
115 115 end
116 116
117 117 def compiler_msg
118 118 @submission = Submission.find(params[:id])
119 119 if @submission.user_id == session[:user_id]
120 120 render :action => 'compiler_msg', :layout => 'empty'
121 121 else
122 122 flash[:notice] = 'Error viewing source'
123 123 redirect_to :action => 'list'
124 124 end
125 125 end
126 126
127 127 def result
128 128 if !GraderConfiguration.show_grading_result
129 129 redirect_to :action => 'list' and return
130 130 end
131 131 @user = User.find(session[:user_id])
132 132 @submission = Submission.find(params[:id])
133 133 if @submission.user!=@user
134 134 flash[:notice] = 'You are not allowed to view result of other users.'
135 135 redirect_to :action => 'list' and return
136 136 end
137 137 prepare_grading_result(@submission)
138 138 end
139 139
140 140 def load_output
141 141 if !GraderConfiguration.show_grading_result or params[:num]==nil
142 142 redirect_to :action => 'list' and return
143 143 end
144 144 @user = User.find(session[:user_id])
145 145 @submission = Submission.find(params[:id])
146 146 if @submission.user!=@user
147 147 flash[:notice] = 'You are not allowed to view result of other users.'
148 148 redirect_to :action => 'list' and return
149 149 end
150 150 case_num = params[:num].to_i
151 151 out_filename = output_filename(@user.login,
152 152 @submission.problem.name,
153 153 @submission.id,
154 154 case_num)
155 155 if !FileTest.exists?(out_filename)
156 156 flash[:notice] = 'Output not found.'
157 157 redirect_to :action => 'list' and return
158 158 end
159 159
160 160 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
161 161 response.headers['Content-Type'] = "application/force-download"
162 162 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
163 163 response.headers["X-Sendfile"] = out_filename
164 164 response.headers['Content-length'] = File.size(out_filename)
165 165 render :nothing => true
166 166 else
167 167 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
168 168 end
169 169 end
170 170
171 171 def error
172 172 @user = User.find(session[:user_id])
173 173 end
174 174
175 175 # announcement refreshing and hiding methods
176 176
177 177 def announcements
178 178 if params.has_key? 'recent'
179 179 prepare_announcements(params[:recent])
180 180 else
181 181 prepare_announcements
182 182 end
183 183 render(:partial => 'announcement',
184 184 :collection => @announcements,
185 185 :locals => {:announcement_effect => true})
186 186 end
187 187
188 188 def confirm_contest_start
189 189 user = User.find(session[:user_id])
190 190 if request.method == 'POST'
191 191 user.update_start_time
192 192 redirect_to :action => 'list'
193 193 else
194 194 @contests = user.contests
195 195 @user = user
196 196 end
197 197 end
198 198
199 199 protected
200 200
201 201 def prepare_announcements(recent=nil)
202 202 if GraderConfiguration.show_tasks_to?(@user)
203 203 @announcements = Announcement.published(true)
204 204 else
205 205 @announcements = Announcement.published
206 206 end
207 207 if recent!=nil
208 208 recent_id = recent.to_i
209 209 @announcements = @announcements.find_all { |a| a.id > recent_id }
210 210 end
211 211 end
212 212
213 213 def prepare_list_information
214 214 @user = User.find(session[:user_id])
215 215 if not GraderConfiguration.multicontests?
216 216 @problems = @user.available_problems
217 217 else
218 218 @contest_problems = @user.available_problems_group_by_contests
219 219 @problems = @user.available_problems
220 220 end
221 221 @prob_submissions = {}
222 222 @problems.each do |p|
223 223 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
224 224 if sub!=nil
225 225 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
226 226 else
227 227 @prob_submissions[p.id] = { :count => 0, :submission => nil }
228 228 end
229 229 end
230 230 prepare_announcements
231 231 end
232 232
233 233 def check_viewability
234 234 @user = User.find(session[:user_id])
235 235 if (!GraderConfiguration.show_tasks_to?(@user)) and
236 236 ((action_name=='submission') or (action_name=='submit'))
237 237 redirect_to :action => 'list' and return
238 238 end
239 239 end
240 240
241 241 def prepare_grading_result(submission)
242 242 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
243 243 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
244 244 else
245 245 # guess task info from problem.full_score
246 246 cases = submission.problem.full_score / 10
247 247 grading_info = {
248 248 'testruns' => cases,
249 249 'testcases' => cases
250 250 }
251 251 end
252 252 @test_runs = []
253 253 if grading_info['testruns'].is_a? Integer
254 254 trun_count = grading_info['testruns']
255 255 trun_count.times do |i|
256 256 @test_runs << [ read_grading_result(@user.login,
257 257 submission.problem.name,
258 258 submission.id,
259 259 i+1) ]
260 260 end
261 261 else
262 262 grading_info['testruns'].keys.sort.each do |num|
263 263 run = []
264 264 testrun = grading_info['testruns'][num]
265 265 testrun.each do |c|
266 266 run << read_grading_result(@user.login,
267 267 submission.problem.name,
268 268 submission.id,
269 269 c)
270 270 end
271 271 @test_runs << run
272 272 end
273 273 end
274 274 end
275 275
276 276 def grading_result_dir(user_name, problem_name, submission_id, case_num)
277 277 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
278 278 end
279 279
280 280 def output_filename(user_name, problem_name, submission_id, case_num)
281 281 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
282 282 return "#{dir}/output.txt"
283 283 end
284 284
285 285 def read_grading_result(user_name, problem_name, submission_id, case_num)
286 286 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
287 287 result_file_name = "#{dir}/result"
288 288 if !FileTest.exists?(result_file_name)
289 289 return {:num => case_num, :msg => 'program did not run'}
290 290 else
291 291 results = File.open(result_file_name).readlines
292 292 run_stat = extract_running_stat(results)
293 293 output_filename = "#{dir}/output.txt"
294 294 if FileTest.exists?(output_filename)
295 295 output_file = true
296 296 output_size = File.size(output_filename)
297 297 else
298 298 output_file = false
299 299 output_size = 0
300 300 end
301 301
@@ -1,236 +1,236
1 1 %h2 Live submit
2 2 %br
3 3
4 - %textarea#text_haha{style: "display:none"}~ @source
4 + %textarea#text_sourcecode{style: "display:none"}~ @source
5 5 .container
6 6 .row
7 7 .col-md-12
8 8 .alert.alert-info
9 9 Write your code in the following box, choose language, and click submit button when finished
10 10 .row
11 11 .col-md-8
12 12 %div#editor{style: 'height: 500px; border-radius: 7px; font-size: 14px;'}
13 13 .col-md-4
14 14 = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form') do
15 15
16 16 = hidden_field_tag 'editor_text', @source
17 17 = hidden_field_tag 'submission[problem_id]', @problem.id
18 18 .form-group
19 19 = label_tag "Task:"
20 20 = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true
21 21
22 22 .form-group
23 23 = label_tag 'Language'
24 24 = select_tag 'language_id', options_from_collection_for_select(Language.all, 'id', 'pretty_name', @lang_id || Language.find_by_pretty_name("Python").id || Language.first.id), class: 'form-control select', style: "width: 100px"
25 25 .form-group
26 26 = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit',
27 27 data: {confirm: "Submitting this source code for task #{@problem.long_name}?"}
28 28 .panel.panel-info
29 29 .panel-heading
30 30 Latest Submission Status
31 31 = link_to "Refresh",get_latest_submission_status_submissions_path(@submission.user,@problem), class: "btn btn-default btn-sm", remote: true if @submission
32 32 .panel-body
33 33 - if @submission
34 34 = render :partial => 'submission_short',
35 35 :locals => {submission: @submission, problem_name: @problem.name, problem_id: @problem.id }
36 36 .row
37 37 .col-md-12
38 38 %h2 Console
39 39 %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20}
40 40
41 41 :javascript
42 42 $(document).ready(function() {
43 43 e = ace.edit("editor")
44 - e.setValue($("#text_haha").val());
44 + e.setValue($("#text_sourcecode").val());
45 45 e.gotoLine(1);
46 46 $("#language_id").trigger('change');
47 47 brython();
48 48 });
49 49
50 50
51 51 %script#__main__{type:'text/python3'}
52 52 :plain
53 53 import sys
54 54 import traceback
55 55
56 56 from browser import document as doc
57 57 from browser import window, alert, console
58 58
59 59 _credits = """ Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
60 60 for supporting Python development. See www.python.org for more information."""
61 61
62 62 _copyright = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com
63 63 All Rights Reserved.
64 64
65 65 Copyright (c) 2001-2013 Python Software Foundation.
66 66 All Rights Reserved.
67 67
68 68 Copyright (c) 2000 BeOpen.com.
69 69 All Rights Reserved.
70 70
71 71 Copyright (c) 1995-2001 Corporation for National Research Initiatives.
72 72 All Rights Reserved.
73 73
74 74 Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
75 75 All Rights Reserved."""
76 76
77 77 _license = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com
78 78 All rights reserved.
79 79
80 80 Redistribution and use in source and binary forms, with or without
81 81 modification, are permitted provided that the following conditions are met:
82 82
83 83 Redistributions of source code must retain the above copyright notice, this
84 84 list of conditions and the following disclaimer. Redistributions in binary
85 85 form must reproduce the above copyright notice, this list of conditions and
86 86 the following disclaimer in the documentation and/or other materials provided
87 87 with the distribution.
88 88 Neither the name of the <ORGANIZATION> nor the names of its contributors may
89 89 be used to endorse or promote products derived from this software without
90 90 specific prior written permission.
91 91
92 92 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
93 93 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94 94 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
95 95 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
96 96 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
97 97 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
98 98 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
99 99 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
100 100 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 101 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
102 102 POSSIBILITY OF SUCH DAMAGE.
103 103 """
104 104
105 105 def credits():
106 106 print(_credits)
107 107 credits.__repr__ = lambda:_credits
108 108
109 109 def copyright():
110 110 print(_copyright)
111 111 copyright.__repr__ = lambda:_copyright
112 112
113 113 def license():
114 114 print(_license)
115 115 license.__repr__ = lambda:_license
116 116
117 117 def write(data):
118 118 doc['console'].value += str(data)
119 119
120 120
121 121 sys.stdout.write = sys.stderr.write = write
122 122 history = []
123 123 current = 0
124 124 _status = "main" # or "block" if typing inside a block
125 125
126 126 # execution namespace
127 127 editor_ns = {'credits':credits,
128 128 'copyright':copyright,
129 129 'license':license,
130 130 '__name__':'__main__'}
131 131
132 132 def cursorToEnd(*args):
133 133 pos = len(doc['console'].value)
134 134 doc['console'].setSelectionRange(pos, pos)
135 135 doc['console'].scrollTop = doc['console'].scrollHeight
136 136
137 137 def get_col(area):
138 138 # returns the column num of cursor
139 139 sel = doc['console'].selectionStart
140 140 lines = doc['console'].value.split('\n')
141 141 for line in lines[:-1]:
142 142 sel -= len(line) + 1
143 143 return sel
144 144
145 145
146 146 def myKeyPress(event):
147 147 global _status, current
148 148 if event.keyCode == 9: # tab key
149 149 event.preventDefault()
150 150 doc['console'].value += " "
151 151 elif event.keyCode == 13: # return
152 152 src = doc['console'].value
153 153 if _status == "main":
154 154 currentLine = src[src.rfind('>>>') + 4:]
155 155 elif _status == "3string":
156 156 currentLine = src[src.rfind('>>>') + 4:]
157 157 currentLine = currentLine.replace('\n... ', '\n')
158 158 else:
159 159 currentLine = src[src.rfind('...') + 4:]
160 160 if _status == 'main' and not currentLine.strip():
161 161 doc['console'].value += '\n>>> '
162 162 event.preventDefault()
163 163 return
164 164 doc['console'].value += '\n'
165 165 history.append(currentLine)
166 166 current = len(history)
167 167 if _status == "main" or _status == "3string":
168 168 try:
169 169 _ = editor_ns['_'] = eval(currentLine, editor_ns)
170 170 if _ is not None:
171 171 write(repr(_)+'\n')
172 172 doc['console'].value += '>>> '
173 173 _status = "main"
174 174 except IndentationError:
175 175 doc['console'].value += '... '
176 176 _status = "block"
177 177 except SyntaxError as msg:
178 178 if str(msg) == 'invalid syntax : triple string end not found' or \
179 179 str(msg).startswith('Unbalanced bracket'):
180 180 doc['console'].value += '... '
181 181 _status = "3string"
182 182 elif str(msg) == 'eval() argument must be an expression':
183 183 try:
184 184 exec(currentLine, editor_ns)
185 185 except:
186 186 traceback.print_exc()
187 187 doc['console'].value += '>>> '
188 188 _status = "main"
189 189 elif str(msg) == 'decorator expects function':
190 190 doc['console'].value += '... '
191 191 _status = "block"
192 192 else:
193 193 traceback.print_exc()
194 194 doc['console'].value += '>>> '
195 195 _status = "main"
196 196 except:
197 197 traceback.print_exc()
198 198 doc['console'].value += '>>> '
199 199 _status = "main"
200 200 elif currentLine == "": # end of block
201 201 block = src[src.rfind('>>>') + 4:].splitlines()
202 202 block = [block[0]] + [b[4:] for b in block[1:]]
203 203 block_src = '\n'.join(block)
204 204 # status must be set before executing code in globals()
205 205 _status = "main"
206 206 try:
207 207 _ = exec(block_src, editor_ns)
208 208 if _ is not None:
209 209 print(repr(_))
210 210 except:
211 211 traceback.print_exc()
212 212 doc['console'].value += '>>> '
213 213 else:
214 214 doc['console'].value += '... '
215 215
216 216 cursorToEnd()
217 217 event.preventDefault()
218 218
219 219 def myKeyDown(event):
220 220 global _status, current
221 221 if event.keyCode == 37: # left arrow
222 222 sel = get_col(doc['console'])
223 223 if sel < 5:
224 224 event.preventDefault()
225 225 event.stopPropagation()
226 226 elif event.keyCode == 36: # line start
227 227 pos = doc['console'].selectionStart
228 228 col = get_col(doc['console'])
229 229 doc['console'].setSelectionRange(pos - col + 4, pos - col + 4)
230 230 event.preventDefault()
231 231 elif event.keyCode == 38: # up
232 232 if current > 0:
233 233 pos = doc['console'].selectionStart
234 234 col = get_col(doc['console'])
235 235 # remove current line
236 236 doc['console'].value = doc['console'].value[:pos - col + 4]
deleted file
deleted file
deleted file
You need to be logged in to leave comments. Login now