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,36 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Football
|
|
4
|
+
class Event < Data
|
|
5
|
+
attr_accessor :response, :id, :sequence, :reference, :clock, :type, :event_type, :description, :alt_description
|
|
6
|
+
|
|
7
|
+
def initialize(data, **opts)
|
|
8
|
+
@response = data
|
|
9
|
+
@id = data["id"]
|
|
10
|
+
update(data, **opts)
|
|
11
|
+
end
|
|
12
|
+
def update(data, **opts)
|
|
13
|
+
@sequence = data["sequence"]
|
|
14
|
+
@reference = data["reference"]
|
|
15
|
+
@clock = data["clock"]
|
|
16
|
+
@type = data["type"]
|
|
17
|
+
@event_type = data["event_type"]
|
|
18
|
+
@description = data["description"] || data["summary"]
|
|
19
|
+
@alt_description = data["alt_description"]
|
|
20
|
+
|
|
21
|
+
self
|
|
22
|
+
end
|
|
23
|
+
def plays
|
|
24
|
+
[]
|
|
25
|
+
end
|
|
26
|
+
def events
|
|
27
|
+
[self]
|
|
28
|
+
end
|
|
29
|
+
def over?
|
|
30
|
+
false # TODO
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Football
|
|
4
|
+
class Game < Data
|
|
5
|
+
attr_accessor :response, :id, :title, :home_id, :away_id, :score, :status, :coverage, :scheduled, :venue, :broadcast, :duration, :attendance, :team_stats, :player_stats, :changes, :lineup, :week, :quarter, :clock, :api
|
|
6
|
+
|
|
7
|
+
attr_reader :week_number, :year, :type
|
|
8
|
+
|
|
9
|
+
def initialize(data, **opts)
|
|
10
|
+
@response = data
|
|
11
|
+
@api = opts[:api]
|
|
12
|
+
# @week = opts[:week]
|
|
13
|
+
|
|
14
|
+
@scoring_raw = Scoring.new(data, game: self)
|
|
15
|
+
@home = team_class.new({}, api: api, game: self)
|
|
16
|
+
@away = team_class.new({}, api: api, game: self)
|
|
17
|
+
|
|
18
|
+
@updates = {}
|
|
19
|
+
@changes = {}
|
|
20
|
+
|
|
21
|
+
@teams_hash = {}
|
|
22
|
+
@team_stats = {}
|
|
23
|
+
@player_stats = {}
|
|
24
|
+
|
|
25
|
+
@quarters_hash = {}
|
|
26
|
+
@score = {}
|
|
27
|
+
|
|
28
|
+
update(data, **opts)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def timeouts
|
|
32
|
+
{}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def period
|
|
36
|
+
quarter
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def summary_stat(team_id, stat_name)
|
|
40
|
+
scoring.dig(team_id, stat_name)
|
|
41
|
+
end
|
|
42
|
+
def stats(team_id)
|
|
43
|
+
team_id.is_a?(Symbol) ? @team_stats[@team_ids[team_id]] : @team_stats[team_id]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def update_stats(team, stats)
|
|
47
|
+
@team_stats.merge!(team.id => stats)
|
|
48
|
+
end
|
|
49
|
+
def update_player_stats(player, stats)
|
|
50
|
+
@player_stats.merge!(player.id => stats.merge!(player: player))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def parse_score(data)
|
|
54
|
+
# home_id = data.dig('home', 'id')
|
|
55
|
+
# away_id = data.dig('away', 'id')
|
|
56
|
+
# rhe = {
|
|
57
|
+
# 'runs' => { home_id => data.dig('home', 'runs'), away_id => data.dig('away', 'runs')},
|
|
58
|
+
# 'hits' => { home_id => data.dig('home', 'hits'), away_id => data.dig('away', 'hits')},
|
|
59
|
+
# 'errors' => { home_id => data.dig('home', 'errors'), away_id => data.dig('away', 'errors')},
|
|
60
|
+
# }
|
|
61
|
+
# @scoring_raw.update(rhe, source: :rhe)
|
|
62
|
+
# update_score(home_id => data.dig('home', 'runs'))
|
|
63
|
+
# update_score(away_id => data.dig('away', 'runs'))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def update(data, source: nil, **opts)
|
|
67
|
+
@id = data['id'] || @id
|
|
68
|
+
# @year = data['year'] || @week&.season.year
|
|
69
|
+
# @type = data['type'] || @week&.season.type
|
|
70
|
+
# @week_number = data['week'] || @week&.sequence
|
|
71
|
+
|
|
72
|
+
@week_number = data['week_number'] || week&.number || opts[:week]&.number || @week_number
|
|
73
|
+
@year = data['year'] || week&.year || opts[:week]&.year || @year
|
|
74
|
+
@type = data['type'] || week&.type || opts[:week]&.type || @type
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@coverage = data['coverage']
|
|
78
|
+
@scheduled = Time.parse(data["scheduled"]) if data["scheduled"]
|
|
79
|
+
update_teams(data)
|
|
80
|
+
@status = data['status'] || @status
|
|
81
|
+
@clock = data['clock'] || @clock
|
|
82
|
+
@quarter = data['quarter'] || @quarter
|
|
83
|
+
@home_rotation = data['home_rotation']
|
|
84
|
+
@away_rotation = data['away_rotation']
|
|
85
|
+
@neutral_site = data['neutral_site']
|
|
86
|
+
@home_points = data['home_points']
|
|
87
|
+
@away_points = data['away_points']
|
|
88
|
+
@venue = Venue.new(data["venue"]) if data["venue"]
|
|
89
|
+
@weather = data['weather']
|
|
90
|
+
@broadcast = Broadcast.new(data['broadcast']) if !data['broadcast'].to_h.empty?
|
|
91
|
+
@attendance = data['attendance']
|
|
92
|
+
@title = data['title'] || @title || generate_title
|
|
93
|
+
|
|
94
|
+
# @links = data['links'] ? structure_links(data['links']) : {}
|
|
95
|
+
|
|
96
|
+
@teams_hash = { @home.id => @home, @away.id => @away } if @home.id && @away.id
|
|
97
|
+
@team_ids = { home: (@home&.id || home_alias), away: (@away&.id || away_alias) }
|
|
98
|
+
|
|
99
|
+
@scoring_raw.update(data, source: source)
|
|
100
|
+
if data['statistics']
|
|
101
|
+
@home.update({ 'statistics' => data.dig('statistics', 'home')}, game: self)
|
|
102
|
+
@away.update({ 'statistics' => data.dig('statistics', 'away')}, game: self)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
create_data(@teams_hash, data['team'], klass: team_class, api: api, game: self) if data['team']
|
|
106
|
+
|
|
107
|
+
self
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def generate_title
|
|
111
|
+
(home && away && "#{home.full_name} vs #{away.full_name}")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def update_teams(data)
|
|
115
|
+
if data['summary']
|
|
116
|
+
@home.update(data.dig('summary', 'home'), game: self)
|
|
117
|
+
@away.update(data.dig('summary', 'away'), game: self)
|
|
118
|
+
else
|
|
119
|
+
@home.update(data['home_team'], game: self) if data['home_team'].is_a?(Hash)
|
|
120
|
+
@away.update(data['away_team'], game: self) if data['away_team'].is_a?(Hash)
|
|
121
|
+
if data['home'].is_a?(String) # this might actually be team ID and not alias. check in NFL
|
|
122
|
+
@home_alias = data['home']
|
|
123
|
+
@home.id ||= @home_alias
|
|
124
|
+
end
|
|
125
|
+
if data['away'].is_a?(String) # this might actually be team ID and not alias. check in NFL
|
|
126
|
+
@away_alias = data['away']
|
|
127
|
+
@away.id ||= @away_alias
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# def update_from_team(id, data)
|
|
133
|
+
# end
|
|
134
|
+
|
|
135
|
+
def home
|
|
136
|
+
@teams_hash[@home_id] || @home
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def home_alias
|
|
140
|
+
@home_alias || @home&.alias
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def away
|
|
144
|
+
@teams_hash[@away_id] || @away
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def away_alias
|
|
148
|
+
@away_alias || @away&.alias
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def tied?
|
|
152
|
+
@score[away_id].to_i == @score[home_id].to_i
|
|
153
|
+
end
|
|
154
|
+
def scoring
|
|
155
|
+
@scoring_raw.scores
|
|
156
|
+
end
|
|
157
|
+
def update_score(score)
|
|
158
|
+
@score.merge!(score)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def leading_team_id
|
|
162
|
+
return nil if tied?
|
|
163
|
+
score.max_by(&:last).first
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def leading_team
|
|
167
|
+
@teams_hash[leading_team_id] || (@away_id == leading_team_id && away) || (@home_id == leading_team_id && home)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def team(team_id)
|
|
171
|
+
@teams_hash[team_id]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def assign_home(team)
|
|
175
|
+
@home_id = team.id
|
|
176
|
+
@teams_hash[team.id] = team
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def assign_away(team)
|
|
180
|
+
@away_id = team.id
|
|
181
|
+
@teams_hash[team.id] = team
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def box
|
|
185
|
+
@box ||= get_box
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def pbp
|
|
189
|
+
if !future? && quarters.empty?
|
|
190
|
+
get_pbp
|
|
191
|
+
end
|
|
192
|
+
@pbp ||= quarters
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def drives
|
|
196
|
+
quarters.flat_map(&:drives).compact
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def plays
|
|
200
|
+
drives.flat_map(&:plays).compact
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def events
|
|
204
|
+
drives.flat_map(&:events).compact
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# def summary
|
|
208
|
+
# @summary ||= get_summary
|
|
209
|
+
# end
|
|
210
|
+
|
|
211
|
+
def quarters
|
|
212
|
+
@quarters_hash.values
|
|
213
|
+
end
|
|
214
|
+
def half_quarters
|
|
215
|
+
quarters.flat_map(&:half_quarters)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# tracking updates
|
|
219
|
+
def remember(key, object)
|
|
220
|
+
@updates[key] = object&.dup
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def not_updated?(key, object)
|
|
224
|
+
@updates[key] == object
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def changed?(key)
|
|
228
|
+
@changes[key]
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def check_newness(key, new_object)
|
|
232
|
+
@changes[key] = !not_updated?(key, new_object)
|
|
233
|
+
remember(key, new_object)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# status helpers
|
|
237
|
+
def realtime_state
|
|
238
|
+
if future?
|
|
239
|
+
'Scheduled'
|
|
240
|
+
elsif delayed?
|
|
241
|
+
'Delayed'
|
|
242
|
+
elsif finished?
|
|
243
|
+
'Final'
|
|
244
|
+
elsif postponed?
|
|
245
|
+
'Postponed'
|
|
246
|
+
elsif halftime?
|
|
247
|
+
'Halftime'
|
|
248
|
+
else
|
|
249
|
+
clock_display
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def clock_display
|
|
254
|
+
if clock && quarter
|
|
255
|
+
"#{clock} #{quarter_display}"
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
def quarter_display
|
|
259
|
+
if quarter > 5
|
|
260
|
+
"#{quarter - 4}OT"
|
|
261
|
+
elsif quarter == 5
|
|
262
|
+
'OT'
|
|
263
|
+
else
|
|
264
|
+
"#{quarter}Q"
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def postponed?
|
|
269
|
+
'postponed' == status
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def unnecessary?
|
|
273
|
+
'unnecessary' == status
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def cancelled?
|
|
277
|
+
['unnecessary', 'postponed'].include? status
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def delayed?
|
|
281
|
+
'delayed' == status
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def future?
|
|
285
|
+
['scheduled', 'created', 'time-tbd'].include? status
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def started?
|
|
289
|
+
['inprogress', 'halftime', 'wdelay', 'delayed'].include? status
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def halftime?
|
|
293
|
+
'halftime' == status
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def finished?
|
|
297
|
+
['complete', 'closed'].include? status
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def completed?
|
|
301
|
+
'complete' == status
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def closed?
|
|
305
|
+
'closed' == status
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# url path helpers
|
|
309
|
+
def path_box
|
|
310
|
+
"#{ path_base }/boxscore"
|
|
311
|
+
end
|
|
312
|
+
def path_extended_box
|
|
313
|
+
"#{ path_base }/extended-boxscore"
|
|
314
|
+
end
|
|
315
|
+
def path_pbp
|
|
316
|
+
"#{ path_base }/pbp"
|
|
317
|
+
end
|
|
318
|
+
def path_roster
|
|
319
|
+
"#{ path_base }/roster"
|
|
320
|
+
end
|
|
321
|
+
def path_statistics
|
|
322
|
+
"#{ path_base }/statistics"
|
|
323
|
+
end
|
|
324
|
+
def path_summary
|
|
325
|
+
"#{ path_base }/summary"
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# data retrieval
|
|
329
|
+
|
|
330
|
+
def get_box
|
|
331
|
+
data = api.get_data(path_box).to_h
|
|
332
|
+
ingest_box(data)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def ingest_box(data)
|
|
336
|
+
data = data
|
|
337
|
+
update(data, source: :box)
|
|
338
|
+
check_newness(:box, @clock)
|
|
339
|
+
data
|
|
340
|
+
# rescue => e
|
|
341
|
+
# binding.pry
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def queue_pbp
|
|
345
|
+
url, headers, options, timeout = api.get_request_info(path_pbp)
|
|
346
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_pbp)}
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def get_pbp
|
|
350
|
+
data = api.get_data(path_pbp).to_h
|
|
351
|
+
ingest_pbp(data)
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
def ingest_pbp(data)
|
|
355
|
+
data = data
|
|
356
|
+
update(data, source: :pbp)
|
|
357
|
+
create_data(@quarters_hash, data[period_key], klass: quarter_class, identifier: 'number', api: api, game: self) if data[period_key]
|
|
358
|
+
check_newness(:pbp, plays.last&.description)
|
|
359
|
+
check_newness(:score, @score)
|
|
360
|
+
@pbp = @quarters_hash.values
|
|
361
|
+
data
|
|
362
|
+
# rescue => e
|
|
363
|
+
# binding.pry
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
def period_key
|
|
367
|
+
'quarters'
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def get_statistics
|
|
371
|
+
data = api.get_data(path_statistics).to_h
|
|
372
|
+
ingest_statistics(data)
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def queue_statistics
|
|
376
|
+
url, headers, options, timeout = api.get_request_info(path_statistics)
|
|
377
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_statistics)}
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def ingest_statistics(data)
|
|
381
|
+
update(data, source: :statistics)
|
|
382
|
+
check_newness(:statistics, @clock)
|
|
383
|
+
data
|
|
384
|
+
# rescue => e
|
|
385
|
+
# binding.pry
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def quarter_class
|
|
389
|
+
Sportradar::Api::Football::Quarter
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def team_class
|
|
393
|
+
Team
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def sim!
|
|
397
|
+
@api = api.sim!
|
|
398
|
+
self
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Football
|
|
4
|
+
class GameStats < Data
|
|
5
|
+
attr_accessor :response, :id, :efficiency, :first_downs, :interceptions, :touchdowns, :name, :market, :alias, :reference, :possession_time, :avg_gain, :safeties, :turnovers, :play_count, :rush_plays, :total_yards, :lost_fumbles, :penalty_yards, :return_yards
|
|
6
|
+
|
|
7
|
+
# attr_writer :rushing, :receiving, :punts, :punt_returns, :penalties, :passing, :misc_returns, :kickoffs, :kick_returns, :int_returns, :fumbles, :field_goals, :extra_points, :defense # probably not necessary, but leaving here in case we want it later
|
|
8
|
+
|
|
9
|
+
def initialize(data)
|
|
10
|
+
@response = data
|
|
11
|
+
@id = data["id"]
|
|
12
|
+
@name = data["name"]
|
|
13
|
+
@market = data["market"]
|
|
14
|
+
@alias = data["alias"]
|
|
15
|
+
@reference = data["reference"]
|
|
16
|
+
@efficiency = data["efficiency"]
|
|
17
|
+
@first_downs = data["first_downs"]
|
|
18
|
+
@interceptions = data["interceptions"]
|
|
19
|
+
@touchdowns = data["touchdowns"]
|
|
20
|
+
@possession_time = data.dig('summary', "possession_time")
|
|
21
|
+
@avg_gain = data.dig('summary', "avg_gain")
|
|
22
|
+
@safeties = data.dig('summary', "safeties")
|
|
23
|
+
@turnovers = data.dig('summary', "turnovers")
|
|
24
|
+
@play_count = data.dig('summary', "play_count")
|
|
25
|
+
@rush_plays = data.dig('summary', "rush_plays")
|
|
26
|
+
@total_yards = data.dig('summary', "total_yards")
|
|
27
|
+
@lost_fumbles = data.dig('summary', "lost_fumbles")
|
|
28
|
+
@penalty_yards = data.dig('summary', "penalty_yards")
|
|
29
|
+
@return_yards = data.dig('summary', "return_yards")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# :skip_test_coverage:
|
|
33
|
+
# These are in methods rather than attributes to use them lazily. Each one is tested in it's respective class
|
|
34
|
+
def rushing
|
|
35
|
+
@rushing ||= if response["rushing"]
|
|
36
|
+
response["rushing"] = parse_out_hashes response["rushing"]
|
|
37
|
+
Sportradar::Api::Football::StatPack::Rushing.new(response["rushing"])
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def receiving
|
|
42
|
+
@receiving ||= if response["receiving"]
|
|
43
|
+
response["receiving"] = parse_out_hashes response["receiving"]
|
|
44
|
+
Sportradar::Api::Football::StatPack::Receiving.new(response["receiving"])
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def punts
|
|
49
|
+
@punts ||= if (data = response["punts"] || response["punting"])
|
|
50
|
+
data = parse_out_hashes data
|
|
51
|
+
Sportradar::Api::Football::StatPack::Punts.new(data)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def punt_returns
|
|
56
|
+
@punt_returns ||= if (data = response["punt_returns"] || response["punt_return"])
|
|
57
|
+
data = parse_out_hashes data
|
|
58
|
+
Sportradar::Api::Football::StatPack::PuntReturns.new(data)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def penalties
|
|
63
|
+
@penalties ||= if (data = response["penalties"] || response["penalty"])
|
|
64
|
+
data = parse_out_hashes data
|
|
65
|
+
Sportradar::Api::Football::StatPack::Penalties.new(data)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def passing
|
|
70
|
+
@passing ||= if response["passing"]
|
|
71
|
+
response["passing"] = parse_out_hashes response["passing"]
|
|
72
|
+
Sportradar::Api::Football::StatPack::Passing.new(response["passing"])
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def misc_returns
|
|
77
|
+
@misc_returns ||= if response["misc_returns"]
|
|
78
|
+
response["misc_returns"] = parse_out_hashes response["misc_returns"]
|
|
79
|
+
Sportradar::Api::Football::StatPack::MiscReturns.new(response["misc_returns"])
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def kickoffs
|
|
84
|
+
@kickoffs ||= if response["kickoffs"]
|
|
85
|
+
response["kickoffs"] = parse_out_hashes response["kickoffs"]
|
|
86
|
+
Sportradar::Api::Football::StatPack::Kickoffs.new(response["kickoffs"])
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def kick_returns
|
|
91
|
+
@kick_returns ||= if (data = response["kick_returns"] || response["kick_return"])
|
|
92
|
+
data = parse_out_hashes data
|
|
93
|
+
Sportradar::Api::Football::StatPack::KickReturns.new(data)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def int_returns
|
|
98
|
+
@int_returns ||= if response["int_returns"]
|
|
99
|
+
response["int_returns"] = parse_out_hashes response["int_returns"]
|
|
100
|
+
Sportradar::Api::Football::StatPack::IntReturns.new(response["int_returns"])
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def fumbles
|
|
105
|
+
@fumbles ||= if response["fumbles"]
|
|
106
|
+
response["fumbles"] = parse_out_hashes response["fumbles"]
|
|
107
|
+
Sportradar::Api::Football::StatPack::Fumbles.new(response["fumbles"])
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def field_goals
|
|
112
|
+
@field_goals ||= if (data = response["field_goals"] || response["field_goal"])
|
|
113
|
+
data = parse_out_hashes data
|
|
114
|
+
Sportradar::Api::Football::StatPack::FieldGoals.new(data)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def extra_points
|
|
119
|
+
@extra_points ||= if (data = response["extra_points"] || response["extra_point"])
|
|
120
|
+
data = parse_out_hashes data
|
|
121
|
+
Sportradar::Api::Football::StatPack::ExtraPoints.new(data)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def defense
|
|
126
|
+
@defense ||= if response["defense"]
|
|
127
|
+
response["defense"] = parse_out_hashes response["defense"]
|
|
128
|
+
Sportradar::Api::Football::StatPack::Defense.new(response["defense"])
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
# :skip_test_coverage:
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Football
|
|
4
|
+
class Ncaafb
|
|
5
|
+
class Api < Request
|
|
6
|
+
attr_accessor :league, :access_level, :error
|
|
7
|
+
|
|
8
|
+
def initialize(access_level = default_access_level)
|
|
9
|
+
@league = 'ncaafb'
|
|
10
|
+
raise ::Sportradar::Api::Error::InvalidAccessLevel unless allowed_access_levels.include? access_level
|
|
11
|
+
@access_level = access_level
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def sim!
|
|
15
|
+
@access_level = "sim-#{default_access_level}"
|
|
16
|
+
self
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def default_year
|
|
20
|
+
default_date.year
|
|
21
|
+
end
|
|
22
|
+
def default_date
|
|
23
|
+
Date.today - 90
|
|
24
|
+
end
|
|
25
|
+
def default_season
|
|
26
|
+
'reg'
|
|
27
|
+
end
|
|
28
|
+
def default_access_level
|
|
29
|
+
if (ENV['SPORTRADAR_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV']) == 'production'
|
|
30
|
+
ENV['SPORTRADAR_ACCESS_NCAAFB'] || 'rt'
|
|
31
|
+
else
|
|
32
|
+
't'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def content_format
|
|
39
|
+
'json'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def request_url(path)
|
|
43
|
+
"/ncaafb-#{access_level}#{version}/#{path}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def api_key
|
|
47
|
+
if !['t', 'sim-t'].include?(access_level)
|
|
48
|
+
::Sportradar::Api.api_key_params('ncaafb', 'production')
|
|
49
|
+
else
|
|
50
|
+
::Sportradar::Api.api_key_params('ncaafb')
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def version
|
|
55
|
+
::Sportradar::Api.version('ncaafb')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def allowed_access_levels
|
|
59
|
+
%w[rt p s b t sim-t]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def allowed_seasons
|
|
63
|
+
["pre", "reg", "pst"]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
__END__
|
|
73
|
+
|
|
74
|
+
ncaafb = Sportradar::Api::Ncaafb.new
|
|
75
|
+
sw = ncaafb.weekly_schedule;
|
|
76
|
+
ss = ncaafb.schedule;
|
|
77
|
+
|
|
78
|
+
ss.games.count
|
|
79
|
+
ss.weeks.count
|
|
80
|
+
ss.weeks.first.response['game'].count
|
|
81
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Sportradar
|
|
2
|
+
module Api
|
|
3
|
+
module Football
|
|
4
|
+
class Ncaafb
|
|
5
|
+
class Conference < Data
|
|
6
|
+
attr_accessor :response, :id, :name, :alias
|
|
7
|
+
|
|
8
|
+
def initialize(data, **opts)
|
|
9
|
+
@response = data
|
|
10
|
+
@api = opts[:api]
|
|
11
|
+
|
|
12
|
+
@id = data["id"]
|
|
13
|
+
@name = data["name"]
|
|
14
|
+
@alias = data["alias"] || data["id"]
|
|
15
|
+
@teams_hash = {}
|
|
16
|
+
@subdivisions_hash = {}
|
|
17
|
+
@assigned_teams = nil
|
|
18
|
+
# binding.pry
|
|
19
|
+
|
|
20
|
+
create_data(@teams_hash, data["teams"], klass: Team, conference: self, api: @api) if data["teams"]
|
|
21
|
+
create_data(@subdivisions_hash, data["subdivisions"], klass: Subdivision, conference: self, api: @api) if data["subdivisions"]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def teams
|
|
25
|
+
@assigned_teams || begin
|
|
26
|
+
if !@subdivisions_hash.empty?
|
|
27
|
+
@subdivisions_hash.each_value.flat_map(&:teams)
|
|
28
|
+
elsif !@teams_hash.empty?
|
|
29
|
+
@teams_hash.values
|
|
30
|
+
else
|
|
31
|
+
[]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
def teams=(array)
|
|
36
|
+
@assigned_teams = array
|
|
37
|
+
end
|
|
38
|
+
def team(code_name)
|
|
39
|
+
teams_by_name[code_name]
|
|
40
|
+
end
|
|
41
|
+
private def teams_by_name
|
|
42
|
+
@teams_by_name ||= teams.map { |t| [t.alias, t] }.to_h
|
|
43
|
+
end
|
|
44
|
+
def conferences
|
|
45
|
+
teams.flat_map(&:conferences)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|