gettc 1.5 → 1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/bin/gettc +45 -29
  3. data/core/lib/gettc.rb +7 -0
  4. data/core/lib/{topcoder → gettc}/download.rb +53 -45
  5. data/core/lib/gettc/generate.rb +145 -0
  6. data/core/lib/{topcoder → gettc}/parse.rb +104 -102
  7. data/core/lib/{topcoder → gettc}/print.rb +11 -11
  8. data/core/lib/{topcoder → gettc}/problem.rb +11 -11
  9. data/core/lib/{topcoder → gettc}/signature.rb +8 -8
  10. data/core/lib/{topcoder → gettc}/types.rb +34 -17
  11. data/core/test/{topcoder → gettc}/download_test.rb +6 -6
  12. data/core/test/gettc/generate_test.rb +31 -0
  13. data/core/test/{topcoder → gettc}/parse_test.rb +26 -26
  14. data/core/test/gettc/signature_test.rb +54 -0
  15. data/core/test/gettc/types_test.rb +24 -0
  16. data/dist/config.yml +1 -0
  17. data/dist/include/cpp/engine.rb +32 -32
  18. data/dist/include/cpp/topcoder +89 -25
  19. data/dist/include/haskell/TopCoder.hs +72 -53
  20. data/dist/include/haskell/engine.rb +49 -47
  21. data/dist/include/java/TopCoder.jar +0 -0
  22. data/dist/include/java/engine.rb +71 -71
  23. data/dist/include/python/engine.rb +46 -0
  24. data/dist/include/python/topcoder/__init__.py +3 -0
  25. data/dist/include/python/topcoder/errors.py +4 -0
  26. data/dist/include/python/topcoder/reader.py +160 -0
  27. data/dist/include/python/topcoder/writer.py +13 -0
  28. data/dist/template/bin/runner.sh +16 -6
  29. data/dist/template/solve/cpp/Makefile +9 -5
  30. data/dist/template/solve/cpp/{name}.cpp +8 -8
  31. data/dist/template/solve/cpp/{name}Runner.cpp +8 -8
  32. data/dist/template/solve/haskell/Makefile +9 -5
  33. data/dist/template/solve/haskell/{name}.hs +1 -1
  34. data/dist/template/solve/haskell/{name}Runner.hs +5 -5
  35. data/dist/template/solve/java/Makefile +18 -0
  36. data/dist/template/solve/java/build.xml +7 -3
  37. data/dist/template/solve/java/{name}.java +1 -1
  38. data/dist/template/solve/java/{name}Runner.java +1 -1
  39. data/dist/template/solve/python/Makefile +27 -0
  40. data/dist/template/solve/python/{name}.py +4 -0
  41. data/dist/template/solve/python/{name}Runner.py +27 -0
  42. data/dist/template/util/check/Makefile +3 -1
  43. data/dist/usage +5 -0
  44. metadata +30 -24
  45. data/Rakefile +0 -41
  46. data/core/lib/topcoder.rb +0 -3
  47. data/core/lib/topcoder/generate.rb +0 -131
  48. data/core/test/topcoder/generate_test.rb +0 -31
  49. data/core/test/topcoder/signature_test.rb +0 -52
  50. data/core/test/topcoder/types_test.rb +0 -24
  51. data/dist/template/solve/cpp/{name}Test.cpp +0 -8
  52. data/dist/template/solve/haskell/{name}Test.hs +0 -10
  53. data/dist/template/solve/java/{name}Test.java +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ce198ab839b5f78ae035a774c6294bd1d8378807
4
- data.tar.gz: 5d0295e172711215ef34efa74b95a03701b9e308
3
+ metadata.gz: 20faeb1bc318f83ee20890b3c36a1722711ade15
4
+ data.tar.gz: f86143dc3392702f57f8b7eba0f5b6d4b9c042dd
5
5
  SHA512:
