codeforces 0.0.1 → 0.0.2

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 (40) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +8 -2
  3. data/README.md +36 -5
  4. data/Rakefile +17 -0
  5. data/codeforces.gemspec +14 -2
  6. data/lib/codeforces.rb +18 -1
  7. data/lib/codeforces/api.rb +25 -0
  8. data/lib/codeforces/api/contest.rb +44 -0
  9. data/lib/codeforces/api/problem_set.rb +38 -0
  10. data/lib/codeforces/api/user.rb +44 -0
  11. data/lib/codeforces/client.rb +81 -0
  12. data/lib/codeforces/helper.rb +15 -0
  13. data/lib/codeforces/models.rb +5 -0
  14. data/lib/codeforces/models/base.rb +14 -0
  15. data/lib/codeforces/models/submission.rb +27 -0
  16. data/lib/codeforces/version.rb +2 -1
  17. data/spec/api_fixtures/Codeforces_Client/_contest_hacks/hacks_374/.yml +10311 -0
  18. data/spec/api_fixtures/Codeforces_Client/_contest_list/list/.yml +2080 -0
  19. data/spec/api_fixtures/Codeforces_Client/_contest_standings/standings_374/.yml +743 -0
  20. data/spec/api_fixtures/Codeforces_Client/_contest_standings/standings_374_offset_1/.yml +707 -0
  21. data/spec/api_fixtures/Codeforces_Client/_contest_status/status_374/.yml +640 -0
  22. data/spec/api_fixtures/Codeforces_Client/_contest_status/status_374_offset_1/.yml +625 -0
  23. data/spec/api_fixtures/Codeforces_Client/_problemset_problem_statices/problem_statistics/.yml +8435 -0
  24. data/spec/api_fixtures/Codeforces_Client/_problemset_problem_statices/problem_statistics_query_tags_dp_/.yml +1608 -0
  25. data/spec/api_fixtures/Codeforces_Client/_problemset_problem_statices/problem_statistics_query_tags_dp_implementation_/.yml +252 -0
  26. data/spec/api_fixtures/Codeforces_Client/_problemset_problems/problems/.yml +8435 -0
  27. data/spec/api_fixtures/Codeforces_Client/_problemset_recent_status/recent_status/.yml +614 -0
  28. data/spec/api_fixtures/Codeforces_Client/_user_info/info_test_tarou/.yml +49 -0
  29. data/spec/api_fixtures/Codeforces_Client/_user_rating/rating_Fefer_Ivan/.yml +260 -0
  30. data/spec/api_fixtures/Codeforces_Client/_user_status/status_Fefer_Ivan/.yml +635 -0
  31. data/spec/api_fixtures/Codeforces_Helper/_each_contest/.yml +2080 -0
  32. data/spec/api_fixtures/Codeforces_Helper/_each_contest/it_is_called_450_or_more_times.yml +2080 -0
  33. data/spec/api_fixtures/Codeforces_Helper/_each_status/first_user/.yml +664 -0
  34. data/spec/api_fixtures/Codeforces_Helper/_each_status/it_is_called_50_times.yml +614 -0
  35. data/spec/api_fixtures/Codeforces_Helper/_user/user_DmitriyH_country/.yml +52 -0
  36. data/spec/api_fixtures/Codeforces_Helper/_user/user_DmitriyH_rating/.yml +52 -0
  37. data/spec/client_spec.rb +178 -0
  38. data/spec/helper_spec.rb +47 -0
  39. data/spec/spec_helper.rb +36 -0
  40. metadata +131 -6
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NmNjYTgwZDYzOGY5MjQ4ZjJiNzRhZDdkMTQyYmRlMjBhYjQ3ZDA4MA==
4
+ YzViOGFiNTI0MjVlMTFmMTNkYTk2YmViZGYxMDhmMmM5OWVlYTQwMw==
5
5
  data.tar.gz: !binary |-
