Description:
[web] analysis mode git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@265 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

r134:d2c58c857008 - - 6 files changed: 240 inserted, 1 deleted

@@ -0,0 +1,18
1 + %td
2 + = test_case[:num]
3 + %td{:style => 'padding-left: 5px; padding-right: 5px'}
4 + = test_case[:msg]
5 + - if test_case[:run_stat]!=nil
6 + %td{:style => 'padding-left: 5px; padding-right: 5px'}
7 + = test_case[:run_stat][:exit_status]
8 + %td{:style => 'padding-left: 5px; padding-right: 3px; text-align: center'}
9 + = test_case[:run_stat][:running_time]
10 + %td{:style => 'padding-left: 5px; padding-right: 10px; text-align: right'}
11 + = number_with_delimiter(test_case[:run_stat][:memory_usage])
12 + %td{:style => 'padding-left: 5px; padding-right: 5px'}
13 + = link_to "output (#{number_to_human_size(test_case[:output_size])})", :action => 'load_output', :id => @submission.id, :num => test_case[:num] if test_case[:output]
14 + - else
15 + %td
16 + %td
17 + %td
18 + %td
@@ -0,0 +1,41
1 + = user_title_bar(@user)
2 +
3 + %h2
4 + Grading Result for Task
5 + = @submission.problem.full_name
6 +
7 + %p
8 + = "Submission: #{@submission.number}"
9 + %br/
10 + = "Submitted at: #{format_short_time(@submission.submitted_at)}"
11 + %br/
12 + = "Graded at #{format_short_time(@submission.graded_at)} "
13 + %br/
14 + = "score: #{(@submission.points*100/@submission.problem.full_score).to_i} " if Configuration['ui.show_score']
15 + = " ["
16 + %tt
17 + = @submission.grader_comment
18 + = "]"
19 +
20 + %table.info
21 + %tr.info-head
22 + %th Runs
23 + %th Cases
24 + %th Result
25 + %th Exit
26 + %th Time (s)
27 + %th Memory (KB)
28 + %th Output
29 + - r = 0
30 + - @test_runs.each do |test_run|
31 + - r += 1
32 + - case_count = test_run.length
33 + - first_case = true
34 + - test_run.each do |test_case|
35 + %tr{:class => ((r%2==0) ? "info-even" : "info-odd")}
36 + - if first_case
37 + %td{:rowspan => case_count}
38 + = r
39 + - first_case = false
40 + = render :partial => 'test_case_result', :locals => {:test_case => test_case}
41 +
@@ -125,6 +125,46
125 end
125 end
126 end
126 end
127
127
128 + def result
129 + if !Configuration.show_grading_result
130 + redirect_to :action => 'list' and return
131 + end
132 + @user = User.find(session[:user_id])
133 + @submission = Submission.find(params[:id])
134 + if @submission.user!=@user
135 + flash[:notice] = 'You are not allowed to view result of other users.'
136 + redirect_to :action => 'list' and return
137 + end
138 + prepare_grading_result(@submission)
139 + end
140 +
141 + def load_output
142 + if !Configuration.show_grading_result or params[:num]==nil
143 + redirect_to :action => 'list' and return
144 + end
145 + @user = User.find(session[:user_id])
146 + @submission = Submission.find(params[:id])
147 + if @submission.user!=@user
148 + flash[:notice] = 'You are not allowed to view result of other users.'
149 + redirect_to :action => 'list' and return
150 + end
151 + case_num = params[:num].to_i
152 + out_filename = output_filename(@user.login,
153 + @submission.problem.name,
154 + @submission.id,
155 + case_num)
156 + if !FileTest.exists?(out_filename)
157 + flash[:notice] = 'Output not found.'
158 + redirect_to :action => 'list' and return
159 + end
160 +
161 + response.headers['Content-Type'] = "application/force-download"
162 + response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
163 + response.headers["X-Sendfile"] = out_filename
164 + response.headers['Content-length'] = File.size(out_filename)
165 + render :nothing => true
166 + end
167 +
128 def error
168 def error
129 @user = User.find(session[:user_id])
169 @user = User.find(session[:user_id])
130 end
170 end
@@ -156,5 +196,105
156 end
196 end
157 end
197 end
158
198
199 + def prepare_grading_result(submission)
200 + grading_info = Configuration.task_grading_info[submission.problem.name]
201 + @test_runs = []
202 + if grading_info['testruns'].is_a? Integer
203 + trun_count = grading_info['testruns']
204 + trun_count.times do |i|
205 + @test_runs << [ read_grading_result(@user.login,
206 + submission.problem.name,
207 + submission.id,
208 + i+1) ]
209 + end
210 + else
211 + grading_info['testruns'].keys.sort.each do |num|
212 + run = []
213 + testrun = grading_info['testruns'][num]
214 + testrun.each do |c|
215 + run << read_grading_result(@user.login,
216 + submission.problem.name,
217 + submission.id,
218 + c)
219 + end
220 + @test_runs << run
221 + end
222 + end
223 + end
224 +
225 + def grading_result_dir(user_name, problem_name, submission_id, case_num)
226 + return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
227 + end
228 +
229 + def output_filename(user_name, problem_name, submission_id, case_num)
230 + dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
231 + return "#{dir}/output.txt"
232 + end
233 +
234 + def read_grading_result(user_name, problem_name, submission_id, case_num)
235 + dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
236 + result_file_name = "#{dir}/result"
237 + if !FileTest.exists?(result_file_name)
238 + return {:num => case_num, :msg => 'program did not run'}
239 + else
240 + results = File.open(result_file_name).readlines
241 + run_stat = extract_running_stat(results)
242 + output_filename = "#{dir}/output.txt"
243 + if FileTest.exists?(output_filename)
244 + output_file = true
245 + output_size = File.size(output_filename)
246 + else
247 + output_file = false
248 + output_size = 0
249 + end
250 +
251 + return {
252 + :num => case_num,
253 + :msg => results[0],
254 + :run_stat => run_stat,
255 + :output => output_file,
256 + :output_size => output_size
257 + }
258 + end
259 + end
260 +
261 + # copied from grader/script/lib/test_request_helper.rb
262 + def extract_running_stat(results)
263 + running_stat_line = results[-1]
264 +
265 + # extract exit status line
266 + run_stat = ""
267 + if !(/[Cc]orrect/.match(results[0]))
268 + run_stat = results[0].chomp
269 + else
270 + run_stat = 'Program exited normally'
271 + end
272 +
273 + logger.info "Stat line: #{running_stat_line}"
274 +
275 + # extract running time
276 + if res = /r(.*)u(.*)s/.match(running_stat_line)
277 + seconds = (res[1].to_f + res[2].to_f)
278 + time_stat = "Time used: #{seconds} sec."
279 + else
280 + seconds = nil
281 + time_stat = "Time used: n/a sec."
282 + end
283 +
284 + # extract memory usage
285 + if res = /s(.*)m/.match(running_stat_line)
286 + memory_used = res[1].to_i
287 + else
288 + memory_used = -1
289 + end
290 +
291 + return {
292 + :msg => "#{run_stat}\n#{time_stat}",
293 + :running_time => seconds,
294 + :exit_status => run_stat,
295 + :memory_usage => memory_used
296 + }
297 + end
298 +
159 end
299 end
160
300
@@ -1,3 +1,5
1 + require 'yaml'
2 +
1 #
3 #
2 # This class also contains various login of the system.
4 # This class also contains various login of the system.
3 #
5 #
@@ -6,6 +8,7
6 SYSTEM_MODE_CONF_KEY = 'system.mode'
8 SYSTEM_MODE_CONF_KEY = 'system.mode'
7
9
8 @@configurations = nil
10 @@configurations = nil
11 + @@task_grading_info = nil
9
12
10 def self.get(key)
13 def self.get(key)
11 if @@configurations == nil
14 if @@configurations == nil
@@ -47,6 +50,10
47 return true
50 return true
48 end
51 end
49
52
53 + def self.show_grading_result
54 + return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
55 + end
56 +
50 def self.allow_test_request(user)
57 def self.allow_test_request(user)
51 mode = get(SYSTEM_MODE_CONF_KEY)
58 mode = get(SYSTEM_MODE_CONF_KEY)
52 if (mode=='contest')
59 if (mode=='contest')
@@ -55,6 +62,13
55 return false if mode=='analysis'
62 return false if mode=='analysis'
56 return true
63 return true
57 end
64 end
65 +
66 + def self.task_grading_info
67 + if @@task_grading_info==nil
68 + read_grading_info
69 + end
70 + return @@task_grading_info
71 + end
58
72
59 protected
73 protected
60 def self.read_config
74 def self.read_config
@@ -74,5 +88,11
74 end
88 end
75 end
89 end
76 end
90 end
91 +
92 + def self.read_grading_info
93 + f = File.open(TASK_GRADING_INFO_FILENAME)
94 + @@task_grading_info = YAML.load(f)
95 + f.close
96 + end
77
97
78 end
98 end
@@ -12,9 +12,12
12 %tt
12 %tt
13 = submission.grader_comment
13 = submission.grader_comment
14 = "]"
14 = "]"
15 + - if Configuration.show_grading_result
16 + = " | "
17 + = link_to '[detailed result]', :action => 'result', :id => submission.id
15 = " | "
18 = " | "
16 = link_to('[msg]', {:action => 'compiler_msg', :id => submission.id}, {:popup => true})
19 = link_to('[msg]', {:action => 'compiler_msg', :id => submission.id}, {:popup => true})
17 = " | "
20 = " | "
18 - = link_to('[source]',{:action => 'source', :id => submission.id})
21 + = link_to('[src]',{:action => 'source', :id => submission.id})
19 = " | "
22 = " | "
20 = link_to '[submissions]', :action => 'submission', :id => problem_name
23 = link_to '[submissions]', :action => 'submission', :id => problem_name
@@ -64,6 +64,23
64 <a href="/tasks/view/dna-mo.pdf">Macao, China</a>&nbsp;&nbsp;
64 <a href="/tasks/view/dna-mo.pdf">Macao, China</a>&nbsp;&nbsp;
65 <a href="/tasks/view/dna-th.pdf">Thailand</a>
65 <a href="/tasks/view/dna-th.pdf">Thailand</a>
66 </p>
66 </p>
67 +
68 + <p> <b>Test data</b> for all tasks:
69 + <a href="/files/testdata/all.zip">.zip</a>
70 + <a href="/files/testdata/all.tgz">.tgz</a><br/>
71 + <b>Beads:</b>
72 + <a href="/files/testdata/beads.zip">.zip</a>
73 + <a href="/files/testdata/beads.tgz">.tgz</a>&nbsp;&nbsp;
74 + <b>Roads:</b>
75 + <a href="/files/testdata/roads.zip">.zip</a>
76 + <a href="/files/testdata/roads.tgz">.tgz</a>&nbsp;&nbsp;
77 + <b>DNA:</b>
78 + <a href="/files/testdata/dna.zip">.zip</a>
79 + <a href="/files/testdata/dna.tgz">.tgz</a><br/>
80 + <b>Notes:</b><br/>
81 + &nbsp;&nbsp;<i>Beads.</i> The zip files contain the testing library that also outputs some magic numbers to verify the correct usage of the library. Files <tt>questions-*.txt</tt> are also prefixed with fake data.<br/>
82 + &nbsp;&nbsp;<i>Roads.</i> The zip files contain <tt>verify.cpp</tt> that checks the output.
83 + </p>
67 </td>
84 </td>
68 </tr>
85 </tr>
69
86
You need to be logged in to leave comments. Login now