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
@@ -0,0 +1,63 @@
1
+ require "gettc/types"
2
+
3
+ module Gettc
4
+ class SignatureError < StandardError
5
+ end
6
+
7
+ class CannotParseSignature < SignatureError
8
+ attr_accessor :source
9
+
10
+ def initialize(source, message = "Cannot parse signature")
11
+ @source = source
12
+ super "#{message}: (#{source}"
13
+ end
14
+ end
15
+
16
+ class InvalidVariableName < SignatureError
17
+ attr_accessor :name
18
+
19
+ def initialize(name, message = "Invalid variable name")
20
+ @name = name
21
+ super "#{message} (#{name})"
22
+ end
23
+ end
24
+
25
+ class Signature
26
+ attr_accessor :type, :name
27
+
28
+ def initialize(type, name)
29
+ @type = type
30
+ @name = name
31
+ end
32
+ end
33
+
34
+ def parse_signature(str)
35
+ str.strip!
36
+
37
+ parts = str.split
38
+ raise CannotParseSignature.new(str) unless parts.size == 2
39
+
40
+ type = parse_type(parts[0])
41
+ name = parts[1]
42
+
43
+ raise InvalidVariableName.new(name) unless name =~ /^[a-zA-Z_]\w*$/
44
+ Signature.new(type, name)
45
+ end
46
+
47
+ def parse_method_signature(str)
48
+ str.strip!
49
+
50
+ sigs = []
51
+
52
+ parts = str.split("(")
53
+ raise CannotParseSignature.new(str) unless parts.size == 2
54
+ sigs << parse_signature(parts[0])
55
+
56
+ str = parts[1]
57
+ raise CannotParseSignature.new(str) unless str[-1] == ")"
58
+
59
+ str.chop.split(",").each { |sig| sigs << parse_signature(sig) }
60
+
61
+ sigs
62
+ end
63
+ end
@@ -0,0 +1,93 @@
1
+ module Gettc
2
+ TypeError = Class.new(StandardError)
3
+
4
+ class UnsupportedType < TypeError
5
+ attr_accessor :type
6
+
7
+ def initialize(type = nil, message = "Not a valid TopCoder type")
8
+ @type = type
9
+ super "#{message}: (#{type})"
10
+ end
11
+ end
12
+
13
+ class Type
14
+ def initialize(is_object)
15
+ @is_object = is_object
16
+ end
17
+
18
+ def obj?
19
+ @is_object
20
+ end
21
+
22
+ def to_s
23
+ return "#{subtype}[]" if self.is_a?(TArray)
24
+
25
+ case self
26
+ when TInt
27
+ "int"
28
+ when TLong
29
+ "long"
30
+ when TFloat
31
+ "float"
32
+ when TDouble
33
+ "double"
34
+ when TChar
35
+ "char"
36
+ when TString
37
+ "String"
38
+ when TBoolean
39
+ "boolean"
40
+ else
41
+ "unknown"
42
+ end
43
+ end
44
+ end
45
+
46
+ TBoolean = Type.new(false)
47
+ TInt = Type.new(false)
48
+ TLong = Type.new(false)
49
+ TFloat = Type.new(false)
50
+ TDouble = Type.new(false)
51
+ TChar = Type.new(false)
52
+ TString = Type.new(true)
53
+
54
+ class TArray < Type
55
+ attr_accessor :subtype
56
+
57
+ def initialize(subtype)
58
+ raise UnsupportedType.new(subtype) unless subtype.is_a?(Type)
59
+ @subtype = subtype
60
+ end
61
+
62
+ def ==(ary)
63
+ ary.is_a?(TArray) && @subtype == ary.subtype
64
+ end
65
+
66
+ def obj?
67
+ true
68
+ end
69
+ end
70
+
71
+ def parse_type(str)
72
+ return TArray.new(parse_type(str[0 .. -3])) if str[-2 .. -1] == "[]"
73
+
74
+ case str
75
+ when "boolean"
76
+ TBoolean
77
+ when "int"
78
+ TInt
79
+ when "long"
80
+ TLong
81
+ when "float"
82
+ TFloat
83
+ when "double"
84
+ TDouble
85
+ when "char"
86
+ TChar
87
+ when "String"
88
+ TString
89
+ else
90
+ raise UnsupportedType.new(str)
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,3 @@
1
+ module Gettc
2
+ VERSION = "2.0"
3
+ end
@@ -0,0 +1,61 @@
1
+ require "test_helper"
2
+ require "gettc/download"
3
+
4
+ class DownloadTest < Test::Unit::TestCase
5
+ def setup
6
+ @downloader = Downloader.new($account)
7
+ end
8
+
9
+ def teardown
10
+ Dir.glob("gettc_http_response*.html").each { |filename| File.delete(filename) }
11
+ end
12
+
13
+ def test_wrong_account
14
+ assert_raises AuthTokenError do
15
+ Downloader.new(Account.new("username", "password"))
16
+ end
17
+ end
18
+
19
+ def test_download_statement
20
+ $problems.each do |hash|
21
+ html = @downloader.download_statement(hash["id"])
22
+ assert_match "<h3>Problem Statement</h3>", html, hash["message"]
23
+ write_problem_html(:statement, hash["name"], html)
24
+ end
25
+ end
26
+
27
+ def test_download_statement_wrong_problem_id
28
+ assert_raises IDNotAvailable do
29
+ @downloader.download_statement(1000000)
30
+ end
31
+ end
32
+
33
+ def test_download_detail
34
+ $problems.each do |hash|
35
+ html = @downloader.download_detail(hash["id"], hash["round_id"])
36
+ assert_match "Problem Detail", html, hash["message"]
37
+ write_problem_html(:detail, hash["name"], html)
38
+ end
39
+ end
40
+
41
+ def test_download_detail_wrong_round_id
42
+ assert_raises HttpError do
43
+ @downloader.download_detail(10297, 1000000)
44
+ end
45
+ end
46
+
47
+ def test_download_solution
48
+ $problems.each do |hash|
49
+ next unless hash["solution_id"]
50
+ html = @downloader.download_solution(hash["id"], hash["round_id"], hash["solution_id"])
51
+ assert_match "TopCoder Statistics - Problem Solution", html, hash["message"]
52
+ write_problem_html(:solution, hash["name"], html)
53
+ end
54
+ end
55
+
56
+ def test_download_solution_wrong_solution_id
57
+ assert_raises BadResponseError do
58
+ @downloader.download_solution(10297, 13751, 1000000)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,70 @@
1
+ require "test_helper"
2
+ require "gettc/generate"
3
+ require "fileutils"
4
+
5
+ class GenerateTest < Test::Unit::TestCase
6
+ def setup
7
+ script_dir = File.dirname(__FILE__)
8
+
9
+ @source_dir = File.join(script_dir, "../../dist")
10
+ raise "#{@source_dir} not found. Consider running `rake dist` first." unless File.exists?(@source_dir)
11
+
12
+ @target_dir = File.join(script_dir, "../data/generated")
13
+ FileUtils.mkdir(@target_dir) unless File.directory?(@target_dir)
14
+
15
+ @generator = Generator.new(@source_dir, @target_dir)
16
+ end
17
+
18
+ def test_initialize
19
+ dump_name = "this_directory_must_not_exist"
20
+ assert_raise SourceDirNotExist do Generator.new(dump_name, @target_dir) end
21
+ assert_raise TargetDirNotExist do Generator.new(@source_dir, dump_name) end
22
+ end
23
+
24
+ def test_problem_dir_exists
25
+ problem = Problem.new
26
+ problem.name = "JustATest"
27
+
28
+ problem_dir = File.join(@target_dir, problem.name)
29
+ FileUtils.mkdir(problem_dir) unless File.exists?(problem_dir)
30
+
31
+ assert_raise ProblemDirExists do @generator.generate(problem) end
32
+ FileUtils.rmdir problem_dir
33
+ end
34
+
35
+ def test_generate_problems
36
+ $problems.each do |hash|
37
+ @problem = hash
38
+
39
+ begin
40
+ @generator.generate(read_problem_yaml(@problem["name"]))
41
+ rescue ProblemDirExists
42
+ puts "Skipped generating #{@problem['name']} because it's already generated."
43
+ end
44
+
45
+ assert_equal hash["images_count"], count_files("prob/images")
46
+ assert_equal 2 * hash["examples_count"], count_files("data/demo")
47
+ assert_equal 2 * hash["systests_count"], count_files("data/sys")
48
+
49
+ assert_file_exists "util/check/check.cpp"
50
+ assert_file_exists "util/check/Makefile"
51
+
52
+ assert_file_exists "bin/runner.rb"
53
+ assert_file_exists "bin/runner.sh"
54
+
55
+ assert_file_exists "prob/#{@problem['name']}.html"
56
+ assert_file_exists "prob/#{@problem['name']}.md"
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def count_files(subdir)
63
+ full_path = File.join(@target_dir, @problem["name"], subdir)
64
+ Dir.new(full_path).entries.reject { |name| [".", ".."].include?(name) }.size
65
+ end
66
+
67
+ def assert_file_exists(filename)
68
+ assert File.exists?(File.join(@target_dir, @problem["name"], filename))
69
+ end
70
+ end
@@ -0,0 +1,78 @@
1
+ require "test_helper"
2
+ require "gettc/parse"
3
+
4
+ class FakeDownloader
5
+ def initialize(problem_name = nil)
6
+ @problem_name = problem_name
7
+ end
8
+
9
+ def download(url)
10
+ "ImageContent"
11
+ end
12
+
13
+ def download_statement(problem_id)
14
+ read_problem_html(:statement, @problem_name)
15
+ end
16
+
17
+ def download_detail(problem_id, round_id)
18
+ read_problem_html(:detail, @problem_name)
19
+ end
20
+
21
+ def download_solution(problem_id, round_id, solution_id)
22
+ read_problem_html(:solution, @problem_name)
23
+ end
24
+
25
+ end
26
+
27
+ class ParseTest < Test::Unit::TestCase
28
+ def test_get_param_value
29
+ assert_equal 13751, Parser.send(:get_param_value,
30
+ "/tc?module=ProblemDetail&rd=13751&pm=10297", "rd").to_i
31
+ assert Parser.send(:get_param_value,
32
+ "/tc?module=ProblemDetail&rd=13751&pm=10297", "cr").nil?
33
+ assert_equal 22717415, Parser.send(:get_param_value,
34
+ "/stat?c=problem_solution&amp;cr=22717415&amp;rd=13751&amp;pm=10297", "cr").to_i
35
+ end
36
+
37
+ def test_indexes
38
+ assert_equal [0, 3], Parser.send(:indexes, "abcde", "bc")
39
+ assert_equal nil, Parser.send(:indexes, "abcde", "f")
40
+ end
41
+
42
+ def test_filter
43
+ parser = Parser.new(FakeDownloader.new(nil))
44
+
45
+ assert_equal "Lorem Ipsum", parser.send(:filter, "<xml> Lorem Ipsum </xml> ")
46
+ assert_equal "2^(3)", parser.send(:filter, "2<sup>3</sup>")
47
+ assert_equal "*hi*", parser.send(:filter, " <b>hi</b>")
48
+
49
+ html = <<-END
50
+ <img src=
51
+ "http://www.topcoder.com/contest/problem/CirclesCountry/case1.gif">
52
+ END
53
+ assert_equal "![image](images/case1.gif)", parser.send(:filter, html)
54
+ end
55
+
56
+ def test_parse_problems
57
+ $problems.each do |hash|
58
+ downloader = FakeDownloader.new(hash["name"])
59
+ problem = Parser.new(downloader).parse(hash["id"])
60
+
61
+ assert_equal hash["name"], problem.name, hash["message"]
62
+ assert_equal hash["source"], problem.source, hash["message"]
63
+ assert_equal hash["definitions_count"], problem.definitions.size, hash["message"]
64
+ assert_equal hash["notes_count"], problem.notes.size, hash["message"]
65
+ assert_equal hash["contraints_count"], problem.constraints.size, hash["message"]
66
+ assert_equal hash["examples_count"], problem.examples.size, hash["message"]
67
+ assert_equal hash["systests_count"], problem.systests.size, hash["message"]
68
+ assert_equal hash["images_count"], problem.images.size, hash["message"]
69
+
70
+ (problem.examples + problem.systests).each do |test_case|
71
+ assert !test_case.input.empty?
72
+ assert !test_case.output.empty?
73
+ end
74
+
75
+ write_problem_yaml(problem)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,71 @@
1
+ require "test/unit"
2
+ require "gettc/signature"
3
+ include Gettc
4
+
5
+ class SignatureTest < Test::Unit::TestCase
6
+ def test_parse_signature
7
+ assert_raise CannotParseSignature do
8
+ parse_signature("invalid_signature")
9
+ end
10
+
11
+ assert_raise UnsupportedType do
12
+ parse_signature("strange_type name")
13
+ end
14
+
15
+ assert_raise InvalidVariableName do
16
+ parse_signature("int not&ok&name")
17
+ end
18
+
19
+ assert_raise InvalidVariableName do
20
+ parse_signature("int 0zero")
21
+ end
22
+
23
+ sig = parse_signature("String[] a_valid_nam3")
24
+ assert_equal TArray.new(TString), sig.type
25
+ assert_equal "a_valid_nam3", sig.name
26
+ end
27
+
28
+ def test_parse_method_signature
29
+ assert_raise CannotParseSignature do
30
+ parse_method_signature("there are no brackets")
31
+ end
32
+
33
+ assert_raise CannotParseSignature do
34
+ parse_method_signature("int main(int main())")
35
+ end
36
+
37
+ assert_raise CannotParseSignature do
38
+ parse_method_signature("int main(oops forget to close bracket")
39
+ end
40
+
41
+ method = " int leastBorders(String[] X , int[] Y, double[] R,"
42
+ method += " char my_x1, long y1 , float x2, int[][] y2) "
43
+ sigs = parse_method_signature(method)
44
+
45
+ assert_equal 8, sigs.size
46
+
47
+ assert_equal TInt, sigs[0].type
48
+ assert_equal "leastBorders", sigs[0].name
49
+
50
+ assert_equal TArray.new(TString), sigs[1].type
51
+ assert_equal "X", sigs[1].name
52
+
53
+ assert_equal TArray.new(TInt), sigs[2].type
54
+ assert_equal "Y", sigs[2].name
55
+
56
+ assert_equal TArray.new(TDouble), sigs[3].type
57
+ assert_equal "R", sigs[3].name
58
+
59
+ assert_equal TChar, sigs[4].type
60
+ assert_equal "my_x1", sigs[4].name
61
+
62
+ assert_equal TLong, sigs[5].type
63
+ assert_equal "y1", sigs[5].name
64
+
65
+ assert_equal TFloat, sigs[6].type
66
+ assert_equal "x2", sigs[6].name
67
+
68
+ assert_equal TArray.new(TArray.new(TInt)), sigs[7].type
69
+ assert_equal "y2", sigs[7].name
70
+ end
71
+ end
@@ -0,0 +1,31 @@
1
+ require "test/unit"
2
+ require "gettc/types"
3
+ include Gettc
4
+
5
+ class TypesTest < Test::Unit::TestCase
6
+ def test_parse_type
7
+ assert_raise UnsupportedType do TArray.new(123) end
8
+ assert_raise UnsupportedType do parse_type("") end
9
+ assert_raise UnsupportedType do parse_type(" ") end
10
+ assert_raise UnsupportedType do parse_type("[]") end
11
+ assert_raise UnsupportedType do parse_type("vector") end
12
+ assert_raise UnsupportedType do parse_type("vector[]") end
13
+
14
+ assert_equal TBoolean, parse_type("boolean")
15
+ assert_equal TInt, parse_type("int")
16
+ assert_equal TLong, parse_type("long")
17
+ assert_equal TFloat, parse_type("float")
18
+ assert_equal TDouble, parse_type("double")
19
+ assert_equal TChar, parse_type("char")
20
+ assert_equal TString, parse_type("String")
21
+
22
+ assert_equal TArray.new(TBoolean), parse_type("boolean[]")
23
+ assert_equal TArray.new(TInt), parse_type("int[]")
24
+ assert_equal TArray.new(TArray.new(TString)), parse_type("String[][]")
25
+ end
26
+
27
+ def test_type_to_s
28
+ assert_equal "String", TString.to_s
29
+ assert_equal "boolean[][]", TArray.new(TArray.new(TBoolean)).to_s
30
+ end
31
+ end