6
- metadata.gz: bdee525b1578930dc32be932897b8cbf29cb9bdcbf2463a748772d4aef35b1420ebd0e87964105980b3d80aedb0151898b957b9cbbb67a31997a2ec668b1a127
7
- data.tar.gz: 6675ce735256bf4b6d9ae8485fb6d9b35fda904e36198a31d11a9a47f84b6b4564cca507216907f31c07df55316d94c35160aa4600a45aa5692ecc78515cd505
6
+ metadata.gz: 45124af073a77ce2ca421da0fdc1d03cc24ed0ca75abe080d29ca0e813857644c8d4832d9160e400516d0499c3e0bee0da71485060cdcf97dc9e76d8633f16ef
7
+ data.tar.gz: d4b0ea56988becb5ed1d7fe91bd0b92d2902ad02ae2d39f9724594c277c7eb2974ec1a10044fce9c755de26c4a2a717dfcb009054bc7e0ca0e800dad5768abc5
data/bin/gettc CHANGED
@@ -1,32 +1,44 @@
1
1
  #! /usr/bin/ruby
2
2
 
3
- require 'topcoder'
4
- include TopCoder
3
+ require "gettc"
4
+ include Gettc
5
5
 
6
- require 'rubygems'
7
- require 'fileutils'
8
- require 'yaml'
6
+ require "rubygems"
7
+ require "fileutils"
8
+ require "yaml"
9
9
 
10
- def root_d
11
- gem_d = Gem.loaded_specs['gettc']
10
+ def init
11
+ $config_d = ENV.fetch "GETTC_HOME", File.expand_path("~/.gettc")
12
+ gem_d = Gem.loaded_specs["gettc"]
12
13
  if gem_d.nil? then
13
- return File.join(File.basename(__FILE__), '../')
14
+ $root_d = File.join File.basename(__FILE__), "../"
14
15
  else
15
- return gem_d.full_gem_path
16
+ $root_d = gem_d.full_gem_path
16
17
  end
17
18
  end
18
19
 
20
+ def replace_config
21
+ FileUtils.mkdir $config_d
22
+ default_d = File.join $root_d, "dist/."
23
+ FileUtils.cp_r default_d, $config_d
24
+ end
25
+
19
26
  def load_config
20
- config_d = File.join File.expand_path('~'), '.gettc'
21
- unless Dir.exists? config_d then
22
- FileUtils.mkdir config_d
23
- default_d = File.join root_d, 'dist/.'
24
- FileUtils.cp_r default_d, config_d
27
+ replace_config unless Dir.exists? $config_d
28
+ config = YAML.load_file File.join($config_d, 'config.yml')
29
+
30
+ version = config["version"]
31
+ unless version.nil? then
32
+ version = Gem::Version.new version
33
+ end
34
+
35
+ if version.nil? or version < Gem::Version.new(VERSION) then
36
+ FileUtils.rm_rf $config_d
37
+ replace_config
25
38
  end
26
- config = YAML.load_file File.join(config_d, 'config.yml')
27
- account = Account.new config['username'], config['password']
28
- source_d = File.join config_d, 'template'
29
- return account, source_d
39
+
40
+ account = Account.new config["username"], config["password"]
41
+ return account
30
42
  end
31
43
 
32
44
  def main
@@ -38,26 +50,30 @@ def main
38
50
  id = ARGV[0].to_i
39
51
  puts "You have given ID = #{id}"
40
52
  begin
41
- account, source_d = load_config
53
+ account = load_config
42
54
  robot = Downloader.new account
43
55
  parser = Parser.new robot
44
- generator = Generator.new source_d, Dir.getwd
56
+ generator = Generator.new $config_d, Dir.getwd
45
57
 
46
- print 'Downloading problem to raw HTML ... '
58
+ print "Downloading problem to raw HTML ... "
47
59
  html = robot.download_problem id
48
- puts 'Done'
60
+ puts "Done"
49
61
 
50
- print 'Parsing problem from raw HTML ... '
62
+ print "Parsing problem from raw HTML ... "
51
63
  prob = parser.parse html
52
- puts 'Done'
64
+ puts "Done"
53
65
 
54
66
  print "Generating problem diectory for #{prob.name} ... "
55
67
  generator.generate prob
56
- puts 'Done'
57
- rescue => err
58
- $stderr.puts err
68
+ puts "Done"
69
+ rescue TemplateError => terr
70
+ puts terr
71
+ rescue StandardError => err
72
+ puts err
59
73
  exit -1
60
- end
61
74
  end
75
+ end
62
76
  end