6
- MzhiNzZhYWM3OGZhYThkMDU3YWE4MDU2ZGIxNzI0MjBhYmZiZjdlMw==
6
+ NDRlNGM3ZTVmN2FiMDRlNGMxMmY0YmI1OTJiNDhmMjEwZWMzYjNlNA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- N2UyZmM1NDJjYTgxZDZkNWFmZjU4YjY5NDgxMzhlZjEzZjg0OGI0NDVhNzEx
10
- ODQ0ZDljYjhkNDI2MzJlYmQwYTc4ZDRlZmNlYjc2NDMxMzk5ZDM4NWU2MTU2
11
- N2JmMGU0ZDQ0MjU2NzEzZThmOTE1NmEzNDMzYmIyMDY2MWVkZTg=
9
+ YzM3ZTZkZTAyOTczZTdiNWIyYTM1YzUwMzJkZjViZjdjOWNmYzBiMDI5Njdl
10
+ MWVlNDg2MDQxM2E1YzNjZWVmOTJiZDlmZDI4ODcxYWJiYzk0M2ViMDQ2YzUy
11
+ NGYyOWUzZTIyZDU0Y2FkZDhmYzkzNzZlMWRjMWZjYjQ2MDk0ODc=
12
12
  data.tar.gz: !binary |-
13
- MzZlOTZiYTk3YWUyZjNhNTY3Y2EzOGM3YzcwMjdkYzQ1OThlYmFiZWM0Nzdm
14
- OTljNTNhNWQ2YmJlMTUxNzljNDNlMTM1ODI3ZWZjM2JhMWZjY2MxOTRhNWNm
15
- NGI5ZWE0OGI1Yzg5NDEyZThhZDZjNDg0OGNjNTAzMmViYmQ0MmY=
13
+ MTM0ZGQ0MzQ5YmRkMzhkYTA5ZjE0NDQzODYxNjJjMGZlZWViZDA3YTFkNDAw
14
+ NTU4NmZjYWU0Yzk0MjI5NzdhNTIwYzU0MTBmYmQwMTIxOGI5MjNkYzg3YjE4
15
+ MGRkZWRkZmE2YzI0ODEyNTYzYTE2YWQ2M2IwZDQyNmYyNDIwYWY=
@@ -8,9 +8,15 @@ rvm:
8
8
 
9
9
  sudo: false
10
10
 
11
- install: echo install
11
+ install:
12
+ - bundle install -j4 --path vendor/bundle
12
13
 
13
- script: echo script
14
+ script:
15
+ - bundle exec rake spec
16
+
17
+ cache:
18
+ directories:
19
+ - vendor/bundle
14
20
 
15
21
  deploy:
16
22
  provider: rubygems
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
- # Codeforces
1
+ # Codeforces API Client Library
2
2
 
3
- TODO: Write a gem description
3
+ The wrapper library for Codeforces API written in Ruby.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  Add this line to your application's Gemfile:
8
8
 
9
9
  ```ruby
10
- gem 'codeforces'
10
+ gem "codeforces"
11
11
  ```
12
12
 
13
13
  And then execute:
@@ -20,12 +20,43 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- TODO: Write usage instructions here
23
+ ```ruby
24
+ require "codeforces"
25
+
26
+ Codeforces.each_contest do |contest|
27
+ puts contest.name
28
+ end
29
+ ```
30
+
31
+ ```ruby
32
+ require "codeforces"
33
+
34
+ tourist = Codeforces.user("tourist")
35
+
36
+ puts tourist.rating
37
+ # -> 3254
38
+
39
+ puts tourist.rank
40
+ # -> international grandmaster
41
+ ```
42
+
43
+ ### API Access
44
+
45
+ ```ruby
46
+ require "codeforces"
47
+
48
+ Codeforces.api.contest.list.each do |contest|
49
+ puts contest.name
50
+ end
51
+ ```
52
+
53
+ See also: http://codeforces.com/api/help/methods
24
54
 
25
55
  ## Contributing
26
56
 
