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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/bin/gettc +60 -69
  3. data/dist/config.yml +1 -1
  4. data/dist/include/cpp/engine.rb +78 -86
  5. data/dist/include/cpp/topcoder +236 -236
  6. data/dist/include/go/engine.rb +53 -61
  7. data/dist/include/haskell/engine.rb +112 -122
  8. data/dist/include/java/engine.rb +187 -184
  9. data/dist/include/javascript/engine.rb +26 -30
  10. data/dist/include/javascript/topcoder.js +3 -3
  11. data/dist/include/javascript/topcoder/errors.js +5 -5
  12. data/dist/include/javascript/topcoder/reader.js +188 -165
  13. data/dist/include/javascript/topcoder/writer.js +37 -33
  14. data/dist/include/python/engine.rb +43 -52
  15. data/dist/include/python/topcoder/__init__.pyc +0 -0
  16. data/dist/include/python/topcoder/__pycache__/__init__.cpython-34.pyc +0 -0
  17. data/dist/include/python/topcoder/__pycache__/errors.cpython-34.pyc +0 -0
  18. data/dist/include/python/topcoder/__pycache__/reader.cpython-34.pyc +0 -0
  19. data/dist/include/python/topcoder/__pycache__/writer.cpython-34.pyc +0 -0
  20. data/dist/include/python/topcoder/errors.pyc +0 -0
  21. data/dist/include/python/topcoder/reader.pyc +0 -0
  22. data/dist/include/python/topcoder/writer.pyc +0 -0
  23. data/dist/include/ruby/engine.rb +47 -52
  24. data/dist/include/ruby/topcoder/reader.rb +205 -193
  25. data/dist/include/ruby/topcoder/writer.rb +39 -37
  26. data/dist/template/bin/runner.rb +146 -151
  27. data/dist/template/bin/runner.sh +96 -96
  28. data/dist/template/prob/{name}.html +1 -1
  29. data/dist/template/solve/cpp/{name}.cpp +3 -4
  30. data/dist/template/solve/cpp/{name}Solver.cpp +14 -14
  31. data/dist/template/solve/go/{name}/{name}.go +3 -3
  32. data/dist/template/solve/go/{name}Solver.go +2 -2
  33. data/dist/template/solve/haskell/{name}.hs +6 -6
  34. data/dist/template/solve/haskell/{name}Solver.hs +10 -10
  35. data/dist/template/solve/java/{name}.java +4 -4
  36. data/dist/template/solve/java/{name}Solver.java +4 -4
  37. data/dist/template/solve/javascript/{name}.js +4 -6
  38. data/dist/template/solve/javascript/{name}Solver.js +11 -9
  39. data/dist/template/solve/python/{name}.py +1 -1
  40. data/dist/template/solve/python/{name}Solver.py +2 -2
  41. data/dist/template/solve/ruby/{name}.rb +4 -4
  42. data/dist/template/solve/ruby/{name}Solver.rb +14 -17
  43. data/dist/template/util/check/check.cpp +19 -19
  44. data/{core/lib → lib}/gettc.rb +0 -0
  45. data/lib/gettc/account.rb +14 -0
  46. data/lib/gettc/download.rb +211 -0
  47. data/lib/gettc/generate.rb +156 -0
  48. data/lib/gettc/parse.rb +237 -0
  49. data/lib/gettc/print.rb +54 -0
  50. data/lib/gettc/problem.rb +39 -0
  51. data/lib/gettc/signature.rb +63 -0
  52. data/lib/gettc/types.rb +93 -0
  53. data/lib/version.rb +3 -0
  54. data/test/gettc/download_test.rb +61 -0
  55. data/test/gettc/generate_test.rb +70 -0
  56. data/test/gettc/parse_test.rb +78 -0
  57. data/test/gettc/signature_test.rb +71 -0
  58. data/test/gettc/types_test.rb +31 -0
  59. metadata +28 -23
  60. data/core/lib/gettc/download.rb +0 -130
  61. data/core/lib/gettc/generate.rb +0 -145
  62. data/core/lib/gettc/parse.rb +0 -233
  63. data/core/lib/gettc/print.rb +0 -56
  64. data/core/lib/gettc/problem.rb +0 -33
  65. data/core/lib/gettc/signature.rb +0 -55
  66. data/core/lib/gettc/types.rb +0 -83
  67. data/core/lib/version.rb +0 -3
  68. data/core/test/gettc/download_test.rb +0 -29
  69. data/core/test/gettc/generate_test.rb +0 -31
  70. data/core/test/gettc/parse_test.rb +0 -104
  71. data/core/test/gettc/signature_test.rb +0 -54
  72. 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: '1.10'
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: 2015-05-14 00:00:00.000000000 Z
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
- - core/lib
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.2.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
- - core/test/gettc/download_test.rb
155
- - core/test/gettc/generate_test.rb
156
- - core/test/gettc/parse_test.rb
157
- - core/test/gettc/signature_test.rb
158
- - core/test/gettc/types_test.rb
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
@@ -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
@@ -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
@@ -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! "&#160;", ""
98
- html.gsub! "&nbsp;", " "
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
- "![image](images/#{image.name})"
108
- rescue StandardError
109
- "![image](#{url})"
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