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: 17 inserted, 5 deleted

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