63
- main
77
+
78
+ init
79
+ main
@@ -0,0 +1,7 @@
1
+ module Gettc
2
+ VERSION = "1.6"
3
+ end
4
+
5
+ require "gettc/download"
6
+ require "gettc/parse"
7
+ require "gettc/generate"
@@ -1,9 +1,9 @@
1
- require 'net/https'
2
- require 'cgi'
3
- require 'uri'
4
- require 'ostruct'
1
+ require "net/https"
2
+ require "cgi"
3
+ require "uri"
4
+ require "ostruct"
5
5
 
6
- module TopCoder
6
+ module Gettc
7
7
  class Account
8
8
  attr_accessor :username, :password
9
9
  def initialize username, password
@@ -31,16 +31,54 @@ module TopCoder
31
31
  super "#{msg} (#{id})"
32
32
  end
33
33
  end
34
+ class ProxyError < DownloadError
35
+ attr_accessor :proxy
36
+ def initialize proxy, msg = 'Proxy error'
37
+ @proxy = proxy
38
+ super "#{msg}: http_proxy = #{proxy}"
39
+ end
40
+ end
34
41
  class Downloader
35
- ROOT = 'http://community.topcoder.com'
42
+ ROOT = "http://community.topcoder.com"
36
43
  LIMIT = 10
37
44
  def initialize account
38
45
  @account = account
39
46
  @proxy = get_proxy
40
47
  @raw = get_cookie
41
48
  end
49
+ def download url
50
+ uri = url
51
+ unless uri.is_a? URI then
52
+ uri = url.start_with?("http") ? URI.parse(url) : URI.join(ROOT, url)
53
+ end
54
+
55
+ connect uri do |http|
56
+ LIMIT.times do
57
+ req = Net::HTTP::Get.new uri.request_uri
58
+ req["cookie"] = @raw
59
+ res = http.request req
60
+
61
+ return res.body if res.is_a? Net::HTTPSuccess
62
+ unless res.is_a? Net::HTTPMovedPermanently then
63
+ raise DownloadError.new res.class.to_s
64
+ end
65
+ uri = URI.parse res["location"]
66
+ end
67
+
68
+ raise DownloadError.new "Tried #{LIMIT} times without success"
69
+ end
70
+ end
71
+ def download_problem id
72
+ url = "/stat?c=problem_statement&pm=#{id}"
73
+ body = download url
74
+ if body.match("<h3>Problem Statement</h3>").nil? then
75
+ raise IDNotAvailable.new id
76
+ end
77
+ return body
78
+ end
79
+ private
42
80
  def get_proxy
43
- uri = URI.parse ENV['http_proxy']
81
+ uri = URI.parse ENV["http_proxy"]
44
82
  proxy = OpenStruct.new
45
83
  proxy.host, proxy.port = uri.host, uri.port
46
84
  if uri.userinfo then
@@ -63,60 +101,30 @@ module TopCoder
63
101
  begin
64
102
  yield http
65
103
  rescue Errno::ECONNRESET
66
- raise DownloadError.new "Check the http_proxy environmental variable"
104
+ raise ProxyError.new @proxy
67
105
  end
68
106
  end
69
107
  end
70
108
  end
71
109
  def get_cookie
72
- uri = URI.join(ROOT, 'tc?&module=Login')
110
+ uri = URI.join(ROOT, "tc?&module=Login")
73
111
 
74
112
  req = Net::HTTP::Post.new uri.request_uri
75
- req.set_form_data({'username' => @account.username,
76
- 'password' => @account.password,
77
- 'rem' => 'on' })
113
+ req.set_form_data({"username" => @account.username,
114
+ "password" => @account.password,
115
+ "rem" => "on" })
78
116
 
79
117
  res = connect uri do |http|
80
118
  http.request req
81
119
  end
82
- raw = res['set-cookie']
120
+ raw = res["set-cookie"]
83
121
 
84
122
  cookie = CGI::Cookie.parse raw
85
- if cookie['tcsso'].empty? then
123
+ if cookie["tcsso"].empty? then
86
124
  raise LoginFailed.new @account, cookie
87
125
  end
88
126
 
89
127
  return raw
90
128
  end
