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