Description:
[grader] change test_request_helper so that it copies additional submitted file git-svn-id: http://theory.cpe.ku.ac.th/grader/judge/trunk/scripts@231 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r55:7137557e8134 - - 2 files changed: 14 inserted, 1 deleted

@@ -1,54 +1,57
1 1 #
2 2 # A runner drives the engine into various tasks.
3 3 #
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 end
23 + # @grader_process.report_inactive if @grader_process!=nil
23 24 return task
24 25 end
25 26
26 27 def grade_problem(problem)
27 28 users = User.find(:all)
28 29 users.each do |u|
29 30 puts "user: #{u.login}"
30 31 last_sub = Submission.find(:first,
31 32 :conditions => "user_id = #{u.id} and " +
32 33 "problem_id = #{problem.id}",
33 34 :order => 'submitted_at DESC')
34 35 if last_sub!=nil
35 36 @engine.grade(last_sub)
36 37 end
37 38 end
38 39 end
39 40
40 41 def grade_oldest_test_request
41 42 test_request = TestRequest.get_inqueue_and_change_status(Task::STATUS_GRADING)
42 43 if test_request!=nil
43 44 @grader_process.report_active(test_request) if @grader_process!=nil
44 45
45 46 @engine.grade(test_request)
46 47 test_request.status_complete!
47 48 end
49 +
50 + # @grader_process.report_inactive if @grader_process!=nil
48 51 return test_request
49 52 end
50 53
51 54 end
52 55
53 56 end
54 57
@@ -1,230 +1,240
1 1 #
2 2 # This part contains various test_request helpers for interfacing
3 3 # with Grader::Engine. There are TestRequestRoomMaker and
4 4 # TestRequestReporter.
5 5
6 6 module Grader
7 7
8 8 #
9 9 # A TestRequestRoomMaker is a helper object for Engine
10 10 # - finds grading room: in user_result_dir/(user)/test_request/ ...
11 11 # - prepare problem configuration for grading --- basically it copy
12 12 # all config files, and copy user's input into the testcase
13 13 # directory. First, it finds the template from problem template
14 14 # directory; if it can't find a template, it'll use the template
15 15 # from default template.
16 16 class TestRequestRoomMaker
17 17 def initialize
18 18 @config = Grader::Configuration.get_instance
19 19 end
20 20
21 21 def produce_grading_room(test_request)
22 22 grading_room = grading_room_dir(test_request)
23 23 FileUtils.mkdir_p(grading_room)
24 +
25 + #
26 + # Also copy additional submitted file to this directory as well.
27 + # The program would see this file only if it is copied
28 + # to the sandbox directory later. The run script should do it.
29 + #
30 + cmd = "cp #{test_request.input_file_name}.files/* #{grading_room}"
31 + system(cmd)
32 +
24 33 grading_room
25 34 end
26 35
27 36 def find_problem_home(test_request)
28 37 problem_name = test_request.problem_name
29 38
30 39 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
31 40
32 41 raise "Test Request: error template not found" if !File.exists?(template_dir)
33 42
34 43 problem_home = problem_home_dir(test_request)
35 44 FileUtils.mkdir_p(problem_home)
36 45
37 46 copy_problem_template(template_dir,problem_home)
38 47 link_input_file(test_request,problem_home)
39 48
40 49 problem_home
41 50 end
42 51
43 52 def save_source(test_request,source_name)
44 53 dir = self.produce_grading_room(test_request)
45 54 submission = test_request.submission
46 55 f = File.open("#{dir}/#{source_name}","w")
47 56 f.write(submission.source)
48 57 f.close
49 58 end
50 59
51 60 def clean_up(test_request)
52 61 problem_home = problem_home_dir(test_request)
53 62 remove_data_files(problem_home)
54 63 end
55 64
56 65 protected
57 66 def grading_room_dir(test_request)
58 67 problem_name = test_request.problem_name
59 68 user = test_request.user
60 - "#{@config.user_result_dir}" +
69 + grading_room = "#{@config.user_result_dir}" +
61 70 "/#{user.login}/test_request" +
62 71 "/#{problem_name}/#{test_request.id}"
72 + grading_room
63 73 end
64 74
65 75 def problem_home_dir(test_request)
66 76 problem_name = test_request.problem_name
67 77 user = test_request.user
68 78 "#{@config.user_result_dir}" +
69 79 "/#{user.login}/test_request/#{problem_name}"
70 80 end
71 81
72 82 def copy_problem_template(template_dir,problem_home)
73 83 cmd = "cp -R #{template_dir}/* #{problem_home}"
74 84 system_and_raise_when_fail(cmd,"Test Request: cannot copy problem template")
75 85 end
76 86
77 87 def link_input_file(test_request,problem_home)
78 88 input_fname = "#{test_request.input_file_name}"
79 89 if !File.exists?(input_fname)
80 90 raise "Test Request: input file not found."
81 91 end
82 92
83 93 input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
84 94 if File.exists?(input_fname_problem_home)
85 95 FileUtils.rm([input_fname_problem_home], :force => true)
86 96 end
87 97
88 98 cmd = "ln -s #{input_fname} #{input_fname_problem_home}"
89 99 system_and_raise_when_fail(cmd,"Test Request: cannot link input file")
90 100 end
91 101
92 102 def remove_data_files(problem_home)
93 103 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
94 104 cmd = "rm #{problem_home}/test_cases/1/*"
95 105 system_and_raise_when_fail(cmd,"Test Request: cannot remove data files")
96 106 end
97 107 end
98 108
99 109 def system_and_raise_when_fail(cmd,msg)
100 110 if !system(cmd)
101 111 raise msg
102 112 end
103 113 end
104 114
105 115 end
106 116
107 117 class TestRequestReporter
108 118 def initialize
109 119 @config = Grader::Configuration.get_instance
110 120 end
111 121
112 122 def report(test_request,test_result_dir)
113 123 save_result(test_request,read_result(test_result_dir))
114 124 end
115 125
116 126 def report_error(test_request, msg)
117 127 save_result(test_request, {:running_stat => {
118 128 :msg => "#{msg}",
119 129 :running_time => nil,
120 130 :exit_status => "Some error occured. Program did not run",
121 131 :memory_usage => nil
122 132 }})
123 133 end
124 134
125 135 protected
126 136 def read_result(test_result_dir)
127 137 # TODO:
128 138 cmp_msg_fname = "#{test_result_dir}/compiler_message"
129 139 cmp_file = File.open(cmp_msg_fname)
130 140 cmp_msg = cmp_file.read
131 141 cmp_file.close
132 142
133 143 result_file_name = "#{test_result_dir}/1/result"
134 144
135 145 if File.exists?(result_file_name)
136 146 output_file_name = "#{test_result_dir}/1/output.txt"
137 147 results = File.open("#{test_result_dir}/1/result").readlines
138 148 stat = extract_running_stat(results)
139 149
140 150 return {
141 151 :output_file_name => output_file_name,
142 152 :running_stat => stat,
143 153 :comment => "",
144 154 :cmp_msg => cmp_msg}
145 155 else
146 156 return {
147 157 :running_stat => nil,
148 158 :comment => "Compilation error",
149 159 :cmp_msg => cmp_msg}
150 160 end
151 161 end
152 162
153 163 def extract_running_stat(results)
154 164 running_stat_line = results[-1]
155 165
156 166 # extract exit status line
157 167 run_stat = ""
158 168 if !(/[Cc]orrect/.match(results[0]))
159 169 run_stat = results[0].chomp
160 170 else
161 171 run_stat = 'Program exited normally'
162 172 end
163 173
164 174 # extract running time
165 175 if res = /r(.*)u(.*)s/.match(running_stat_line)
166 176 seconds = (res[1].to_f + res[2].to_f)
167 177 time_stat = "Time used: #{seconds} sec."
168 178 else
169 179 seconds = nil
170 180 time_stat = "Time used: n/a sec."
171 181 end
172 182
173 183 # extract memory usage
174 184 if res = /s(.*)m/.match(running_stat_line)
175 185 memory_used = res[1].to_i
176 186 else
177 187 memory_used = -1
178 188 end
179 189
180 190 return {
181 191 :msg => "#{run_stat}\n#{time_stat}",
182 192 :running_time => seconds,
183 193 :exit_status => run_stat,
184 194 :memory_usage => memory_used
185 195 }
186 196 end
187 197
188 198 def save_result(test_request,result)
189 199 if result[:output_file_name]!=nil
190 200 test_request.output_file_name = link_output_file(test_request,
191 201 result[:output_file_name])
192 202 end
193 203 test_request.graded_at = Time.now
194 204 test_request.compiler_message = (result[:cmp_msg] or '')
195 205 test_request.grader_comment = (result[:comment] or '')
196 206 if result[:running_stat]!=nil
197 207 test_request.running_stat = (result[:running_stat][:msg] or '')
198 208 test_request.running_time = (result[:running_stat][:running_time] or nil)
199 209 test_request.exit_status = result[:running_stat][:exit_status]
200 210 test_request.memory_usage = result[:running_stat][:memory_usage]
201 211 else
202 212 test_request.running_stat = ''
203 213 end
204 214 test_request.save
205 215 end
206 216
207 217 protected
208 218 def link_output_file(test_request, fname)
209 219 target_file_name = random_output_file_name(test_request.user,
210 220 test_request.problem)
211 221 FileUtils.mkdir_p(File.dirname(target_file_name))
212 222 cmd = "ln -s #{fname} #{target_file_name}"
213 223 if !system(cmd)
214 224 raise "TestRequestReporter: cannot move output file"
215 225 end
216 226 return target_file_name
217 227 end
218 228
219 229 def random_output_file_name(user,problem)
220 230 problem_name = TestRequest.name_of(problem)
221 231 begin
222 232 tmpname = "#{@config.test_request_output_base_dir}" +
223 233 "/#{user.login}/#{problem_name}/#{rand(10000)}"
224 234 end while File.exists?(tmpname)
225 235 tmpname
226 236 end
227 237
228 238 end
229 239
230 240 end
You need to be logged in to leave comments. Login now