Description:
fix allow admin to submit to any problem
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r682:405106fcdb33 - - 7 files changed: 18 inserted, 6 deleted

@@ -1,185 +1,185
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 - if @submission.valid?
89 + if @submission.valid?(@current_user)
90 90 if @submission.save == false
91 91 flash[:notice] = 'Error saving your submission'
92 92 elsif Task.create(:submission_id => @submission.id,
93 93 :status => Task::STATUS_INQUEUE) == false
94 94 flash[:notice] = 'Error adding your submission to task queue'
95 95 end
96 96 else
97 97 prepare_list_information
98 98 render :action => 'list' and return
99 99 end
100 100 redirect_to :action => 'list'
101 101 end
102 102
103 103 def source
104 104 submission = Submission.find(params[:id])
105 105 if ((submission.user_id == session[:user_id]) and
106 106 (submission.problem != nil) and
107 107 (submission.problem.available))
108 108 send_data(submission.source,
109 109 {:filename => submission.download_filename,
110 110 :type => 'text/plain'})
111 111 else
112 112 flash[:notice] = 'Error viewing source'
113 113 redirect_to :action => 'list'
114 114 end
115 115 end
116 116
117 117 def compiler_msg
118 118 @submission = Submission.find(params[:id])
119 119 if @submission.user_id == session[:user_id]
120 120 render :action => 'compiler_msg', :layout => 'empty'
121 121 else
122 122 flash[:notice] = 'Error viewing source'
123 123 redirect_to :action => 'list'
124 124 end
125 125 end
126 126
127 127 def 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})
@@ -1,108 +1,113
1 1 class SubmissionsController < ApplicationController
2 2 before_action :authenticate
3 3 before_action :submission_authorization, only: [:show, :direct_edit_submission, :download, :edit]
4 4 before_action :admin_authorization, only: [:rejudge]
5 5
6 6 # GET /submissions
7 7 # GET /submissions.json
8 8 # Show problem selection and user's submission of that problem
9 9 def index
10 10 @user = @current_user
11 11 @problems = @user.available_problems
12 12
13 13 if params[:problem_id]==nil
14 14 @problem = nil
15 15 @submissions = nil
16 16 else
17 17 @problem = Problem.find_by_id(params[:problem_id])
18 18 if (@problem == nil) or (not @problem.available)
19 19 redirect_to main_list_path
20 20 flash[:notice] = 'Error: submissions for that problem are not viewable.'
21 21 return
22 22 end
23 23 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
24 24 end
25 25 end
26 26
27 27 # GET /submissions/1
28 28 # GET /submissions/1.json
29 29 def show
30 30 @submission = Submission.find(params[:id])
31 31
32 32 #log the viewing
33 33 user = User.find(session[:user_id])
34 34 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
35 35
36 36 @task = @submission.task
37 37 end
38 38
39 39 def download
40 40 @submission = Submission.find(params[:id])
41 41 send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'})
42 42 end
43 43
44 44 def compiler_msg
45 45 @submission = Submission.find(params[:id])
46 46 respond_to do |format|
47 47 format.js
48 48 end
49 49 end
50 50
51 51 #on-site new submission on specific problem
52 52 def direct_edit_problem
53 53 @problem = Problem.find(params[:problem_id])
54 54 @source = ''
55 + if (params[:user_id])
56 + u = User.find(params[:user_id])
57 + @submission = Submission.find_last_by_user_and_problem(u.id,@problem.id)
58 + @source = @submission.source.to_s if @submission and @submission.source
59 + end
55 60 render 'edit'
56 61 end
57 62
58 63 # GET /submissions/1/edit
59 64 def edit
60 65 @submission = Submission.find(params[:id])
61 66 @source = @submission.source.to_s
62 67 @problem = @submission.problem
63 68 @lang_id = @submission.language.id
64 69 end
65 70
66 71
67 72 def get_latest_submission_status
68 73 @problem = Problem.find(params[:pid])
69 74 @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
70 75 puts User.find(params[:uid]).login
71 76 puts Problem.find(params[:pid]).name
72 77 puts 'nil' unless @submission
73 78 respond_to do |format|
74 79 format.js
75 80 end
76 81 end
77 82
78 83 # GET /submissions/:id/rejudge
79 84 def rejudge
80 85 @submission = Submission.find(params[:id])
81 86 @task = @submission.task
82 87 @task.status_inqueue! if @task
83 88 respond_to do |format|
84 89 format.js
85 90 end
86 91 end
87 92
88 93 protected
89 94
90 95 def submission_authorization
91 96 #admin always has privileged
92 97 if @current_user.admin?
93 98 return true
94 99 end
95 100
96 101 sub = Submission.find(params[:id])
97 102 if sub.problem.available?
98 103 puts "sub = #{sub.user.id}, current = #{@current_user.id}"
99 104 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
100 105 end
101 106
102 107 #default to NO
103 108 unauthorized_redirect
104 109 return false
105 110 end
106 111
107 112
108 113 end
@@ -44,119 +44,123
44 44 problems = Problem.available_problems
45 45 problems.each do |problem|
46 46 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
47 47 submissions << sub if sub!=nil
48 48 end
49 49 submissions
50 50 end
51 51
52 52 def self.find_by_user_problem_number(user_id, problem_id, number)
53 53 where("user_id = ? AND problem_id = ? AND number = ?",user_id,problem_id,number).first
54 54 end
55 55
56 56 def self.find_all_by_user_problem(user_id, problem_id)
57 57 where("user_id = ? AND problem_id = ?",user_id,problem_id)
58 58 end
59 59
60 60 def download_filename
61 61 if self.problem.output_only
62 62 return self.source_filename
63 63 else
64 64 timestamp = self.submitted_at.localtime.strftime("%H%M%S")
65 65 return "#{self.problem.name}-#{timestamp}.#{self.language.ext}"
66 66 end
67 67 end
68 68
69 69 protected
70 70
71 71 def self.find_option_in_source(option, source)
72 72 if source==nil
73 73 return nil
74 74 end
75 75 i = 0
76 76 source.each_line do |s|
77 77 if s =~ option
78 78 words = s.split
79 79 return words[1]
80 80 end
81 81 i = i + 1
82 82 if i==10
83 83 return nil
84 84 end
85 85 end
86 86 return nil
87 87 end
88 88
89 89 def self.find_language_in_source(source, source_filename="")
90 90 langopt = find_option_in_source(/^LANG:/,source)
91 91 if langopt
92 92 return (Language.find_by_name(langopt) ||
93 93 Language.find_by_pretty_name(langopt))
94 94 else
95 95 if source_filename
96 96 return Language.find_by_extension(source_filename.split('.').last)
97 97 else
98 98 return nil
99 99 end
100 100 end
101 101 end
102 102
103 103 def self.find_problem_in_source(source, source_filename="")
104 104 prob_opt = find_option_in_source(/^TASK:/,source)
105 105 if problem = Problem.find_by_name(prob_opt)
106 106 return problem
107 107 else
108 108 if source_filename
109 109 return Problem.find_by_name(source_filename.split('.').first)
110 110 else
111 111 return nil
112 112 end
113 113 end
114 114 end
115 115
116 116 def assign_problem
117 117 if self.problem_id!=-1
118 118 begin
119 119 self.problem = Problem.find(self.problem_id)
120 120 rescue ActiveRecord::RecordNotFound
121 121 self.problem = nil
122 122 end
123 123 else
124 124 self.problem = Submission.find_problem_in_source(self.source,
125 125 self.source_filename)
126 126 end
127 127 end
128 128
129 129 def assign_language
130 130 self.language = Submission.find_language_in_source(self.source,
131 131 self.source_filename)
132 132 end
133 133
134 134 # validation codes
135 135 def must_specify_language
136 136 return if self.source==nil
137 137
138 138 # for output_only tasks
139 139 return if self.problem!=nil and self.problem.output_only
140 -
140 +
141 141 if self.language==nil
142 142 errors.add('source',"Cannot detect language. Did you submit a correct source file?") unless self.language!=nil
143 143 end
144 144 end
145 145
146 146 def must_have_valid_problem
147 147 return if self.source==nil
148 148 if self.problem==nil
149 149 errors.add('problem',"must be specified.")
150 - elsif (!self.problem.available) and (self.new_record?)
151 - errors.add('problem',"must be valid.")
150 + else
151 + #admin always have right
152 + return if self.user.admin?
153 +
154 + #check if user has the right to submit the problem
155 + errors.add('problem',"must be valid.") if (!self.user.available_problem.include?(self.problem)) and (self.new_record?)
152 156 end
153 157 end
154 158
155 159 # callbacks
156 160 def assign_latest_number_if_new_recond
157 161 return if !self.new_record?
158 162 latest = Submission.find_last_by_user_and_problem(self.user_id, self.problem_id)
159 163 self.number = (latest==nil) ? 1 : latest.number + 1;
160 164 end
161 165
162 166 end
@@ -199,192 +199,193
199 199 time_limit = GraderConfiguration.contest_time_limit
200 200 if time_limit == nil
201 201 return nil
202 202 end
203 203 if contest_stat==nil or contest_stat.started_at==nil
204 204 return (Time.now.gmtime + time_limit) - Time.now.gmtime
205 205 else
206 206 finish_time = contest_stat.started_at + time_limit
207 207 current_time = Time.now.gmtime
208 208 if current_time > finish_time
209 209 return 0
210 210 else
211 211 return finish_time - current_time
212 212 end
213 213 end
214 214 else
215 215 return nil
216 216 end
217 217 end
218 218
219 219 def contest_finished?
220 220 if GraderConfiguration.contest_mode?
221 221 return false if site==nil
222 222 return site.finished?
223 223 elsif GraderConfiguration.indv_contest_mode?
224 224 return false if self.contest_stat(true)==nil
225 225 return contest_time_left == 0
226 226 else
227 227 return false
228 228 end
229 229 end
230 230
231 231 def contest_started?
232 232 if GraderConfiguration.indv_contest_mode?
233 233 stat = self.contest_stat
234 234 return ((stat != nil) and (stat.started_at != nil))
235 235 elsif GraderConfiguration.contest_mode?
236 236 return true if site==nil
237 237 return site.started
238 238 else
239 239 return true
240 240 end
241 241 end
242 242
243 243 def update_start_time
244 244 stat = self.contest_stat
245 245 if stat.nil? or stat.started_at.nil?
246 246 stat ||= UserContestStat.new(:user => self)
247 247 stat.started_at = Time.now.gmtime
248 248 stat.save
249 249 end
250 250 end
251 251
252 252 def problem_in_user_contests?(problem)
253 253 problem_contests = problem.contests.all
254 254
255 255 if problem_contests.length == 0 # this is public contest
256 256 return true
257 257 end
258 258
259 259 contests.each do |contest|
260 260 if problem_contests.find {|c| c.id == contest.id }
261 261 return true
262 262 end
263 263 end
264 264 return false
265 265 end
266 266
267 267 def available_problems_group_by_contests
268 268 contest_problems = []
269 269 pin = {}
270 270 contests.enabled.each do |contest|
271 271 available_problems = contest.problems.available
272 272 contest_problems << {
273 273 :contest => contest,
274 274 :problems => available_problems
275 275 }
276 276 available_problems.each {|p| pin[p.id] = true}
277 277 end
278 278 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
279 279 contest_problems << {
280 280 :contest => nil,
281 281 :problems => other_avaiable_problems
282 282 }
283 283 return contest_problems
284 284 end
285 285
286 286 def solve_all_available_problems?
287 287 available_problems.each do |p|
288 288 u = self
289 289 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
290 290 return false if !p or !sub or sub.points < p.full_score
291 291 end
292 292 return true
293 293 end
294 294
295 + #get a list of available problem
295 296 def available_problems
296 297 if not GraderConfiguration.multicontests?
297 298 if GraderConfiguration.use_problem_group?
298 299 return available_problems_in_group
299 300 else
300 301 return Problem.available_problems
301 302 end
302 303 else
303 304 contest_problems = []
304 305 pin = {}
305 306 contests.enabled.each do |contest|
306 307 contest.problems.available.each do |problem|
307 308 if not pin.has_key? problem.id
308 309 contest_problems << problem
309 310 end
310 311 pin[problem.id] = true
311 312 end
312 313 end
313 314 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
314 315 return contest_problems + other_avaiable_problems
315 316 end
316 317 end
317 318
318 319 def available_problems_in_group
319 320 problem = []
320 321 self.groups.each do |group|
321 322 group.problems.where(available: true).each { |p| problem << p }
322 323 end
323 324 problem.uniq!
324 325 if problem
325 326 problem.sort! do |a,b|
326 327 case
327 328 when a.date_added < b.date_added
328 329 1
329 330 when a.date_added > b.date_added
330 331 -1
331 332 else
332 333 a.name <=> b.name
333 334 end
334 335 end
335 336 return problem
336 337 else
337 338 return []
338 339 end
339 340 end
340 341
341 342 def can_view_problem?(problem)
342 343 return true if admin?
343 344 return available_problems.include? problem
344 345 end
345 346
346 347 def self.clear_last_login
347 348 User.update_all(:last_ip => nil)
348 349 end
349 350
350 351 protected
351 352 def encrypt_new_password
352 353 return if password.blank?
353 354 self.salt = (10+rand(90)).to_s
354 355 self.hashed_password = User.encrypt(self.password,self.salt)
355 356 end
356 357
357 358 def assign_default_site
358 359 # have to catch error when migrating (because self.site is not available).
359 360 begin
360 361 if self.site==nil
361 362 self.site = Site.find_by_name('default')
362 363 if self.site==nil
363 364 self.site = Site.find(1) # when 'default has be renamed'
364 365 end
365 366 end
366 367 rescue
367 368 end
368 369 end
369 370
370 371 def assign_default_contest
371 372 # have to catch error when migrating (because self.site is not available).
372 373 begin
373 374 if self.contests.length == 0
374 375 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
375 376 if default_contest
376 377 self.contests = [default_contest]
377 378 end
378 379 end
379 380 rescue
380 381 end
381 382 end
382 383
383 384 def password_required?
384 385 self.hashed_password.blank? || !self.password.blank?
385 386 end
386 387
387 388 def self.encrypt(string,salt)
388 389 Digest::SHA1.hexdigest(salt + string)
389 390 end
390 391
@@ -1,60 +1,60
1 1 - content_for :head do
2 2 = stylesheet_link_tag 'problems'
3 3 %h1 Problems
4 4 %p
5 5 = link_to 'Import problems', {:action => 'import'}, class: 'btn btn-success btn-sm'
6 6 = link_to 'New problem', new_problem_path, class: 'btn btn-success btn-sm'
7 7 = link_to 'Bulk Manage', { action: 'manage'}, class: 'btn btn-info btn-sm'
8 8 = link_to 'Turn off all problems', {:action => 'turn_all_off'}, class: 'btn btn-default btn-sm'
9 9 = link_to 'Turn on all problems', {:action => 'turn_all_on'}, class: 'btn btn-default btn-sm'
10 10 .submitbox
11 11 = form_tag :action => 'quick_create' do
12 12 %b Quick New:
13 13 %label{:for => "problem_name"} Name
14 14 = text_field 'problem', 'name'
15 15 |
16 16 %label{:for => "problem_full_name"} Full name
17 17 = text_field 'problem', 'full_name'
18 18 = submit_tag "Create"
19 19 %table.table.table-condense.table-hover
20 20 %thead
21 21 %th Name
22 22 %th Full name
23 23 %th.text-right Full score
24 24 %th
25 25 Submit
26 26 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Admin can always submit to any problem' } [?]
27 27 %th Date added
28 28 %th.text-center
29 29 Avail?
30 30 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
31 31 %th.text-center
32 32 View Data?
33 33 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user view the testcase of this problem?' } [?]
34 34 %th.text-center
35 35 Test?
36 36 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
37 37 - if GraderConfiguration.multicontests?
38 38 %th Contests
39 39 - for problem in @problems
40 40 %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
41 41 - @problem=problem
42 42 %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1
43 43 %td
44 44 = problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
45 45 = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, problem
46 46 %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1
47 - %td= link_to "Submit", direct_edit_problem_submissions_path(problem), class: 'btn btn-xs btn-primary'
47 + %td= link_to "Submit", direct_edit_problem_submissions_path(problem,@current_user.id), class: 'btn btn-xs btn-primary'
48 48 %td= problem.date_added
49 49 %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}")
50 50 %td= toggle_button(@problem.view_testcase?, toggle_view_testcase_problem_path(@problem), "problem-view-testcase-#{@problem.id}")
51 51 %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}")
52 52 - if GraderConfiguration.multicontests?
53 53 %td
54 54 = problem.contests.collect { |c| c.name }.join(', ')
55 55 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
56 56 %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
57 57 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block'
58 58 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
59 59 %br/
60 60 = link_to '[New problem]', :action => 'new'
@@ -1,123 +1,125
1 1 %h2 Live submit
2 2 %br
3 3
4 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 + - # submission form
14 15 = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form') do
15 16
16 17 = hidden_field_tag 'editor_text', @source
17 18 = hidden_field_tag 'submission[problem_id]', @problem.id
18 19 .form-group
19 20 = label_tag "Task:"
20 21 = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true
21 22
22 23 .form-group
23 24 = label_tag 'Language'
24 25 = 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 26 .form-group
26 27 = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit',
27 28 data: {confirm: "Submitting this source code for task #{@problem.long_name}?"}
29 + - # latest submission status
28 30 .panel.panel-info
29 31 .panel-heading
30 32 Latest Submission Status
31 33 = link_to "Refresh",get_latest_submission_status_submissions_path(@submission.user,@problem), class: "btn btn-default btn-sm", remote: true if @submission
32 34 .panel-body
33 35 - if @submission
34 36 = render :partial => 'submission_short',
35 37 :locals => {submission: @submission, problem_name: @problem.name, problem_id: @problem.id }
36 38 .row
37 39 .col-md-12
38 40 %h2 Console
39 41 %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20}
40 42
41 43 :javascript
42 44 $(document).ready(function() {
43 45 e = ace.edit("editor")
44 46 e.setValue($("#text_sourcecode").val());
45 47 e.gotoLine(1);
46 48 $("#language_id").trigger('change');
47 49 brython();
48 50 });
49 51
50 52
51 53 %script#__main__{type:'text/python3'}
52 54 :plain
53 55 import sys
54 56 import traceback
55 57
56 58 from browser import document as doc
57 59 from browser import window, alert, console
58 60
59 61 _credits = """ Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
60 62 for supporting Python development. See www.python.org for more information."""
61 63
62 64 _copyright = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com
63 65 All Rights Reserved.
64 66
65 67 Copyright (c) 2001-2013 Python Software Foundation.
66 68 All Rights Reserved.
67 69
68 70 Copyright (c) 2000 BeOpen.com.
69 71 All Rights Reserved.
70 72
71 73 Copyright (c) 1995-2001 Corporation for National Research Initiatives.
72 74 All Rights Reserved.
73 75
74 76 Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
75 77 All Rights Reserved."""
76 78
77 79 _license = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com
78 80 All rights reserved.
79 81
80 82 Redistribution and use in source and binary forms, with or without
81 83 modification, are permitted provided that the following conditions are met:
82 84
83 85 Redistributions of source code must retain the above copyright notice, this
84 86 list of conditions and the following disclaimer. Redistributions in binary
85 87 form must reproduce the above copyright notice, this list of conditions and
86 88 the following disclaimer in the documentation and/or other materials provided
87 89 with the distribution.
88 90 Neither the name of the <ORGANIZATION> nor the names of its contributors may
89 91 be used to endorse or promote products derived from this software without
90 92 specific prior written permission.
91 93
92 94 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
93 95 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94 96 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
95 97 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
96 98 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
97 99 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
98 100 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
99 101 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
100 102 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 103 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
102 104 POSSIBILITY OF SUCH DAMAGE.
103 105 """
104 106
105 107 def credits():
106 108 print(_credits)
107 109 credits.__repr__ = lambda:_credits
108 110
109 111 def copyright():
110 112 print(_copyright)
111 113 copyright.__repr__ = lambda:_copyright
112 114
113 115 def license():
114 116 print(_license)
115 117 license.__repr__ = lambda:_license
116 118
117 119 def write(data):
118 120 doc['console'].value += str(data)
119 121
120 122
121 123 sys.stdout.write = sys.stderr.write = write
122 124 history = []
123 125 current = 0
@@ -1,114 +1,114
1 1 CafeGrader::Application.routes.draw do
2 2 resources :tags
3 3 get "sources/direct_edit"
4 4
5 5 root :to => 'main#login'
6 6
7 7 #logins
8 8 get 'login/login', to: 'login#login'
9 9
10 10 resources :contests
11 11
12 12 resources :sites
13 13
14 14 resources :announcements do
15 15 member do
16 16 get 'toggle','toggle_front'
17 17 end
18 18 end
19 19
20 20 resources :problems do
21 21 member do
22 22 get 'toggle'
23 23 get 'toggle_test'
24 24 get 'toggle_view_testcase'
25 25 get 'stat'
26 26 end
27 27 collection do
28 28 get 'turn_all_off'
29 29 get 'turn_all_on'
30 30 get 'import'
31 31 get 'manage'
32 32 end
33 33 end
34 34
35 35 resources :groups do
36 36 member do
37 37 post 'add_user', to: 'groups#add_user', as: 'add_user'
38 38 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
39 39 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
40 40 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
41 41 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
42 42 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
43 43 end
44 44 collection do
45 45
46 46 end
47 47 end
48 48
49 49 resources :testcases, only: [] do
50 50 member do
51 51 get 'download_input'
52 52 get 'download_sol'
53 53 end
54 54 collection do
55 55 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
56 56 end
57 57 end
58 58
59 59 resources :grader_configuration, controller: 'configurations'
60 60
61 61 resources :users do
62 62 member do
63 63 get 'toggle_activate', 'toggle_enable'
64 64 get 'stat'
65 65 end
66 66 end
67 67
68 68 resources :submissions do
69 69 member do
70 70 get 'download'
71 71 get 'compiler_msg'
72 72 get 'rejudge'
73 73 end
74 74 collection do
75 75 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
76 - get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
76 + get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
77 77 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
78 78 end
79 79 end
80 80
81 81
82 82
83 83 #main
84 84 get "main/list"
85 85 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
86 86
87 87 #user admin
88 88 get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
89 89 post 'user_admin', to: 'user_admin#create'
90 90 delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
91 91
92 92 #report
93 93 get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
94 94 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
95 95 get "report/login"
96 96 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
97 97 post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
98 98
99 99
100 100 #
101 101 get 'tasks/view/:file.:ext' => 'tasks#view'
102 102 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
103 103 get 'heartbeat/:id/edit' => 'heartbeat#edit'
104 104
105 105 #grader
106 106 get 'graders/list', to: 'graders#list', as: 'grader_list'
107 107
108 108
109 109 # See how all your routes lay out with "rake routes"
110 110
111 111 # This is a legacy wild controller route that's not recommended for RESTful applications.
112 112 # Note: This route will make all actions in every controller accessible via GET requests.
113 113 match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
114 114 end
You need to be logged in to leave comments. Login now