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.
- checksums.yaml +8 -8
- data/.travis.yml +8 -2
- data/README.md +36 -5
- data/Rakefile +17 -0
- data/codeforces.gemspec +14 -2
- data/lib/codeforces.rb +18 -1
- data/lib/codeforces/api.rb +25 -0
- data/lib/codeforces/api/contest.rb +44 -0
- data/lib/codeforces/api/problem_set.rb +38 -0
- data/lib/codeforces/api/user.rb +44 -0
- data/lib/codeforces/client.rb +81 -0
- data/lib/codeforces/helper.rb +15 -0
- data/lib/codeforces/models.rb +5 -0
- data/lib/codeforces/models/base.rb +14 -0
- data/lib/codeforces/models/submission.rb +27 -0
- data/lib/codeforces/version.rb +2 -1
- data/spec/api_fixtures/Codeforces_Client/_contest_hacks/hacks_374/.yml +10311 -0
- data/spec/api_fixtures/Codeforces_Client/_contest_list/list/.yml +2080 -0
- data/spec/api_fixtures/Codeforces_Client/_contest_standings/standings_374/.yml +743 -0
- data/spec/api_fixtures/Codeforces_Client/_contest_standings/standings_374_offset_1/.yml +707 -0
- data/spec/api_fixtures/Codeforces_Client/_contest_status/status_374/.yml +640 -0
- data/spec/api_fixtures/Codeforces_Client/_contest_status/status_374_offset_1/.yml +625 -0
- data/spec/api_fixtures/Codeforces_Client/_problemset_problem_statices/problem_statistics/.yml +8435 -0
- data/spec/api_fixtures/Codeforces_Client/_problemset_problem_statices/problem_statistics_query_tags_dp_/.yml +1608 -0
- data/spec/api_fixtures/Codeforces_Client/_problemset_problem_statices/problem_statistics_query_tags_dp_implementation_/.yml +252 -0
- data/spec/api_fixtures/Codeforces_Client/_problemset_problems/problems/.yml +8435 -0
- data/spec/api_fixtures/Codeforces_Client/_problemset_recent_status/recent_status/.yml +614 -0
- data/spec/api_fixtures/Codeforces_Client/_user_info/info_test_tarou/.yml +49 -0
- data/spec/api_fixtures/Codeforces_Client/_user_rating/rating_Fefer_Ivan/.yml +260 -0
- data/spec/api_fixtures/Codeforces_Client/_user_status/status_Fefer_Ivan/.yml +635 -0
- data/spec/api_fixtures/Codeforces_Helper/_each_contest/.yml +2080 -0
- data/spec/api_fixtures/Codeforces_Helper/_each_contest/it_is_called_450_or_more_times.yml +2080 -0
- data/spec/api_fixtures/Codeforces_Helper/_each_status/first_user/.yml +664 -0
- data/spec/api_fixtures/Codeforces_Helper/_each_status/it_is_called_50_times.yml +614 -0
- data/spec/api_fixtures/Codeforces_Helper/_user/user_DmitriyH_country/.yml +52 -0
- data/spec/api_fixtures/Codeforces_Helper/_user/user_DmitriyH_rating/.yml +52 -0
- data/spec/client_spec.rb +178 -0
- data/spec/helper_spec.rb +47 -0
- data/spec/spec_helper.rb +36 -0
- metadata +131 -6
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzViOGFiNTI0MjVlMTFmMTNkYTk2YmViZGYxMDhmMmM5OWVlYTQwMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NDRlNGM3ZTVmN2FiMDRlNGMxMmY0YmI1OTJiNDhmMjEwZWMzYjNlNA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YzM3ZTZkZTAyOTczZTdiNWIyYTM1YzUwMzJkZjViZjdjOWNmYzBiMDI5Njdl
|
10
|
+
MWVlNDg2MDQxM2E1YzNjZWVmOTJiZDlmZDI4ODcxYWJiYzk0M2ViMDQ2YzUy
|
11
|
+
NGYyOWUzZTIyZDU0Y2FkZDhmYzkzNzZlMWRjMWZjYjQ2MDk0ODc=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTM0ZGQ0MzQ5YmRkMzhkYTA5ZjE0NDQzODYxNjJjMGZlZWViZDA3YTFkNDAw
|
14
|
+
NTU4NmZjYWU0Yzk0MjI5NzdhNTIwYzU0MTBmYmQwMTIxOGI5MjNkYzg3YjE4
|
15
|
+
MGRkZWRkZmE2YzI0ODEyNTYzYTE2YWQ2M2IwZDQyNmYyNDIwYWY=
|
data/.travis.yml
CHANGED
@@ -8,9 +8,15 @@ rvm:
|
|
8
8
|
|
9
9
|
sudo: false
|
10
10
|
|
11
|
-
install:
|
11
|
+
install:
|
12
|
+
- bundle install -j4 --path vendor/bundle
|
12
13
|
|
13
|
-
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
|
-
|
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
|
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
|
-
|
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/
|
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
|
+
|
data/codeforces.gemspec
CHANGED
@@ -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
|
data/lib/codeforces.rb
CHANGED
@@ -1,5 +1,22 @@
|
|
1
|
+
require "codeforces/client"
|
1
2
|
require "codeforces/version"
|
2
3
|
|
3
4
|
module Codeforces
|
4
|
-
|
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
|