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: 24 inserted, 10 deleted

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