Description:
autonew skips submissions with bad problems, forbids getch, better compiler msg when preprocessing fails, reports compile error when the executable is too large (100MB)
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r132:ca6ce454fda9 - - 2 files changed: 18 inserted, 4 deleted

@@ -156,192 +156,195
156 print ",#{problem.name}"
156 print ",#{problem.name}"
157 end
157 end
158 print "\n"
158 print "\n"
159
159
160 @users.each_value do |user|
160 @users.each_value do |user|
161 print "#{user.login},#{user.email}"
161 print "#{user.login},#{user.email}"
162 @problems.each_value do |problem|
162 @problems.each_value do |problem|
163 if @results.has_key? [user.id, problem.id]
163 if @results.has_key? [user.id, problem.id]
164 print ",#{@results[[user.id,problem.id]][:points]}"
164 print ",#{@results[[user.id,problem.id]][:points]}"
165 else
165 else
166 print ","
166 print ","
167 end
167 end
168 end
168 end
169 print "\n"
169 print "\n"
170 end
170 end
171 end
171 end
172 end
172 end
173
173
174 def grader_general_loop(engine, grader_proc, options)
174 def grader_general_loop(engine, grader_proc, options)
175 runner = Grader::Runner.new(engine, grader_proc)
175 runner = Grader::Runner.new(engine, grader_proc)
176 while true
176 while true
177
177
178 if check_stopfile # created by calling grader stop
178 if check_stopfile # created by calling grader stop
179 clear_stopfile
179 clear_stopfile
180 log "stopped (with stop file)"
180 log "stopped (with stop file)"
181 break
181 break
182 end
182 end
183
183
184 task = yield(runner)
184 task = yield(runner)
185
185
186 if task==nil
186 if task==nil
187 sleep(1)
187 sleep(1)
188 end
188 end
189 end
189 end
190 end
190 end
191
191
192 def grader_queue_loop(grader_proc, options)
192 def grader_queue_loop(grader_proc, options)
193 log "Grader: queue"
193 log "Grader: queue"
194 engine = Grader::Engine.new
194 engine = Grader::Engine.new
195 grader_general_loop(engine, grader_proc, options) do |runner|
195 grader_general_loop(engine, grader_proc, options) do |runner|
196 runner.grade_oldest_task
196 runner.grade_oldest_task
197 end
197 end
198 end
198 end
199
199
200 def grader_test_request_loop(grader_proc, options)
200 def grader_test_request_loop(grader_proc, options)
201 log "Grader: test_request"
201 log "Grader: test_request"
202 engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
202 engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
203 :reporter => Grader::TestRequestReporter.new)
203 :reporter => Grader::TestRequestReporter.new)
204 grader_general_loop(engine, grader_proc, options) do |runner|
204 grader_general_loop(engine, grader_proc, options) do |runner|
205 runner.grade_oldest_test_request
205 runner.grade_oldest_test_request
206 end
206 end
207 end
207 end
208
208
209 def grader_autonew_loop(grader_proc, options)
209 def grader_autonew_loop(grader_proc, options)
210 log "Grader: autonew"
210 log "Grader: autonew"
211
211
212 if options[:report]
212 if options[:report]
213 result_collector = ResultCollector.new
213 result_collector = ResultCollector.new
214 else
214 else
215 result_collector = nil
215 result_collector = nil
216 end
216 end
217
217
218 if options[:dry_run]
218 if options[:dry_run]
219 puts "Running in dry mode"
219 puts "Running in dry mode"
220 end
220 end
221
221
222 prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run],
222 prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run],
223 :result_collector => result_collector)
223 :result_collector => result_collector)
224
224
225 engine = Grader::Engine.new(:reporter => prob_reporter)
225 engine = Grader::Engine.new(:reporter => prob_reporter)
226 runner = Grader::Runner.new(engine, grader_proc)
226 runner = Grader::Runner.new(engine, grader_proc)
227
227
228 grader_proc.report_active if grader_proc!=nil
228 grader_proc.report_active if grader_proc!=nil
229
229
230 latest_submitted_at = nil
230 latest_submitted_at = nil
231 graded_submission_ids = {}
231 graded_submission_ids = {}
232
232
233 while true
233 while true
234
234
235 if check_stopfile # created by calling grader stop
235 if check_stopfile # created by calling grader stop
236 clear_stopfile
236 clear_stopfile
237 log "stopped (with stop file)"
237 log "stopped (with stop file)"
238 break
238 break
239 end
239 end
240
240
241 if latest_submitted_at==nil
241 if latest_submitted_at==nil
242 submissions = Submission.all
242 submissions = Submission.all
243 else
243 else
244 submissions = Submission.all(:conditions => ["submitted_at >= :latest",
244 submissions = Submission.all(:conditions => ["submitted_at >= :latest",
245 {:latest => latest_submitted_at}])
245 {:latest => latest_submitted_at}])
246 end
246 end
247
247
248 graded_any = false
248 graded_any = false
249
249
250 if submissions.length != 0
250 if submissions.length != 0
251 submissions.each do |submission|
251 submissions.each do |submission|
252 + if (submission.problem == nil) or (!submission.problem.available)
253 + next
254 + end
252 if ! graded_submission_ids[submission.id]
255 if ! graded_submission_ids[submission.id]
253 runner.grade_submission(submission)
256 runner.grade_submission(submission)
254 graded_submission_ids[submission.id] = true
257 graded_submission_ids[submission.id] = true
255 if (!latest_submitted_at or
258 if (!latest_submitted_at or
256 latest_submitted_at < submission.submitted_at)
259 latest_submitted_at < submission.submitted_at)
257 latest_submitted_at = submission.submitted_at
260 latest_submitted_at = submission.submitted_at
258 end
261 end
259 puts "graded: #{submission.id}"
262 puts "graded: #{submission.id}"
260 puts "latest: #{latest_submitted_at}"
263 puts "latest: #{latest_submitted_at}"
261 graded_any = true
264 graded_any = true
262 end
265 end
263 end
266 end
264 end
267 end
265
268
266 if ! graded_any
269 if ! graded_any
267 sleep(1)
270 sleep(1)
268 end
271 end
269 end
272 end
270 end
273 end
271
274
272 def grader_grade_problems(grader_proc, options)
275 def grader_grade_problems(grader_proc, options)
273 if options[:report]
276 if options[:report]
274 result_collector = ResultCollector.new
277 result_collector = ResultCollector.new
275 else
278 else
276 result_collector = nil
279 result_collector = nil
277 end
280 end
278
281
279 if options[:dry_run]
282 if options[:dry_run]
280 puts "Running in dry mode"
283 puts "Running in dry mode"
281 end
284 end
282
285
283 prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run],
286 prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run],
284 :result_collector => result_collector)
287 :result_collector => result_collector)
285 engine = Grader::Engine.new(:reporter => prob_reporter)
288 engine = Grader::Engine.new(:reporter => prob_reporter)
286 runner = Grader::Runner.new(engine, grader_proc)
289 runner = Grader::Runner.new(engine, grader_proc)
287
290
288 grader_proc.report_active if grader_proc!=nil
291 grader_proc.report_active if grader_proc!=nil
289
292
290 ARGV.each do |prob_name|
293 ARGV.each do |prob_name|
291 prob = Problem.find_by_name(prob_name)
294 prob = Problem.find_by_name(prob_name)
292 if prob==nil
295 if prob==nil
293 puts "cannot find problem: #{prob_name}"
296 puts "cannot find problem: #{prob_name}"
294 else
297 else
295 runner.grade_problem(prob)
298 runner.grade_problem(prob)
296 end
299 end
297 end
300 end
298
301
299 if options[:report]
302 if options[:report]
300 result_collector.print_report_by_user
303 result_collector.print_report_by_user
301 end
304 end
302 end
305 end
303
306
304 def grader_grade_contests(grader_proc, options)
307 def grader_grade_contests(grader_proc, options)
305 # always use dry run when grading during contest
308 # always use dry run when grading during contest
306 dry_run = options[:dry_run] = true
309 dry_run = options[:dry_run] = true
307
310
308 contest_name = ARGV.shift
311 contest_name = ARGV.shift
309
312
310 contest = Contest.find_by_name(contest_name)
313 contest = Contest.find_by_name(contest_name)
311 if contest==nil
314 if contest==nil
312 puts "cannot find contest: #{contest_name}"
315 puts "cannot find contest: #{contest_name}"
313 exit(0)
316 exit(0)
314 end
317 end
315
318
316 if options[:report]
319 if options[:report]
317 result_collector = ResultCollector.new
320 result_collector = ResultCollector.new
318 else
321 else
319 result_collector = nil
322 result_collector = nil
320 end
323 end
321
324
322 if options[:dry_run]
325 if options[:dry_run]
323 puts "Running in dry mode"
326 puts "Running in dry mode"
324 end
327 end
325
328
326 prob_reporter = Grader::SubmissionReporter.new(:dry_run => dry_run,
329 prob_reporter = Grader::SubmissionReporter.new(:dry_run => dry_run,
327 :result_collector => result_collector)
330 :result_collector => result_collector)
328 engine = Grader::Engine.new(:reporter => prob_reporter)
331 engine = Grader::Engine.new(:reporter => prob_reporter)
329 runner = Grader::Runner.new(engine, grader_proc)
332 runner = Grader::Runner.new(engine, grader_proc)
330
333
331 grader_proc.report_active if grader_proc!=nil
334 grader_proc.report_active if grader_proc!=nil
332
335
333 contest.problems.each do |problem|
336 contest.problems.each do |problem|
334 puts "Grading: #{problem.name}"
337 puts "Grading: #{problem.name}"
335 runner.grade_problem(problem,
338 runner.grade_problem(problem,
336 :user_conditions => lambda do |u|
339 :user_conditions => lambda do |u|
337 u.contest_finished? and
340 u.contest_finished? and
338 u.contest_ids.include?(contest.id)
341 u.contest_ids.include?(contest.id)
339 end)
342 end)
340 end
343 end
341
344
342 if options[:report]
345 if options[:report]
343 result_collector.print_report_by_user
346 result_collector.print_report_by_user
344 end
347 end
345 end
348 end
346
349
347 def grader_grade_submissions(grader_proc, options)
350 def grader_grade_submissions(grader_proc, options)
@@ -1,130 +1,141
1 #!/usr/bin/ruby
1 #!/usr/bin/ruby
2
2
3 require 'fileutils'
3 require 'fileutils'
4
4
5 ##############################
5 ##############################
6 #
6 #
7 # Standard Compile Script
7 # Standard Compile Script
8 #
8 #
9 # Supported compilers:
9 # Supported compilers:
10 # gcc, g++, and fpc.
10 # gcc, g++, and fpc.
11 #
11 #
12 ##############################
12 ##############################
13
13
14 def talk(msg)
14 def talk(msg)
15 if ENV['TALKATIVE']!=nil
15 if ENV['TALKATIVE']!=nil
16 puts str
16 puts str
17 end
17 end
18
18
19 if ENV['GRADER_LOGGING']!=nil
19 if ENV['GRADER_LOGGING']!=nil
20 log_fname = ENV['GRADER_LOGGING']
20 log_fname = ENV['GRADER_LOGGING']
21 fp = File.open(log_fname,"a")
21 fp = File.open(log_fname,"a")
22 fp.puts("run: #{Time.new.strftime("%H:%M")} #{msg}")
22 fp.puts("run: #{Time.new.strftime("%H:%M")} #{msg}")
23 fp.close
23 fp.close
24 end
24 end
25 end
25 end
26
26
27 C_COMPILER = "gcc"
27 C_COMPILER = "gcc"
28 CPLUSPLUS_COMPILER = "g++"
28 CPLUSPLUS_COMPILER = "g++"
29 PASCAL_COMPILER = "fpc"
29 PASCAL_COMPILER = "fpc"
30
30
31 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
31 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
32 CPLUSPLUS_OPTIONS = "-O2 -s -static -DCONTEST -lm -Wall"
32 CPLUSPLUS_OPTIONS = "-O2 -s -static -DCONTEST -lm -Wall"
33 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
33 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
34
34
35 # Check for the correct number of arguments. Otherwise, print usage.
35 # Check for the correct number of arguments. Otherwise, print usage.
36 if ARGV.length == 0 or ARGV.length > 4
36 if ARGV.length == 0 or ARGV.length > 4
37 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
37 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
38 puts
38 puts
39 puts "<source-file> is defaulted to \"source\"."
39 puts "<source-file> is defaulted to \"source\"."
40 puts "<output-file> is defaulted to \"a.out\"."
40 puts "<output-file> is defaulted to \"a.out\"."
41 puts "<message-file> is defaulted to \"compiler_message\"."
41 puts "<message-file> is defaulted to \"compiler_message\"."
42 puts
42 puts
43 exit(127)
43 exit(127)
44 end
44 end
45
45
46 PARAMS = {
46 PARAMS = {
47 :source_file => [1,'source'],
47 :source_file => [1,'source'],
48 :output_file => [2,'a.out'],
48 :output_file => [2,'a.out'],
49 :message_file => [3,'compiler_message']
49 :message_file => [3,'compiler_message']
50 }
50 }
51
51
52 params = {}
52 params = {}
53 params[:prog_lang] = ARGV[0]
53 params[:prog_lang] = ARGV[0]
54 PARAMS.each_key do |param_name|
54 PARAMS.each_key do |param_name|
55 index, default = PARAMS[param_name]
55 index, default = PARAMS[param_name]
56 if ARGV.length > index
56 if ARGV.length > index
57 params[param_name] = ARGV[index]
57 params[param_name] = ARGV[index]
58 else
58 else
59 params[param_name] = default
59 params[param_name] = default
60 end
60 end
61 talk "#{param_name}: #{params[param_name]}"
61 talk "#{param_name}: #{params[param_name]}"
62 end
62 end
63
63
64 # Remove any remaining output files or message files.
64 # Remove any remaining output files or message files.
65 if FileTest.exists? params[:output_file]
65 if FileTest.exists? params[:output_file]
66 FileUtils.rm(params[:output_file])
66 FileUtils.rm(params[:output_file])
67 end
67 end
68 if FileTest.exists? params[:message_file]
68 if FileTest.exists? params[:message_file]
69 FileUtils.rm(params[:message_file])
69 FileUtils.rm(params[:message_file])
70 end
70 end
71
71
72 # Check if the source file exists before attempt compiling.
72 # Check if the source file exists before attempt compiling.
73 if !FileTest.exists? params[:source_file]
73 if !FileTest.exists? params[:source_file]
74 talk("ERROR: The source file does not exist!")
74 talk("ERROR: The source file does not exist!")
75 open(params[:message_file],"w") do |f|
75 open(params[:message_file],"w") do |f|
76 f.puts "ERROR: The source file did not exist."
76 f.puts "ERROR: The source file did not exist."
77 end
77 end
78 exit(127)
78 exit(127)
79 end
79 end
80
80
81 if params[:prog_lang]=='cpp':
81 if params[:prog_lang]=='cpp':
82 params[:prog_lang] = 'c++'
82 params[:prog_lang] = 'c++'
83 end
83 end
84
84
85 - forbidden_functions = ['system', 'fopen', 'freopen', 'open', 'remove', 'rename']
85 + forbidden_functions = ['system', 'fopen', 'freopen', 'open', 'remove', 'rename', 'getch']
86 redefine_list = []
86 redefine_list = []
87 forbidden_count = 0
87 forbidden_count = 0
88 forbidden_key = (rand(8999) + 1000).to_s
88 forbidden_key = (rand(8999) + 1000).to_s
89 forbidden_functions.each do |f|
89 forbidden_functions.each do |f|
90 redefine_list << "-D#{f}=forbidden#{forbidden_key}#{forbidden_count}"
90 redefine_list << "-D#{f}=forbidden#{forbidden_key}#{forbidden_count}"
91 forbidden_count += 1
91 forbidden_count += 1
92 end
92 end
93 redefine_str = redefine_list.join ' '
93 redefine_str = redefine_list.join ' '
94 puts redefine_str
94 puts redefine_str
95
95
96 # Compile.
96 # Compile.
97 case params[:prog_lang]
97 case params[:prog_lang]
98
98
99 when "c"
99 when "c"
100 - command = "#{C_COMPILER} -E #{params[:source_file]} -o source_prep.c"
100 + command = "#{C_COMPILER} -E #{params[:source_file]} -o source_prep.c 2> #{params[:message_file]}"
101 system(command)
101 system(command)
102 + if FileTest.exist? "source_prep.c"
102 command = "#{C_COMPILER} source_prep.c #{redefine_str} -o #{params[:output_file]} #{C_OPTIONS} 2> #{params[:message_file]}"
103 command = "#{C_COMPILER} source_prep.c #{redefine_str} -o #{params[:output_file]} #{C_OPTIONS} 2> #{params[:message_file]}"
103 - puts command
104 system(command)
104 system(command)
105 + end
105
106
106 when "c++"
107 when "c++"
107 - command = "#{CPLUSPLUS_COMPILER} -E #{params[:source_file]} -o source_prep.cpp"
108 + command = "#{CPLUSPLUS_COMPILER} -E #{params[:source_file]} -o source_prep.cpp 2> #{params[:message_file]}"
108 system(command)
109 system(command)
110 + if FileTest.exist? "source_prep.cpp"
109 command = "#{CPLUSPLUS_COMPILER} #{redefine_str} source_prep.cpp -o #{params[:output_file]} #{CPLUSPLUS_OPTIONS} 2> #{params[:message_file]}"
111 command = "#{CPLUSPLUS_COMPILER} #{redefine_str} source_prep.cpp -o #{params[:output_file]} #{CPLUSPLUS_OPTIONS} 2> #{params[:message_file]}"
110 system(command)
112 system(command)
113 + end
111
114
112 when "pas"
115 when "pas"
113 command = "#{PASCAL_COMPILER} #{params[:source_file]} -ooutpas #{PASCAL_OPTIONS} > #{params[:message_file]}"
116 command = "#{PASCAL_COMPILER} #{params[:source_file]} -ooutpas #{PASCAL_OPTIONS} > #{params[:message_file]}"
114 system(command)
117 system(command)
115 FileUtils.mv("output", params[:output_file])
118 FileUtils.mv("output", params[:output_file])
116
119
117 else
120 else
118 talk("ERROR: Invalid language specified!")
121 talk("ERROR: Invalid language specified!")
119 open(params[:message_file],"w") do |f|
122 open(params[:message_file],"w") do |f|
120 f.puts "ERROR: Invalid language specified!"
123 f.puts "ERROR: Invalid language specified!"
121 end
124 end
122 exit(127)
125 exit(127)
123 end
126 end
124
127
125 # Report success or failure.
128 # Report success or failure.
126 if FileTest.exists? params[:output_file]
129 if FileTest.exists? params[:output_file]
127 talk "Compilation was successful!"
130 talk "Compilation was successful!"
131 +
132 + if File.size(params[:output_file]) > 100000000
133 + talk "But the executable is too big."
134 + open(params[:message_file],"w+") do |f|
135 + f.puts "Executable is too large."
136 + end
137 + File.delete(params[:output_file])
138 + end
128 else
139 else
129 talk "ERROR: Something was wrong during the compilation!"
140 talk "ERROR: Something was wrong during the compilation!"
130 end
141 end
You need to be logged in to leave comments. Login now