gettc 1.5 → 1.6

Sign up to get free protection for your applications and to get access to all the features.
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