hive-stalker 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fe189ec6141b4b1fc8bc94733dcc72bc6a878d7f
4
+ data.tar.gz: afca1d0ad149d706275dda33cf5243045e48320c
5
+ SHA512:
6
+ metadata.gz: 69cd58d14dc01d27de88849a1b6bd8c8839784e1e91df77e2a1ffe0e66ea20228e4e4ef5505d8cb25638a3310a4c799ce69a5f8faa7b9ba797d48cb7b0810866
7
+ data.tar.gz: b30990b731fc9c78ac428067fd5b3e72d300579d3c2e6cebc1b1e12cc70ce7f434858a37402352cc20457cc3d03f2d07c95ef378b43db158dbb8b90779accacd
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ spec/.examples.txt
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Change log
2
+
3
+ This document represents a high-level overview of changes made to this project.
4
+ It will not list every miniscule change, but will allow you to view - at a
5
+ glance - what to expact from upgrading to a new version.
6
+
7
+ ## [unpublished]
8
+
9
+ ### Added
10
+
11
+ ### Changed
12
+
13
+ ### Fixed
14
+
15
+ ### Security
16
+
17
+ ### Deprecated
18
+
19
+ ### Removed
20
+
21
+ ## [0.1.0] - 2016-12-22
22
+
23
+ ### Added
24
+
25
+ - Basic client and wrappper to access player data from Hive2 API.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sunscout.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2016 Michael Senn
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,6 @@
1
+ # Sunscout
2
+
3
+ ## License
4
+
5
+ The gem is available as open source under the terms of the [Apache-2.0 License](http://opensource.org/licenses/Apache-2.0).
6
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/TODO.md ADDED
@@ -0,0 +1,4 @@
1
+ # Dev
2
+
3
+ - Integration tests (hitting the Hive API)
4
+ - Documentation of classes
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "hive-stalker"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "hive-stalker"
7
+ spec.version = '0.1.0'
8
+ spec.authors = ["Michael Senn"]
9
+ spec.email = ["michael@morrolan.ch"]
10
+
11
+ spec.summary = %q{Binding to Natural Selection 2's Hive2 ELO system}
12
+ # spec.description = %q{}
13
+ spec.homepage = "https://bitbucket.org/Lavode/hivestalker"
14
+ spec.license = "Apache-2.0"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "typhoeus"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.12"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "yard"
27
+ end
28
+
@@ -0,0 +1,9 @@
1
+ module HiveStalker
2
+ # Error raised when communication with the Hive2 API fails, e.g. when:
3
+ # - Connection times out
4
+ # - DNS resolution fails
5
+ # - API returns non-successful status code
6
+ # - API returns invalid or incomplete JSON
7
+ class APIError < StandardError
8
+ end
9
+ end
@@ -0,0 +1,94 @@
1
+ # coding: utf-8
2
+
3
+ require 'json'
4
+ require 'typhoeus'
5
+
6
+ module HiveStalker
7
+ # Low-level binding to the Hive2 HTTP API.
8
+ # @example Basic usage
9
+ # require 'hive_stalker'
10
+ # client = HiveStalker::Client.new
11
+ # begin
12
+ # data = client.get_player_data(48221310)
13
+ # puts "Playtime: #{ data[:time_total] }s"
14
+ # rescue APIError => e
15
+ # puts "Error when querying player data:"
16
+ # puts e.message
17
+ # if e.cause
18
+ # puts "Caused by:"
19
+ # puts e.cause.message
20
+ # end
21
+ # end
22
+ class Client
23
+ # Default API endpoint of Hive2 API, which will be used unless overwritten.
24
+ # `%{{action}}` is a placeholder for the to-be-performed action.
25
+ HIVE_ENDPOINT = 'http://hive2.ns2cdt.com/api/%{action}'
26
+ # Path of 'get player data' action. `%{{player_id}}` is a placeholder for
27
+ # the to-be-queried player's account ID.
28
+ GET_PLAYER_DATA = 'get/playerData/%{player_id}'
29
+
30
+ # API endpoint of Hive2 API.
31
+ # @return [String]
32
+ attr_reader :endpoint
33
+
34
+ # Initialize a new instance of the class.
35
+ #
36
+ # @param endpoint [String] API endpoint of Hive2 API. Defaults to
37
+ # {Client::HIVE_ENDPOINT}.
38
+ # Must contain `%{{action}}` as placeholder for the action.
39
+ def initialize(endpoint: HIVE_ENDPOINT)
40
+ @endpoint = endpoint
41
+ end
42
+
43
+ # Retrieve statistics of a given player.
44
+ #
45
+ # @param player_id [Fixnum] Account ID for which to query data.
46
+ # @return [Hash<Symbol, Object>] Hash with player statistics.
47
+ # @raise [APIError] In case of errors communicating with the API.
48
+ def get_player_data(player_id)
49
+ raw_data = call_api(GET_PLAYER_DATA, player_id: player_id)
50
+
51
+ begin
52
+ {
53
+ player_id: raw_data.fetch('pid'),
54
+ steam_id: raw_data.fetch('steamid'),
55
+ alias: raw_data.fetch('alias'),
56
+ score: raw_data.fetch('score'),
57
+ level: raw_data.fetch('level'),
58
+ experience: raw_data.fetch('xp'),
59
+ badges_enabled: raw_data.fetch('badges_enabled'),
60
+ badges: raw_data.fetch('badges') || [],
61
+ skill: raw_data.fetch('skill'),
62
+ time_total: raw_data.fetch('time_played'),
63
+ time_marine: raw_data.fetch('marine_playtime'),
64
+ time_alien: raw_data.fetch('alien_playtime'),
65
+ time_commander: raw_data.fetch('commander_time'),
66
+ reinforced_tier: raw_data.fetch('reinforced_tier'),
67
+ adagrad_sum: raw_data.fetch('adagrad_sum')
68
+ }
69
+ rescue KeyError => e
70
+ raise APIError, "Incomplete JSON received from API: #{ e.message }"
71
+ end
72
+ end
73
+
74
+ private
75
+ def call_api(action, **kwargs)
76
+ url = HIVE_ENDPOINT % { action: action }
77
+ url = url % kwargs
78
+
79
+ response = Typhoeus.get(url)
80
+ if response.success?
81
+ begin
82
+ JSON.parse(response.body)
83
+ rescue JSON::ParserError
84
+ raise APIError, "Invalid JSON received from API."
85
+ end
86
+ elsif response.code == 0
87
+ raise APIError, "Error while connecting to API: #{ response.return_message }"
88
+ else
89
+ raise APIError, "Non-success status code recieved from API: #{ response.code }"
90
+ end
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,89 @@
1
+ module HiveStalker
2
+ # Container for various player statistics. Essentially a glorified struct.
3
+ class PlayerData
4
+ # Player ID, probably NS2/Hive2-internal.
5
+ # @return [Fixnum]
6
+ attr_reader :player_id
7
+
8
+ # Steam account ID.
9
+ # @return [Fixnum]
10
+ attr_reader :steam_id
11
+
12
+ # User alias (in-game name)
13
+ # @return [String]
14
+ attr_reader :alias
15
+
16
+ # Score - not sure where it's used or shown.
17
+ # @return [Fixnum]
18
+ attr_reader :score
19
+
20
+ # Level
21
+ # @return [Fixnum]
22
+ attr_reader :level
23
+
24
+ # Experience points
25
+ # @return [Fixnum]
26
+ attr_reader :experience
27
+
28
+ # Whether badges are enabled.
29
+ #
30
+ # Not sure where this comes from.
31
+ # @return [TrueClass, FalseClass]
32
+ attr_reader :badges_enabled
33
+
34
+ # Array of badges. Always empty so far.
35
+ # @return [Array]
36
+ attr_reader :badges
37
+
38
+ # Skill / ELO
39
+ # @return [Fixnum]
40
+ attr_reader :skill
41
+
42
+ # Total time played in seconds.
43
+ #
44
+ # This equals {#time_marine} + {#time_alien}
45
+ # @return [Fixnum]
46
+ attr_reader :time_total
47
+
48
+ # Time played as marines in seconds.
49
+ # @return [Fixnum]
50
+ attr_reader :time_marine
51
+
52
+ # Time played as aliens in seconds.
53
+ # @return [Fixnum]
54
+ attr_reader :time_alien
55
+
56
+ # Time played as commander in seconds.
57
+ # @return [Fixnum]
58
+ attr_reader :time_commander
59
+
60
+ # Don't know what this is. Always nil.
61
+ # @return [NilClass]
62
+ attr_reader :reinforced_tier
63
+
64
+ # AdaGrad sum (https://en.wikipedia.org/wiki/Stochastic_gradient_descent#AdaGrad).
65
+ # @return [Float]
66
+ attr_reader :adagrad_sum
67
+
68
+
69
+ # Initialize a new instance of the class.
70
+ #
71
+ # @param kwargs [Hash<Symbol, Object>] data with which to initialize the
72
+ # instance's attributes.
73
+ def initialize(**kwargs)
74
+ @player_id = kwargs[:player_id]
75
+ @steam_id = kwargs[:steam_id]
76
+ @score = kwargs[:score]
77
+ @level = kwargs[:level]
78
+ @experience = kwargs[:experience]
79
+ @badges_enabled = kwargs[:badges_enabled]
80
+ @badges = kwargs[:badges]
81
+ @time_total = kwargs[:time_total]
82
+ @time_marine = kwargs[:time_marine]
83
+ @time_alien = kwargs[:time_alien]
84
+ @time_commander = kwargs[:time_commander]
85
+ @reinforced_tier = kwargs[:reinforced_tier]
86
+ @adagrad_sum = kwargs[:adagrad_sum]
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,42 @@
1
+ module HiveStalker
2
+ # High-level binding to the Hive2 HTTP API.
3
+ # @example Basic usage
4
+ # require 'hive_stalker'
5
+ # stalker = HiveStalker::Stalker.new
6
+ # begin
7
+ # data = stalker.get_player_data('STEAM_0:0:24110655')
8
+ # puts "--- #{ data.alias } ---"
9
+ # puts "Playtime: #{ data.time_total }s"
10
+ # puts "Skill: #{ data.skill }"
11
+ # rescue APIError => e
12
+ # puts "Could not retrieve player statistics."
13
+ # puts e.message
14
+ # end
15
+ class Stalker
16
+ # API client which is used.
17
+ # @return [Client]
18
+ attr_reader :client
19
+
20
+ # Initialize a new instance of the class.
21
+ #
22
+ # @param kwargs [Hash] Configuration settings which are passed through to
23
+ # the underlying client. See {Client#initialize} for details.
24
+ def initialize(**kwargs)
25
+ @client = Client.new(kwargs)
26
+ end
27
+
28
+ # Retrieve statistics of a given player.
29
+ #
30
+ # @param steam_id [String, Fixnum] Any supported Steam or account ID.
31
+ #
32
+ # See {SteamID.from_string} for supported formats.
33
+ # @return [PlayerData] Object containing player statistics.
34
+ # @raise [APIError] In case of errors communicating with the API.
35
+ # @raise [ArgumentError] If the supplied string could not be converted to
36
+ # an account ID.
37
+ def get_player_data(steam_id)
38
+ account_id = SteamID.from_string(steam_id)
39
+ PlayerData.new(@client.get_player_data(account_id))
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,45 @@
1
+ module HiveStalker
2
+ # Module to convert various formats of Steam IDs into an account ID.
3
+ module SteamID
4
+ STEAM_ID_64_OFFSET = 61197960265728
5
+
6
+ PATTERN_STEAM_ID = /^STEAM_0:([0-9]):([0-9]+)$/
7
+ PATTERN_STEAM_ID_3 = /^U:([0-9]{1,2}):([0-9]+)$/
8
+ PATTERN_STEAM_ID_64 = /^765([0-9]+)$/
9
+ PATTERN_ACCOUNT_ID = /^[0-9]{8}$/
10
+
11
+ # Convert Steam ID into account ID suitable for API calls.
12
+ # @param s [String] Steam ID, either of:
13
+ # - Steam ID: STEAM_0:0:24110655
14
+ # - Steam ID 3: U:1:48221310
15
+ # - Steam ID 64: 76561198008487038
16
+ # - Account ID: 48221310
17
+ # @return [Fixnum] Account ID
18
+ # @raise [ArgumentError] If the supplied string could not be converted to
19
+ # an account ID.
20
+ def self.from_string(s)
21
+ # In case we get a fixnum.
22
+ s = s.to_s
23
+
24
+ # https://developer.valvesoftware.com/wiki/SteamID#Format
25
+ PATTERN_ACCOUNT_ID.match(s) do |m|
26
+ return s.to_i
27
+ end
28
+
29
+ PATTERN_STEAM_ID.match(s) do |m|
30
+ return m[1].to_i + m[2].to_i * 2
31
+ end
32
+
33
+ PATTERN_STEAM_ID_3.match(s) do |m|
34
+ return m[2].to_i
35
+ end
36
+
37
+ PATTERN_STEAM_ID_64.match(s) do |m|
38
+ return m[1].to_i - STEAM_ID_64_OFFSET
39
+ end
40
+
41
+ # If we get until here, we did not match any regex.
42
+ raise ArgumentError, "#{ s.inspect } is not a supported SteamID."
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,11 @@
1
+ # coding: utf-8
2
+
3
+ require 'hive_stalker/steam_id'
4
+ require 'hive_stalker/client'
5
+ require 'hive_stalker/stalker'
6
+ require 'hive_stalker/player_data'
7
+ require 'hive_stalker/api_error'
8
+
9
+ module HiveStalker
10
+ # Your code goes here...
11
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hive-stalker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Senn
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-12-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: typhoeus
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
84
+ email:
85
+ - michael@morrolan.ch
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - CHANGELOG.md
93
+ - Gemfile
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - TODO.md
98
+ - bin/console
99
+ - bin/setup
100
+ - hive-stalker.gemspec
101
+ - lib/hive_stalker.rb
102
+ - lib/hive_stalker/api_error.rb
103
+ - lib/hive_stalker/client.rb
104
+ - lib/hive_stalker/player_data.rb
105
+ - lib/hive_stalker/stalker.rb
106
+ - lib/hive_stalker/steam_id.rb
107
+ homepage: https://bitbucket.org/Lavode/hivestalker
108
+ licenses:
109
+ - Apache-2.0
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.5.2
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Binding to Natural Selection 2's Hive2 ELO system
131
+ test_files: []