91
- def download url
92
- uri = url
93
- unless uri.is_a? URI then
94
- uri = url.start_with?('http') ? URI.parse(url) : URI.join(ROOT, url)
95
- end
96
-
97
- connect uri do |http|
98
- LIMIT.times do
99
- req = Net::HTTP::Get.new uri.request_uri
100
- req['cookie'] = @raw
101
- res = http.request req
102
-
103
- return res.body if res.is_a? Net::HTTPSuccess
104
- unless res.is_a? Net::HTTPMovedPermanently then
105
- raise DownloadError.new res.class.to_s
106
- end
107
- uri = URI.parse res['location']
108
- end
109
-
110
- raise DownloadError.new "Tried #{LIMIT} times without success"
111
- end
112
- end
113
- def download_problem id
114
- url = "/stat?c=problem_statement&pm=#{id}"
115
- body = download url
116
- if body.match('<h3>Problem Statement</h3>').nil? then
117
- raise IDNotAvailable.new id
118
- end
119
- return body
120
- end
121
129
  end
122
- end
130
+ end
@@ -0,0 +1,145 @@
1
+ require "fileutils"
2
+ require "pathname"
3
+ require "erb"
4
+
5
+ require "gettc/problem"
6
+ require "gettc/signature"
7
+ require "gettc/print"
8
+
9
+ module Gettc
10
+ GenerateError = Class.new StandardError
11
+ class ProblemDirExists < GenerateError
12
+ attr_accessor :dir
13
+ def initialize dir, msg = nil
14
+ if msg.nil? then
15
+ msg = "Cannot create problem directory because it already exists"
16
+ end
17
+ @dir = dir
18
+ super "#{msg} (#{dir})"
19
+ end
20
+ end
21
+ class SourceDirNotExist < GenerateError
22
+ attr_accessor :dir
23
+ def initialize dir, msg = "Source directory does not exist"
24
+ @dir = dir
25
+ super "#{msg} (#{dir})"
26
+ end
27
+ end
28
+ class TargetDirNotExist < GenerateError
29
+ attr_accessor :dir
30
+ def initialize dir, msg = "Target directory does not exist"
31
+ @dir = dir
32
+ super "#{msg} (#{dir})"
33
+ end
34
+ end
35
+ class TemplateError < GenerateError
36
+ attr_accessor :dir
37
+ def initialize err, source, msg = "Template error"
38
+ @err = err
39
+ @source = source
40
+ super "#{msg} (#{source})\n#{err}"
41
+ end
42
+ end
43
+ class Generator
44
+ def initialize config_d, target_d
45
+ @source_d = File.join config_d, "template"
46
+ @target_d = target_d
47
+ raise SourceDirNotExist.new @source_d unless File.directory? @source_d
48
+ raise TargetDirNotExist.new @target_d unless File.directory? @target_d
49
+
50
+ include_d = File.join config_d, "include"
51
+ load_engines include_d
52
+ end
53
+ def generate prob
54
+ @prob = prob
55
+ @prob_d = File.join @target_d, prob.name
56
+ raise ProblemDirExists.new @prob_d if File.exists? @prob_d
57
+ FileUtils.mkdir @prob_d
58
+
59
+ method_sig = @prob.definitions["Method signature"]
60
+ if method_sig.nil? then
61
+ $stderr.puts "[Warning] No definition for method signature found"
62
+ else
63
+ vars = parse_method_signature method_sig
64
+ func = vars.shift
65
+ end
66
+ @context = binding
67
+
68
+ walk @source_d, @prob_d
69
+ end
70
+ private
71
+ def gen_images images, images_d
72
+ images.each do |image|
73
+ filename = File.join images_d, image.name
74
+ File.open filename, "wb" do |f| f.write image.content end
75
+ end
76
+ end
77
+ def gen_cases cases, data_d
78
+ cases.each_index do |i|
79
+ c = cases[i]
80
+ File.open File.join(data_d, "#{i.to_s}.in"), "w" do |f|
81
+ f.write c.input
82
+ end
83
+ File.open File.join(data_d, "#{i.to_s}.out"), "w" do |f|
84
+ f.write c.output
85
+ end
86
+ end
87
+ end
88
+ def gen_template source, target
89
+ before = File.open source, "r" do |f| f.read end
90
+ begin
91
+ after = ERB.new(before).result @context
92
+ rescue SyntaxError, NameError => err
93
+ raise TemplateError.new err, source
94
+ end
95
+ File.open target, "w" do |f| f.write after end
96
+ end
97
+ def filter target_d, name
98
+ if name == "{images_d}" then
99
+ gen_images @prob.images, target_d
100
+ elsif name == "{examples_d}" then
101
+ gen_cases @prob.examples, target_d
102
+ elsif name == "{systests_d}" then
103
+ gen_cases @prob.systests, target_d
104
+ else
105
+ target_n = name.gsub /\{(\w*)\}/ do |match|
106
+ @prob.name if $1 == "name"
107
+ end
108
+ return target_n
109
+ end
110
+ return nil
111
+ end
112
+ def load_engines include_d
113
+ return unless File.exists? include_d
114
+ Dir.foreach include_d do |name|
115
+ child = File.join include_d, name
116
+ if File.directory? child then
117
+ engine = File.join child, "engine.rb"
118
+ if File.exists? engine then
119
+ unless (Pathname.new engine).absolute? then
120
+ engine = "./" + engine
121
+ end
122
+ require engine
123
+ end
124
+ end
125
+ end
126
+ end
127
+ def walk source_d, target_d
128
+ Dir.foreach source_d do |name|
129
+ if name != "." and name != ".." then
130
+ source_p = File.join source_d, name
131
+ target_n = filter target_d, name
132
+ unless target_n.nil? then
133
+ target_p = File.join target_d, target_n
134
+ if File.directory? source_p then
135
+ FileUtils.mkdir target_p unless File.exists? target_p
136
+ walk source_p, target_p
137
+ elsif File.file? source_p then
138
+ gen_template source_p, target_p
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -1,18 +1,81 @@
1
- require 'topcoder/problem'
2
- require 'topcoder/download'
1
+ require "gettc/problem"
2
+ require "gettc/download"
3
3
 
