Description:
add options for grading all submissions of a specific problem (grafted from branch algo-bm 8ed1c0aa59eaf8e22e40fc765c1fba4ac88a34b5)
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r184:4e43dab877a1 - - 2 files changed: 28 inserted, 7 deleted

@@ -25,53 +25,64
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 - (2) grader environment [mode]
49 + (2) grader environment [mode] [options]
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 + queue: repeatedly check the task queue and grade any available tasks
55 +
56 + prob: re-grade every user latest submission of the specific problem.
57 + the problem name must be specified by the next argument.
58 +
59 + additional options:
60 +
61 + --all-sub re-grade every submissions instead of just the latest submission of each user.
62 + sub: re-grader the specified submission.
63 + The submission ID to be re-graded must be specified by the next argument.
64 +
54 65 (3) create stop-file to stop running grader in queue mode
55 66 (4) You are here.
56 67 USAGE
57 68 end
58 69
59 70 def process_options_and_stop_file
60 71 # The list of options are:
61 72 # - stop [all|process ids]
62 73 # -
63 74
64 75 # Process 'help' option
65 76 if (ARGV.length==1) and (/help/.match(ARGV[0]))
66 77 display_manual
67 78 exit(0)
68 79 end
69 80
70 81 # Process 'stop' option.
71 82 if (ARGV.length >= 1) and (ARGV[0]=='stop')
72 83 if ARGV.length==1
73 84 puts "you should specify pid-list or 'all'"
74 85 display_manual
75 86 elsif (ARGV.length==2) and (ARGV[1]=='all')
76 87 stop_grader(:all)
77 88 puts "A global stop file ('stop.all') created."
@@ -84,62 +95,66
84 95 end
85 96 exit(0)
86 97 end
87 98
88 99 # Check stop file.
89 100 if check_stopfile
90 101 puts "Stop file exists. Terminated."
91 102 clear_stopfile
92 103 exit(0)
93 104 end
94 105
95 106 #default options
96 107 options = {
97 108 :mode => 'queue',
98 109 :environment => 'exam',
99 110 :dry_run => false,
100 111 }
101 112
102 113 # Process mode and environment option
103 114 if ARGV.length >= 1
104 115 options[:environment] = ARGV.shift
105 116 if ARGV.length >=1
106 117 options[:mode] = ARGV.shift
107 118 end
119 + else
120 + puts 'no argument specified, using default mode and environment.'
108 121 end
109 122
110 123 options[:dry_run] = (ARGV.delete('--dry') != nil)
111 124 if options[:dry_run] and (not ['prob','contest','autonew'].include? options[:mode])
112 125 puts "Dry run currently works only for 'prob' or 'contest' modes."
113 126 exit(0)
114 127 end
115 128
116 129 options[:report] = (ARGV.delete('--report') != nil)
117 130 if options[:report] and (not ['prob','contest','autonew'].include? options[:mode])
118 131 puts "Report currently works only for 'prob' or 'contest' modes."
119 132 exit(0)
120 133 end
121 134
135 + options[:all_sub] = (ARGV.delete('--all-sub') != nil)
136 +
122 137 return options
123 138 end
124 139
125 140 class ResultCollector
126 141 def initialize
127 142 @results = {}
128 143 @problems = {}
129 144 @users = {}
130 145 end
131 146
132 147 def after_save_hook(submission, grading_result)
133 148 end
134 149
135 150 def save(submission, grading_result)
136 151 user = submission.user
137 152 problem = submission.problem
138 153 if not @problems.has_key? problem.id
139 154 @problems[problem.id] = problem
140 155 end
141 156 if not @users.has_key? user.id
142 157 @users[user.id] = user
143 158 end
144 159 @results[[user.id, problem.id]] = grading_result
145 160
@@ -274,49 +289,49
274 289
275 290 def grader_grade_problems(grader_proc, options)
276 291 if options[:report]
277 292 result_collector = ResultCollector.new
278 293 else
279 294 result_collector = nil
280 295 end
281 296
282 297 if options[:dry_run]
283 298 puts "Running in dry mode"
284 299 end
285 300
286 301 prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run],
287 302 :result_collector => result_collector)
288 303 engine = Grader::Engine.new(:reporter => prob_reporter)
289 304 runner = Grader::Runner.new(engine, grader_proc)
290 305
291 306 grader_proc.report_active if grader_proc!=nil
292 307
293 308 ARGV.each do |prob_name|
294 309 prob = Problem.find_by_name(prob_name)
295 310 if prob==nil
296 311 puts "cannot find problem: #{prob_name}"
297 312 else
298 - runner.grade_problem(prob)
313 + runner.grade_problem(prob,options)
299 314 end
300 315 end
301 316
302 317 if options[:report]
303 318 result_collector.print_report_by_user
304 319 end
305 320 end
306 321
307 322 def grader_grade_contests(grader_proc, options)
308 323 # always use dry run when grading during contest
309 324 dry_run = options[:dry_run] = true
310 325
311 326 contest_name = ARGV.shift
312 327
313 328 contest = Contest.find_by_name(contest_name)
314 329 if contest==nil
315 330 puts "cannot find contest: #{contest_name}"
316 331 exit(0)
317 332 end
318 333
319 334 if options[:report]
320 335 result_collector = ResultCollector.new
321 336 else
322 337 result_collector = nil
@@ -357,48 +372,49
357 372 puts "Grading #{sub_id}"
358 373 begin
359 374 submission = Submission.find(sub_id.to_i)
360 375 rescue ActiveRecord::RecordNotFound
361 376 puts "Submission #{sub_id} not found"
362 377 submission = nil
363 378 end
364 379
365 380 if submission!=nil
366 381 runner.grade_submission(submission)
367 382 end
368 383 end
369 384 end
370 385
371 386 #########################################
372 387 # main program
373 388 #########################################
374 389
375 390 options = process_options_and_stop_file
376 391 GRADER_ENV = options[:environment]
377 392 grader_mode = options[:mode]
378 393 dry_run = options[:dry_run]
379 394
380 395 puts "environment: #{GRADER_ENV}"
396 + puts "grader mode: #{grader_mode}"
381 397 require File.join(File.dirname(__FILE__),'config/environment')
382 398
383 399 # add grader_mode to config
384 400 # this is needed because method log needs it. TODO: clean this up
385 401 class << config
386 402 attr_accessor :grader_mode
387 403 end
388 404 config.grader_mode = grader_mode
389 405
390 406 # reading rails environment
391 407 log 'Reading rails environment'
392 408
393 409 RAILS_ENV = config.rails_env
394 410 require RAILS_ROOT + '/config/environment'
395 411
396 412 # register grader process
397 413 if config.report_grader
398 414 grader_proc = GraderProcess.register(config.grader_hostname,
399 415 Process.pid,
400 416 grader_mode)
401 417 else
402 418 grader_proc = nil
403 419 end
404 420
@@ -4,58 +4,63
4 4
5 5 module Grader
6 6
7 7 class Runner
8 8
9 9 def initialize(engine, grader_process=nil)
10 10 @engine = engine
11 11 @grader_process = grader_process
12 12 end
13 13
14 14 def grade_oldest_task
15 15 task = Task.get_inqueue_and_change_status(Task::STATUS_GRADING)
16 16 if task!=nil
17 17 @grader_process.report_active(task) if @grader_process!=nil
18 18
19 19 submission = Submission.find(task.submission_id)
20 20 @engine.grade(submission)
21 21 task.status_complete!
22 22 @grader_process.report_inactive(task) if @grader_process!=nil
23 23 end
24 24 return task
25 25 end
26 26
27 27 def grade_problem(problem, options={})
28 - users = User.find(:all)
29 - users.each do |u|
28 + User.find_each do |u|
30 29 puts "user: #{u.login}"
31 30 if options[:user_conditions]!=nil
32 31 con_proc = options[:user_conditions]
33 32 next if not con_proc.call(u)
34 33 end
35 - last_sub = Submission.find_last_by_user_and_problem(u.id,problem.id)
36 - if last_sub!=nil
37 - @engine.grade(last_sub)
34 + if options[:all_sub]
35 + Submission.where(user_id: u.id,problem_id: problem.id).find_each do |sub|
36 + @engine.grade(sub)
37 + end
38 + else
39 + last_sub = Submission.find_last_by_user_and_problem(u.id,problem.id)
40 + if last_sub!=nil
41 + @engine.grade(last_sub)
42 + end
38 43 end
39 44 end
40 45 end
41 46
42 47 def grade_submission(submission)
43 48 puts "Submission: #{submission.id} by #{submission.user.full_name}"
44 49 @engine.grade(submission)
45 50 end
46 51
47 52 def grade_oldest_test_request
48 53 test_request = TestRequest.get_inqueue_and_change_status(Task::STATUS_GRADING)
49 54 if test_request!=nil
50 55 @grader_process.report_active(test_request) if @grader_process!=nil
51 56
52 57 @engine.grade(test_request)
53 58 test_request.status_complete!
54 59 @grader_process.report_inactive(test_request) if @grader_process!=nil
55 60 end
56 61 return test_request
57 62 end
58 63
59 64 end
60 65
61 66 end
You need to be logged in to leave comments. Login now