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

r92:274af5f15b1f - - 4 files changed: 93 inserted, 19 deleted

@@ -47,30 +47,24
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', 'prob', 'test_request'
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 - #########################################
60 - # main program
61 - #########################################
62 -
63 - # Reading environment and options.
64 -
65 59 def process_options_and_stop_file
66 60 # The list of options are:
67 61 # - stop [all|process ids]
68 62 # -
69 63
70 64 # Process 'help' option
71 65 if (ARGV.length==1) and (/help/.match(ARGV[0]))
72 66 display_manual
73 67 exit(0)
74 68 end
75 69
76 70 # Process 'stop' option.
@@ -106,32 +100,83
106 100 }
107 101
108 102 # Process mode and environment option
109 103 if ARGV.length >= 1
110 104 options[:environment] = ARGV.shift
111 105 if ARGV.length >=1
112 106 options[:mode] = ARGV.shift
113 107 end
114 108 end
115 109
116 110 options[:dry_run] = (ARGV.delete('--dry') != nil)
117 111 if options[:dry_run] and (not options[:mode] == 'prob')
118 - puts "Dry run currently works for 'prob' mode."
112 + puts "Dry run currently works only for 'prob' mode."
113 + exit(0)
114 + end
115 +
116 + options[:report] = (ARGV.delete('--report') != nil)
117 + if options[:report] and (not options[:mode] == 'prob')
118 + puts "Report currently works only for 'prob' mode."
119 119 exit(0)
120 120 end
121 121
122 122 return options
123 123 end
124 124
125 - # ======= Main ========
125 + class ResultCollector
126 + def initialize
127 + @results = {}
128 + @problems = {}
129 + @users = {}
130 + end
131 +
132 + def save(user, problem, grading_result)
133 + if not @problems.has_key? problem.id
134 + @problems[problem.id] = problem
135 + end
136 + if not @users.has_key? user.id
137 + @users[user.id] = user
138 + end
139 + @results[[user.id, problem.id]] = grading_result
140 + end
141 +
142 + def print_report_by_user
143 + puts "---------------------"
144 + puts " REPORT"
145 + puts "---------------------"
146 +
147 + print "login"
148 + @problems.each_value do |problem|
149 + print ",#{problem.name}"
150 + end
151 + print "\n"
152 +
153 + @users.each_value do |user|
154 + print "#{user.login}"
155 + @problems.each_value do |problem|
156 + if @results.has_key? [user.id, problem.id]
157 + print ",#{@results[[user.id,problem.id]][:points]}"
158 + else
159 + print ","
160 + end
161 + end
162 + print "\n"
163 + end
164 + end
165 + end
166 +
167 + #########################################
168 + # main program
169 + #########################################
170 +
126 171 options = process_options_and_stop_file
127 172 GRADER_ENV = options[:environment]
128 173 grader_mode = options[:mode]
129 174 dry_run = options[:dry_run]
130 175
131 176 puts "environment: #{GRADER_ENV}"
132 177 require File.join(File.dirname(__FILE__),'config/environment')
133 178
134 179 # add grader_mode to config
135 180 # this is needed because method log needs it. TODO: clean this up
136 181 class << config
137 182 attr_accessor :grader_mode
@@ -165,62 +210,75
165 210 end
166 211
167 212 #
168 213 # MAIN LOOP
169 214 #
170 215
171 216 case grader_mode
172 217 when "queue", "test_request"
173 218 log "Grader: #{grader_mode}"
174 219 if grader_mode=="queue"
175 220 engine = Grader::Engine.new
176 221 else
177 - engine = Grader::Engine.new(Grader::TestRequestRoomMaker.new,
178 - Grader::TestRequestReporter.new)
222 + engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
223 + :reporter => Grader::TestRequestReporter.new)
179 224 end
180 225
181 226 runner = Grader::Runner.new(engine, grader_proc)
182 227 while true
183 228
184 229 if check_stopfile # created by calling grader stop
185 230 clear_stopfile
186 231 log "stopped (with stop file)"
187 232 break
188 233 end
189 234
190 235 if grader_mode=="queue"
191 236 task = runner.grade_oldest_task
192 237 else
193 238 task = runner.grade_oldest_test_request
194 239 end
195 240 if task==nil
196 241 sleep(1)
197 242 end
198 243 end
199 244
200 245 when "prob"
201 - engine = Grader::Engine.new(nil, Grader::SubmissionReporter.new(dry_run))
246 + if options[:report]
247 + result_collector = ResultCollector.new
248 + else
249 + result_collector = nil
250 + end
251 +
252 + engine = (Grader::Engine.
253 + new(:reporter =>
254 + Grader::SubmissionReporter.new(:dry_run => dry_run,
255 + :result_collector => result_collector)))
202 256 runner = Grader::Runner.new(engine, grader_proc)
203 257
204 258 grader_proc.report_active if grader_proc!=nil
205 259
206 260 ARGV.each do |prob_name|
207 261 prob = Problem.find_by_name(prob_name)
208 262 if prob==nil
209 263 puts "cannot find problem: #{prob_name}"
210 264 else
211 265 runner.grade_problem(prob)
212 266 end
213 267 end
214 268
269 + if options[:report]
270 + result_collector.print_report_by_user
271 + end
272 +
215 273 when "sub"
216 274 engine = Grader::Engine.new
217 275 runner = Grader::Runner.new(engine, grader_proc)
218 276
219 277 grader_proc.report_active if grader_proc!=nil
220 278
221 279 ARGV.each do |sub_id|
222 280 puts "Grading #{sub_id}"
223 281 begin
224 282 submission = Submission.find(sub_id.to_i)
225 283 rescue ActiveRecord::RecordNotFound
226 284 puts "Record not found"
@@ -5,29 +5,37
5 5 module Grader
6 6
7 7 #
8 8 # A grader engine grades a submission, against anything: a test
9 9 # data, or a user submitted test data. It uses two helpers objects:
10 10 # room_maker and reporter.
11 11 #
12 12 class Engine
13 13
14 14 attr_writer :room_maker
15 15 attr_writer :reporter
16 16
17 - def initialize(room_maker=nil, reporter=nil)
17 + def initialize(options={})
18 + # default options
19 + if not options.include? :room_maker
20 + options[:room_maker] = Grader::SubmissionRoomMaker.new
21 + end
22 + if not options.include? :reporter
23 + options[:reporter] = Grader::SubmissionReporter.new
24 + end
25 +
18 26 @config = Grader::Configuration.get_instance
19 27
20 - @room_maker = room_maker || Grader::SubmissionRoomMaker.new
21 - @reporter = reporter || Grader::SubmissionReporter.new
28 + @room_maker = options[:room_maker]
29 + @reporter = options[:reporter]
22 30 end
23 31
24 32 # takes a submission, asks room_maker to produce grading directories,
25 33 # calls grader scripts, and asks reporter to save the result
26 34 def grade(submission)
27 35 current_dir = `pwd`.chomp
28 36
29 37 user = submission.user
30 38 problem = submission.problem
31 39
32 40 # TODO: will have to create real exception for this
33 41 if user==nil or problem == nil
@@ -23,31 +23,39
23 23 def save_source(submission,source_name)
24 24 dir = self.produce_grading_room(submission)
25 25 f = File.open("#{dir}/#{source_name}","w")
26 26 f.write(submission.source)
27 27 f.close
28 28 end
29 29
30 30 def clean_up(submission)
31 31 end
32 32 end
33 33
34 34 class SubmissionReporter
35 - def initialize(dry_run=false)
35 + def initialize(options={})
36 + options = {:dry_run => false, :result_collector => nil}.merge(options)
36 37 @config = Grader::Configuration.get_instance
37 - @dry_run = dry_run
38 + @dry_run = options[:dry_run]
39 + @result_collector = options[:result_collector]
38 40 end
39 41
40 42 def report(sub,test_result_dir)
41 - save_result(sub,read_result(test_result_dir))
43 + result = read_result(test_result_dir)
44 + if @result_collector
45 + @result_collector.save(sub.user,
46 + sub.problem,
47 + result)
48 + end
49 + save_result(sub,result)
42 50 end
43 51
44 52 def report_error(sub,msg)
45 53 save_result(sub,{:points => 0,
46 54 :comment => "Grading error: #{msg}" })
47 55 end
48 56
49 57 protected
50 58 def read_result(test_result_dir)
51 59 cmp_msg_fname = "#{test_result_dir}/compiler_message"
52 60 if FileTest.exist?(cmp_msg_fname)
53 61 cmp_file = File.open(cmp_msg_fname)
@@ -147,26 +147,26
147 147 def create_normal_submission_mock_from_file(source_fname)
148 148 create_submission_from_file(1, @user_user1, @problem_test_normal, source_fname)
149 149 end
150 150
151 151 end
152 152
153 153 describe "A grader engine, when grading test requests" do
154 154
155 155 include GraderEngineHelperMethods
156 156
157 157 before(:each) do
158 158 @config = Grader::Configuration.get_instance
159 - @engine = Grader::Engine.new(Grader::TestRequestRoomMaker.new,
160 - Grader::TestRequestReporter.new)
159 + @engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
160 + :reporter => Grader::TestRequestReporter.new)
161 161 init_sandbox
162 162 end
163 163
164 164 it "should report error if there is no problem template" do
165 165 problem = stub(Problem,
166 166 :id => 1, :name => 'nothing')
167 167 grader_should(:grade => 'test1_correct.c',
168 168 :on => problem,
169 169 :with => 'in1.txt',
170 170 :and_report => {
171 171 :graded_at= => nil,
172 172 :compiler_message= => '',
You need to be logged in to leave comments. Login now