4
- require 'uri'
5
- require 'pathname'
6
- require 'hpricot'
4
+ require "uri"
5
+ require "pathname"
6
+ require "hpricot"
7
7
 
8
- module TopCoder
8
+ module Gettc
9
9
  class Parser
10
10
  def initialize downloader
11
11
  @downloader = downloader
12
12
  @images = []
13
13
  end
14
+ def parse html
15
+ @images = []
16
+ prob = Problem.new
17
+ doc = Hpricot(html)
18
+
19
+ prob.name = parse_name doc.search("tr/td.statTextBig").html
20
+ prob.notes = nil
21
+ prob.constraints = nil
22
+ prob.examples = nil
23
+
24
+ html = doc.search("td.problemText/table").html
25
+
26
+ _, x = indexes html, h3("Problem Statement")
27
+ y, z = indexes html, h3("Definition")
28
+ prob.statement = parse_statement html[x .. y]
14
29
 
15
- ## @section Utils
30
+ x, y = indexes html, h3("Notes")
31
+ if x.nil? then
32
+ prob.notes = []
33
+ x, y = indexes html, h3("Constraints")
34
+ if x.nil? then
35
+ prob.constraints = []
36
+ x, y = indexes html, h3("Examples")
37
+ if x.nil? then
38
+ prob.examples = []
39
+ x = -2
40
+ end
41
+ end
42
+ end
43
+ prob.definitions = parse_definitions html[z .. x]
44
+
45
+ if prob.notes.nil? then
46
+ z, x = indexes html, h3("Constraints")
47
+ if z.nil? then
48
+ prob.constraints = []
49
+ z, x = indexes html, h3("Examples")
50
+ if z.nil? then
51
+ prob.examples = []
52
+ z = - 2
53
+ end
54
+ end
55
+ prob.notes = parse_notes html[y .. z]
56
+ x, y = z, x
57
+ end
58
+
59
+ if prob.constraints.nil? then
60
+ z, x = indexes html, h3("Examples")
61
+ if z.nil? then
62
+ prob.examples = []
63
+ z = -2
64
+ end
65
+ prob.constraints = parse_constraints html[y .. z]
66
+ end
67
+
68
+ if prob.examples.nil? then
69
+ prob.examples = parse_examples html[x .. -2]
70
+ end
71
+
72
+ prob.images = @images
73
+ prob.url, prob.source, prob.systests = parse_details doc
74
+
75
+ return prob
76
+ end
77
+ private
78
+ ## @section General helpers
16
79
 
