codeforces 0.0.1 → 0.0.2

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