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 +
@@ -80,81 +80,221
80 flash[:notice] = 'Error adding your submission to task queue'
80 flash[:notice] = 'Error adding your submission to task queue'
81 end
81 end
82 else
82 else
83 prepare_list_information
83 prepare_list_information
84 render :action => 'list' and return
84 render :action => 'list' and return
85 end
85 end
86 redirect_to :action => 'list'
86 redirect_to :action => 'list'
87 end
87 end
88
88
89 def source
89 def source
90 submission = Submission.find(params[:id])
90 submission = Submission.find(params[:id])
91 if submission.user_id == session[:user_id]
91 if submission.user_id == session[:user_id]
92 if submission.problem.output_only
92 if submission.problem.output_only
93 fname = submission.source_filename
93 fname = submission.source_filename
94 else
94 else
95 fname = submission.problem.name + '.' + submission.language.ext
95 fname = submission.problem.name + '.' + submission.language.ext
96 end
96 end
97 send_data(submission.source,
97 send_data(submission.source,
98 {:filename => fname,
98 {:filename => fname,
99 :type => 'text/plain'})
99 :type => 'text/plain'})
100 else
100 else
101 flash[:notice] = 'Error viewing source'
101 flash[:notice] = 'Error viewing source'
102 redirect_to :action => 'list'
102 redirect_to :action => 'list'
103 end
103 end
104 end
104 end
105
105
106 def compiler_msg
106 def compiler_msg
107 @submission = Submission.find(params[:id])
107 @submission = Submission.find(params[:id])
108 if @submission.user_id == session[:user_id]
108 if @submission.user_id == session[:user_id]
109 render :action => 'compiler_msg', :layout => 'empty'
109 render :action => 'compiler_msg', :layout => 'empty'
110 else
110 else
111 flash[:notice] = 'Error viewing source'
111 flash[:notice] = 'Error viewing source'
112 redirect_to :action => 'list'
112 redirect_to :action => 'list'
113 end
113 end
114 end
114 end
115
115
116 def submission
116 def submission
117 @user = User.find(session[:user_id])
117 @user = User.find(session[:user_id])
118 @problems = Problem.find_available_problems
118 @problems = Problem.find_available_problems
119 if params[:id]==nil
119 if params[:id]==nil
120 @problem = nil
120 @problem = nil
121 @submissions = nil
121 @submissions = nil
122 else
122 else
123 @problem = Problem.find_by_name(params[:id])
123 @problem = Problem.find_by_name(params[:id])
124 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
124 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
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
131
171
132 protected
172 protected
133 def prepare_list_information
173 def prepare_list_information
134 @problems = Problem.find_available_problems
174 @problems = Problem.find_available_problems
135 @prob_submissions = Array.new
175 @prob_submissions = Array.new
136 @user = User.find(session[:user_id])
176 @user = User.find(session[:user_id])
137 @problems.each do |p|
177 @problems.each do |p|
138 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
178 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
139 if sub!=nil
179 if sub!=nil
140 @prob_submissions << { :count => sub.number, :submission => sub }
180 @prob_submissions << { :count => sub.number, :submission => sub }
141 else
181 else
142 @prob_submissions << { :count => 0, :submission => nil }
182 @prob_submissions << { :count => 0, :submission => nil }
143 end
183 end
144 end
184 end
145
185
146 @announcements = Announcement.find(:all,
186 @announcements = Announcement.find(:all,
147 :conditions => "published = 1",
187 :conditions => "published = 1",
148 :order => "created_at DESC")
188 :order => "created_at DESC")
149 end
189 end
150
190
151 def check_viewability
191 def check_viewability
152 @user = User.find(session[:user_id])
192 @user = User.find(session[:user_id])
153 if (!Configuration.show_tasks_to?(@user)) and
193 if (!Configuration.show_tasks_to?(@user)) and
154 ((action_name=='submission') or (action_name=='submit'))
194 ((action_name=='submission') or (action_name=='submit'))
155 redirect_to :action => 'list' and return
195 redirect_to :action => 'list' and return
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,78 +1,98
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 #
4 class Configuration < ActiveRecord::Base
6 class Configuration < ActiveRecord::Base
5
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
12 self.read_config
15 self.read_config
13 end
16 end
14 return @@configurations[key]
17 return @@configurations[key]
15 end
18 end
16
19
17 def self.[](key)
20 def self.[](key)
18 self.get(key)
21 self.get(key)
19 end
22 end
20
23
21 def self.reload
24 def self.reload
22 self.read_config
25 self.read_config
23 end
26 end
24
27
25 def self.clear
28 def self.clear
26 @@configurations = nil
29 @@configurations = nil
27 end
30 end
28
31
29 #
32 #
30 # View decision
33 # View decision
31 #
34 #
32 def self.show_submitbox_to?(user)
35 def self.show_submitbox_to?(user)
33 mode = get(SYSTEM_MODE_CONF_KEY)
36 mode = get(SYSTEM_MODE_CONF_KEY)
34 return false if mode=='analysis'
37 return false if mode=='analysis'
35 if (mode=='contest')
38 if (mode=='contest')
36 return false if (user.site!=nil) and
39 return false if (user.site!=nil) and
37 ((user.site.started!=true) or (user.site.finished?))
40 ((user.site.started!=true) or (user.site.finished?))
38 end
41 end
39 return true
42 return true
40 end
43 end
41
44
42 def self.show_tasks_to?(user)
45 def self.show_tasks_to?(user)
43 mode = get(SYSTEM_MODE_CONF_KEY)
46 mode = get(SYSTEM_MODE_CONF_KEY)
44 if (mode=='contest')
47 if (mode=='contest')
45 return false if (user.site!=nil) and (user.site.started!=true)
48 return false if (user.site!=nil) and (user.site.started!=true)
46 end
49 end
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')
53 return false if (user.site!=nil) and ((user.site.started!=true) or (user.site.time_left < 30.minutes))
60 return false if (user.site!=nil) and ((user.site.started!=true) or (user.site.time_left < 30.minutes))
54 end
61 end
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
61 @@configurations = {}
75 @@configurations = {}
62 Configuration.find(:all).each do |conf|
76 Configuration.find(:all).each do |conf|
63 key = conf.key
77 key = conf.key
64 val = conf.value
78 val = conf.value
65 case conf.value_type
79 case conf.value_type
66 when 'string'
80 when 'string'
67 @@configurations[key] = val
81 @@configurations[key] = val
68
82
69 when 'integer'
83 when 'integer'
70 @@configurations[key] = val.to_i
84 @@configurations[key] = val.to_i
71
85
72 when 'boolean'
86 when 'boolean'
73 @@configurations[key] = (val=='true')
87 @@configurations[key] = (val=='true')
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
@@ -1,20 +1,23
1
1
2 - if submission==nil
2 - if submission==nil
3 = "-"
3 = "-"
4 - else
4 - else
5 - if submission.graded_at==nil
5 - if submission.graded_at==nil
6 Submitted at
6 Submitted at
7 = format_short_time(submission.submitted_at)
7 = format_short_time(submission.submitted_at)
8 - else
8 - else
9 = "Graded at #{format_short_time(submission.graded_at)}, "
9 = "Graded at #{format_short_time(submission.graded_at)}, "
10 = "score: #{(submission.points*100/submission.problem.full_score).to_i} " if Configuration['ui.show_score']
10 = "score: #{(submission.points*100/submission.problem.full_score).to_i} " if Configuration['ui.show_score']
11 = " ["
11 = " ["
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
@@ -19,53 +19,70
19 Overview
19 Overview
20 </td>
20 </td>
21 </tr>
21 </tr>
22 <tr>
22 <tr>
23 <td class="desc-odd">
23 <td class="desc-odd">
24 <p>
24 <p>
25 <strong>Cover:</strong>
25 <strong>Cover:</strong>
26 <a href="/tasks/view/cover-en.pdf">Official English</a>&nbsp;&nbsp;
26 <a href="/tasks/view/cover-en.pdf">Official English</a>&nbsp;&nbsp;
27 <a href="/tasks/view/cover-id.pdf">Indonesia</a>&nbsp;&nbsp;
27 <a href="/tasks/view/cover-id.pdf">Indonesia</a>&nbsp;&nbsp;
28 <a href="/tasks/view/cover-jp.pdf">Japan</a>&nbsp;&nbsp;
28 <a href="/tasks/view/cover-jp.pdf">Japan</a>&nbsp;&nbsp;
29 <a href="/tasks/view/cover-kr.pdf">Korea</a>&nbsp;&nbsp;
29 <a href="/tasks/view/cover-kr.pdf">Korea</a>&nbsp;&nbsp;
30 <a href="/tasks/view/cover-th.pdf">Thailand</a>&nbsp;&nbsp;</p>
30 <a href="/tasks/view/cover-th.pdf">Thailand</a>&nbsp;&nbsp;</p>
31 </p>
31 </p>
32 <p>
32 <p>
33 <strong>Descriptions of all tasks:</strong>
33 <strong>Descriptions of all tasks:</strong>
34 <a href="/tasks/view/apio2008-cn.pdf">China</a>&nbsp;&nbsp;
34 <a href="/tasks/view/apio2008-cn.pdf">China</a>&nbsp;&nbsp;
35 <a href="/tasks/view/apio2008-jp.pdf">Japan</a><br/>
35 <a href="/tasks/view/apio2008-jp.pdf">Japan</a><br/>
36
36
37 <strong>Beads:</strong>
37 <strong>Beads:</strong>
38 <a href="/tasks/view/beads-en.pdf">Official English</a>&nbsp;&nbsp;
38 <a href="/tasks/view/beads-en.pdf">Official English</a>&nbsp;&nbsp;
39 <a href="/tasks/view/apio2008-cn.pdf">China (all tasks)</a>&nbsp;&nbsp;
39 <a href="/tasks/view/apio2008-cn.pdf">China (all tasks)</a>&nbsp;&nbsp;
40 <a href="/tasks/view/beads-tw.pdf">Chinese Taipei</a>&nbsp;&nbsp;
40 <a href="/tasks/view/beads-tw.pdf">Chinese Taipei</a>&nbsp;&nbsp;
41 <a href="/tasks/view/beads-id.pdf">Indonesia</a>&nbsp;&nbsp;
41 <a href="/tasks/view/beads-id.pdf">Indonesia</a>&nbsp;&nbsp;
42 <a href="/tasks/view/beads-jp.pdf">Japan</a>&nbsp;&nbsp;
42 <a href="/tasks/view/beads-jp.pdf">Japan</a>&nbsp;&nbsp;
43 <a href="/tasks/view/beads-kr.pdf">Korea</a>&nbsp;&nbsp;
43 <a href="/tasks/view/beads-kr.pdf">Korea</a>&nbsp;&nbsp;
44 <a href="/tasks/view/beads-mo.pdf">Macao, China</a>&nbsp;&nbsp;
44 <a href="/tasks/view/beads-mo.pdf">Macao, China</a>&nbsp;&nbsp;
45 <a href="/tasks/view/beads-th.pdf">Thailand</a><br/>
45 <a href="/tasks/view/beads-th.pdf">Thailand</a><br/>
46
46
47 <strong>Roads:</strong>
47 <strong>Roads:</strong>
48 <a href="/tasks/view/roads-en.pdf">Official English</a>&nbsp;&nbsp;
48 <a href="/tasks/view/roads-en.pdf">Official English</a>&nbsp;&nbsp;
49 <a href="/tasks/view/apio2008-cn.pdf">China (all tasks)</a>&nbsp;&nbsp;
49 <a href="/tasks/view/apio2008-cn.pdf">China (all tasks)</a>&nbsp;&nbsp;
50 <a href="/tasks/view/roads-tw.pdf">Chinese Taipei</a>&nbsp;&nbsp;
50 <a href="/tasks/view/roads-tw.pdf">Chinese Taipei</a>&nbsp;&nbsp;
51 <a href="/tasks/view/roads-id.pdf">Indonesia</a>&nbsp;&nbsp;
51 <a href="/tasks/view/roads-id.pdf">Indonesia</a>&nbsp;&nbsp;
52 <a href="/tasks/view/roads-jp.pdf">Japan</a>&nbsp;&nbsp;
52 <a href="/tasks/view/roads-jp.pdf">Japan</a>&nbsp;&nbsp;
53 <a href="/tasks/view/roads-kr.pdf">Korea</a>&nbsp;&nbsp;
53 <a href="/tasks/view/roads-kr.pdf">Korea</a>&nbsp;&nbsp;
54 <a href="/tasks/view/roads-mo.pdf">Macao, China</a>&nbsp;&nbsp;
54 <a href="/tasks/view/roads-mo.pdf">Macao, China</a>&nbsp;&nbsp;
55 <a href="/tasks/view/roads-th.pdf">Thailand</a><br/>
55 <a href="/tasks/view/roads-th.pdf">Thailand</a><br/>
56
56
57 <strong>DNA:</strong>
57 <strong>DNA:</strong>
58 <a href="/tasks/view/dna-en.pdf">Official English</a>&nbsp;&nbsp;
58 <a href="/tasks/view/dna-en.pdf">Official English</a>&nbsp;&nbsp;
59 <a href="/tasks/view/apio2008-cn.pdf">China (all tasks)</a>&nbsp;&nbsp;
59 <a href="/tasks/view/apio2008-cn.pdf">China (all tasks)</a>&nbsp;&nbsp;
60 <a href="/tasks/view/dna-tw.pdf">Chinese Taipei</a>&nbsp;&nbsp;
60 <a href="/tasks/view/dna-tw.pdf">Chinese Taipei</a>&nbsp;&nbsp;
61 <a href="/tasks/view/dna-id.pdf">Indonesia</a>&nbsp;&nbsp;
61 <a href="/tasks/view/dna-id.pdf">Indonesia</a>&nbsp;&nbsp;
62 <a href="/tasks/view/dna-jp.pdf">Japan</a>&nbsp;&nbsp;
62 <a href="/tasks/view/dna-jp.pdf">Japan</a>&nbsp;&nbsp;
63 <a href="/tasks/view/dna-kr.pdf">Korea</a>&nbsp;&nbsp;
63 <a href="/tasks/view/dna-kr.pdf">Korea</a>&nbsp;&nbsp;
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
70 <%= render :partial => 'problem', :collection => @problems %>
87 <%= render :partial => 'problem', :collection => @problems %>
71 </table>
88 </table>
You need to be logged in to leave comments. Login now