27
- 1. Fork it ( https://github.com/[my-github-username]/codeforces/fork )
57
+ 1. Fork it ( https://github.com/sh19910711/codeforces-api-client/fork )
28
58
  2. Create your feature branch (`git checkout -b my-new-feature`)
29
59
  3. Commit your changes (`git commit -am 'Add some feature'`)
30
60
  4. Push to the branch (`git push origin my-new-feature`)
31
61
  5. Create a new Pull Request
62
+
data/Rakefile CHANGED
@@ -1,2 +1,19 @@
1
1
  require "bundler/gem_tasks"
2
2
 
3
+ require "rspec/core/rake_task"
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = [
6
+ "--format doc",
7
+ "--color",
8
+ ]
9
+ end
10
+
11
+ require "rspec/core/rake_task"
12
+ RSpec::Core::RakeTask.new(:spec_current) do |t|
13
+ t.rspec_opts = [
14
+ "--format doc",
15
+ "--color",
16
+ "--tag current",
17
+ ]
18
+ end
19
+
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Codeforces::VERSION
9
9
  spec.authors = ["Hiroyuki Sano"]
10
10
  spec.email = ["sh19910711@gmail.com"]
11
- spec.summary = %q{}
12
- spec.homepage = ""
11
+ spec.summary = %q{The wrapper library for Codeforces API.}
12
+ spec.homepage = "https://github.com/sh19910711/codeforces-api-client"
13
13
  spec.license = "MIT"
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0")
@@ -17,6 +17,18 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
+ spec.required_ruby_version = ">= 1.9.3"
21
+
22
+ spec.add_runtime_dependency "sawyer", "~> 0.6"
23
+ spec.add_runtime_dependency "addressable", "~> 2.3.6"
24
+
20
25
  spec.add_development_dependency "bundler", "~> 1.7"
21
26
  spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency "vcr"
29
+ spec.add_development_dependency "webmock"
30
+
31
+ if ENV["CODEFORCES_DEBUG"] === "yes"
32
+ spec.add_development_dependency "byebug"
33
+ end
22
34
  end
@@ -1,5 +1,22 @@
1
+ require "codeforces/client"
1
2
  require "codeforces/version"
2
3
 
3
4
  module Codeforces
4
- # Your code goes here...
5
+
6
+ class << self
7
+
8
+ def client
9
+ @client ||= Client.new
10
+ end
11
+
12
+ private
13
+
14
+ def method_missing(method, *args, &block)
15
+ super unless client.respond_to?(method)
16
+ client.send method, *args, &block
17
+ end
18
+
19
+ end
20
+
5
21
  end
22
+
@@ -0,0 +1,25 @@
1
+ require "codeforces/api/contest"
2
+ require "codeforces/api/problem_set"
3
+ require "codeforces/api/user"
4
+
5
+ class Codeforces::Api
6
+
7
+ attr_reader :client
8
+
9
+ def initialize(new_client)
10
+ @client = new_client
11
+ end
12
+
13
+ def contest
14
+ @contest ||= ::Codeforces::Api::Contest.new(client)
15
+ end
16
+
17
+ def problemset
18
+ @problem_set ||= ::Codeforces::Api::ProblemSet.new(client)
19
+ end
20
+
21
+ def user
22
+ @user ||= ::Codeforces::Api::User.new(client)
23
+ end
24
+
25
+ end
@@ -0,0 +1,44 @@
1
+ class Codeforces::Api
2
+
3
+ class Contest
4
+
5
+ attr_reader :client
6
+
7
+ def initialize(base_client)
8
+ @client = base_client
9
+ end
10
+
11
+ def hacks(contest_id, options = {})
12
+ options[:query] ||= {}
13
+ options[:query].merge! :contestId => contest_id
14
+ get("contest.hacks", options)
15
+ end
16
+
17
+ def list(options = {})
18
+ get("contest.list", options)
19
+ end
20
+
21
+ def standings(contest_id, options = {})
22
+ options[:query] ||= {}
23
+ options[:query].merge! :contestId => contest_id
24
+ options[:query].merge! paginate(options[:offset])
25
+ get("contest.standings", options).rows
26
+ end
27
+
28
+ def status(contest_id, options = {})
29
+ options[:query] ||= {}
30
+ options[:query].merge! :contestId => contest_id
31
+ options[:query].merge! paginate(options[:offset])
32
+ get("contest.status", options)
33
+ end
34
+
35
+ private
36
+
37
+ def method_missing(method, *args, &block)
38
+ client.send method, *args, &block
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
@@ -0,0 +1,38 @@
1
+ class Codeforces::Api
2
+
3
+ class ProblemSet
4
+
5
+ attr_reader :client
6
+
7
+ def initialize(base_client)
8
+ @client = base_client
9
+ end
10
+
11
+ def problems(options = {})
12
+ options[:query] ||= {}
13
+ options[:query][:tags] = multi_values(options[:query][:tags]) unless options[:query][:tags].nil?
14
+ get("problemset.problems", options).problems
15
+ end
16
+
17
+ def problem_statistics(options = {})
18
+ options[:query] ||= {}
19
+ options[:query][:tags] = multi_values(options[:query][:tags]) unless options[:query][:tags].nil?
20
+ get("problemset.problems", options).problemStatistics
21
+ end
22
+
23
+ def recent_status(options = {})
24
+ options[:query] ||= {}
25
+ options[:query].merge! paginate(0)
26
+ get("problemset.recentStatus", options)
27
+ end
28
+
29
+ private
30
+
31
+ def method_missing(method, *args, &block)
32
+ client.send method, *args, &block
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
@@ -0,0 +1,44 @@
1
+ class Codeforces::Api
2
+
3
+ class User
4
+
5
+ attr_reader :client
6
+
7
+ def initialize(base_client)
8
+ @client = base_client
9
+ end
10
+
11
+ def info(handles, options = {})
12
+ handles = [handles] unless handles.is_a?(Array)
13
+ options[:query] ||= {}
14
+ options[:query][:handles] = multi_values(handles)
15
+ get("user.info", options)
16
+ end
17
+
18
+ def rated_list(options = {})
19
+ get("user.ratedList", options)
20
+ end
21
+
22
+ def rating(handle, options = {})
23
+ options[:query] ||= {}
24
+ options[:query].merge! :handle => handle
25
+ get("user.rating", options)
26
+ end
27
+
28
+ def status(handle, options = {})
29
+ options[:query] ||= {}
30
+ options[:query].merge! :handle => handle
31
+ options[:query].merge! paginate(options[:offset])
32
+ get("user.status", options)
33
+ end
34
+
35
+ private
36
+
37
+ def method_missing(method, *args, &block)
38
+ client.send method, *args, &block
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
@@ -0,0 +1,81 @@
1
+ require "sawyer"
2
+ require "logger"
3
+ require "addressable/uri"
4
+ require "codeforces/api"
5
+ require "codeforces/client"
6
+ require "codeforces/helper"
7
+ require "codeforces/models"
8
+
9
+ class Codeforces::Client
10
+
11
+ include Codeforces::Helper
12
+
13
+ DEFAULT_ENDPOINT = "http://codeforces.com/api/"
14
+ DEFAULT_PAGE_COUNT = 50
15
+
16
+ attr_reader :endpoint
17
+
18
+ def initialize(endpoint = DEFAULT_ENDPOINT)
19
+ @endpoint = endpoint
20
+ end
21
+
22
+ def logger
23
+ @logger ||= new_logger
24
+ end
25
+
26
+ def agent
27
+ @agent ||= ::Sawyer::Agent.new(DEFAULT_ENDPOINT)
28
+ end
29
+
30
+ def last_response
31
+ @last_response
32
+ end
33
+
34
+ def get(path, options = {})
35
+ request_uri = ::Addressable::URI.new
36
+ options[:query] ||= {}
37
+ request_uri.query_values = options[:query]
38
+ request(:get, "#{path}#{request_uri.query.empty? ? "" : "?#{request_uri.query}"}", options[:data], options).result
39
+ end
40
+
41
+ def request(method, path, data, options = {})
42
+ logger.debug "#{method.upcase} #{URI.join endpoint, path}"
43
+ @last_response = agent.call(method, path, data)
44
+
45
+ unless last_response.data.status === "OK"
46
+ raise "Error: #{last_response.data.status}"
47
+ end
48
+
49
+ last_response.data
50
+ end
51
+
52
+ def paginate(offset)
53
+ offset = 0 if offset.nil?
54
+ result = {
55
+ :from => DEFAULT_PAGE_COUNT * offset + 1,
56
+ :count => DEFAULT_PAGE_COUNT,
57
+ }
58
+ end
59
+
60
+ def multi_values(values)
61
+ values.join ";"
62
+ end
63
+
64
+ def api
65
+ @api ||= ::Codeforces::Api.new(self)
66
+ end
67
+
68
+ def submission(status)
69
+ ::Codeforces::Models::Submission.new self, status
70
+ end
71
+
72
+ private
73
+
74
+ def new_logger
75
+ logger = ::Logger.new(STDOUT)
76
+ logger.level = ::Logger::INFO
77
+ logger
78
+ end
79
+
80
+ end
81
+
@@ -0,0 +1,15 @@
1
+ module Codeforces::Helper
2
+
3
+ def each_contest
4
+ api.contest.list.each {|contest| yield(contest) if block_given? }
5
+ end
6
+
7
+ def user(handle)
8
+ api.user.info(handle).first
9
+ end
10
+
11
+ def each_status
12
+ api.problemset.recent_status.map {|status| submission status }.each {|status| yield(status) if block_given? }
13
+ end
14
+
15
+ end
@@ -0,0 +1,5 @@
1
+ require "codeforces/models/base"
2
+ require "codeforces/models/submission"
3
+
4
+ module Codeforces::Models; end
5
+
@@ -0,0 +1,14 @@
1
+ module Codeforces::Models
2
+
3
+ class Base
4
+
5
+ attr_reader :client
6
+
7
+ def initialize(client)
8
+ @client = client
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+