sportradar 0.0.11 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile +1 -1
- data/README.md +11 -0
- data/lib/sportradar.rb +16 -0
- data/lib/sportradar/nfl/team_rosters.rb +2 -2
- data/lib/sportradar/nhl/boxscore.rb +17 -0
- data/lib/sportradar/nhl/daily_schedule.rb +13 -0
- data/lib/sportradar/nhl/game_summary.rb +17 -0
- data/lib/sportradar/nhl/models/event.rb +171 -0
- data/lib/sportradar/nhl/models/penalty.rb +63 -0
- data/lib/sportradar/nhl/models/period.rb +70 -0
- data/lib/sportradar/nhl/models/play_player_stat.rb +124 -0
- data/lib/sportradar/nhl/models/scoring_play.rb +76 -0
- data/lib/sportradar/nhl/models/scoring_player.rb +25 -0
- data/lib/sportradar/nhl/parsers/boxscore_parser.rb +223 -0
- data/lib/sportradar/nhl/parsers/play_by_play_parser.rb +65 -0
- data/lib/sportradar/nhl/team_roster.rb +17 -0
- data/lib/sportradar/nhl/team_rosters.rb +29 -0
- data/lib/sportradar/nhl/teams_request.rb +39 -0
- data/lib/sportradar/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bc168b82f0579a852d39bb5c7f8b37deb2fa3ee
|
4
|
+
data.tar.gz: 027a52c50e00e65ac48b8e8cd9a8dd3fef3fd741
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45ececc3591c930e81699f5fa872a256d29e5ab979309e9eb882bec11bc9340d11a999573f53b342c767160c52ac2ba825cd2517f11469c7c0469780e0e326d1
|
7
|
+
data.tar.gz: 0995270a287da7e020a13f89670db2c63b9ccb0c056dfab3aa78ee27fb9d47270893715d51e96252f03f79e2e801dd3956b53bb9a3109e493033e2fa4a31b315
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.3.
|
1
|
+
2.3.1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -182,8 +182,19 @@ Defaults to and supports NHL Classic API feed version 3 only (not Official).
|
|
182
182
|
#### API Requests
|
183
183
|
|
184
184
|
* `Sportradar::Nhl::LeagueHierarchy.new().fetch`
|
185
|
+
* `Sportradar::Nhl::DailySchedule.new(date: Date.today).fetch`
|
185
186
|
* `Sportradar::Nhl::LeagueSchedule.new(year: '2016', interval_type: <reg|pre|pst>).fetch`
|
187
|
+
* `Sportradar::Nhl::Boxscore.new(event_id: '<game_guid>').fetch`
|
188
|
+
* `Sportradar::Nhl::GameSummary.new(event_id: '<game_guid>').fetch`
|
186
189
|
* `Sportradar::Nhl::PlayByPlay.new(event_id: '<game_guid>').fetch`
|
190
|
+
* `Sportradar::Nhl::TeamRoster.perform`
|
191
|
+
* `Sportradar::Nhl::TeamRoster.new(team_id: '44151f7a-0f24-11e2-8525-18a905767e44').fetch`
|
192
|
+
|
193
|
+
#### Bulk Saves
|
194
|
+
|
195
|
+
Some helpers will call `.save` for each response as separate items.
|
196
|
+
|
197
|
+
* `Sportradar::Nhl::TeamRosters.perform`
|
187
198
|
|
188
199
|
### Model Helpers
|
189
200
|
|
data/lib/sportradar.rb
CHANGED
@@ -98,9 +98,25 @@ require 'sportradar/nfl/rankings'
|
|
98
98
|
require 'sportradar/nfl/standings'
|
99
99
|
require 'sportradar/nfl/season_statistics'
|
100
100
|
|
101
|
+
require 'sportradar/nhl/models/event'
|
102
|
+
require 'sportradar/nhl/models/period'
|
103
|
+
require 'sportradar/nhl/models/play_player_stat'
|
104
|
+
require 'sportradar/nhl/models/scoring_player'
|
105
|
+
require 'sportradar/nhl/models/scoring_play'
|
106
|
+
require 'sportradar/nhl/models/penalty'
|
107
|
+
|
108
|
+
require 'sportradar/nhl/parsers/boxscore_parser'
|
109
|
+
require 'sportradar/nhl/parsers/play_by_play_parser'
|
110
|
+
|
111
|
+
require 'sportradar/nhl/boxscore'
|
112
|
+
require 'sportradar/nhl/daily_schedule'
|
113
|
+
require 'sportradar/nhl/game_summary'
|
101
114
|
require 'sportradar/nhl/league_hierarchy'
|
102
115
|
require 'sportradar/nhl/league_schedule'
|
103
116
|
require 'sportradar/nhl/play_by_play'
|
117
|
+
require 'sportradar/nhl/teams_request'
|
118
|
+
require 'sportradar/nhl/team_roster'
|
119
|
+
require 'sportradar/nhl/team_rosters'
|
104
120
|
|
105
121
|
Oj.default_options = {}
|
106
122
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
class Boxscore < Sportradar::ApiRequest
|
4
|
+
def initialize(event_id:)
|
5
|
+
@event_id = event_id
|
6
|
+
end
|
7
|
+
|
8
|
+
def path
|
9
|
+
"games/#{event_id}/boxscore.json"
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
attr_reader :event_id
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
class GameSummary < Sportradar::ApiRequest
|
4
|
+
def initialize(event_id:)
|
5
|
+
@event_id = event_id
|
6
|
+
end
|
7
|
+
|
8
|
+
def path
|
9
|
+
"games/#{event_id}/summary.json"
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
attr_reader :event_id
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
module Models
|
4
|
+
class Event
|
5
|
+
|
6
|
+
EVENT_TYPES = %w(emptynetgoal endperiod endshootoutperiod evenstrength faceoff giveaway goal goaliechange hit penalty penaltygoal penaltyshotmissed penaltyshotsaved powerplay shootoutgoal shootoutshotmissed shootoutshotsaved shotmissed shotsaved startshootoutperiod stoppage takeaway teamtimeout tvtimeout)
|
7
|
+
PLAY_TYPES = %w(emptynetgoal faceoff giveaway goal hit penalty penaltygoal penaltyshotmissed penaltyshotsaved powerplay shootoutgoal shootoutshotmissed shootoutshotsaved shotmissed shotsaved takeaway)
|
8
|
+
STOPPAGE_TYPES = %w(stoppage teamtimeout tvtimeout endperiod)
|
9
|
+
SCORING_PLAY_TYPES = %w(goal penaltygoal shootoutgoal)
|
10
|
+
PENALTY_TYPES = %w(penalty)
|
11
|
+
|
12
|
+
def initialize(period:, attributes:)
|
13
|
+
@period = period
|
14
|
+
@attributes = attributes
|
15
|
+
build_statistics
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
if coordinates?
|
20
|
+
"#{period_number} - #{clock} - #{event_type}: #{description} [#{coordinate_x}, #{coordinate_y}]"
|
21
|
+
else
|
22
|
+
"#{period_number} - #{clock} - #{event_type}: #{description}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def id
|
27
|
+
@attributes['id']
|
28
|
+
end
|
29
|
+
|
30
|
+
def game_id
|
31
|
+
period.game_id
|
32
|
+
end
|
33
|
+
|
34
|
+
def team
|
35
|
+
@attributes['attribution'] || {}
|
36
|
+
end
|
37
|
+
|
38
|
+
def team_id
|
39
|
+
team.dig('id')
|
40
|
+
end
|
41
|
+
|
42
|
+
def team_goal_side
|
43
|
+
team.dig('team_goal')
|
44
|
+
end
|
45
|
+
|
46
|
+
def has_team?
|
47
|
+
!team_id.nil?
|
48
|
+
end
|
49
|
+
|
50
|
+
def period
|
51
|
+
@period
|
52
|
+
end
|
53
|
+
|
54
|
+
def period_id
|
55
|
+
@period.id
|
56
|
+
end
|
57
|
+
|
58
|
+
def period_number
|
59
|
+
@period.number
|
60
|
+
end
|
61
|
+
|
62
|
+
def time_code
|
63
|
+
min, sec = clock.split(':').map(&:to_i)
|
64
|
+
"PT#{min}M#{sec}S"
|
65
|
+
end
|
66
|
+
|
67
|
+
def clock
|
68
|
+
@attributes['clock'] || '0'
|
69
|
+
end
|
70
|
+
|
71
|
+
def clock_secs
|
72
|
+
begin
|
73
|
+
if clock && clock.include?(':')
|
74
|
+
mins, secs = clock.split(':').map(&:to_i)
|
75
|
+
Time.parse("00:#{mins}:#{secs}").
|
76
|
+
seconds_since_midnight.to_i
|
77
|
+
end
|
78
|
+
rescue => e
|
79
|
+
return 0
|
80
|
+
end
|
81
|
+
end
|
82
|
+
alias_method :period_seconds, :clock_secs
|
83
|
+
|
84
|
+
def id
|
85
|
+
@attributes['id']
|
86
|
+
end
|
87
|
+
|
88
|
+
def description
|
89
|
+
@attributes['description'] || 0
|
90
|
+
end
|
91
|
+
|
92
|
+
def event_type
|
93
|
+
@attributes['event_type']
|
94
|
+
end
|
95
|
+
|
96
|
+
def coordinates
|
97
|
+
@attributes['location'] || {}
|
98
|
+
end
|
99
|
+
|
100
|
+
def coordinates?
|
101
|
+
@attributes['location'].present?
|
102
|
+
end
|
103
|
+
|
104
|
+
def coordinate_x
|
105
|
+
coordinates['coord_x']
|
106
|
+
end
|
107
|
+
|
108
|
+
def coordinate_y
|
109
|
+
coordinates['coord_y']
|
110
|
+
end
|
111
|
+
|
112
|
+
def official
|
113
|
+
@attributes['official']
|
114
|
+
end
|
115
|
+
|
116
|
+
def strength
|
117
|
+
@attributes['strength']
|
118
|
+
end
|
119
|
+
|
120
|
+
def wall_clock
|
121
|
+
@attributes['wall_clock']
|
122
|
+
end
|
123
|
+
|
124
|
+
def zone
|
125
|
+
@attributes['zone']
|
126
|
+
end
|
127
|
+
|
128
|
+
def updated_at
|
129
|
+
@attributes['updated']
|
130
|
+
end
|
131
|
+
|
132
|
+
def statistics
|
133
|
+
@attributes['statistics'] || []
|
134
|
+
end
|
135
|
+
|
136
|
+
def play_player_stats
|
137
|
+
@play_player_stats ||= []
|
138
|
+
end
|
139
|
+
|
140
|
+
def scoring_players
|
141
|
+
@scoring_players ||= []
|
142
|
+
end
|
143
|
+
|
144
|
+
def penalty?
|
145
|
+
PENALTY_TYPES.include?(event_type)
|
146
|
+
end
|
147
|
+
|
148
|
+
def play?
|
149
|
+
PLAY_TYPES.include?(event_type)
|
150
|
+
end
|
151
|
+
|
152
|
+
def scoring_play?
|
153
|
+
SCORING_PLAY_TYPES.include?(event_type)
|
154
|
+
end
|
155
|
+
|
156
|
+
def stoppage?
|
157
|
+
STOPPAGE_TYPES.include?(event_type)
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def build_statistics
|
163
|
+
statistics.each do |statistic|
|
164
|
+
play_player_stats << Models::PlayPlayerStat.new(event: self, attributes: statistic)
|
165
|
+
scoring_players << Models::ScoringPlayer.new(event: self, attributes: statistic) if scoring_play?
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
module Models
|
4
|
+
class Penalty < Event
|
5
|
+
def to_s
|
6
|
+
"#{super} - #{minutes} mins - #{label}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def duration
|
10
|
+
@attributes.dig('duration')
|
11
|
+
end
|
12
|
+
|
13
|
+
def minutes
|
14
|
+
duration.to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def name
|
18
|
+
ActiveSupport::Inflector.parameterize(penalty_type)
|
19
|
+
end
|
20
|
+
|
21
|
+
def penalty_type
|
22
|
+
@attributes.dig('penalty_type')
|
23
|
+
end
|
24
|
+
alias_method :label, :penalty_type
|
25
|
+
|
26
|
+
def player_id
|
27
|
+
play_player_stats.each do |stat|
|
28
|
+
if stat.penalty? && !stat.player_id.nil?
|
29
|
+
return stat.player_id
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def seconds
|
37
|
+
minutes * 60
|
38
|
+
end
|
39
|
+
|
40
|
+
def team_penalty
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_h
|
45
|
+
{
|
46
|
+
id: id,
|
47
|
+
game_id: game_id,
|
48
|
+
player_id: player_id,
|
49
|
+
team_id: team_id,
|
50
|
+
minutes: minutes,
|
51
|
+
name: name,
|
52
|
+
period_number: period_number,
|
53
|
+
period_seconds: period_seconds,
|
54
|
+
sports_ml_key: id,
|
55
|
+
team_penalty: team_penalty,
|
56
|
+
time_code: time_code,
|
57
|
+
seconds: seconds,
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
module Models
|
4
|
+
class Period
|
5
|
+
def initialize(game_id:, attributes:)
|
6
|
+
@game_id = game_id
|
7
|
+
@attributes = attributes
|
8
|
+
build_events
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"Period #{number}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def abbreviation
|
16
|
+
"#{number}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def game_id
|
20
|
+
@game_id
|
21
|
+
end
|
22
|
+
|
23
|
+
def id
|
24
|
+
@id
|
25
|
+
end
|
26
|
+
|
27
|
+
def number
|
28
|
+
@attributes['number'] || 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def events
|
32
|
+
@events ||= []
|
33
|
+
end
|
34
|
+
|
35
|
+
def events_data
|
36
|
+
@actions ||= @attributes.dig('events') || []
|
37
|
+
end
|
38
|
+
|
39
|
+
def penalties
|
40
|
+
@penalties ||= []
|
41
|
+
end
|
42
|
+
|
43
|
+
def plays
|
44
|
+
@plays ||= []
|
45
|
+
end
|
46
|
+
|
47
|
+
def scoring_plays
|
48
|
+
@scoring_plays ||= []
|
49
|
+
end
|
50
|
+
|
51
|
+
def stoppages
|
52
|
+
@stoppages ||= []
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def build_events
|
58
|
+
events_data.each do |event_data|
|
59
|
+
event = Models::Event.new(period: self, attributes: event_data)
|
60
|
+
events << event
|
61
|
+
plays << event if event.play?
|
62
|
+
stoppages << event if event.stoppage?
|
63
|
+
penalties << Models::Penalty.new(period: self, attributes: event_data) if event.penalty?
|
64
|
+
scoring_plays << Models::ScoringPlay.new(period: self, attributes: event_data) if event.scoring_play?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
module Models
|
4
|
+
class PlayPlayerStat
|
5
|
+
def initialize(event:, attributes:)
|
6
|
+
@event = event
|
7
|
+
@attributes = attributes
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
[
|
12
|
+
period_number,
|
13
|
+
clock,
|
14
|
+
description,
|
15
|
+
team_name,
|
16
|
+
full_name,
|
17
|
+
stat,
|
18
|
+
].join(' ')
|
19
|
+
end
|
20
|
+
|
21
|
+
def event
|
22
|
+
@event
|
23
|
+
end
|
24
|
+
|
25
|
+
def event_id
|
26
|
+
@event.id
|
27
|
+
end
|
28
|
+
|
29
|
+
def description
|
30
|
+
@event.description
|
31
|
+
end
|
32
|
+
|
33
|
+
def period
|
34
|
+
@event.period
|
35
|
+
end
|
36
|
+
|
37
|
+
def period_number
|
38
|
+
period.number
|
39
|
+
end
|
40
|
+
|
41
|
+
def clock
|
42
|
+
@event.clock
|
43
|
+
end
|
44
|
+
|
45
|
+
def player
|
46
|
+
@attributes.dig('player') || {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def player_id
|
50
|
+
player.dig('id')
|
51
|
+
end
|
52
|
+
|
53
|
+
def jersey
|
54
|
+
player.dig('jersey')
|
55
|
+
end
|
56
|
+
|
57
|
+
def full_name
|
58
|
+
player.dig('full_name')
|
59
|
+
end
|
60
|
+
|
61
|
+
def team
|
62
|
+
@attributes.dig('team') || {}
|
63
|
+
end
|
64
|
+
|
65
|
+
def team_id
|
66
|
+
team.dig('id')
|
67
|
+
end
|
68
|
+
|
69
|
+
def team_market
|
70
|
+
team.dig('market')
|
71
|
+
end
|
72
|
+
|
73
|
+
def team_name
|
74
|
+
team.dig('name')
|
75
|
+
end
|
76
|
+
|
77
|
+
def stat
|
78
|
+
{
|
79
|
+
player_id: player_id,
|
80
|
+
goal: goal?,
|
81
|
+
penalty: penalty?,
|
82
|
+
saved: saved?,
|
83
|
+
shootout: shootout?,
|
84
|
+
strength: strength,
|
85
|
+
type: type,
|
86
|
+
zone: zone,
|
87
|
+
}.compact
|
88
|
+
end
|
89
|
+
|
90
|
+
def goal?
|
91
|
+
@attributes.dig('goal') == true
|
92
|
+
end
|
93
|
+
|
94
|
+
def penalty?
|
95
|
+
type == 'penalty'
|
96
|
+
end
|
97
|
+
|
98
|
+
def saved?
|
99
|
+
@attributes.dig('saved') == true
|
100
|
+
end
|
101
|
+
|
102
|
+
def shootout?
|
103
|
+
@attributes.dig('shootout') == true
|
104
|
+
end
|
105
|
+
|
106
|
+
def strength
|
107
|
+
@attributes.dig('strength')
|
108
|
+
end
|
109
|
+
|
110
|
+
def type
|
111
|
+
@attributes.dig('type')
|
112
|
+
end
|
113
|
+
|
114
|
+
def win?
|
115
|
+
@attributes.dig('win') == true
|
116
|
+
end
|
117
|
+
|
118
|
+
def zone
|
119
|
+
@attributes.dig('zone')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
module Models
|
4
|
+
class ScoringPlay < Event
|
5
|
+
def points
|
6
|
+
1
|
7
|
+
end
|
8
|
+
|
9
|
+
def scored_at
|
10
|
+
wall_clock
|
11
|
+
end
|
12
|
+
|
13
|
+
def scoring_method
|
14
|
+
if empty_net? || penalty_goal? || shootout_goal?
|
15
|
+
'goal'
|
16
|
+
else
|
17
|
+
event_type
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def scoring_type
|
22
|
+
case strength
|
23
|
+
when 'even'
|
24
|
+
'ev'
|
25
|
+
when 'powerplay'
|
26
|
+
'pp'
|
27
|
+
when 'shorthanded'
|
28
|
+
'sh'
|
29
|
+
else
|
30
|
+
if shootout_goal?
|
31
|
+
'so'
|
32
|
+
else
|
33
|
+
strength
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def scoring_how
|
39
|
+
event_type
|
40
|
+
end
|
41
|
+
|
42
|
+
def empty_net
|
43
|
+
event_type == 'emptynetgoal'
|
44
|
+
end
|
45
|
+
|
46
|
+
def empty_net?
|
47
|
+
empty_net
|
48
|
+
end
|
49
|
+
|
50
|
+
def penalty_goal
|
51
|
+
event_type == 'penaltygoal'
|
52
|
+
end
|
53
|
+
|
54
|
+
def penalty_goal?
|
55
|
+
penalty_goal
|
56
|
+
end
|
57
|
+
|
58
|
+
def shootout_goal?
|
59
|
+
event_type == 'shootoutgoal'
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_h
|
63
|
+
{
|
64
|
+
id: id,
|
65
|
+
game_id: game_id,
|
66
|
+
points: points,
|
67
|
+
scored_at: scored_at,
|
68
|
+
scoring_method: scoring_method,
|
69
|
+
scoring_type: scoring_type,
|
70
|
+
empty_net: empty_net,
|
71
|
+
}.compact
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
module Models
|
4
|
+
class ScoringPlayer < PlayPlayerStat
|
5
|
+
def role
|
6
|
+
if goal? && type == 'shot'
|
7
|
+
'scorer'
|
8
|
+
elsif goal? && type == 'shotagainst' && !saved?
|
9
|
+
'goalie'
|
10
|
+
else
|
11
|
+
type
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def scoring_play_id
|
16
|
+
event.id
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#{super} - #{role}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
module Parsers
|
4
|
+
class BoxscoreParser
|
5
|
+
def initialize(json: {})
|
6
|
+
@json = json['game'] || json
|
7
|
+
end
|
8
|
+
|
9
|
+
def game_id
|
10
|
+
json['id']
|
11
|
+
end
|
12
|
+
|
13
|
+
def attendance
|
14
|
+
json['attendance']
|
15
|
+
end
|
16
|
+
|
17
|
+
def period
|
18
|
+
json['period'].to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
def scheduled_at
|
22
|
+
json['scheduled'] && json['scheduled'].to_datetime
|
23
|
+
end
|
24
|
+
|
25
|
+
def started_at
|
26
|
+
json['start_time'] && json['start_time'].to_datetime
|
27
|
+
end
|
28
|
+
|
29
|
+
def ended_at
|
30
|
+
json['end_time'] && json['end_time'].to_datetime
|
31
|
+
end
|
32
|
+
alias_method :completed, :ended_at
|
33
|
+
|
34
|
+
def over?
|
35
|
+
status == 'closed'
|
36
|
+
end
|
37
|
+
|
38
|
+
def status
|
39
|
+
json['status']
|
40
|
+
end
|
41
|
+
|
42
|
+
def clock
|
43
|
+
json['clock']
|
44
|
+
end
|
45
|
+
|
46
|
+
def clock_attributes
|
47
|
+
{
|
48
|
+
clock: clock,
|
49
|
+
clock_secs: clock_secs,
|
50
|
+
duration: duration_secs,
|
51
|
+
period: period,
|
52
|
+
ended_at: ended_at,
|
53
|
+
status: status,
|
54
|
+
}.compact
|
55
|
+
end
|
56
|
+
|
57
|
+
def clock_secs
|
58
|
+
begin
|
59
|
+
if clock && clock.include?(':')
|
60
|
+
mins, secs = clock.split(':').map(&:to_i)
|
61
|
+
Time.parse("00:#{mins}:#{secs}").
|
62
|
+
seconds_since_midnight.to_i
|
63
|
+
end
|
64
|
+
rescue => e
|
65
|
+
puts e
|
66
|
+
return 0
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def duration
|
71
|
+
json['total_game_duration']
|
72
|
+
end
|
73
|
+
|
74
|
+
def duration_secs
|
75
|
+
begin
|
76
|
+
if duration && duration.include?(':')
|
77
|
+
mins, secs = duration.split(':').map(&:to_i)
|
78
|
+
hours = mins / 60
|
79
|
+
mins = mins % 60
|
80
|
+
Time.parse("#{hours}:#{mins}:#{secs}").
|
81
|
+
seconds_since_midnight.to_i
|
82
|
+
end
|
83
|
+
rescue => e
|
84
|
+
return 0
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def home_team_json
|
89
|
+
json['home'] || {}
|
90
|
+
end
|
91
|
+
|
92
|
+
def home_team_id
|
93
|
+
home_team_json['id']
|
94
|
+
end
|
95
|
+
|
96
|
+
def home_team_scoring_data
|
97
|
+
home_team_json['scoring'] || {}
|
98
|
+
end
|
99
|
+
|
100
|
+
def home_team_scoring
|
101
|
+
{
|
102
|
+
goals: home_team_json['points'],
|
103
|
+
}.merge(home_team_scoring_periods).
|
104
|
+
compact
|
105
|
+
end
|
106
|
+
|
107
|
+
def home_team_scoring_periods
|
108
|
+
team_scoring_periods(data: home_team_scoring_data)
|
109
|
+
end
|
110
|
+
|
111
|
+
def away_team_json
|
112
|
+
json['away'] || {}
|
113
|
+
end
|
114
|
+
|
115
|
+
def away_team_id
|
116
|
+
away_team_json['id']
|
117
|
+
end
|
118
|
+
|
119
|
+
def away_team_scoring_data
|
120
|
+
away_team_json['scoring'] || {}
|
121
|
+
end
|
122
|
+
|
123
|
+
def away_team_scoring
|
124
|
+
{
|
125
|
+
goals: away_team_json['points'],
|
126
|
+
}.merge(away_team_scoring_periods).
|
127
|
+
compact
|
128
|
+
end
|
129
|
+
|
130
|
+
def away_team_scoring_periods
|
131
|
+
team_scoring_periods(data: away_team_scoring_data)
|
132
|
+
end
|
133
|
+
|
134
|
+
def team_scoring_periods(data:)
|
135
|
+
{}.tap do |scoring_periods|
|
136
|
+
overtime_points = 0
|
137
|
+
scoring_periods[:goals_overtime] = overtime_points
|
138
|
+
scoring_periods[:goals_shootout] = 0
|
139
|
+
|
140
|
+
data.map do |scoring_data|
|
141
|
+
if period = scoring_data['sequence'].to_i
|
142
|
+
if period > 0 && period <= 3
|
143
|
+
key = "goals_period_#{period}".to_sym
|
144
|
+
scoring_periods[key] =
|
145
|
+
scoring_data['points'].to_i
|
146
|
+
elsif period > 3
|
147
|
+
period_type = (scoring_data['type'] || 'period').downcase
|
148
|
+
if period_type == 'overtime'
|
149
|
+
key = "goals_#{period_type}_#{scoring_data['number'].to_i}".to_sym
|
150
|
+
scoring_periods[key] =
|
151
|
+
scoring_data['points'].to_i
|
152
|
+
overtime_points += scoring_data['points'].to_i
|
153
|
+
scoring_periods[:goals_overtime] = overtime_points
|
154
|
+
elsif period_type == 'shootout'
|
155
|
+
key = "goals_#{period_type}".to_sym
|
156
|
+
scoring_periods[key] =
|
157
|
+
scoring_data['points'].to_i
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
scoring_periods[:goals_overtime] = overtime_points
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def game_scoring_attributes
|
167
|
+
{
|
168
|
+
attendance: attendance,
|
169
|
+
home_team_outcome: home_team_outcome,
|
170
|
+
home_team_score: home_team_score,
|
171
|
+
away_team_outcome: away_team_outcome,
|
172
|
+
away_team_score: away_team_score,
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
def home_team_score
|
177
|
+
home_team_scoring[:goals] || 0
|
178
|
+
end
|
179
|
+
|
180
|
+
def home_team_outcome
|
181
|
+
if over?
|
182
|
+
if home_team_score > away_team_score
|
183
|
+
'win'
|
184
|
+
elsif home_team_score < away_team_score
|
185
|
+
'loss'
|
186
|
+
else
|
187
|
+
'tie'
|
188
|
+
end
|
189
|
+
else
|
190
|
+
'undecided'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def away_team_score
|
195
|
+
away_team_scoring[:goals] || 0
|
196
|
+
end
|
197
|
+
|
198
|
+
def away_team_outcome
|
199
|
+
if over?
|
200
|
+
if home_team_score < away_team_score
|
201
|
+
'win'
|
202
|
+
elsif home_team_score > away_team_score
|
203
|
+
'loss'
|
204
|
+
else
|
205
|
+
'tie'
|
206
|
+
end
|
207
|
+
else
|
208
|
+
'undecided'
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def game_attributes
|
213
|
+
clock_attributes.merge(game_scoring_attributes).
|
214
|
+
compact
|
215
|
+
end
|
216
|
+
|
217
|
+
private
|
218
|
+
|
219
|
+
attr_reader :json
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
module Parsers
|
4
|
+
class PlayByPlayParser
|
5
|
+
def initialize(game_play_by_play: {})
|
6
|
+
@game_play_by_play = game_play_by_play['game'] || game_play_by_play
|
7
|
+
end
|
8
|
+
|
9
|
+
def game_id
|
10
|
+
game_play_by_play['id']
|
11
|
+
end
|
12
|
+
|
13
|
+
def away
|
14
|
+
game_play_by_play['away'] || {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def away_team_id
|
18
|
+
away['id']
|
19
|
+
end
|
20
|
+
|
21
|
+
def home
|
22
|
+
game_play_by_play['home'] || {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def periods
|
26
|
+
@periods ||= build_periods || []
|
27
|
+
end
|
28
|
+
|
29
|
+
def has_periods?
|
30
|
+
periods.count > 0
|
31
|
+
end
|
32
|
+
|
33
|
+
def events
|
34
|
+
(periods || []).map(&:events).flatten
|
35
|
+
end
|
36
|
+
|
37
|
+
def penalties
|
38
|
+
(periods || []).map(&:penalties).flatten
|
39
|
+
end
|
40
|
+
|
41
|
+
def plays
|
42
|
+
(periods || []).map(&:plays).flatten
|
43
|
+
end
|
44
|
+
|
45
|
+
def scoring_plays
|
46
|
+
(periods || []).map(&:scoring_plays).flatten
|
47
|
+
end
|
48
|
+
|
49
|
+
def stoppages
|
50
|
+
(periods || []).map(&:stoppages).flatten
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
attr_reader :game_play_by_play
|
56
|
+
|
57
|
+
def build_periods
|
58
|
+
game_play_by_play.
|
59
|
+
dig('periods').
|
60
|
+
map { |attributes| Models::Period.new(game_id: game_id, attributes: attributes) }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
class TeamRosters < Sportradar::Nhl::TeamsRequest
|
4
|
+
def self.fetch
|
5
|
+
new.fetch
|
6
|
+
end
|
7
|
+
|
8
|
+
def fetch
|
9
|
+
team_rosters = []
|
10
|
+
|
11
|
+
team_ids.each do |team_ids|
|
12
|
+
team_rosters << TeamRoster.new(team_id: team_ids).fetch
|
13
|
+
end
|
14
|
+
|
15
|
+
{ 'teams' => team_rosters }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.perform
|
19
|
+
new.perform
|
20
|
+
end
|
21
|
+
|
22
|
+
def perform
|
23
|
+
team_ids.each do |team_id|
|
24
|
+
TeamRoster.new(team_id: team_id).save
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Nhl
|
3
|
+
class TeamsRequest
|
4
|
+
private
|
5
|
+
|
6
|
+
def team_ids
|
7
|
+
teams.map { |team| team['id'] }.sort
|
8
|
+
end
|
9
|
+
|
10
|
+
def hierarchy
|
11
|
+
_hierarchy ||= LeagueHierarchy.new.fetch
|
12
|
+
end
|
13
|
+
|
14
|
+
def conferences
|
15
|
+
conferences ||= hierarchy['conferences']
|
16
|
+
end
|
17
|
+
|
18
|
+
def divisions
|
19
|
+
@divisions = []
|
20
|
+
|
21
|
+
conferences.each do |league|
|
22
|
+
@divisions << league['divisions']
|
23
|
+
end
|
24
|
+
|
25
|
+
@divisions.flatten
|
26
|
+
end
|
27
|
+
|
28
|
+
def teams
|
29
|
+
@teams = []
|
30
|
+
|
31
|
+
divisions.each do |division|
|
32
|
+
@teams << division['teams']
|
33
|
+
end
|
34
|
+
|
35
|
+
@teams.flatten
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/sportradar/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sportradar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stattleship
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-10-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -242,9 +242,23 @@ files:
|
|
242
242
|
- lib/sportradar/nfl/weekly_leaders.rb
|
243
243
|
- lib/sportradar/nfl/weekly_play_by_play.rb
|
244
244
|
- lib/sportradar/nfl/weekly_schedule.rb
|
245
|
+
- lib/sportradar/nhl/boxscore.rb
|
246
|
+
- lib/sportradar/nhl/daily_schedule.rb
|
247
|
+
- lib/sportradar/nhl/game_summary.rb
|
245
248
|
- lib/sportradar/nhl/league_hierarchy.rb
|
246
249
|
- lib/sportradar/nhl/league_schedule.rb
|
250
|
+
- lib/sportradar/nhl/models/event.rb
|
251
|
+
- lib/sportradar/nhl/models/penalty.rb
|
252
|
+
- lib/sportradar/nhl/models/period.rb
|
253
|
+
- lib/sportradar/nhl/models/play_player_stat.rb
|
254
|
+
- lib/sportradar/nhl/models/scoring_play.rb
|
255
|
+
- lib/sportradar/nhl/models/scoring_player.rb
|
256
|
+
- lib/sportradar/nhl/parsers/boxscore_parser.rb
|
257
|
+
- lib/sportradar/nhl/parsers/play_by_play_parser.rb
|
247
258
|
- lib/sportradar/nhl/play_by_play.rb
|
259
|
+
- lib/sportradar/nhl/team_roster.rb
|
260
|
+
- lib/sportradar/nhl/team_rosters.rb
|
261
|
+
- lib/sportradar/nhl/teams_request.rb
|
248
262
|
- lib/sportradar/version.rb
|
249
263
|
- sample.env
|
250
264
|
- sportradar.gemspec
|