sportradar-api 0.9.12 → 0.11.21
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 +4 -4
- data/.env.sample +6 -0
- data/.travis.yml +1 -0
- data/Gemfile.lock +32 -30
- data/README.md +12 -9
- data/lib/sportradar/api/baseball/README.md +28 -0
- data/lib/sportradar/api/baseball/error.rb +25 -0
- data/lib/sportradar/api/baseball/event.rb +44 -0
- data/lib/sportradar/api/baseball/events/at_bat.rb +96 -0
- data/lib/sportradar/api/baseball/events/lineup.rb +41 -0
- data/lib/sportradar/api/baseball/events/warming_up.rb +35 -0
- data/lib/sportradar/api/baseball/fielder.rb +26 -0
- data/lib/sportradar/api/baseball/game.rb +472 -0
- data/lib/sportradar/api/baseball/half_inning.rb +69 -0
- data/lib/sportradar/api/baseball/inning.rb +42 -0
- data/lib/sportradar/api/baseball/lineup.rb +116 -0
- data/lib/sportradar/api/baseball/mlb/division.rb +32 -0
- data/lib/sportradar/api/baseball/mlb/hierarchy.rb +273 -0
- data/lib/sportradar/api/baseball/mlb/league.rb +27 -0
- data/lib/sportradar/api/baseball/mlb.rb +84 -0
- data/lib/sportradar/api/baseball/outcome.rb +87 -0
- data/lib/sportradar/api/baseball/pitch.rb +245 -0
- data/lib/sportradar/api/baseball/player.rb +119 -0
- data/lib/sportradar/api/baseball/record.rb +42 -0
- data/lib/sportradar/api/baseball/runner.rb +78 -0
- data/lib/sportradar/api/baseball/scoring.rb +86 -0
- data/lib/sportradar/api/baseball/team.rb +147 -0
- data/lib/sportradar/api/baseball/venue.rb +51 -0
- data/lib/sportradar/api/baseball.rb +46 -0
- data/lib/sportradar/api/basketball/broadcast.rb +15 -0
- data/lib/sportradar/api/basketball/game.rb +339 -0
- data/lib/sportradar/api/basketball/injury.rb +41 -0
- data/lib/sportradar/api/basketball/nba/conference.rb +27 -0
- data/lib/sportradar/api/basketball/nba/division.rb +30 -0
- data/lib/sportradar/api/basketball/nba/game.rb +62 -0
- data/lib/sportradar/api/basketball/nba/hierarchy.rb +47 -0
- data/lib/sportradar/api/basketball/nba/player.rb +160 -0
- data/lib/sportradar/api/basketball/nba/quarter.rb +51 -0
- data/lib/sportradar/api/basketball/nba/schedule.rb +43 -0
- data/lib/sportradar/api/basketball/nba/scoring.rb +15 -0
- data/lib/sportradar/api/basketball/nba/season.rb +54 -0
- data/lib/sportradar/api/basketball/nba/series.rb +82 -0
- data/lib/sportradar/api/basketball/nba/team.rb +74 -0
- data/lib/sportradar/api/basketball/nba.rb +129 -0
- data/lib/sportradar/api/basketball/ncaamb/bracket.rb +44 -0
- data/lib/sportradar/api/basketball/ncaamb/conference.rb +41 -0
- data/lib/sportradar/api/basketball/ncaamb/division.rb +42 -0
- data/lib/sportradar/api/basketball/ncaamb/game.rb +75 -0
- data/lib/sportradar/api/basketball/ncaamb/half.rb +49 -0
- data/lib/sportradar/api/basketball/ncaamb/hierarchy.rb +65 -0
- data/lib/sportradar/api/basketball/ncaamb/player.rb +162 -0
- data/lib/sportradar/api/basketball/ncaamb/round.rb +55 -0
- data/lib/sportradar/api/basketball/ncaamb/schedule.rb +41 -0
- data/lib/sportradar/api/basketball/ncaamb/season.rb +55 -0
- data/lib/sportradar/api/basketball/ncaamb/team.rb +61 -0
- data/lib/sportradar/api/basketball/ncaamb/tournament.rb +154 -0
- data/lib/sportradar/api/basketball/ncaamb.rb +149 -0
- data/lib/sportradar/api/basketball/play.rb +75 -0
- data/lib/sportradar/api/basketball/plays/assist.rb +14 -0
- data/lib/sportradar/api/basketball/plays/base.rb +126 -0
- data/lib/sportradar/api/basketball/plays/block.rb +14 -0
- data/lib/sportradar/api/basketball/plays/clear_path_foul.rb +11 -0
- data/lib/sportradar/api/basketball/plays/deadball.rb +11 -0
- data/lib/sportradar/api/basketball/plays/defensive_three_seconds.rb +11 -0
- data/lib/sportradar/api/basketball/plays/delay.rb +11 -0
- data/lib/sportradar/api/basketball/plays/ejection.rb +14 -0
- data/lib/sportradar/api/basketball/plays/end_period.rb +28 -0
- data/lib/sportradar/api/basketball/plays/flagrant_one.rb +11 -0
- data/lib/sportradar/api/basketball/plays/flagrant_two.rb +11 -0
- data/lib/sportradar/api/basketball/plays/foul.rb +17 -0
- data/lib/sportradar/api/basketball/plays/free_throw_made.rb +23 -0
- data/lib/sportradar/api/basketball/plays/free_throw_miss.rb +25 -0
- data/lib/sportradar/api/basketball/plays/jumpball.rb +12 -0
- data/lib/sportradar/api/basketball/plays/kickball.rb +11 -0
- data/lib/sportradar/api/basketball/plays/lineup_change.rb +11 -0
- data/lib/sportradar/api/basketball/plays/offensive_foul.rb +11 -0
- data/lib/sportradar/api/basketball/plays/official_timeout.rb +11 -0
- data/lib/sportradar/api/basketball/plays/open_inbound.rb +9 -0
- data/lib/sportradar/api/basketball/plays/open_tip.rb +11 -0
- data/lib/sportradar/api/basketball/plays/personal_foul.rb +9 -0
- data/lib/sportradar/api/basketball/plays/rebound.rb +28 -0
- data/lib/sportradar/api/basketball/plays/review.rb +11 -0
- data/lib/sportradar/api/basketball/plays/shooting_foul.rb +9 -0
- data/lib/sportradar/api/basketball/plays/shot_made.rb +22 -0
- data/lib/sportradar/api/basketball/plays/shot_miss.rb +22 -0
- data/lib/sportradar/api/basketball/plays/steal.rb +11 -0
- data/lib/sportradar/api/basketball/plays/team_timeout.rb +14 -0
- data/lib/sportradar/api/basketball/plays/technical_foul.rb +14 -0
- data/lib/sportradar/api/basketball/plays/three_point_made.rb +14 -0
- data/lib/sportradar/api/basketball/plays/three_point_miss.rb +11 -0
- data/lib/sportradar/api/basketball/plays/timeout.rb +24 -0
- data/lib/sportradar/api/basketball/plays/turnover.rb +19 -0
- data/lib/sportradar/api/basketball/plays/tv_timeout.rb +11 -0
- data/lib/sportradar/api/basketball/plays/two_point_made.rb +14 -0
- data/lib/sportradar/api/basketball/plays/two_point_miss.rb +11 -0
- data/lib/sportradar/api/basketball/plays.rb +39 -0
- data/lib/sportradar/api/basketball/record.rb +28 -0
- data/lib/sportradar/api/basketball/scoring.rb +103 -0
- data/lib/sportradar/api/basketball/season.rb +20 -0
- data/lib/sportradar/api/basketball/team.rb +136 -0
- data/lib/sportradar/api/basketball/venue.rb +54 -0
- data/lib/sportradar/api/basketball.rb +35 -0
- data/lib/sportradar/api/{nfl/broadcast.rb → broadcast.rb} +1 -1
- data/lib/sportradar/api/content/article.rb +1 -1
- data/lib/sportradar/api/content/article_list.rb +1 -1
- data/lib/sportradar/api/content.rb +17 -5
- data/lib/sportradar/api/data.rb +53 -0
- data/lib/sportradar/api/football/README.md +62 -0
- data/lib/sportradar/api/football/drive.rb +114 -0
- data/lib/sportradar/api/football/event.rb +36 -0
- data/lib/sportradar/api/football/game.rb +404 -0
- data/lib/sportradar/api/football/game_stats.rb +135 -0
- data/lib/sportradar/api/football/ncaafb/api.rb +81 -0
- data/lib/sportradar/api/football/ncaafb/conference.rb +53 -0
- data/lib/sportradar/api/football/ncaafb/division.rb +42 -0
- data/lib/sportradar/api/football/ncaafb/drive.rb +36 -0
- data/lib/sportradar/api/football/ncaafb/game.rb +130 -0
- data/lib/sportradar/api/football/ncaafb/play.rb +97 -0
- data/lib/sportradar/api/football/ncaafb/player.rb +31 -0
- data/lib/sportradar/api/football/ncaafb/quarter.rb +15 -0
- data/lib/sportradar/api/football/ncaafb/subdivision.rb +43 -0
- data/lib/sportradar/api/football/ncaafb/team.rb +49 -0
- data/lib/sportradar/api/football/ncaafb/week.rb +24 -0
- data/lib/sportradar/api/football/ncaafb.rb +273 -0
- data/lib/sportradar/api/football/nfl/api.rb +76 -0
- data/lib/sportradar/api/football/nfl/conference.rb +35 -0
- data/lib/sportradar/api/football/nfl/depth_chart.rb +53 -0
- data/lib/sportradar/api/football/nfl/division.rb +37 -0
- data/lib/sportradar/api/football/nfl/drive.rb +19 -0
- data/lib/sportradar/api/football/nfl/event.rb +19 -0
- data/lib/sportradar/api/football/nfl/game.rb +77 -0
- data/lib/sportradar/api/football/nfl/league_depth_chart.rb +41 -0
- data/lib/sportradar/api/football/nfl/play.rb +27 -0
- data/lib/sportradar/api/football/nfl/player.rb +31 -0
- data/lib/sportradar/api/football/nfl/quarter.rb +15 -0
- data/lib/sportradar/api/football/nfl/team.rb +42 -0
- data/lib/sportradar/api/football/nfl/team_depth_chart.rb +44 -0
- data/lib/sportradar/api/football/nfl/week.rb +24 -0
- data/lib/sportradar/api/football/nfl.rb +322 -0
- data/lib/sportradar/api/football/play.rb +116 -0
- data/lib/sportradar/api/football/play_statistics.rb +313 -0
- data/lib/sportradar/api/football/player.rb +121 -0
- data/lib/sportradar/api/football/quarter.rb +46 -0
- data/lib/sportradar/api/football/record.rb +48 -0
- data/lib/sportradar/api/football/scoring.rb +92 -0
- data/lib/sportradar/api/football/situation.rb +32 -0
- data/lib/sportradar/api/football/stat_pack/defense.rb +20 -20
- data/lib/sportradar/api/football/stat_pack/extra_points.rb +5 -4
- data/lib/sportradar/api/football/stat_pack/field_goals.rb +6 -5
- data/lib/sportradar/api/football/stat_pack/fumbles.rb +11 -9
- data/lib/sportradar/api/football/stat_pack/kick_returns.rb +8 -7
- data/lib/sportradar/api/football/stat_pack/kickoffs.rb +9 -7
- data/lib/sportradar/api/football/stat_pack/misc_returns.rb +1 -1
- data/lib/sportradar/api/football/stat_pack/passing.rb +13 -11
- data/lib/sportradar/api/football/stat_pack/penalties.rb +2 -2
- data/lib/sportradar/api/football/stat_pack/punt_returns.rb +7 -6
- data/lib/sportradar/api/football/stat_pack/punts.rb +12 -10
- data/lib/sportradar/api/football/stat_pack/receiving.rb +10 -9
- data/lib/sportradar/api/football/stat_pack/rushing.rb +11 -9
- data/lib/sportradar/api/football/stat_pack.rb +7 -3
- data/lib/sportradar/api/football/team.rb +160 -0
- data/lib/sportradar/api/football/venue.rb +25 -0
- data/lib/sportradar/api/football/week.rb +57 -0
- data/lib/sportradar/api/football.rb +47 -0
- data/lib/sportradar/api/images/asset.rb +2 -1
- data/lib/sportradar/api/images/ref.rb +15 -0
- data/lib/sportradar/api/images.rb +51 -9
- data/lib/sportradar/api/mma/event.rb +111 -0
- data/lib/sportradar/api/mma/fight.rb +107 -0
- data/lib/sportradar/api/mma/fighter.rb +95 -0
- data/lib/sportradar/api/mma/judge.rb +70 -0
- data/lib/sportradar/api/mma/league.rb +63 -0
- data/lib/sportradar/api/mma/referee.rb +70 -0
- data/lib/sportradar/api/mma/result.rb +68 -0
- data/lib/sportradar/api/mma/roster.rb +72 -0
- data/lib/sportradar/api/mma/schedule.rb +53 -0
- data/lib/sportradar/api/mma/score.rb +83 -0
- data/lib/sportradar/api/mma/venue.rb +72 -0
- data/lib/sportradar/api/mma.rb +195 -0
- data/lib/sportradar/api/poll.rb +40 -0
- data/lib/sportradar/api/request.rb +40 -8
- data/lib/sportradar/api/soccer/schedule.rb +1 -0
- data/lib/sportradar/api/version.rb +1 -1
- data/lib/sportradar/api.rb +20 -34
- metadata +157 -34
- data/lib/sportradar/api/nfl/.play_statistics.rb.swo +0 -0
- data/lib/sportradar/api/nfl/changelog.rb +0 -17
- data/lib/sportradar/api/nfl/coach.rb +0 -17
- data/lib/sportradar/api/nfl/conference.rb +0 -16
- data/lib/sportradar/api/nfl/depth_chart.rb +0 -47
- data/lib/sportradar/api/nfl/division.rb +0 -16
- data/lib/sportradar/api/nfl/draft.rb +0 -16
- data/lib/sportradar/api/nfl/drive.rb +0 -73
- data/lib/sportradar/api/nfl/event.rb +0 -19
- data/lib/sportradar/api/nfl/franchise.rb +0 -14
- data/lib/sportradar/api/nfl/game.rb +0 -94
- data/lib/sportradar/api/nfl/game_statistic.rb +0 -133
- data/lib/sportradar/api/nfl/hierarchy.rb +0 -19
- data/lib/sportradar/api/nfl/injury.rb +0 -16
- data/lib/sportradar/api/nfl/league_depth_chart.rb +0 -26
- data/lib/sportradar/api/nfl/play.rb +0 -39
- data/lib/sportradar/api/nfl/play_statistics.rb +0 -247
- data/lib/sportradar/api/nfl/player.rb +0 -49
- data/lib/sportradar/api/nfl/position.rb +0 -14
- data/lib/sportradar/api/nfl/quarter.rb +0 -29
- data/lib/sportradar/api/nfl/scoring.rb +0 -25
- data/lib/sportradar/api/nfl/season.rb +0 -23
- data/lib/sportradar/api/nfl/situation.rb +0 -18
- data/lib/sportradar/api/nfl/statistic.rb +0 -28
- data/lib/sportradar/api/nfl/summary.rb +0 -17
- data/lib/sportradar/api/nfl/team.rb +0 -56
- data/lib/sportradar/api/nfl/team_depth_chart.rb +0 -44
- data/lib/sportradar/api/nfl/venue.rb +0 -22
- data/lib/sportradar/api/nfl/week.rb +0 -16
- data/lib/sportradar/api/nfl.rb +0 -205
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Basketball
|
|
4
|
+
class Scoring < Data
|
|
5
|
+
attr_accessor :response, :api, :id, :home, :away, :scores
|
|
6
|
+
|
|
7
|
+
def initialize(data, **opts)
|
|
8
|
+
@api = opts[:api]
|
|
9
|
+
@game = opts[:game]
|
|
10
|
+
|
|
11
|
+
@scores = {}
|
|
12
|
+
@id = data['id']
|
|
13
|
+
|
|
14
|
+
update(data, **opts)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def update(data, source: nil, **opts)
|
|
18
|
+
new_scores = case source
|
|
19
|
+
when :box
|
|
20
|
+
parse_from_box(data)
|
|
21
|
+
when :pbp
|
|
22
|
+
parse_from_pbp(data)
|
|
23
|
+
when :summary
|
|
24
|
+
parse_from_box(data)
|
|
25
|
+
else
|
|
26
|
+
if data['quarter'] || data['half']
|
|
27
|
+
parse_from_pbp(data)
|
|
28
|
+
elsif data['team']
|
|
29
|
+
parse_from_box(data)
|
|
30
|
+
else # schedule requests
|
|
31
|
+
{}
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
# parse data structure
|
|
35
|
+
# handle data from team (all quarters)
|
|
36
|
+
# handle data from quarter (both teams)
|
|
37
|
+
# handle data from game?
|
|
38
|
+
@scores.each { |k, v| v.merge!(new_scores.delete(k) || {} ) }
|
|
39
|
+
new_scores.each { |k, v| @scores.merge!(k => v) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def points(team_id)
|
|
43
|
+
@score[team_id].to_i
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def parse_from_box(data)
|
|
50
|
+
return {} if data.dig('team', 0, 'scoring').is_a?(String) || data.dig('team', 0, 'scoring').nil? # game hasn't started yet
|
|
51
|
+
period_name = data.dig('team', 0, 'scoring').keys.first
|
|
52
|
+
id = data.dig('team', 0, 'id')
|
|
53
|
+
da = data.dig('team', 0, 'scoring', period_name)
|
|
54
|
+
da_ot = data.dig('team', 0, 'scoring', 'overtime')
|
|
55
|
+
arr = [da].compact.flatten(1)
|
|
56
|
+
a = arr + [da_ot].compact.flatten(1)
|
|
57
|
+
a.each { |h| h[id] = h.delete('points').to_i }
|
|
58
|
+
id = data.dig('team', 1, 'id')
|
|
59
|
+
da = data.dig('team', 1, 'scoring', period_name)
|
|
60
|
+
da_ot = data.dig('team', 1, 'scoring', 'overtime')
|
|
61
|
+
arr = [da].compact.flatten(1)
|
|
62
|
+
b = arr + [da_ot].compact.flatten(1)
|
|
63
|
+
b.each { |h| h[id] = h.delete('points').to_i }
|
|
64
|
+
a.zip(b).map{ |a, b| [a['sequence'].to_i, a.merge(b)] }.sort{ |(a,_), (b,_)| a <=> b }.to_h
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def parse_from_box(data)
|
|
68
|
+
id = data.dig('home', 'id')
|
|
69
|
+
# binding.pry if id
|
|
70
|
+
da = data.dig('home', 'scoring')
|
|
71
|
+
return {} unless da
|
|
72
|
+
da.each { |h| h[id] = h.delete('points').to_i }
|
|
73
|
+
id = data.dig('away', 'id')
|
|
74
|
+
db = data.dig('away', 'scoring')
|
|
75
|
+
return {} unless db
|
|
76
|
+
db.each { |h| h[id] = h.delete('points').to_i }
|
|
77
|
+
da.zip(db).map{ |a, b| [a['sequence'].to_i, a.merge(b)] }.sort{ |(a,_), (b,_)| a <=> b }.to_h
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def parse_from_pbp(data)
|
|
81
|
+
period_name = data.key?('quarter') ? 'quarter' : 'half'
|
|
82
|
+
period_name = 'periods'
|
|
83
|
+
return {} unless data[period_name] # game hasn't started
|
|
84
|
+
quarters = data[period_name]#[1..-1]
|
|
85
|
+
overtimes = data['overtime']
|
|
86
|
+
overtimes = [overtimes] if !overtimes.is_a?(Array)
|
|
87
|
+
quarters = quarters[0] if (quarters.is_a?(Array) && (quarters.size == 1) && quarters.first.is_a?(Array))
|
|
88
|
+
data = (quarters + overtimes).compact.map{|q| q['scoring'] }
|
|
89
|
+
data.map.with_index(1) { |h, i| [i, { h.dig('home', 'id') => h.dig('home', 'points').to_i, h.dig('away', 'id') => h.dig('away', 'points').to_i }] }.to_h
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# def period_name
|
|
93
|
+
# 'quarter'
|
|
94
|
+
# end
|
|
95
|
+
|
|
96
|
+
def parse_from_summary(data)
|
|
97
|
+
#
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Basketball
|
|
4
|
+
class Season < Data
|
|
5
|
+
attr_accessor :response
|
|
6
|
+
|
|
7
|
+
# def initialize(data, **opts)
|
|
8
|
+
# @response = data
|
|
9
|
+
# @api = opts[:api]
|
|
10
|
+
|
|
11
|
+
# @id = response['id']
|
|
12
|
+
# @name = response['name']
|
|
13
|
+
# @alias = response['alias']
|
|
14
|
+
|
|
15
|
+
# end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Basketball
|
|
4
|
+
class Team < Data
|
|
5
|
+
attr_accessor :response, :id, :market, :name, :alias, :full_name, :venue, :records, :player_stats, :team_stats, :seed
|
|
6
|
+
|
|
7
|
+
def initialize(data, **opts)
|
|
8
|
+
@response = data
|
|
9
|
+
@api = opts[:api]
|
|
10
|
+
|
|
11
|
+
@games_hash = {}
|
|
12
|
+
@players_hash = {}
|
|
13
|
+
@player_stats = {}
|
|
14
|
+
@records = {}
|
|
15
|
+
@stats = nil
|
|
16
|
+
@points = nil
|
|
17
|
+
|
|
18
|
+
case data
|
|
19
|
+
when String
|
|
20
|
+
@id = data
|
|
21
|
+
when Hash
|
|
22
|
+
@id = data['id']
|
|
23
|
+
update(data, **opts)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def profile
|
|
28
|
+
Profile.new(self)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def update(data, **opts)
|
|
32
|
+
handle_names(data)
|
|
33
|
+
@venue = Venue.new(data['venue']) if data['venue']
|
|
34
|
+
|
|
35
|
+
@seed = data['seed'].to_i if data['seed']
|
|
36
|
+
@alias = data['alias'] if data['alias']
|
|
37
|
+
@points = data['points'].to_i if data['points']
|
|
38
|
+
# @home = data['home'] == 'true' if data['home']
|
|
39
|
+
# @away = data['away'] == 'true' if data['away']
|
|
40
|
+
# @scoring = data.dig('scoring', 'quarter') if data.dig('scoring', 'quarter')
|
|
41
|
+
|
|
42
|
+
parse_records(data) if data['records']
|
|
43
|
+
# binding.pry if data['players']
|
|
44
|
+
parse_players(data.dig('players'), opts[:game]) if data.dig('players')
|
|
45
|
+
# parse_stats(data['statistics']) if data['statistics']
|
|
46
|
+
if opts[:game]
|
|
47
|
+
add_game(opts[:game])
|
|
48
|
+
opts[:game].update_score(id => @points) if @points
|
|
49
|
+
opts[:game].update_stats(self, data['statistics']) if data['statistics']
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
def handle_names(data)
|
|
53
|
+
# need to do some more work here
|
|
54
|
+
@name = data['name'] if data['name']
|
|
55
|
+
if data['name'] && !data.key?('market')
|
|
56
|
+
@full_name = data['name']
|
|
57
|
+
elsif data['name'] && data['market']
|
|
58
|
+
@market = data['market']
|
|
59
|
+
@full_name = [@market, data['name']].join(' ')
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def record(type = 'overall')
|
|
64
|
+
@records[type]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def games
|
|
68
|
+
@games_hash.values
|
|
69
|
+
end
|
|
70
|
+
def add_game(game)
|
|
71
|
+
@games_hash[game.id] = game.id if game
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# def parse_stats(data)
|
|
75
|
+
# @stats = data
|
|
76
|
+
# end
|
|
77
|
+
|
|
78
|
+
def players
|
|
79
|
+
get_roster if @players_hash.empty?
|
|
80
|
+
@players_hash.values
|
|
81
|
+
end
|
|
82
|
+
alias :roster :players
|
|
83
|
+
def parse_players(data, game)
|
|
84
|
+
create_data(@players_hash, data, klass: player_class, api: api, team: self, game: game)
|
|
85
|
+
end
|
|
86
|
+
def update_player_stats(player, stats, game = nil)
|
|
87
|
+
game ? game.update_player_stats(player, stats) : @player_stats.merge!(player.id => stats.merge!(player: player))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def get_roster
|
|
91
|
+
data = api.get_data(path_roster)
|
|
92
|
+
ingest_roster(data)
|
|
93
|
+
end
|
|
94
|
+
def ingest_roster(data)
|
|
95
|
+
update(data)
|
|
96
|
+
data
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def get_season_stats
|
|
100
|
+
data = api.get_data(path_season_stats)
|
|
101
|
+
ingest_season_stats(data)
|
|
102
|
+
end
|
|
103
|
+
def ingest_season_stats(data)
|
|
104
|
+
parse_season_stats(data)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def parse_records(data)
|
|
108
|
+
@records['overall'] = Record.new(data, type: 'overall')
|
|
109
|
+
data['records'].each { |record| @records[record['record_type']] = Record.new(record, type: record['record_type']) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def parse_season_stats(data)
|
|
113
|
+
@team_stats = data.dig('own_record')
|
|
114
|
+
update(data)
|
|
115
|
+
player_data = data.dig('players')
|
|
116
|
+
create_data(@players_hash, player_data, klass: player_class, api: api, team: self)
|
|
117
|
+
data
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def path_base
|
|
121
|
+
"teams/#{ id }"
|
|
122
|
+
end
|
|
123
|
+
def path_base_stats(season_year = api.default_year, default_season = api.default_season)
|
|
124
|
+
"seasontd/#{season_year}/#{default_season}/teams/#{id}"
|
|
125
|
+
end
|
|
126
|
+
def path_roster
|
|
127
|
+
"#{ path_base }/profile"
|
|
128
|
+
end
|
|
129
|
+
def path_season_stats
|
|
130
|
+
"#{ path_base_stats }/statistics"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Basketball
|
|
4
|
+
class Venue < Data
|
|
5
|
+
attr_accessor :response, :id, :name, :address, :city, :state, :country, :zip, :capacity, :timezone
|
|
6
|
+
@all_hash = {}
|
|
7
|
+
def self.new(data, **opts)
|
|
8
|
+
existing = @all_hash[data['id']]
|
|
9
|
+
if existing
|
|
10
|
+
existing.update(data, **opts)
|
|
11
|
+
existing
|
|
12
|
+
else
|
|
13
|
+
@all_hash[data['id']] = super
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
def self.all
|
|
17
|
+
@all_hash.values
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def initialize(data, **opts)
|
|
21
|
+
@response = data
|
|
22
|
+
@id = data["id"]
|
|
23
|
+
|
|
24
|
+
update(data, **opts)
|
|
25
|
+
end
|
|
26
|
+
def update(data, **opts)
|
|
27
|
+
@name = data['name']
|
|
28
|
+
@address = data['address']
|
|
29
|
+
@city = data['city']
|
|
30
|
+
@state = data['state']
|
|
31
|
+
@zip = data['zip']
|
|
32
|
+
@country = data['country']
|
|
33
|
+
@capacity = data['capacity']
|
|
34
|
+
@timezone = data['timezone']
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def location
|
|
38
|
+
"#{name}, #{city}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
KEYS_SCHEDULE = ["id", "name", "capacity", "address", "city", "state", "zip", "country"]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
__END__
|
|
48
|
+
|
|
49
|
+
sr = Sportradar::Api::Nba.new
|
|
50
|
+
lh = sr.league_hierarchy;
|
|
51
|
+
t = lh.teams.first;
|
|
52
|
+
t.venue.id
|
|
53
|
+
t.venue.name
|
|
54
|
+
t.venue.city
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require_relative 'basketball/season'
|
|
2
|
+
require_relative 'basketball/game'
|
|
3
|
+
require_relative 'basketball/team'
|
|
4
|
+
require_relative 'basketball/record'
|
|
5
|
+
require_relative 'basketball/venue'
|
|
6
|
+
require_relative 'basketball/broadcast'
|
|
7
|
+
require_relative 'basketball/injury'
|
|
8
|
+
require_relative 'basketball/plays'
|
|
9
|
+
require_relative 'basketball/scoring'
|
|
10
|
+
|
|
11
|
+
require_relative 'basketball/nba'
|
|
12
|
+
require_relative 'basketball/nba/hierarchy'
|
|
13
|
+
require_relative 'basketball/nba/conference'
|
|
14
|
+
require_relative 'basketball/nba/division'
|
|
15
|
+
require_relative 'basketball/nba/season'
|
|
16
|
+
require_relative 'basketball/nba/series'
|
|
17
|
+
require_relative 'basketball/nba/schedule'
|
|
18
|
+
require_relative 'basketball/nba/game'
|
|
19
|
+
require_relative 'basketball/nba/team'
|
|
20
|
+
require_relative 'basketball/nba/player'
|
|
21
|
+
require_relative 'basketball/nba/quarter'
|
|
22
|
+
|
|
23
|
+
require_relative 'basketball/ncaamb'
|
|
24
|
+
require_relative 'basketball/ncaamb/season'
|
|
25
|
+
require_relative 'basketball/ncaamb/schedule'
|
|
26
|
+
require_relative 'basketball/ncaamb/tournament'
|
|
27
|
+
require_relative 'basketball/ncaamb/round'
|
|
28
|
+
require_relative 'basketball/ncaamb/bracket'
|
|
29
|
+
require_relative 'basketball/ncaamb/game'
|
|
30
|
+
require_relative 'basketball/ncaamb/half'
|
|
31
|
+
require_relative 'basketball/ncaamb/hierarchy'
|
|
32
|
+
require_relative 'basketball/ncaamb/division'
|
|
33
|
+
require_relative 'basketball/ncaamb/conference'
|
|
34
|
+
require_relative 'basketball/ncaamb/team'
|
|
35
|
+
require_relative 'basketball/ncaamb/player'
|
|
@@ -16,7 +16,7 @@ module Sportradar
|
|
|
16
16
|
@credit = data["credit"]
|
|
17
17
|
@content = data["content"]["long"] if data["content"] && data["content"]["long"]
|
|
18
18
|
@provider = OpenStruct.new(data["provider"]) if data["provider"]
|
|
19
|
-
@references = parse_into_array(selector: response["refs"]
|
|
19
|
+
@references = parse_into_array(selector: response["refs"], klass: Sportradar::Api::Content::Reference) if response["refs"]
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def transaction?
|
|
@@ -9,7 +9,7 @@ module Sportradar
|
|
|
9
9
|
@provider = data["provider"]
|
|
10
10
|
@start_time = Time.parse(data["start_time"]) if data["start_time"]
|
|
11
11
|
@end_time = Time.parse(data["end_time"]) if data["end_time"]
|
|
12
|
-
@articles = parse_into_array(selector: response["
|
|
12
|
+
@articles = parse_into_array(selector: response["items"], klass: Sportradar::Api::Content::Article) if response["items"]
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
end
|
|
@@ -3,7 +3,7 @@ module Sportradar
|
|
|
3
3
|
class Content < Request
|
|
4
4
|
attr_accessor :sport, :access_level
|
|
5
5
|
|
|
6
|
-
def initialize( sport, access_level =
|
|
6
|
+
def initialize( sport, access_level = default_access_level)
|
|
7
7
|
raise Sportradar::Api::Error::InvalidSport unless allowed_sports.include? sport
|
|
8
8
|
@sport = sport
|
|
9
9
|
raise Sportradar::Api::Error::InvalidAccessLevel unless allowed_access_levels.include? access_level
|
|
@@ -13,8 +13,8 @@ module Sportradar
|
|
|
13
13
|
def news( date = Date.today, content_type: 'all' )
|
|
14
14
|
raise Sportradar::Api::Error::InvalidType unless allowed_news_types.include? content_type
|
|
15
15
|
response = get request_url("#{provider }/news/#{date_path(date)}/#{content_type}")
|
|
16
|
-
if response.success? && response["
|
|
17
|
-
Sportradar::Api::Content::ArticleList.new response
|
|
16
|
+
if response.success? && response["items"]
|
|
17
|
+
Sportradar::Api::Content::ArticleList.new response.to_h
|
|
18
18
|
else
|
|
19
19
|
response
|
|
20
20
|
end
|
|
@@ -23,8 +23,8 @@ module Sportradar
|
|
|
23
23
|
def analysis( date = Date.today, content_type: 'all' )
|
|
24
24
|
raise Sportradar::Api::Error::InvalidType unless allowed_analysis_types.include? content_type
|
|
25
25
|
response = get request_url("#{provider }/analysis/#{date_path(date)}/#{content_type}")
|
|
26
|
-
if response.success? && response["
|
|
27
|
-
Sportradar::Api::Content::ArticleList.new response
|
|
26
|
+
if response.success? && response["items"]
|
|
27
|
+
Sportradar::Api::Content::ArticleList.new response.to_h
|
|
28
28
|
else
|
|
29
29
|
response
|
|
30
30
|
end
|
|
@@ -32,10 +32,22 @@ module Sportradar
|
|
|
32
32
|
|
|
33
33
|
private
|
|
34
34
|
|
|
35
|
+
def default_access_level
|
|
36
|
+
if (ENV['SPORTRADAR_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV']) == 'production'
|
|
37
|
+
'p'
|
|
38
|
+
else
|
|
39
|
+
't'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
35
43
|
def request_url(path)
|
|
36
44
|
"/content-#{sport}-#{access_level}#{version}/#{path}"
|
|
37
45
|
end
|
|
38
46
|
|
|
47
|
+
def content_format
|
|
48
|
+
'json'
|
|
49
|
+
end
|
|
50
|
+
|
|
39
51
|
def api_key
|
|
40
52
|
if access_level == 'p'
|
|
41
53
|
Sportradar::Api.api_key_params("content_#{sport}", "production")
|
data/lib/sportradar/api/data.rb
CHANGED
|
@@ -18,6 +18,59 @@ module Sportradar
|
|
|
18
18
|
[ klass.new(selector) ]
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
|
+
def parse_into_array_with_options(selector: , klass: , **opts)
|
|
22
|
+
if selector.is_a?(Array)
|
|
23
|
+
selector.map {|x| klass.new(x, **opts) }
|
|
24
|
+
elsif selector.is_a?(Hash)
|
|
25
|
+
[ klass.new(selector, **opts) ]
|
|
26
|
+
else
|
|
27
|
+
[]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def structure_links(links_arr)
|
|
32
|
+
links_arr.map { |hash| [hash['rel'], hash['href'].gsub('.xml', '')] }.to_h
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @param existing [Hash{String=>Data}] Existing data hash, ID => entity
|
|
36
|
+
# @param data [Hash, Array] new data to update with
|
|
37
|
+
def update_data(existing, data)
|
|
38
|
+
case data
|
|
39
|
+
when Array
|
|
40
|
+
data.each { |hash| existing[hash['id']].update(hash) }
|
|
41
|
+
when Hash
|
|
42
|
+
existing[data['id']].update(data)
|
|
43
|
+
else
|
|
44
|
+
# raise
|
|
45
|
+
end
|
|
46
|
+
existing
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @param existing [Hash{String=>Data}] Existing data hash, ID => entity
|
|
50
|
+
# @param data [Hash, Array] new data to update with
|
|
51
|
+
def create_data(existing = {}, data, klass: nil, identifier: 'id', **opts)
|
|
52
|
+
existing ||= {} # handles nil case, typically during object instantiation
|
|
53
|
+
case data
|
|
54
|
+
when [], {}
|
|
55
|
+
existing
|
|
56
|
+
when Array
|
|
57
|
+
data.each do |hash|
|
|
58
|
+
current = existing[hash[identifier]]
|
|
59
|
+
if current
|
|
60
|
+
current.update(hash, **opts)
|
|
61
|
+
else
|
|
62
|
+
current = klass.new(hash, **opts)
|
|
63
|
+
existing[current.id] = current
|
|
64
|
+
end
|
|
65
|
+
existing[current.id]
|
|
66
|
+
end
|
|
67
|
+
when Hash
|
|
68
|
+
existing[data[identifier]] = klass.new(data, **opts)
|
|
69
|
+
else
|
|
70
|
+
# raise
|
|
71
|
+
end
|
|
72
|
+
existing
|
|
73
|
+
end
|
|
21
74
|
|
|
22
75
|
def parse_out_hashes(data_element)
|
|
23
76
|
if data_element && data_element.is_a?(Array)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Sportradar Football
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
## NFL
|
|
6
|
+
|
|
7
|
+
Get started with official NFL api v1:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
nfl = Sportradar::Api::Football::Nfl.new
|
|
11
|
+
nfl = Sportradar::Api::Football::Nfl.new(year: 2016)
|
|
12
|
+
res = nfl.get_schedule # => res is the raw response data hash. the `nfl` object now has weeks present to interact with
|
|
13
|
+
res = nfl.get_weekly_schedule # => res is the raw response data hash. the `nfl` object now has weeks present to interact with
|
|
14
|
+
nfl.weeks.count # => 17
|
|
15
|
+
nfl.games.count # => 256
|
|
16
|
+
nfl.weeks.first.games.count # => 16
|
|
17
|
+
game = nfl.games.sample # => Sportradar::Api::Football::Nfl::Game
|
|
18
|
+
res = game.get_pbp # => res is raw response data hash. the `game` object now has quarters/drives/plays to interact with
|
|
19
|
+
game.quarters.size # => 4 (unless the game went to overtime)
|
|
20
|
+
game.drives.size # => (20-30) most NFL games have between 20 and 30 drives
|
|
21
|
+
game.plays.size # => 150 most NFL games have about 150 total plays
|
|
22
|
+
|
|
23
|
+
game.get_statistics # => res is raw response data hash. the `game` object now has team stats to interact with
|
|
24
|
+
game.home.stats.passing # => Sportradar::Api::Football::StatPack::Passing => passing stats
|
|
25
|
+
game.home.stats.passing.players.first
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
nfl = Marshal.load(File.binread('nfl.bin'));
|
|
31
|
+
ncaafb = Marshal.load(File.binread('ncaafb.bin'));
|
|
32
|
+
g1 = nfl.games.sample;
|
|
33
|
+
g2 = ncaafb.games.sample
|
|
34
|
+
g2.year
|
|
35
|
+
g1.year
|
|
36
|
+
games = [g1, g2]
|
|
37
|
+
games.map(&:year)
|
|
38
|
+
games.map(&:week)
|
|
39
|
+
games.map(&:week_number)
|
|
40
|
+
g1
|
|
41
|
+
g1.year
|
|
42
|
+
g1.week_number
|
|
43
|
+
games.map(&:type)
|
|
44
|
+
games.map(&:path_pbp)
|
|
45
|
+
games.map(&:plays)
|
|
46
|
+
games.map(&:drives).map(&:count)
|
|
47
|
+
games.map(&:plays).map(&:count)
|
|
48
|
+
games.map(&:quarter)
|
|
49
|
+
games.map(&:score)
|
|
50
|
+
games.each(&:get_statistics);
|
|
51
|
+
games.each(&:get_box);
|
|
52
|
+
games.map(&:score)
|
|
53
|
+
games.each(&:get_pbp);
|
|
54
|
+
games.map(&:plays).map(&:count)
|
|
55
|
+
games.map(&:drives).map(&:count)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
uri = '2015/REG/1/WKY/MSH'
|
|
59
|
+
game = Sportradar::Api::Football::Ncaafb::Game.new('uri' => uri)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Football
|
|
4
|
+
class Drive < Data
|
|
5
|
+
attr_accessor :response, :api, :id, :sequence, :start_reason, :end_reason, :play_count, :duration, :first_downs, :gain, :penalty_yards, :scoring_drive, :quarter, :team
|
|
6
|
+
|
|
7
|
+
def self.new(data, **opts)
|
|
8
|
+
if data['type'] == 'event'
|
|
9
|
+
Event.new(data, **opts)
|
|
10
|
+
else
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(data, **opts)
|
|
16
|
+
@id = data["id"]
|
|
17
|
+
@api = opts[:api]
|
|
18
|
+
@plays_hash = {}
|
|
19
|
+
@events_hash = {}
|
|
20
|
+
|
|
21
|
+
update(data, **opts)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def update(data, **opts)
|
|
25
|
+
@response = data
|
|
26
|
+
@type = data['type']
|
|
27
|
+
@team = data['team']
|
|
28
|
+
@clock = data['clock']
|
|
29
|
+
@overtime = !!opts[:quarter]&.overtime? || @overtime
|
|
30
|
+
|
|
31
|
+
@sequence = data["sequence"]
|
|
32
|
+
@start_reason = data["start_reason"]
|
|
33
|
+
@end_reason = data["end_reason"]
|
|
34
|
+
@play_count = data["play_count"]
|
|
35
|
+
@duration = data["duration"]
|
|
36
|
+
@first_downs = data["first_downs"]
|
|
37
|
+
@gain = data["gain"]
|
|
38
|
+
@penalty_yards = data["penalty_yards"]
|
|
39
|
+
@scoring_drive = data["scoring_drive"]
|
|
40
|
+
|
|
41
|
+
@quarter_data = data['quarter']
|
|
42
|
+
@team_data = data['team']
|
|
43
|
+
|
|
44
|
+
handle_plays_and_events(data, **opts)
|
|
45
|
+
|
|
46
|
+
self
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def overtime?
|
|
50
|
+
@overtime
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def plays
|
|
54
|
+
@plays_hash.values
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def events
|
|
58
|
+
@events_hash.values
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def over?
|
|
62
|
+
@end_reason != 'UNKNOWN' && !@end_reason.nil?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def end_reason_possibilities
|
|
66
|
+
[
|
|
67
|
+
'UNKNOWN',
|
|
68
|
+
'Touchdown',
|
|
69
|
+
'Safety',
|
|
70
|
+
'Field Goal',
|
|
71
|
+
'Missed FG',
|
|
72
|
+
'Blocked FG',
|
|
73
|
+
'Blocked FG, Downs',
|
|
74
|
+
'Blocked FG, Safety',
|
|
75
|
+
'Punt',
|
|
76
|
+
'Blocked Punt',
|
|
77
|
+
'Blocked Punt, Downs',
|
|
78
|
+
'Blocked Punt, Safety',
|
|
79
|
+
'Downs',
|
|
80
|
+
'Interception',
|
|
81
|
+
'Fumble',
|
|
82
|
+
'Fumble, Safety',
|
|
83
|
+
'Muffed FG',
|
|
84
|
+
'Muffed Punt',
|
|
85
|
+
'Muffed Kickoff',
|
|
86
|
+
'Kickoff',
|
|
87
|
+
'Own Kickoff',
|
|
88
|
+
'Onside Kick',
|
|
89
|
+
'Kickoff, No Play',
|
|
90
|
+
'End of Half',
|
|
91
|
+
'End of Game',
|
|
92
|
+
]
|
|
93
|
+
end
|
|
94
|
+
def normalized_end_reason
|
|
95
|
+
case end_reason
|
|
96
|
+
when 'Touchdown'
|
|
97
|
+
'Touchdown'
|
|
98
|
+
when 'Field Goal', 'Missed FG', "Blocked FG, Downs", 'Muffed FG', 'Blocked FG, Safety'
|
|
99
|
+
'Field Goal'
|
|
100
|
+
when 'Downs'
|
|
101
|
+
'Downs'
|
|
102
|
+
when 'Interception', 'Fumble'
|
|
103
|
+
'Turnover'
|
|
104
|
+
when 'Punt'
|
|
105
|
+
'Punt'
|
|
106
|
+
else
|
|
107
|
+
'Other'
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|