gettc 1.10 → 2.0

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