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

r122:ed471e6e96ca - - 1 file changed: 15 inserted, 2 deleted

@@ -1,401 +1,414
1 1 #!/usr/bin/ruby
2 2
3 3 def stop_grader(id)
4 4 if id==:all
5 5 File.open(File.dirname(__FILE__) + "/stop.all",'w').close
6 6 else
7 7 File.open(File.dirname(__FILE__) + "/stop.#{id}",'w').close
8 8 end
9 9 end
10 10
11 11 def check_stopfile
12 12 FileTest.exist?(File.dirname(__FILE__) + "/stop.all") or
13 13 FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
14 14 end
15 15
16 16 def clear_stopfile
17 17 if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 18 File.delete(File.dirname(__FILE__) + "/stop.#{Process.pid}")
19 19 end
20 20 end
21 21
22 22 def config
23 23 Grader::Configuration.get_instance
24 24 end
25 25
26 26 def log_file_name
27 27 if !File.exists?(config.log_dir)
28 28 raise "Log directory does not exist: #{config.log_dir}"
29 29 end
30 30 config.log_dir +
31 31 "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
32 32 end
33 33
34 34 def log(str)
35 35 if config.talkative
36 36 puts str
37 37 end
38 38 if config.logging
39 39 fp = File.open(log_file_name,"a")
40 40 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
41 41 fp.close
42 42 end
43 43 end
44 44
45 45 def display_manual
46 46 puts <<USAGE
47 47 Grader.
48 48 using: (1) grader
49 49 (2) grader environment [mode]
50 50 (3) grader stop [all|pids-list]
51 51 (4) grader --help
52 52 (1) call grader with environment = 'exam', mode = 'queue'
53 53 (2) possible modes are: 'queue', 'test_request', 'prob', 'sub', 'contest', and 'autonew'
54 54 (3) create stop-file to stop running grader in queue mode
55 55 (4) You are here.
56 56 USAGE
57 57 end
58 58
59 59 def process_options_and_stop_file
60 60 # The list of options are:
61 61 # - stop [all|process ids]
62 62 # -
63 63
64 64 # Process 'help' option
65 65 if (ARGV.length==1) and (/help/.match(ARGV[0]))
66 66 display_manual
67 67 exit(0)
68 68 end
69 69
70 70 # Process 'stop' option.
71 71 if (ARGV.length >= 1) and (ARGV[0]=='stop')
72 72 if ARGV.length==1
73 73 puts "you should specify pid-list or 'all'"
74 74 display_manual
75 75 elsif (ARGV.length==2) and (ARGV[1]=='all')
76 76 stop_grader(:all)
77 77 puts "A global stop file ('stop.all') created."
78 78 puts "You should remove it manually later."
79 79 else
80 80 (1..ARGV.length-1).each do |i|
81 81 stop_grader(ARGV[i])
82 82 end
83 83 puts "stop file(s) created"
84 84 end
85 85 exit(0)
86 86 end
87 87
88 88 # Check stop file.
89 89 if check_stopfile
90 90 puts "Stop file exists. Terminated."
91 91 clear_stopfile
92 92 exit(0)
93 93 end
94 94
95 95 #default options
96 96 options = {
97 97 :mode => 'queue',
98 98 :environment => 'exam',
99 99 :dry_run => false,
100 100 }
101 101
102 102 # Process mode and environment option
103 103 if ARGV.length >= 1
104 104 options[:environment] = ARGV.shift
105 105 if ARGV.length >=1
106 106 options[:mode] = ARGV.shift
107 107 end
108 108 end
109 109
110 110 options[:dry_run] = (ARGV.delete('--dry') != nil)
111 111 if options[:dry_run] and (not ['prob','contest','autonew'].include? options[:mode])
112 112 puts "Dry run currently works only for 'prob' or 'contest' modes."
113 113 exit(0)
114 114 end
115 115
116 116 options[:report] = (ARGV.delete('--report') != nil)
117 - if options[:report] and (not ['prob','contest'].include? options[:mode])
117 + if options[:report] and (not ['prob','contest','autonew'].include? options[:mode])
118 118 puts "Report currently works only for 'prob' or 'contest' modes."
119 119 exit(0)
120 120 end
121 121
122 122 return options
123 123 end
124 124
125 125 class ResultCollector
126 126 def initialize
127 127 @results = {}
128 128 @problems = {}
129 129 @users = {}
130 130 end
131 131
132 + def after_save_hook(user, problem, grading_result)
133 + end
134 +
132 135 def save(user, problem, grading_result)
133 136 if not @problems.has_key? problem.id
134 137 @problems[problem.id] = problem
135 138 end
136 139 if not @users.has_key? user.id
137 140 @users[user.id] = user
138 141 end
139 142 @results[[user.id, problem.id]] = grading_result
143 +
144 + after_save_hook(user, problem, grading_result)
140 145 end
141 146
142 147 def print_report_by_user
143 148 puts "---------------------"
144 149 puts " REPORT"
145 150 puts "---------------------"
146 151
147 152 print "login,email"
148 153 @problems.each_value do |problem|
149 154 print ",#{problem.name}"
150 155 end
151 156 print "\n"
152 157
153 158 @users.each_value do |user|
154 159 print "#{user.login},#{user.email}"
155 160 @problems.each_value do |problem|
156 161 if @results.has_key? [user.id, problem.id]
157 162 print ",#{@results[[user.id,problem.id]][:points]}"
158 163 else
159 164 print ","
160 165 end
161 166 end
162 167 print "\n"
163 168 end
164 169 end
165 170 end
166 171
167 172 def grader_general_loop(engine, grader_proc, options)
168 173 runner = Grader::Runner.new(engine, grader_proc)
169 174 while true
170 175
171 176 if check_stopfile # created by calling grader stop
172 177 clear_stopfile
173 178 log "stopped (with stop file)"
174 179 break
175 180 end
176 181
177 182 task = yield(runner)
178 183
179 184 if task==nil
180 185 sleep(1)
181 186 end
182 187 end
183 188 end
184 189
185 190 def grader_queue_loop(grader_proc, options)
186 191 log "Grader: queue"
187 192 engine = Grader::Engine.new
188 193 grader_general_loop(engine, grader_proc, options) do |runner|
189 194 runner.grade_oldest_task
190 195 end
191 196 end
192 197
193 198 def grader_test_request_loop(grader_proc, options)
194 199 log "Grader: test_request"
195 200 engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
196 201 :reporter => Grader::TestRequestReporter.new)
197 202 grader_general_loop(engine, grader_proc, options) do |runner|
198 203 runner.grade_oldest_test_request
199 204 end
200 205 end
201 206
202 207 def grader_autonew_loop(grader_proc, options)
203 208 log "Grader: autonew"
204 209
210 + if options[:report]
211 + result_collector = ResultCollector.new
212 + else
213 + result_collector = nil
214 + end
215 +
205 216 if options[:dry_run]
206 217 puts "Running in dry mode"
207 218 end
208 219
209 - prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run])
220 + prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run],
221 + :result_collector => result_collector)
222 +
210 223 engine = Grader::Engine.new(:reporter => prob_reporter)
211 224 runner = Grader::Runner.new(engine, grader_proc)
212 225
213 226 grader_proc.report_active if grader_proc!=nil
214 227
215 228 latest_submitted_at = nil
216 229 graded_submission_ids = {}
217 230
218 231 while true
219 232
220 233 if check_stopfile # created by calling grader stop
221 234 clear_stopfile
222 235 log "stopped (with stop file)"
223 236 break
224 237 end
225 238
226 239 if latest_submitted_at==nil
227 240 submissions = Submission.all
228 241 else
229 242 submissions = Submission.all(:conditions => ["submitted_at >= :latest",
230 243 {:latest => latest_submitted_at}])
231 244 end
232 245
233 246 graded_any = false
234 247
235 248 if submissions.length != 0
236 249 submissions.each do |submission|
237 250 if ! graded_submission_ids[submission.id]
238 251 runner.grade_submission(submission)
239 252 graded_submission_ids[submission.id] = true
240 253 if (!latest_submitted_at or
241 254 latest_submitted_at < submission.submitted_at)
242 255 latest_submitted_at = submission.submitted_at
243 256 end
244 257 puts "graded: #{submission.id}"
245 258 puts "latest: #{latest_submitted_at}"
246 259 graded_any = true
247 260 end
248 261 end
249 262 end
250 263
251 264 if ! graded_any
252 265 sleep(1)
253 266 end
254 267 end
255 268 end
256 269
257 270 def grader_grade_problems(grader_proc, options)
258 271 if options[:report]
259 272 result_collector = ResultCollector.new
260 273 else
261 274 result_collector = nil
262 275 end
263 276
264 277 if options[:dry_run]
265 278 puts "Running in dry mode"
266 279 end
267 280
268 281 prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run],
269 282 :result_collector => result_collector)
270 283 engine = Grader::Engine.new(:reporter => prob_reporter)
271 284 runner = Grader::Runner.new(engine, grader_proc)
272 285
273 286 grader_proc.report_active if grader_proc!=nil
274 287
275 288 ARGV.each do |prob_name|
276 289 prob = Problem.find_by_name(prob_name)
277 290 if prob==nil
278 291 puts "cannot find problem: #{prob_name}"
279 292 else
280 293 runner.grade_problem(prob)
281 294 end
282 295 end
283 296
284 297 if options[:report]
285 298 result_collector.print_report_by_user
286 299 end
287 300 end
288 301
289 302 def grader_grade_contests(grader_proc, options)
290 303 # always use dry run when grading during contest
291 304 dry_run = options[:dry_run] = true
292 305
293 306 contest_name = ARGV.shift
294 307
295 308 contest = Contest.find_by_name(contest_name)
296 309 if contest==nil
297 310 puts "cannot find contest: #{contest_name}"
298 311 exit(0)
299 312 end
300 313
301 314 if options[:report]
302 315 result_collector = ResultCollector.new
303 316 else
304 317 result_collector = nil
305 318 end
306 319
307 320 if options[:dry_run]
308 321 puts "Running in dry mode"
309 322 end
310 323
311 324 prob_reporter = Grader::SubmissionReporter.new(:dry_run => dry_run,
312 325 :result_collector => result_collector)
313 326 engine = Grader::Engine.new(:reporter => prob_reporter)
314 327 runner = Grader::Runner.new(engine, grader_proc)
315 328
316 329 grader_proc.report_active if grader_proc!=nil
317 330
318 331 contest.problems.each do |problem|
319 332 puts "Grading: #{problem.name}"
320 333 runner.grade_problem(problem,
321 334 :user_conditions => lambda do |u|
322 335 u.contest_finished? and
323 336 u.contest_ids.include?(contest.id)
324 337 end)
325 338 end
326 339
327 340 if options[:report]
328 341 result_collector.print_report_by_user
329 342 end
330 343 end
331 344
332 345 def grader_grade_submissions(grader_proc, options)
333 346 engine = Grader::Engine.new
334 347 runner = Grader::Runner.new(engine, grader_proc)
335 348
336 349 grader_proc.report_active if grader_proc!=nil
337 350
338 351 ARGV.each do |sub_id|
339 352 puts "Grading #{sub_id}"
340 353 begin
341 354 submission = Submission.find(sub_id.to_i)
342 355 rescue ActiveRecord::RecordNotFound
343 356 puts "Record not found"
344 357 submission = nil
345 358 end
346 359
347 360 if submission!=nil
348 361 runner.grade_submission(submission)
349 362 end
350 363 end
351 364 end
352 365
353 366 #########################################
354 367 # main program
355 368 #########################################
356 369
357 370 options = process_options_and_stop_file
358 371 GRADER_ENV = options[:environment]
359 372 grader_mode = options[:mode]
360 373 dry_run = options[:dry_run]
361 374
362 375 puts "environment: #{GRADER_ENV}"
363 376 require File.join(File.dirname(__FILE__),'config/environment')
364 377
365 378 # add grader_mode to config
366 379 # this is needed because method log needs it. TODO: clean this up
367 380 class << config
368 381 attr_accessor :grader_mode
369 382 end
370 383 config.grader_mode = grader_mode
371 384
372 385 # reading rails environment
373 386 log 'Reading rails environment'
374 387
375 388 RAILS_ENV = config.rails_env
376 389 require RAILS_ROOT + '/config/environment'
377 390
378 391 # register grader process
379 392 if config.report_grader
380 393 grader_proc = GraderProcess.register(config.grader_hostname,
381 394 Process.pid,
382 395 grader_mode)
383 396 else
384 397 grader_proc = nil
385 398 end
386 399
387 400 #set loggin environment
388 401 ENV['GRADER_LOGGING'] = log_file_name
389 402
390 403 # register exit handler to report inactive, and terminated
391 404 at_exit do
392 405 if grader_proc!=nil
393 406 grader_proc.report_inactive
394 407 grader_proc.terminate
395 408 end
396 409 end
397 410
398 411 #
399 412 # MAIN LOOP
400 413 #
401 414
You need to be logged in to leave comments. Login now