Description:
added --dry option to grader prob mode
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r91:5df0d71260f4 - - 2 files changed: 72 inserted, 46 deleted

@@ -15,203 +15,225
15
15
16 def clear_stopfile
16 def clear_stopfile
17 if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
17 if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 system("rm " + File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 system("rm " + File.dirname(__FILE__) + "/stop.#{Process.pid}")
19 end
19 end
20 end
20 end
21
21
22 def config
22 def config
23 Grader::Configuration.get_instance
23 Grader::Configuration.get_instance
24 end
24 end
25
25
26 def log_file_name
26 def log_file_name
27 if !File.exists?(config.log_dir)
27 if !File.exists?(config.log_dir)
28 raise "Log directory does not exist: #{config.log_dir}"
28 raise "Log directory does not exist: #{config.log_dir}"
29 end
29 end
30 config.log_dir +
30 config.log_dir +
31 "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
31 "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
32 end
32 end
33
33
34 def log(str)
34 def log(str)
35 if config.talkative
35 if config.talkative
36 puts str
36 puts str
37 end
37 end
38 if config.logging
38 if config.logging
39 fp = File.open(log_file_name,"a")
39 fp = File.open(log_file_name,"a")
40 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
40 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
41 fp.close
41 fp.close
42 end
42 end
43 end
43 end
44
44
45 def display_manual
45 def display_manual
46 puts <<USAGE
46 puts <<USAGE
47 Grader.
47 Grader.
48 using: (1) grader
48 using: (1) grader
49 (2) grader environment [mode]
49 (2) grader environment [mode]
50 (3) grader stop [all|pids-list]
50 (3) grader stop [all|pids-list]
51 (4) grader --help
51 (4) grader --help
52 (1) call grader with environment = 'exam', mode = 'queue'
52 (1) call grader with environment = 'exam', mode = 'queue'
53 (2) possible modes are: 'queue', 'prob', 'test_request'
53 (2) possible modes are: 'queue', 'prob', 'test_request'
54 (3) create stop-file to stop running grader in queue mode
54 (3) create stop-file to stop running grader in queue mode
55 (4) You are here.
55 (4) You are here.
56 USAGE
56 USAGE
57 end
57 end
58
58
59 #########################################
59 #########################################
60 # main program
60 # main program
61 #########################################
61 #########################################
62
62
63 - # with --help
63 + # Reading environment and options.
64 - if (ARGV.length==1) and (/help/.match(ARGV[0]))
64 +
65 - display_manual
65 + def process_options_and_stop_file
66 - exit(0)
66 + # The list of options are:
67 + # - stop [all|process ids]
68 + # -
69 +
70 + # Process 'help' option
71 + if (ARGV.length==1) and (/help/.match(ARGV[0]))
72 + display_manual
73 + exit(0)
74 + end
75 +
76 + # Process 'stop' option.
77 + if (ARGV.length >= 1) and (ARGV[0]=='stop')
78 + if ARGV.length==1
79 + puts "you should specify pid-list or 'all'"
80 + display_manual
81 + elsif (ARGV.length==2) and (ARGV[1]=='all')
82 + stop_grader(:all)
83 + puts "A global stop file ('stop.all') created."
84 + puts "You should remove it manually later."
85 + else
86 + (1..ARGV.length-1).each do |i|
87 + stop_grader(ARGV[i])
88 + end
89 + puts "stop file(s) created"
90 + end
91 + exit(0)
92 + end
93 +
94 + # Check stop file.
95 + if check_stopfile
96 + puts "Stop file exists. Terminated."
97 + clear_stopfile
98 + exit(0)
99 + end
100 +
101 + #default options
102 + options = {
103 + :mode => 'queue',
104 + :environment => 'exam',
105 + :dry_run => false,
106 + }
107 +
108 + # Process mode and environment option
109 + if ARGV.length >= 1
110 + options[:environment] = ARGV.shift
111 + if ARGV.length >=1
112 + options[:mode] = ARGV.shift
113 + end
114 + end
115 +
116 + options[:dry_run] = (ARGV.delete('--dry') != nil)
117 + if options[:dry_run] and (not options[:mode] == 'prob')
118 + puts "Dry run currently works for 'prob' mode."
119 + exit(0)
120 + end
121 +
122 + return options
67 end
123 end
68
124
69 - # reading environment and options
125 + # ======= Main ========
70 - if (ARGV.length >= 1) and (ARGV[0]=='stop')
126 + options = process_options_and_stop_file
71 - if ARGV.length==1
127 + GRADER_ENV = options[:environment]
72 - puts "you should specify pid-list or 'all'"
128 + grader_mode = options[:mode]
73 - display_manual
129 + dry_run = options[:dry_run]
74 - elsif (ARGV.length==2) and (ARGV[1]=='all')
75 - stop_grader(:all)
76 - puts "A global stop file ('stop.all') created."
77 - puts "You should remove it manually later."
78 - else
79 - (1..ARGV.length-1).each do |i|
80 - stop_grader(ARGV[i])
81 - end
82 - puts "stop file(s) created"
83 - end
84 - exit(0)
85 - end
86 -
87 - if check_stopfile
88 - puts "Stop file exists. Terminated."
89 - clear_stopfile
90 - exit(0)
91 - end
92 -
93 - grader_mode = 'queue'
94 - if ARGV.length >= 1
95 - GRADER_ENV = ARGV[0]
96 - if ARGV.length >=2
97 - grader_mode = ARGV[1]
98 - end
99 - else
100 - GRADER_ENV = 'exam'
101 - end
102
130
103 puts "environment: #{GRADER_ENV}"
131 puts "environment: #{GRADER_ENV}"
104 require File.join(File.dirname(__FILE__),'config/environment')
132 require File.join(File.dirname(__FILE__),'config/environment')
105
133
106 # add grader_mode to config
134 # add grader_mode to config
107 # this is needed because method log needs it. TODO: clean this up
135 # this is needed because method log needs it. TODO: clean this up
108 class << config
136 class << config
109 attr_accessor :grader_mode
137 attr_accessor :grader_mode
110 end
138 end
111 config.grader_mode = grader_mode
139 config.grader_mode = grader_mode
112
140
113 # reading rails environment
141 # reading rails environment
114 log 'Reading rails environment'
142 log 'Reading rails environment'
115
143
116 RAILS_ENV = config.rails_env
144 RAILS_ENV = config.rails_env
117 require RAILS_ROOT + '/config/environment'
145 require RAILS_ROOT + '/config/environment'
118
146
119 # register grader process
147 # register grader process
120 if config.report_grader
148 if config.report_grader
121 grader_proc = GraderProcess.register(config.grader_hostname,
149 grader_proc = GraderProcess.register(config.grader_hostname,
122 Process.pid,
150 Process.pid,
123 grader_mode)
151 grader_mode)
124 else
152 else
125 grader_proc = nil
153 grader_proc = nil
126 end
154 end
127
155
128 #set loggin environment
156 #set loggin environment
129 ENV['GRADER_LOGGING'] = log_file_name
157 ENV['GRADER_LOGGING'] = log_file_name
130
158
131 # register exit handler to report inactive, and terminated
159 # register exit handler to report inactive, and terminated
132 at_exit do
160 at_exit do
133 if grader_proc!=nil
161 if grader_proc!=nil
134 grader_proc.report_inactive
162 grader_proc.report_inactive
135 grader_proc.terminate
163 grader_proc.terminate
136 end
164 end
137 end
165 end
138
166
139 #
167 #
140 # MAIN LOOP
168 # MAIN LOOP
141 #
169 #
142
170
143 case grader_mode
171 case grader_mode
144 when "queue", "test_request"
172 when "queue", "test_request"
145 log "Grader: #{grader_mode}"
173 log "Grader: #{grader_mode}"
146 if grader_mode=="queue"
174 if grader_mode=="queue"
147 engine = Grader::Engine.new
175 engine = Grader::Engine.new
148 else
176 else
149 engine = Grader::Engine.new(Grader::TestRequestRoomMaker.new,
177 engine = Grader::Engine.new(Grader::TestRequestRoomMaker.new,
150 Grader::TestRequestReporter.new)
178 Grader::TestRequestReporter.new)
151 end
179 end
152
180
153 runner = Grader::Runner.new(engine, grader_proc)
181 runner = Grader::Runner.new(engine, grader_proc)
154 while true
182 while true
155
183
156 if check_stopfile # created by calling grader stop
184 if check_stopfile # created by calling grader stop
157 clear_stopfile
185 clear_stopfile
158 log "stopped (with stop file)"
186 log "stopped (with stop file)"
159 break
187 break
160 end
188 end
161
189
162 if grader_mode=="queue"
190 if grader_mode=="queue"
163 task = runner.grade_oldest_task
191 task = runner.grade_oldest_task
164 else
192 else
165 task = runner.grade_oldest_test_request
193 task = runner.grade_oldest_test_request
166 end
194 end
167 if task==nil
195 if task==nil
168 sleep(1)
196 sleep(1)
169 end
197 end
170 end
198 end
171
199
172 when "prob"
200 when "prob"
173 - engine = Grader::Engine.new
201 + engine = Grader::Engine.new(nil, Grader::SubmissionReporter.new(dry_run))
174 runner = Grader::Runner.new(engine, grader_proc)
202 runner = Grader::Runner.new(engine, grader_proc)
175
203
176 grader_proc.report_active if grader_proc!=nil
204 grader_proc.report_active if grader_proc!=nil
177
205
178 - ARGV.shift
179 - ARGV.shift
180 -
181 ARGV.each do |prob_name|
206 ARGV.each do |prob_name|
182 prob = Problem.find_by_name(prob_name)
207 prob = Problem.find_by_name(prob_name)
183 if prob==nil
208 if prob==nil
184 puts "cannot find problem: #{prob_name}"
209 puts "cannot find problem: #{prob_name}"
185 else
210 else
186 runner.grade_problem(prob)
211 runner.grade_problem(prob)
187 end
212 end
188 end
213 end
189
214
190 when "sub"
215 when "sub"
191 engine = Grader::Engine.new
216 engine = Grader::Engine.new
192 runner = Grader::Runner.new(engine, grader_proc)
217 runner = Grader::Runner.new(engine, grader_proc)
193
218
194 grader_proc.report_active if grader_proc!=nil
219 grader_proc.report_active if grader_proc!=nil
195
220
196 - ARGV.shift
197 - ARGV.shift
198 -
199 ARGV.each do |sub_id|
221 ARGV.each do |sub_id|
200 puts "Grading #{sub_id}"
222 puts "Grading #{sub_id}"
201 begin
223 begin
202 submission = Submission.find(sub_id.to_i)
224 submission = Submission.find(sub_id.to_i)
203 rescue ActiveRecord::RecordNotFound
225 rescue ActiveRecord::RecordNotFound
204 puts "Record not found"
226 puts "Record not found"
205 submission = nil
227 submission = nil
206 end
228 end
207
229
208 if submission!=nil
230 if submission!=nil
209 runner.grade_submission(submission)
231 runner.grade_submission(submission)
210 end
232 end
211 end
233 end
212
234
213 else
235 else
214 display_manual
236 display_manual
215 exit(0)
237 exit(0)
216 end
238 end
217
239
@@ -1,123 +1,127
1 module Grader
1 module Grader
2
2
3 class SubmissionRoomMaker
3 class SubmissionRoomMaker
4 def initialize
4 def initialize
5 @config = Grader::Configuration.get_instance
5 @config = Grader::Configuration.get_instance
6 end
6 end
7
7
8 def produce_grading_room(submission)
8 def produce_grading_room(submission)
9 user = submission.user
9 user = submission.user
10 problem = submission.problem
10 problem = submission.problem
11 grading_room = "#{@config.user_result_dir}/" +
11 grading_room = "#{@config.user_result_dir}/" +
12 "#{user.login}/#{problem.name}/#{submission.id}"
12 "#{user.login}/#{problem.name}/#{submission.id}"
13
13
14 FileUtils.mkdir_p(grading_room)
14 FileUtils.mkdir_p(grading_room)
15 grading_room
15 grading_room
16 end
16 end
17
17
18 def find_problem_home(submission)
18 def find_problem_home(submission)
19 problem = submission.problem
19 problem = submission.problem
20 "#{@config.problems_dir}/#{problem.name}"
20 "#{@config.problems_dir}/#{problem.name}"
21 end
21 end
22
22
23 def save_source(submission,source_name)
23 def save_source(submission,source_name)
24 dir = self.produce_grading_room(submission)
24 dir = self.produce_grading_room(submission)
25 f = File.open("#{dir}/#{source_name}","w")
25 f = File.open("#{dir}/#{source_name}","w")
26 f.write(submission.source)
26 f.write(submission.source)
27 f.close
27 f.close
28 end
28 end
29
29
30 def clean_up(submission)
30 def clean_up(submission)
31 end
31 end
32 end
32 end
33
33
34 class SubmissionReporter
34 class SubmissionReporter
35 - def initialize
35 + def initialize(dry_run=false)
36 @config = Grader::Configuration.get_instance
36 @config = Grader::Configuration.get_instance
37 + @dry_run = dry_run
37 end
38 end
38
39
39 def report(sub,test_result_dir)
40 def report(sub,test_result_dir)
40 save_result(sub,read_result(test_result_dir))
41 save_result(sub,read_result(test_result_dir))
41 end
42 end
42
43
43 def report_error(sub,msg)
44 def report_error(sub,msg)
44 save_result(sub,{:points => 0,
45 save_result(sub,{:points => 0,
45 :comment => "Grading error: #{msg}" })
46 :comment => "Grading error: #{msg}" })
46 end
47 end
47
48
48 protected
49 protected
49 def read_result(test_result_dir)
50 def read_result(test_result_dir)
50 cmp_msg_fname = "#{test_result_dir}/compiler_message"
51 cmp_msg_fname = "#{test_result_dir}/compiler_message"
51 if FileTest.exist?(cmp_msg_fname)
52 if FileTest.exist?(cmp_msg_fname)
52 cmp_file = File.open(cmp_msg_fname)
53 cmp_file = File.open(cmp_msg_fname)
53 cmp_msg = cmp_file.read
54 cmp_msg = cmp_file.read
54 cmp_file.close
55 cmp_file.close
55 else
56 else
56 cmp_msg = ""
57 cmp_msg = ""
57 end
58 end
58
59
59 result_fname = "#{test_result_dir}/result"
60 result_fname = "#{test_result_dir}/result"
60 comment_fname = "#{test_result_dir}/comment"
61 comment_fname = "#{test_result_dir}/comment"
61 if FileTest.exist?(result_fname)
62 if FileTest.exist?(result_fname)
62 comment = ""
63 comment = ""
63 begin
64 begin
64 result_file = File.open(result_fname)
65 result_file = File.open(result_fname)
65 result = result_file.readline.to_i
66 result = result_file.readline.to_i
66 result_file.close
67 result_file.close
67 rescue
68 rescue
68 result = 0
69 result = 0
69 comment = "error reading result file."
70 comment = "error reading result file."
70 end
71 end
71
72
72 begin
73 begin
73 comment_file = File.open(comment_fname)
74 comment_file = File.open(comment_fname)
74 comment += comment_file.readline.chomp
75 comment += comment_file.readline.chomp
75 comment_file.close
76 comment_file.close
76 rescue
77 rescue
77 comment += ""
78 comment += ""
78 end
79 end
79
80
80 return {:points => result,
81 return {:points => result,
81 :comment => comment,
82 :comment => comment,
82 :cmp_msg => cmp_msg}
83 :cmp_msg => cmp_msg}
83 else
84 else
84 if FileTest.exist?("#{test_result_dir}/a.out")
85 if FileTest.exist?("#{test_result_dir}/a.out")
85 return {:points => 0,
86 return {:points => 0,
86 :comment => 'error during grading',
87 :comment => 'error during grading',
87 :cmp_msg => cmp_msg}
88 :cmp_msg => cmp_msg}
88 else
89 else
89 return {:points => 0,
90 return {:points => 0,
90 :comment => 'compilation error',
91 :comment => 'compilation error',
91 :cmp_msg => cmp_msg}
92 :cmp_msg => cmp_msg}
92 end
93 end
93 end
94 end
94 end
95 end
95
96
96 def save_result(submission,result)
97 def save_result(submission,result)
97 problem = submission.problem
98 problem = submission.problem
98 submission.graded_at = Time.now.gmtime
99 submission.graded_at = Time.now.gmtime
99 points = result[:points]
100 points = result[:points]
100 submission.points = points
101 submission.points = points
101 comment = @config.report_comment(result[:comment])
102 comment = @config.report_comment(result[:comment])
102
103
103 #
104 #
104 # TODO: FIX THIS MESSAGE
105 # TODO: FIX THIS MESSAGE
105 #
106 #
106 if problem == nil
107 if problem == nil
107 submission.grader_comment = 'PASSED: ' + comment + '(problem is nil)'
108 submission.grader_comment = 'PASSED: ' + comment + '(problem is nil)'
108 elsif points == problem.full_score
109 elsif points == problem.full_score
109 #submission.grader_comment = 'PASSED: ' + comment
110 #submission.grader_comment = 'PASSED: ' + comment
110 submission.grader_comment = comment
111 submission.grader_comment = comment
111 elsif result[:comment].chomp =~ /^[\[\]P]+$/
112 elsif result[:comment].chomp =~ /^[\[\]P]+$/
112 submission.grader_comment = 'PASSED: ' + comment + '(inconsistent score)'
113 submission.grader_comment = 'PASSED: ' + comment + '(inconsistent score)'
113 else
114 else
114 #submission.grader_comment = 'FAILED: ' + comment
115 #submission.grader_comment = 'FAILED: ' + comment
115 submission.grader_comment = comment
116 submission.grader_comment = comment
116 end
117 end
117 submission.compiler_message = result[:cmp_msg] or ''
118 submission.compiler_message = result[:cmp_msg] or ''
118 - submission.save
119 +
120 + if not @dry_run
121 + submission.save
122 + end
119 end
123 end
120
124
121 end
125 end
122
126
123 end
127 end
You need to be logged in to leave comments. Login now