Description:
added contest mode
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r93:bdd89e00b68d - - 2 files changed: 55 inserted, 7 deleted

@@ -21,277 +21,321
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 def process_options_and_stop_file
59 def process_options_and_stop_file
60 # The list of options are:
60 # The list of options are:
61 # - stop [all|process ids]
61 # - stop [all|process ids]
62 # -
62 # -
63
63
64 # Process 'help' option
64 # Process 'help' option
65 if (ARGV.length==1) and (/help/.match(ARGV[0]))
65 if (ARGV.length==1) and (/help/.match(ARGV[0]))
66 display_manual
66 display_manual
67 exit(0)
67 exit(0)
68 end
68 end
69
69
70 # Process 'stop' option.
70 # Process 'stop' option.
71 if (ARGV.length >= 1) and (ARGV[0]=='stop')
71 if (ARGV.length >= 1) and (ARGV[0]=='stop')
72 if ARGV.length==1
72 if ARGV.length==1
73 puts "you should specify pid-list or 'all'"
73 puts "you should specify pid-list or 'all'"
74 display_manual
74 display_manual
75 elsif (ARGV.length==2) and (ARGV[1]=='all')
75 elsif (ARGV.length==2) and (ARGV[1]=='all')
76 stop_grader(:all)
76 stop_grader(:all)
77 puts "A global stop file ('stop.all') created."
77 puts "A global stop file ('stop.all') created."
78 puts "You should remove it manually later."
78 puts "You should remove it manually later."
79 else
79 else
80 (1..ARGV.length-1).each do |i|
80 (1..ARGV.length-1).each do |i|
81 stop_grader(ARGV[i])
81 stop_grader(ARGV[i])
82 end
82 end
83 puts "stop file(s) created"
83 puts "stop file(s) created"
84 end
84 end
85 exit(0)
85 exit(0)
86 end
86 end
87
87
88 # Check stop file.
88 # Check stop file.
89 if check_stopfile
89 if check_stopfile
90 puts "Stop file exists. Terminated."
90 puts "Stop file exists. Terminated."
91 clear_stopfile
91 clear_stopfile
92 exit(0)
92 exit(0)
93 end
93 end
94
94
95 #default options
95 #default options
96 options = {
96 options = {
97 :mode => 'queue',
97 :mode => 'queue',
98 :environment => 'exam',
98 :environment => 'exam',
99 :dry_run => false,
99 :dry_run => false,
100 }
100 }
101
101
102 # Process mode and environment option
102 # Process mode and environment option
103 if ARGV.length >= 1
103 if ARGV.length >= 1
104 options[:environment] = ARGV.shift
104 options[:environment] = ARGV.shift
105 if ARGV.length >=1
105 if ARGV.length >=1
106 options[:mode] = ARGV.shift
106 options[:mode] = ARGV.shift
107 end
107 end
108 end
108 end
109
109
110 options[:dry_run] = (ARGV.delete('--dry') != nil)
110 options[:dry_run] = (ARGV.delete('--dry') != nil)
111 if options[:dry_run] and (not options[:mode] == 'prob')
111 if options[:dry_run] and (not options[:mode] == 'prob')
112 puts "Dry run currently works only for 'prob' mode."
112 puts "Dry run currently works only for 'prob' mode."
113 exit(0)
113 exit(0)
114 end
114 end
115
115
116 options[:report] = (ARGV.delete('--report') != nil)
116 options[:report] = (ARGV.delete('--report') != nil)
117 - if options[:report] and (not options[:mode] == 'prob')
117 + if options[:report] and (not ['prob','contest'].include? options[:mode])
118 puts "Report currently works only for 'prob' mode."
118 puts "Report currently works only for 'prob' mode."
119 exit(0)
119 exit(0)
120 end
120 end
121
121
122 return options
122 return options
123 end
123 end
124
124
125 class ResultCollector
125 class ResultCollector
126 def initialize
126 def initialize
127 @results = {}
127 @results = {}
128 @problems = {}
128 @problems = {}
129 @users = {}
129 @users = {}
130 end
130 end
131
131
132 def save(user, problem, grading_result)
132 def save(user, problem, grading_result)
133 if not @problems.has_key? problem.id
133 if not @problems.has_key? problem.id
134 @problems[problem.id] = problem
134 @problems[problem.id] = problem
135 end
135 end
136 if not @users.has_key? user.id
136 if not @users.has_key? user.id
137 @users[user.id] = user
137 @users[user.id] = user
138 end
138 end
139 @results[[user.id, problem.id]] = grading_result
139 @results[[user.id, problem.id]] = grading_result
140 end
140 end
141
141
142 def print_report_by_user
142 def print_report_by_user
143 puts "---------------------"
143 puts "---------------------"
144 puts " REPORT"
144 puts " REPORT"
145 puts "---------------------"
145 puts "---------------------"
146
146
147 print "login"
147 print "login"
148 @problems.each_value do |problem|
148 @problems.each_value do |problem|
149 print ",#{problem.name}"
149 print ",#{problem.name}"
150 end
150 end
151 print "\n"
151 print "\n"
152
152
153 @users.each_value do |user|
153 @users.each_value do |user|
154 print "#{user.login}"
154 print "#{user.login}"
155 @problems.each_value do |problem|
155 @problems.each_value do |problem|
156 if @results.has_key? [user.id, problem.id]
156 if @results.has_key? [user.id, problem.id]
157 print ",#{@results[[user.id,problem.id]][:points]}"
157 print ",#{@results[[user.id,problem.id]][:points]}"
158 else
158 else
159 print ","
159 print ","
160 end
160 end
161 end
161 end
162 print "\n"
162 print "\n"
163 end
163 end
164 end
164 end
165 end
165 end
166
166
167 #########################################
167 #########################################
168 # main program
168 # main program
169 #########################################
169 #########################################
170
170
171 options = process_options_and_stop_file
171 options = process_options_and_stop_file
172 GRADER_ENV = options[:environment]
172 GRADER_ENV = options[:environment]
173 grader_mode = options[:mode]
173 grader_mode = options[:mode]
174 dry_run = options[:dry_run]
174 dry_run = options[:dry_run]
175
175
176 puts "environment: #{GRADER_ENV}"
176 puts "environment: #{GRADER_ENV}"
177 require File.join(File.dirname(__FILE__),'config/environment')
177 require File.join(File.dirname(__FILE__),'config/environment')
178
178
179 # add grader_mode to config
179 # add grader_mode to config
180 # this is needed because method log needs it. TODO: clean this up
180 # this is needed because method log needs it. TODO: clean this up
181 class << config
181 class << config
182 attr_accessor :grader_mode
182 attr_accessor :grader_mode
183 end
183 end
184 config.grader_mode = grader_mode
184 config.grader_mode = grader_mode
185
185
186 # reading rails environment
186 # reading rails environment
187 log 'Reading rails environment'
187 log 'Reading rails environment'
188
188
189 RAILS_ENV = config.rails_env
189 RAILS_ENV = config.rails_env
190 require RAILS_ROOT + '/config/environment'
190 require RAILS_ROOT + '/config/environment'
191
191
192 # register grader process
192 # register grader process
193 if config.report_grader
193 if config.report_grader
194 grader_proc = GraderProcess.register(config.grader_hostname,
194 grader_proc = GraderProcess.register(config.grader_hostname,
195 Process.pid,
195 Process.pid,
196 grader_mode)
196 grader_mode)
197 else
197 else
198 grader_proc = nil
198 grader_proc = nil
199 end
199 end
200
200
201 #set loggin environment
201 #set loggin environment
202 ENV['GRADER_LOGGING'] = log_file_name
202 ENV['GRADER_LOGGING'] = log_file_name
203
203
204 # register exit handler to report inactive, and terminated
204 # register exit handler to report inactive, and terminated
205 at_exit do
205 at_exit do
206 if grader_proc!=nil
206 if grader_proc!=nil
207 grader_proc.report_inactive
207 grader_proc.report_inactive
208 grader_proc.terminate
208 grader_proc.terminate
209 end
209 end
210 end
210 end
211
211
212 #
212 #
213 # MAIN LOOP
213 # MAIN LOOP
214 #
214 #
215
215
216 case grader_mode
216 case grader_mode
217 when "queue", "test_request"
217 when "queue", "test_request"
218 log "Grader: #{grader_mode}"
218 log "Grader: #{grader_mode}"
219 if grader_mode=="queue"
219 if grader_mode=="queue"
220 engine = Grader::Engine.new
220 engine = Grader::Engine.new
221 else
221 else
222 engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
222 engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
223 :reporter => Grader::TestRequestReporter.new)
223 :reporter => Grader::TestRequestReporter.new)
224 end
224 end
225
225
226 runner = Grader::Runner.new(engine, grader_proc)
226 runner = Grader::Runner.new(engine, grader_proc)
227 while true
227 while true
228
228
229 if check_stopfile # created by calling grader stop
229 if check_stopfile # created by calling grader stop
230 clear_stopfile
230 clear_stopfile
231 log "stopped (with stop file)"
231 log "stopped (with stop file)"
232 break
232 break
233 end
233 end
234
234
235 if grader_mode=="queue"
235 if grader_mode=="queue"
236 task = runner.grade_oldest_task
236 task = runner.grade_oldest_task
237 else
237 else
238 task = runner.grade_oldest_test_request
238 task = runner.grade_oldest_test_request
239 end
239 end
240 if task==nil
240 if task==nil
241 sleep(1)
241 sleep(1)
242 end
242 end
243 end
243 end
244
244
245 when "prob"
245 when "prob"
246 if options[:report]
246 if options[:report]
247 result_collector = ResultCollector.new
247 result_collector = ResultCollector.new
248 else
248 else
249 result_collector = nil
249 result_collector = nil
250 end
250 end
251 -
251 +
252 - engine = (Grader::Engine.
252 + if options[:dry_run]
253 - new(:reporter =>
253 + puts "Running in dry mode"
254 - Grader::SubmissionReporter.new(:dry_run => dry_run,
254 + end
255 - :result_collector => result_collector)))
255 +
256 + prob_reporter = Grader::SubmissionReporter.new(:dry_run => dry_run,
257 + :result_collector => result_collector)
258 + engine = Grader::Engine.new(:reporter => prob_reporter)
256 runner = Grader::Runner.new(engine, grader_proc)
259 runner = Grader::Runner.new(engine, grader_proc)
257
260
258 grader_proc.report_active if grader_proc!=nil
261 grader_proc.report_active if grader_proc!=nil
259
262
260 ARGV.each do |prob_name|
263 ARGV.each do |prob_name|
261 prob = Problem.find_by_name(prob_name)
264 prob = Problem.find_by_name(prob_name)
262 if prob==nil
265 if prob==nil
263 puts "cannot find problem: #{prob_name}"
266 puts "cannot find problem: #{prob_name}"
264 else
267 else
265 runner.grade_problem(prob)
268 runner.grade_problem(prob)
266 end
269 end
267 end
270 end
268
271
269 if options[:report]
272 if options[:report]
270 result_collector.print_report_by_user
273 result_collector.print_report_by_user
271 end
274 end
272
275
276 + when "contest"
277 + # always use dry run when grading during contest
278 + contest_name = ARGV.shift
279 +
280 + options[:dry_run] = true
281 +
282 + contest = Contest.find_by_name(contest_name)
283 + if contest==nil
284 + puts "cannot find contest: #{contest_name}"
285 + exit(0)
286 + end
287 +
288 + if options[:report]
289 + result_collector = ResultCollector.new
290 + else
291 + result_collector = nil
292 + end
293 +
294 + if options[:dry_run]
295 + puts "Running in dry mode"
296 + end
297 +
298 + prob_reporter = Grader::SubmissionReporter.new(:dry_run => dry_run,
299 + :result_collector => result_collector)
300 + engine = Grader::Engine.new(:reporter => prob_reporter)
301 + runner = Grader::Runner.new(engine, grader_proc)
302 +
303 + grader_proc.report_active if grader_proc!=nil
304 +
305 + contest.problems.each do |problem|
306 + puts "Grading: #{problem.name}"
307 + runner.grade_problem(problem,
308 + :user_conditions => lambda {|u| u.contest_finished?})
309 + end
310 +
311 + if options[:report]
312 + result_collector.print_report_by_user
313 + end
314 +
273 when "sub"
315 when "sub"
274 engine = Grader::Engine.new
316 engine = Grader::Engine.new
275 runner = Grader::Runner.new(engine, grader_proc)
317 runner = Grader::Runner.new(engine, grader_proc)
276
318
277 grader_proc.report_active if grader_proc!=nil
319 grader_proc.report_active if grader_proc!=nil
278
320
279 ARGV.each do |sub_id|
321 ARGV.each do |sub_id|
280 puts "Grading #{sub_id}"
322 puts "Grading #{sub_id}"
281 begin
323 begin
282 submission = Submission.find(sub_id.to_i)
324 submission = Submission.find(sub_id.to_i)
283 rescue ActiveRecord::RecordNotFound
325 rescue ActiveRecord::RecordNotFound
284 puts "Record not found"
326 puts "Record not found"
285 submission = nil
327 submission = nil
286 end
328 end
287
329
288 if submission!=nil
330 if submission!=nil
289 runner.grade_submission(submission)
331 runner.grade_submission(submission)
290 end
332 end
291 end
333 end
292
334
335 +
336 +
293 else
337 else
294 display_manual
338 display_manual
295 exit(0)
339 exit(0)
296 end
340 end
297
341
@@ -1,58 +1,62
1 #
1 #
2 # A runner drives the engine into various tasks.
2 # A runner drives the engine into various tasks.
3 #
3 #
4
4
5 module Grader
5 module Grader
6
6
7 class Runner
7 class Runner
8
8
9 def initialize(engine, grader_process=nil)
9 def initialize(engine, grader_process=nil)
10 @engine = engine
10 @engine = engine
11 @grader_process = grader_process
11 @grader_process = grader_process
12 end
12 end
13
13
14 def grade_oldest_task
14 def grade_oldest_task
15 task = Task.get_inqueue_and_change_status(Task::STATUS_GRADING)
15 task = Task.get_inqueue_and_change_status(Task::STATUS_GRADING)
16 if task!=nil
16 if task!=nil
17 @grader_process.report_active(task) if @grader_process!=nil
17 @grader_process.report_active(task) if @grader_process!=nil
18
18
19 submission = Submission.find(task.submission_id)
19 submission = Submission.find(task.submission_id)
20 @engine.grade(submission)
20 @engine.grade(submission)
21 task.status_complete!
21 task.status_complete!
22 @grader_process.report_inactive(task) if @grader_process!=nil
22 @grader_process.report_inactive(task) if @grader_process!=nil
23 end
23 end
24 return task
24 return task
25 end
25 end
26
26
27 - def grade_problem(problem)
27 + def grade_problem(problem, options={})
28 users = User.find(:all)
28 users = User.find(:all)
29 users.each do |u|
29 users.each do |u|
30 puts "user: #{u.login}"
30 puts "user: #{u.login}"
31 + if options[:user_conditions]!=nil
32 + con_proc = options[:user_conditions]
33 + next if not con_proc.call(u)
34 + end
31 last_sub = Submission.find_last_by_user_and_problem(u.id,problem.id)
35 last_sub = Submission.find_last_by_user_and_problem(u.id,problem.id)
32 if last_sub!=nil
36 if last_sub!=nil
33 @engine.grade(last_sub)
37 @engine.grade(last_sub)
34 end
38 end
35 end
39 end
36 end
40 end
37
41
38 def grade_submission(submission)
42 def grade_submission(submission)
39 puts "Submission: #{submission.id} by #{submission.user.full_name}"
43 puts "Submission: #{submission.id} by #{submission.user.full_name}"
40 @engine.grade(submission)
44 @engine.grade(submission)
41 end
45 end
42
46
43 def grade_oldest_test_request
47 def grade_oldest_test_request
44 test_request = TestRequest.get_inqueue_and_change_status(Task::STATUS_GRADING)
48 test_request = TestRequest.get_inqueue_and_change_status(Task::STATUS_GRADING)
45 if test_request!=nil
49 if test_request!=nil
46 @grader_process.report_active(test_request) if @grader_process!=nil
50 @grader_process.report_active(test_request) if @grader_process!=nil
47
51
48 @engine.grade(test_request)
52 @engine.grade(test_request)
49 test_request.status_complete!
53 test_request.status_complete!
50 @grader_process.report_inactive(test_request) if @grader_process!=nil
54 @grader_process.report_inactive(test_request) if @grader_process!=nil
51 end
55 end
52 return test_request
56 return test_request
53 end
57 end
54
58
55 end
59 end
56
60
57 end
61 end
58
62
You need to be logged in to leave comments. Login now