17
80
  def indexes str, substr
18
81
  from = str.index substr
@@ -21,13 +84,18 @@ module TopCoder
21
84
  return from - 1, to
22
85
  end
23
86
  def filter html
24
- unless html.valid_encoding? then
25
- html = html.encode Encoding::UTF_8, invaid: :replace, undef: :replace, replace: ''
26
- end
27
- html.gsub! /<b>(\w*)<\/b>/ do |match| "*#{$1}*" end
28
- html.gsub! /<sup>(\w*)<\/sup>/ do |match| "^(#{$1})" end
29
- html.gsub! '&#160;', ''
30
- html.gsub! '&nbsp;', ' '
87
+ html = html.force_encoding("ISO-8859-1").encode("utf-8",
88
+ invaid: :replace,
89
+ undef: :replace,
90
+ replace: "")
91
+ html.gsub! /<b>(\w*)<\/b>/ do |match|
92
+ "*#{$1}*"
93
+ end
94
+ html.gsub! /<sup>(\w*)<\/sup>/ do |match|
95
+ "^(#{$1})"
96
+ end
97
+ html.gsub! "&#160;", ""
98
+ html.gsub! "&nbsp;", " "
31
99
  text = Hpricot(html).to_plain_text
32
100
  text.gsub! /\[img:(http:\/\/[^\]]*)\]/ do |match|
33
101
  url = $1
@@ -50,7 +118,7 @@ module TopCoder
50
118
  ## @section Parse problem parts
51
119
 
52
120
  def parse_name html
53
- html.sub! 'Problem Statement for', ''
121
+ html.sub! "Problem Statement for", ""
54
122
  return filter html
55
123
  end
56
124
  def parse_statement html
@@ -58,8 +126,8 @@ module TopCoder
58
126
  end
59
127
  def parse_definitions html
60
128
  defs = { }
61
- Hpricot(html).search '/tr/td.statText/table/tr' do |tr|
62
- tds = tr.search '/td.statText'
129
+ Hpricot(html).search "/tr/td.statText/table/tr" do |tr|
130
+ tds = tr.search "/td.statText"
63
131
  if tds.size == 2 then
64
132
  key = tds[0].to_plain_text[0 .. -2]
65
133
  value = tds[1].to_plain_text
@@ -70,8 +138,8 @@ module TopCoder
70
138
  end
71
139
  def parse_notes html
72
140
  notes = []
73
- Hpricot(html).search '/tr' do |tr|
74
- tds = tr.search '/td.statText'
141
+ Hpricot(html).search "/tr" do |tr|
142
+ tds = tr.search "/td.statText"
75
143
  notes << filter(tds[1].html) if tds.size == 2
76
144
  end
77
145
  return notes
@@ -83,13 +151,13 @@ module TopCoder
83
151
  ## @section Parse cases
84
152
 
85
153
  def filter_inout text
86
- text.gsub! '{', '['
87
- text.gsub! '}', ']'
154
+ text.gsub! "{", "["
155
+ text.gsub! "}", "]"
88
156
  return text.strip
89
157
  end
90
158
  def parse_input html
91
159
  text = nil
92
- Hpricot(html).search '/table/tr/td.statText' do |td|
160
+ Hpricot(html).search "/table/tr/td.statText" do |td|
93
161
  input = td.to_plain_text.strip
94
162
  if text.nil? then
95
163
  text = input
@@ -101,7 +169,7 @@ module TopCoder
101
169
  end
102
170
  def parse_output html
103
171
  text = Hpricot(html).to_plain_text
104
- text.sub! 'Returns: ', ''
172
+ text.sub! "Returns: ", ""
105
173
  return filter_inout text
106
174
  end
107
175
  def parse_reason html
@@ -109,7 +177,7 @@ module TopCoder
109
177
  end
110
178
  def parse_examples html
111
179
  examples = []
112
- tds = Hpricot(html).search('/tr/td.statText/table/tr/td.statText')
180
+ tds = Hpricot(html).search("/tr/td.statText/table/tr/td.statText")
113
181
  i = 0
114
182
  while i < tds.size do
