gettc 1.10 → 2.0
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.
- checksums.yaml +4 -4
- data/bin/gettc +60 -69
- data/dist/config.yml +1 -1
- data/dist/include/cpp/engine.rb +78 -86
- data/dist/include/cpp/topcoder +236 -236
- data/dist/include/go/engine.rb +53 -61
- data/dist/include/haskell/engine.rb +112 -122
- data/dist/include/java/engine.rb +187 -184
- data/dist/include/javascript/engine.rb +26 -30
- data/dist/include/javascript/topcoder.js +3 -3
- data/dist/include/javascript/topcoder/errors.js +5 -5
- data/dist/include/javascript/topcoder/reader.js +188 -165
- data/dist/include/javascript/topcoder/writer.js +37 -33
- data/dist/include/python/engine.rb +43 -52
- data/dist/include/python/topcoder/__init__.pyc +0 -0
- data/dist/include/python/topcoder/__pycache__/__init__.cpython-34.pyc +0 -0
- data/dist/include/python/topcoder/__pycache__/errors.cpython-34.pyc +0 -0
- data/dist/include/python/topcoder/__pycache__/reader.cpython-34.pyc +0 -0
- data/dist/include/python/topcoder/__pycache__/writer.cpython-34.pyc +0 -0
- data/dist/include/python/topcoder/errors.pyc +0 -0
- data/dist/include/python/topcoder/reader.pyc +0 -0
- data/dist/include/python/topcoder/writer.pyc +0 -0
- data/dist/include/ruby/engine.rb +47 -52
- data/dist/include/ruby/topcoder/reader.rb +205 -193
- data/dist/include/ruby/topcoder/writer.rb +39 -37
- data/dist/template/bin/runner.rb +146 -151
- data/dist/template/bin/runner.sh +96 -96
- data/dist/template/prob/{name}.html +1 -1
- data/dist/template/solve/cpp/{name}.cpp +3 -4
- data/dist/template/solve/cpp/{name}Solver.cpp +14 -14
- data/dist/template/solve/go/{name}/{name}.go +3 -3
- data/dist/template/solve/go/{name}Solver.go +2 -2
- data/dist/template/solve/haskell/{name}.hs +6 -6
- data/dist/template/solve/haskell/{name}Solver.hs +10 -10
- data/dist/template/solve/java/{name}.java +4 -4
- data/dist/template/solve/java/{name}Solver.java +4 -4
- data/dist/template/solve/javascript/{name}.js +4 -6
- data/dist/template/solve/javascript/{name}Solver.js +11 -9
- data/dist/template/solve/python/{name}.py +1 -1
- data/dist/template/solve/python/{name}Solver.py +2 -2
- data/dist/template/solve/ruby/{name}.rb +4 -4
- data/dist/template/solve/ruby/{name}Solver.rb +14 -17
- data/dist/template/util/check/check.cpp +19 -19
- data/{core/lib → lib}/gettc.rb +0 -0
- data/lib/gettc/account.rb +14 -0
- data/lib/gettc/download.rb +211 -0
- data/lib/gettc/generate.rb +156 -0
- data/lib/gettc/parse.rb +237 -0
- data/lib/gettc/print.rb +54 -0
- data/lib/gettc/problem.rb +39 -0
- data/lib/gettc/signature.rb +63 -0
- data/lib/gettc/types.rb +93 -0
- data/lib/version.rb +3 -0
- data/test/gettc/download_test.rb +61 -0
- data/test/gettc/generate_test.rb +70 -0
- data/test/gettc/parse_test.rb +78 -0
- data/test/gettc/signature_test.rb +71 -0
- data/test/gettc/types_test.rb +31 -0
- metadata +28 -23
- data/core/lib/gettc/download.rb +0 -130
- data/core/lib/gettc/generate.rb +0 -145
- data/core/lib/gettc/parse.rb +0 -233
- data/core/lib/gettc/print.rb +0 -56
- data/core/lib/gettc/problem.rb +0 -33
- data/core/lib/gettc/signature.rb +0 -55
- data/core/lib/gettc/types.rb +0 -83
- data/core/lib/version.rb +0 -3
- data/core/test/gettc/download_test.rb +0 -29
- data/core/test/gettc/generate_test.rb +0 -31
- data/core/test/gettc/parse_test.rb +0 -104
- data/core/test/gettc/signature_test.rb +0 -54
- data/core/test/gettc/types_test.rb +0 -28
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gettc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '
|
4
|
+
version: '2.0'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hpricot
|
@@ -49,20 +49,6 @@ extensions: []
|
|
49
49
|
extra_rdoc_files: []
|
50
50
|
files:
|
51
51
|
- bin/gettc
|
52
|
-
- core/lib/gettc.rb
|
53
|
-
- core/lib/gettc/download.rb
|
54
|
-
- core/lib/gettc/generate.rb
|
55
|
-
- core/lib/gettc/parse.rb
|
56
|
-
- core/lib/gettc/print.rb
|
57
|
-
- core/lib/gettc/problem.rb
|
58
|
-
- core/lib/gettc/signature.rb
|
59
|
-
- core/lib/gettc/types.rb
|
60
|
-
- core/lib/version.rb
|
61
|
-
- core/test/gettc/download_test.rb
|
62
|
-
- core/test/gettc/generate_test.rb
|
63
|
-
- core/test/gettc/parse_test.rb
|
64
|
-
- core/test/gettc/signature_test.rb
|
65
|
-
- core/test/gettc/types_test.rb
|
66
52
|
- dist/config.yml
|
67
53
|
- dist/include/cpp/engine.rb
|
68
54
|
- dist/include/cpp/topcoder
|
@@ -84,6 +70,10 @@ files:
|
|
84
70
|
- dist/include/python/engine.rb
|
85
71
|
- dist/include/python/topcoder/__init__.py
|
86
72
|
- dist/include/python/topcoder/__init__.pyc
|
73
|
+
- dist/include/python/topcoder/__pycache__/__init__.cpython-34.pyc
|
74
|
+
- dist/include/python/topcoder/__pycache__/errors.cpython-34.pyc
|
75
|
+
- dist/include/python/topcoder/__pycache__/reader.cpython-34.pyc
|
76
|
+
- dist/include/python/topcoder/__pycache__/writer.cpython-34.pyc
|
87
77
|
- dist/include/python/topcoder/errors.py
|
88
78
|
- dist/include/python/topcoder/errors.pyc
|
89
79
|
- dist/include/python/topcoder/reader.py
|
@@ -127,13 +117,28 @@ files:
|
|
127
117
|
- dist/template/util/check/Makefile
|
128
118
|
- dist/template/util/check/check.cpp
|
129
119
|
- dist/usage
|
120
|
+
- lib/gettc.rb
|
121
|
+
- lib/gettc/account.rb
|
122
|
+
- lib/gettc/download.rb
|
123
|
+
- lib/gettc/generate.rb
|
124
|
+
- lib/gettc/parse.rb
|
125
|
+
- lib/gettc/print.rb
|
126
|
+
- lib/gettc/problem.rb
|
127
|
+
- lib/gettc/signature.rb
|
128
|
+
- lib/gettc/types.rb
|
129
|
+
- lib/version.rb
|
130
|
+
- test/gettc/download_test.rb
|
131
|
+
- test/gettc/generate_test.rb
|
132
|
+
- test/gettc/parse_test.rb
|
133
|
+
- test/gettc/signature_test.rb
|
134
|
+
- test/gettc/types_test.rb
|
130
135
|
homepage: http://seri.github.io/gettc
|
131
136
|
licenses: []
|
132
137
|
metadata: {}
|
133
138
|
post_install_message:
|
134
139
|
rdoc_options: []
|
135
140
|
require_paths:
|
136
|
-
-
|
141
|
+
- lib
|
137
142
|
required_ruby_version: !ruby/object:Gem::Requirement
|
138
143
|
requirements:
|
139
144
|
- - ">="
|
@@ -146,13 +151,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
151
|
version: '0'
|
147
152
|
requirements: []
|
148
153
|
rubyforge_project:
|
149
|
-
rubygems_version: 2.
|
154
|
+
rubygems_version: 2.4.8
|
150
155
|
signing_key:
|
151
156
|
specification_version: 4
|
152
157
|
summary: TopCoder offline arena supporting multiple languages
|
153
158
|
test_files:
|
154
|
-
-
|
155
|
-
-
|
156
|
-
-
|
157
|
-
-
|
158
|
-
-
|
159
|
+
- test/gettc/download_test.rb
|
160
|
+
- test/gettc/generate_test.rb
|
161
|
+
- test/gettc/parse_test.rb
|
162
|
+
- test/gettc/signature_test.rb
|
163
|
+
- test/gettc/types_test.rb
|
data/core/lib/gettc/download.rb
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
require "net/https"
|
2
|
-
require "cgi"
|
3
|
-
require "uri"
|
4
|
-
require "ostruct"
|
5
|
-
|
6
|
-
module Gettc
|
7
|
-
class Account
|
8
|
-
attr_accessor :username, :password
|
9
|
-
def initialize username, password
|
10
|
-
@username = username
|
11
|
-
@password = password
|
12
|
-
end
|
13
|
-
def to_s
|
14
|
-
return "#{@username}|#{@password}"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
class DownloadError < StandardError
|
18
|
-
end
|
19
|
-
class LoginFailed < DownloadError
|
20
|
-
attr_accessor :account, :cookie
|
21
|
-
def initialize account, cookie, msg = 'Wrong username or password'
|
22
|
-
@account = account
|
23
|
-
@cookie = cookie
|
24
|
-
super "#{msg}\nAccount: #{@account}\nCookie: #{@cookie}\n"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
class IDNotAvailable < DownloadError
|
28
|
-
attr_accessor :id
|
29
|
-
def initialize id, msg = 'ID not available'
|
30
|
-
@id = id
|
31
|
-
super "#{msg} (#{id})"
|
32
|
-
end
|
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
|
41
|
-
class Downloader
|
42
|
-
ROOT = "http://community.topcoder.com"
|
43
|
-
LIMIT = 10
|
44
|
-
def initialize account
|
45
|
-
@account = account
|
46
|
-
@proxy = get_proxy
|
47
|
-
@raw = get_cookie
|
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
|
80
|
-
def get_proxy
|
81
|
-
uri = URI.parse ENV["http_proxy"]
|
82
|
-
proxy = OpenStruct.new
|
83
|
-
proxy.host, proxy.port = uri.host, uri.port
|
84
|
-
if uri.userinfo then
|
85
|
-
proxy.user, proxy.pass = uri.userinfo.split /:/
|
86
|
-
else
|
87
|
-
proxy.user, proxy.pass = nil, nil
|
88
|
-
end
|
89
|
-
return proxy
|
90
|
-
rescue URI::InvalidURIError
|
91
|
-
return nil
|
92
|
-
end
|
93
|
-
def connect uri
|
94
|
-
if @proxy.nil? then
|
95
|
-
Net::HTTP.start(uri.host, uri.port) do |http|
|
96
|
-
yield http
|
97
|
-
end
|
98
|
-
else
|
99
|
-
Net::HTTP.start(uri.host, uri.port, @proxy.host, @proxy.port,
|
100
|
-
@proxy.user, @proxy.pass) do |http|
|
101
|
-
begin
|
102
|
-
yield http
|
103
|
-
rescue Errno::ECONNRESET
|
104
|
-
raise ProxyError.new @proxy
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
def get_cookie
|
110
|
-
uri = URI.join(ROOT, "tc?&module=Login")
|
111
|
-
|
112
|
-
req = Net::HTTP::Post.new uri.request_uri
|
113
|
-
req.set_form_data({"username" => @account.username,
|
114
|
-
"password" => @account.password,
|
115
|
-
"rem" => "on" })
|
116
|
-
|
117
|
-
res = connect uri do |http|
|
118
|
-
http.request req
|
119
|
-
end
|
120
|
-
raw = res["set-cookie"]
|
121
|
-
|
122
|
-
cookie = CGI::Cookie.parse raw
|
123
|
-
if cookie["tcsso"].empty? then
|
124
|
-
raise LoginFailed.new @account, cookie
|
125
|
-
end
|
126
|
-
|
127
|
-
return raw
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
data/core/lib/gettc/generate.rb
DELETED
@@ -1,145 +0,0 @@
|
|
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
|
data/core/lib/gettc/parse.rb
DELETED
@@ -1,233 +0,0 @@
|
|
1
|
-
require "gettc/problem"
|
2
|
-
require "gettc/download"
|
3
|
-
|
4
|
-
require "uri"
|
5
|
-
require "pathname"
|
6
|
-
require "hpricot"
|
7
|
-
|
8
|
-
module Gettc
|
9
|
-
class Parser
|
10
|
-
def initialize downloader
|
11
|
-
@downloader = downloader
|
12
|
-
@images = []
|
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]
|
29
|
-
|
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
|
79
|
-
|
80
|
-
def indexes str, substr
|
81
|
-
from = str.index substr
|
82
|
-
return nil if from.nil?
|
83
|
-
to = from + substr.size
|
84
|
-
return from - 1, to
|
85
|
-
end
|
86
|
-
def filter html
|
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! " ", ""
|
98
|
-
html.gsub! " ", " "
|
99
|
-
text = Hpricot(html).to_plain_text
|
100
|
-
text.gsub! /\[img:(http:\/\/[^\]]*)\]/ do |match|
|
101
|
-
url = $1
|
102
|
-
image = Image.new
|
103
|
-
image.name = Pathname.new(url).basename
|
104
|
-
begin
|
105
|
-
image.content = @downloader.download url
|
106
|
-
@images << image
|
107
|
-
""
|
108
|
-
rescue StandardError
|
109
|
-
""
|
110
|
-
end
|
111
|
-
end
|
112
|
-
return text
|
113
|
-
end
|
114
|
-
def h3 tag
|
115
|
-
return "<h3>#{tag}</h3>"
|
116
|
-
end
|
117
|
-
|
118
|
-
## @section Parse problem parts
|
119
|
-
|
120
|
-
def parse_name html
|
121
|
-
html.sub! "Problem Statement for", ""
|
122
|
-
return filter html
|
123
|
-
end
|
124
|
-
def parse_statement html
|
125
|
-
return filter html
|
126
|
-
end
|
127
|
-
def parse_definitions html
|
128
|
-
defs = { }
|
129
|
-
Hpricot(html).search "/tr/td.statText/table/tr" do |tr|
|
130
|
-
tds = tr.search "/td.statText"
|
131
|
-
if tds.size == 2 then
|
132
|
-
key = tds[0].to_plain_text[0 .. -2]
|
133
|
-
value = tds[1].to_plain_text
|
134
|
-
defs[key] = value
|
135
|
-
end
|
136
|
-
end
|
137
|
-
return defs
|
138
|
-
end
|
139
|
-
def parse_notes html
|
140
|
-
notes = []
|
141
|
-
Hpricot(html).search "/tr" do |tr|
|
142
|
-
tds = tr.search "/td.statText"
|
143
|
-
notes << filter(tds[1].html) if tds.size == 2
|
144
|
-
end
|
145
|
-
return notes
|
146
|
-
end
|
147
|
-
def parse_constraints html
|
148
|
-
return parse_notes html
|
149
|
-
end
|
150
|
-
|
151
|
-
## @section Parse cases
|
152
|
-
|
153
|
-
def filter_inout text
|
154
|
-
text.gsub! "{", "["
|
155
|
-
text.gsub! "}", "]"
|
156
|
-
return text.strip
|
157
|
-
end
|
158
|
-
def parse_input html
|
159
|
-
text = nil
|
160
|
-
Hpricot(html).search "/table/tr/td.statText" do |td|
|
161
|
-
input = td.to_plain_text.strip
|
162
|
-
if text.nil? then
|
163
|
-
text = input
|
164
|
-
else
|
165
|
-
text << ",\n" << input
|
166
|
-
end
|
167
|
-
end
|
168
|
-
return filter_inout text
|
169
|
-
end
|
170
|
-
def parse_output html
|
171
|
-
text = Hpricot(html).to_plain_text
|
172
|
-
text.sub! "Returns: ", ""
|
173
|
-
return filter_inout text
|
174
|
-
end
|
175
|
-
def parse_reason html
|
176
|
-
return filter html
|
177
|
-
end
|
178
|
-
def parse_examples html
|
179
|
-
examples = []
|
180
|
-
tds = Hpricot(html).search("/tr/td.statText/table/tr/td.statText")
|
181
|
-
i = 0
|
182
|
-
while i < tds.size do
|
183
|
-
example = Case.new
|
184
|
-
example.input = parse_input tds[i].html
|
185
|
-
example.output = parse_output tds[i += 1].html
|
186
|
-
example.reason = parse_reason tds[i += 1].html
|
187
|
-
examples << example
|
188
|
-
i += 1
|
189
|
-
end
|
190
|
-
return examples
|
191
|
-
end
|
192
|
-
def parse_systests html
|
193
|
-
systests = []
|
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"
|
199
|
-
if tds.size == 3 then
|
200
|
-
test = Case.new
|
201
|
-
test.input = filter_inout tds[0].to_plain_text
|
202
|
-
test.output = filter_inout tds[1].to_plain_text
|
203
|
-
systests << test
|
204
|
-
end
|
205
|
-
end
|
206
|
-
return systests
|
207
|
-
end
|
208
|
-
def download_systests detail_url
|
209
|
-
detail = @downloader.download detail_url
|
210
|
-
Hpricot(detail).search "a[@href^=/stat?c=problem_solution]" do |url|
|
211
|
-
solution = @downloader.download url.attributes["href"]
|
212
|
-
systests = parse_systests solution
|
213
|
-
return systests unless systests.empty?
|
214
|
-
end
|
215
|
-
return []
|
216
|
-
end
|
217
|
-
def parse_details doc
|
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
|
221
|
-
source = filter elem.html
|
222
|
-
begin
|
223
|
-
systests = download_systests url
|
224
|
-
unless systests.empty? then
|
225
|
-
return url, source, systests
|
226
|
-
end
|
227
|
-
rescue DownloadError
|
228
|
-
end
|
229
|
-
end
|
230
|
-
return url, source, systests
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|