Description:
handle the case when problem id or submission id is null. Grader will simply skip such request. Add more report on console (for command line grading) (mercurial grafted from d233105d3965c5368c9b33125f390e39b25f910e)
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r181:5c6f0b732e70 - - 2 files changed: 30 inserted, 30 deleted

@@ -313,97 +313,97
313 contest = Contest.find_by_name(contest_name)
313 contest = Contest.find_by_name(contest_name)
314 if contest==nil
314 if contest==nil
315 puts "cannot find contest: #{contest_name}"
315 puts "cannot find contest: #{contest_name}"
316 exit(0)
316 exit(0)
317 end
317 end
318
318
319 if options[:report]
319 if options[:report]
320 result_collector = ResultCollector.new
320 result_collector = ResultCollector.new
321 else
321 else
322 result_collector = nil
322 result_collector = nil
323 end
323 end
324
324
325 if options[:dry_run]
325 if options[:dry_run]
326 puts "Running in dry mode"
326 puts "Running in dry mode"
327 end
327 end
328
328
329 prob_reporter = Grader::SubmissionReporter.new(:dry_run => dry_run,
329 prob_reporter = Grader::SubmissionReporter.new(:dry_run => dry_run,
330 :result_collector => result_collector)
330 :result_collector => result_collector)
331 engine = Grader::Engine.new(:reporter => prob_reporter)
331 engine = Grader::Engine.new(:reporter => prob_reporter)
332 runner = Grader::Runner.new(engine, grader_proc)
332 runner = Grader::Runner.new(engine, grader_proc)
333
333
334 grader_proc.report_active if grader_proc!=nil
334 grader_proc.report_active if grader_proc!=nil
335
335
336 contest.problems.each do |problem|
336 contest.problems.each do |problem|
337 puts "Grading: #{problem.name}"
337 puts "Grading: #{problem.name}"
338 runner.grade_problem(problem,
338 runner.grade_problem(problem,
339 :user_conditions => lambda do |u|
339 :user_conditions => lambda do |u|
340 u.contest_finished? and
340 u.contest_finished? and
341 u.contest_ids.include?(contest.id)
341 u.contest_ids.include?(contest.id)
342 end)
342 end)
343 end
343 end
344
344
345 if options[:report]
345 if options[:report]
346 result_collector.print_report_by_user
346 result_collector.print_report_by_user
347 end
347 end
348 end
348 end
349
349
350 def grader_grade_submissions(grader_proc, options)
350 def grader_grade_submissions(grader_proc, options)
351 engine = Grader::Engine.new
351 engine = Grader::Engine.new
352 runner = Grader::Runner.new(engine, grader_proc)
352 runner = Grader::Runner.new(engine, grader_proc)
353
353
354 grader_proc.report_active if grader_proc!=nil
354 grader_proc.report_active if grader_proc!=nil
355
355
356 ARGV.each do |sub_id|
356 ARGV.each do |sub_id|
357 puts "Grading #{sub_id}"
357 puts "Grading #{sub_id}"
358 begin
358 begin
359 submission = Submission.find(sub_id.to_i)
359 submission = Submission.find(sub_id.to_i)
360 rescue ActiveRecord::RecordNotFound
360 rescue ActiveRecord::RecordNotFound
361 - puts "Record not found"
361 + puts "Submission #{sub_id} not found"
362 submission = nil
362 submission = nil
363 end
363 end
364
364
365 if submission!=nil
365 if submission!=nil
366 runner.grade_submission(submission)
366 runner.grade_submission(submission)
367 end
367 end
368 end
368 end
369 end
369 end
370
370
371 #########################################
371 #########################################
372 # main program
372 # main program
373 #########################################
373 #########################################
374
374
375 options = process_options_and_stop_file
375 options = process_options_and_stop_file
376 GRADER_ENV = options[:environment]
376 GRADER_ENV = options[:environment]
377 grader_mode = options[:mode]
377 grader_mode = options[:mode]
378 dry_run = options[:dry_run]
378 dry_run = options[:dry_run]
379
379
380 puts "environment: #{GRADER_ENV}"
380 puts "environment: #{GRADER_ENV}"
381 require File.join(File.dirname(__FILE__),'config/environment')
381 require File.join(File.dirname(__FILE__),'config/environment')
382
382
383 # add grader_mode to config
383 # add grader_mode to config
384 # this is needed because method log needs it. TODO: clean this up
384 # this is needed because method log needs it. TODO: clean this up
385 class << config
385 class << config
386 attr_accessor :grader_mode
386 attr_accessor :grader_mode
387 end
387 end
388 config.grader_mode = grader_mode
388 config.grader_mode = grader_mode
389
389
390 # reading rails environment
390 # reading rails environment
391 log 'Reading rails environment'
391 log 'Reading rails environment'
392
392
393 RAILS_ENV = config.rails_env
393 RAILS_ENV = config.rails_env
394 require RAILS_ROOT + '/config/environment'
394 require RAILS_ROOT + '/config/environment'
395
395
396 # register grader process
396 # register grader process
397 if config.report_grader
397 if config.report_grader
398 grader_proc = GraderProcess.register(config.grader_hostname,
398 grader_proc = GraderProcess.register(config.grader_hostname,
399 Process.pid,
399 Process.pid,
400 grader_mode)
400 grader_mode)
401 else
401 else
402 grader_proc = nil
402 grader_proc = nil
403 end
403 end
404
404
405 #set loggin environment
405 #set loggin environment
406 ENV['GRADER_LOGGING'] = log_file_name
406 ENV['GRADER_LOGGING'] = log_file_name
407
407
408 # register exit handler to report inactive, and terminated
408 # register exit handler to report inactive, and terminated
409 at_exit do
409 at_exit do
@@ -1,182 +1,182
1 require 'fileutils'
1 require 'fileutils'
2 require File.join(File.dirname(__FILE__),'dir_init')
2 require File.join(File.dirname(__FILE__),'dir_init')
3
3
4 module Grader
4 module Grader
5
5
6 #
6 #
7 # A grader engine grades a submission, against anything: a test
7 # A grader engine grades a submission, against anything: a test
8 # data, or a user submitted test data. It uses two helpers objects:
8 # data, or a user submitted test data. It uses two helpers objects:
9 # room_maker and reporter.
9 # room_maker and reporter.
10 #
10 #
11 class Engine
11 class Engine
12
12
13 attr_writer :room_maker
13 attr_writer :room_maker
14 attr_writer :reporter
14 attr_writer :reporter
15
15
16 def initialize(options={})
16 def initialize(options={})
17 # default options
17 # default options
18 if not options.include? :room_maker
18 if not options.include? :room_maker
19 options[:room_maker] = Grader::SubmissionRoomMaker.new
19 options[:room_maker] = Grader::SubmissionRoomMaker.new
20 end
20 end
21 if not options.include? :reporter
21 if not options.include? :reporter
22 options[:reporter] = Grader::SubmissionReporter.new
22 options[:reporter] = Grader::SubmissionReporter.new
23 end
23 end
24
24
25 @config = Grader::Configuration.get_instance
25 @config = Grader::Configuration.get_instance
26
26
27 @room_maker = options[:room_maker]
27 @room_maker = options[:room_maker]
28 @reporter = options[:reporter]
28 @reporter = options[:reporter]
29 end
29 end
30
30
31 # takes a submission, asks room_maker to produce grading directories,
31 # takes a submission, asks room_maker to produce grading directories,
32 # calls grader scripts, and asks reporter to save the result
32 # calls grader scripts, and asks reporter to save the result
33 def grade(submission)
33 def grade(submission)
34 current_dir = FileUtils.pwd
34 current_dir = FileUtils.pwd
35
35
36 user = submission.user
36 user = submission.user
37 problem = submission.problem
37 problem = submission.problem
38
38
39 - # TODO: will have to create real exception for this
39 + begin
40 - if user==nil or problem == nil
40 + # TODO: will have to create real exception for this
41 - @reporter.report_error(submission,"Grading error: problem with submission")
41 + if user==nil or problem == nil
42 - #raise "engine: user or problem is nil"
42 + @reporter.report_error(submission,"Grading error: problem with submission")
43 - end
43 + raise "engine: user or problem is nil"
44 -
44 + end
45 - # TODO: this is another hack so that output only task can be judged
46 - if submission.language!=nil
47 - language = submission.language.name
48 - lang_ext = submission.language.ext
49 - else
50 - language = 'c'
51 - lang_ext = 'c'
52 - end
53
45
54 - # This is needed because older version of std-scripts/compile
46 + # TODO: this is another hack so that output only task can be judged
55 - # only look for c++.
47 + if submission.language!=nil
56 - if language == 'cpp'
48 + language = submission.language.name
57 - language = 'c++'
49 + lang_ext = submission.language.ext
58 - end
50 + else
51 + language = 'c'
52 + lang_ext = 'c'
53 + end
59
54
60 - # COMMENT: should it be only source.ext?
55 + # This is needed because older version of std-scripts/compile
61 - if problem!=nil
56 + # only look for c++.
62 - source_name = "#{problem.name}.#{lang_ext}"
57 + if language == 'cpp'
63 - else
58 + language = 'c++'
64 - source_name = "source.#{lang_ext}"
59 + end
65 - end
66
60
67 - begin
61 + # COMMENT: should it be only source.ext?
62 + if problem!=nil
63 + source_name = "#{problem.name}.#{lang_ext}"
64 + else
65 + source_name = "source.#{lang_ext}"
66 + end
67 +
68 grading_dir = @room_maker.produce_grading_room(submission)
68 grading_dir = @room_maker.produce_grading_room(submission)
69 @room_maker.save_source(submission,source_name)
69 @room_maker.save_source(submission,source_name)
70 problem_home = @room_maker.find_problem_home(submission)
70 problem_home = @room_maker.find_problem_home(submission)
71
71
72 # puts "GRADING DIR: #{grading_dir}"
72 # puts "GRADING DIR: #{grading_dir}"
73 # puts "PROBLEM DIR: #{problem_home}"
73 # puts "PROBLEM DIR: #{problem_home}"
74
74
75 if !FileTest.exist?(problem_home)
75 if !FileTest.exist?(problem_home)
76 puts "PROBLEM DIR: #{problem_home}"
76 puts "PROBLEM DIR: #{problem_home}"
77 - puts "No test data. (check problem dir)"
77 + raise "engine: No test data."
78 - raise "No test data."
79 end
78 end
80
79
81 dinit = DirInit::Manager.new(problem_home)
80 dinit = DirInit::Manager.new(problem_home)
82
81
83 dinit.setup do
82 dinit.setup do
84 copy_log = copy_script(problem_home)
83 copy_log = copy_script(problem_home)
85 save_copy_log(problem_home,copy_log)
84 save_copy_log(problem_home,copy_log)
86 end
85 end
87
86
88 call_judge(problem_home,language,grading_dir,source_name)
87 call_judge(problem_home,language,grading_dir,source_name)
89
88
90 @reporter.report(submission,"#{grading_dir}/test-result")
89 @reporter.report(submission,"#{grading_dir}/test-result")
91
90
92 dinit.teardown do
91 dinit.teardown do
93 copy_log = load_copy_log(problem_home)
92 copy_log = load_copy_log(problem_home)
94 clear_copy_log(problem_home)
93 clear_copy_log(problem_home)
95 clear_script(copy_log,problem_home)
94 clear_script(copy_log,problem_home)
96 end
95 end
97
96
98 rescue RuntimeError => msg
97 rescue RuntimeError => msg
99 @reporter.report_error(submission, msg)
98 @reporter.report_error(submission, msg)
99 + puts "ERROR: #{msg}"
100
100
101 ensure
101 ensure
102 @room_maker.clean_up(submission)
102 @room_maker.clean_up(submission)
103 Dir.chdir(current_dir) # this is really important
103 Dir.chdir(current_dir) # this is really important
104 end
104 end
105 end
105 end
106
106
107 protected
107 protected
108
108
109 def talk(str)
109 def talk(str)
110 if @config.talkative
110 if @config.talkative
111 puts str
111 puts str
112 end
112 end
113 end
113 end
114
114
115 def call_judge(problem_home,language,grading_dir,fname)
115 def call_judge(problem_home,language,grading_dir,fname)
116 ENV['PROBLEM_HOME'] = problem_home
116 ENV['PROBLEM_HOME'] = problem_home
117 ENV['RUBYOPT'] = ''
117 ENV['RUBYOPT'] = ''
118
118
119 talk grading_dir
119 talk grading_dir
120 Dir.chdir grading_dir
120 Dir.chdir grading_dir
121 cmd = "#{problem_home}/script/judge #{language} #{fname}"
121 cmd = "#{problem_home}/script/judge #{language} #{fname}"
122 talk "CMD: #{cmd}"
122 talk "CMD: #{cmd}"
123 system(cmd)
123 system(cmd)
124 end
124 end
125
125
126 def get_std_script_dir
126 def get_std_script_dir
127 GRADER_ROOT + '/std-script'
127 GRADER_ROOT + '/std-script'
128 end
128 end
129
129
130 def copy_script(problem_home)
130 def copy_script(problem_home)
131 script_dir = "#{problem_home}/script"
131 script_dir = "#{problem_home}/script"
132 std_script_dir = get_std_script_dir
132 std_script_dir = get_std_script_dir
133
133
134 - raise "std-script directory not found" if !FileTest.exist?(std_script_dir)
134 + raise "engine: std-script directory not found" if !FileTest.exist?(std_script_dir)
135
135
136 scripts = Dir[std_script_dir + '/*']
136 scripts = Dir[std_script_dir + '/*']
137
137
138 copied = []
138 copied = []
139
139
140 scripts.each do |s|
140 scripts.each do |s|
141 fname = File.basename(s)
141 fname = File.basename(s)
142 next if FileTest.directory?(s)
142 next if FileTest.directory?(s)
143 if !FileTest.exist?("#{script_dir}/#{fname}")
143 if !FileTest.exist?("#{script_dir}/#{fname}")
144 copied << fname
144 copied << fname
145 FileUtils.cp(s, "#{script_dir}", :preserve => true)
145 FileUtils.cp(s, "#{script_dir}", :preserve => true)
146 end
146 end
147 end
147 end
148
148
149 return copied
149 return copied
150 end
150 end
151
151
152 def copy_log_filename(problem_home)
152 def copy_log_filename(problem_home)
153 return File.join(problem_home, '.scripts_copied')
153 return File.join(problem_home, '.scripts_copied')
154 end
154 end
155
155
156 def save_copy_log(problem_home, log)
156 def save_copy_log(problem_home, log)
157 f = File.new(copy_log_filename(problem_home),"w")
157 f = File.new(copy_log_filename(problem_home),"w")
158 log.each do |fname|
158 log.each do |fname|
159 f.write("#{fname}\n")
159 f.write("#{fname}\n")
160 end
160 end
161 f.close
161 f.close
162 end
162 end
163
163
164 def load_copy_log(problem_home)
164 def load_copy_log(problem_home)
165 f = File.new(copy_log_filename(problem_home),"r")
165 f = File.new(copy_log_filename(problem_home),"r")
166 log = []
166 log = []
167 f.readlines.each do |line|
167 f.readlines.each do |line|
168 log << line.strip
168 log << line.strip
169 end
169 end
170 f.close
170 f.close
171 log
171 log
172 end
172 end
173
173
174 def clear_copy_log(problem_home)
174 def clear_copy_log(problem_home)
175 File.delete(copy_log_filename(problem_home))
175 File.delete(copy_log_filename(problem_home))
176 end
176 end
177
177
178 def clear_script(log,problem_home)
178 def clear_script(log,problem_home)
179 log.each do |s|
179 log.each do |s|
180 FileUtils.rm("#{problem_home}/script/#{s}")
180 FileUtils.rm("#{problem_home}/script/#{s}")
181 end
181 end
182 end
182 end
You need to be logged in to leave comments. Login now