115
183
  example = Case.new
@@ -123,11 +191,11 @@ module TopCoder
123
191
  end
124
192
  def parse_systests html
125
193
  systests = []
126
- _, y = indexes html, '<!-- System Testing -->'
127
- z, _ = indexes html, '<!-- End System Testing -->'
128
- return systests if not y or not z
129
- Hpricot(html[y .. z]).search '/table/tr[@valign=top]' do |tr|
130
- tds = tr.search '/td.statText'
194
+ _, y = indexes html, "<!-- System Testing -->"
195
+ z, _ = indexes html, "<!-- End System Testing -->"
196
+ return systests unless y and z
197
+ Hpricot(html[y .. z]).search "/table/tr[@valign=top]" do |tr|
198
+ tds = tr.search "/td.statText"
131
199
  if tds.size == 3 then
132
200
  test = Case.new
133
201
  test.input = filter_inout tds[0].to_plain_text
@@ -139,17 +207,17 @@ module TopCoder
139
207
  end
140
208
  def download_systests detail_url
141
209
  detail = @downloader.download detail_url
142
- Hpricot(detail).search 'a[@href^=/stat?c=problem_solution]' do |url|
143
- solution = @downloader.download url.attributes['href']
210
+ Hpricot(detail).search "a[@href^=/stat?c=problem_solution]" do |url|
211
+ solution = @downloader.download url.attributes["href"]
144
212
  systests = parse_systests solution
145
- return systests if not systests.empty?
213
+ return systests unless systests.empty?
146
214
  end
147
215
  return []
148
216
  end
149
217
  def parse_details doc
150
- url, source, systests = '', '', []
151
- doc.search 'a[@href^=/tc?module=ProblemDetail]' do |elem|
152
- url = URI.join(Downloader::ROOT, elem.attributes['href']).to_s
218
+ url, source, systests = "", "", []
219
+ doc.search "a[@href^=/tc?module=ProblemDetail]" do |elem|
220
+ url = URI.join(Downloader::ROOT, elem.attributes["href"]).to_s
153
221
  source = filter elem.html
154
222
  begin
155
223
  systests = download_systests url
@@ -161,71 +229,5 @@ module TopCoder
161
229
  end
162
230
  return url, source, systests
163
231
  end
164
-
165
- ## @section Main method
166
-
167
- def parse html
168
- @images = []
169
- prob = Problem.new
170
- doc = Hpricot(html)
171
-
172
- prob.name = parse_name doc.search('tr/td.statTextBig').html
173
- prob.notes = nil
174
- prob.constraints = nil
175
- prob.examples = nil
176
-
177
- html = doc.search('td.problemText/table').html
178
-
179
- _, x = indexes html, h3('Problem Statement')
180
- y, z = indexes html, h3('Definition')
181
- prob.statement = parse_statement html[x .. y]
182
-
183
- x, y = indexes html, h3('Notes')
184
- if x.nil? then
185
- prob.notes = []
186
- x, y = indexes html, h3('Constraints')
187
- if x.nil? then
188
- prob.constraints = []
189
- x, y = indexes html, h3('Examples')
190
- if x.nil? then
191
- prob.examples = []
192
- x = -2
193
- end
194
- end
195
- end
196
- prob.definitions = parse_definitions html[z .. x]
197
-
198
- if prob.notes.nil? then
199
- z, x = indexes html, h3('Constraints')
200
- if z.nil? then
201
- prob.constraints = []
202
- z, x = indexes html, h3('Examples')
203
- if z.nil? then
204
- prob.examples = []
205
- z = - 2
206
- end
207
- end
208
- prob.notes = parse_notes html[y .. z]
209
- x, y = z, x
210
- end
211
-
212
- if prob.constraints.nil? then
213
- z, x = indexes html, h3('Examples')
214
- if z.nil? then
215
- prob.examples = []
216
- z = -2
217
- end
218
- prob.constraints = parse_constraints html[y .. z]
219
- end
220
-
221
- if prob.examples.nil? then
222
- prob.examples = parse_examples html[x .. -2]
223
- end
224
-
225
- prob.images = @images
226
- prob.url, prob.source, prob.systests = parse_details doc
227
-
228
- return prob
229
- end
230
232
  end
231
- end
233
+ end