sportradar-api 0.10.55 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +28 -26
- data/README.md +7 -6
- data/lib/sportradar/api/baseball/{REAME.md → README.md} +0 -0
- data/lib/sportradar/api/baseball/game.rb +29 -2
- data/lib/sportradar/api/baseball/mlb/hierarchy.rb +1 -0
- data/lib/sportradar/api/baseball/record.rb +0 -4
- data/lib/sportradar/api/baseball/venue.rb +2 -1
- data/lib/sportradar/api/basketball/game.rb +2 -2
- data/lib/sportradar/api/basketball/record.rb +0 -4
- data/lib/sportradar/api/basketball/venue.rb +2 -1
- data/lib/sportradar/api/data.rb +3 -3
- data/lib/sportradar/api/football/README.md +62 -0
- data/lib/sportradar/api/football/drive.rb +105 -0
- data/lib/sportradar/api/football/event.rb +33 -0
- data/lib/sportradar/api/football/game.rb +389 -0
- data/lib/sportradar/api/football/game_stats.rb +135 -0
- data/lib/sportradar/api/football/ncaafb/api.rb +76 -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 +16 -0
- data/lib/sportradar/api/football/ncaafb/game.rb +110 -0
- data/lib/sportradar/api/football/ncaafb/play.rb +20 -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 +45 -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/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/play.rb +20 -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/week.rb +24 -0
- data/lib/sportradar/api/football/nfl.rb +293 -0
- data/lib/sportradar/api/football/play.rb +93 -0
- data/lib/sportradar/api/football/player.rb +111 -0
- data/lib/sportradar/api/football/quarter.rb +42 -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 +20 -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 +43 -0
- data/lib/sportradar/api/mma/venue.rb +1 -1
- data/lib/sportradar/api/request.rb +19 -2
- data/lib/sportradar/api/version.rb +1 -1
- data/lib/sportradar/api.rb +0 -41
- metadata +41 -43
- data/lib/sportradar/api/ncaafb/drive.rb +0 -89
- data/lib/sportradar/api/ncaafb/game.rb +0 -161
- data/lib/sportradar/api/ncaafb/play.rb +0 -39
- data/lib/sportradar/api/ncaafb/player.rb +0 -61
- data/lib/sportradar/api/ncaafb/quarter.rb +0 -37
- data/lib/sportradar/api/ncaafb/season.rb +0 -71
- data/lib/sportradar/api/ncaafb/team.rb +0 -69
- data/lib/sportradar/api/ncaafb/week.rb +0 -33
- data/lib/sportradar/api/ncaafb.rb +0 -185
- data/lib/sportradar/api/nfl/.play_statistics.rb.swo +0 -0
- data/lib/sportradar/api/nfl/broadcast.rb +0 -13
- 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 -17
- 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 -123
- 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 -249
- data/lib/sportradar/api/nfl/player.rb +0 -56
- 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 -211
@@ -0,0 +1,389 @@
|
|
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 summary_stat(team_id, stat_name)
|
36
|
+
scoring.dig(team_id, stat_name)
|
37
|
+
end
|
38
|
+
def stats(team_id)
|
39
|
+
team_id.is_a?(Symbol) ? @team_stats[@team_ids[team_id]] : @team_stats[team_id]
|
40
|
+
end
|
41
|
+
|
42
|
+
def update_stats(team, stats)
|
43
|
+
@team_stats.merge!(team.id => stats)
|
44
|
+
end
|
45
|
+
def update_player_stats(player, stats)
|
46
|
+
@player_stats.merge!(player.id => stats.merge!(player: player))
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse_score(data)
|
50
|
+
# home_id = data.dig('home', 'id')
|
51
|
+
# away_id = data.dig('away', 'id')
|
52
|
+
# rhe = {
|
53
|
+
# 'runs' => { home_id => data.dig('home', 'runs'), away_id => data.dig('away', 'runs')},
|
54
|
+
# 'hits' => { home_id => data.dig('home', 'hits'), away_id => data.dig('away', 'hits')},
|
55
|
+
# 'errors' => { home_id => data.dig('home', 'errors'), away_id => data.dig('away', 'errors')},
|
56
|
+
# }
|
57
|
+
# @scoring_raw.update(rhe, source: :rhe)
|
58
|
+
# update_score(home_id => data.dig('home', 'runs'))
|
59
|
+
# update_score(away_id => data.dig('away', 'runs'))
|
60
|
+
end
|
61
|
+
|
62
|
+
def update(data, source: nil, **opts)
|
63
|
+
@id = data['id'] || @id
|
64
|
+
# @year = data['year'] || @week&.season.year
|
65
|
+
# @type = data['type'] || @week&.season.type
|
66
|
+
# @week_number = data['week'] || @week&.sequence
|
67
|
+
|
68
|
+
@week_number = data['week_number'] || week&.number || opts[:week]&.number || @week_number
|
69
|
+
@year = data['year'] || week&.year || opts[:week]&.year || @year
|
70
|
+
@type = data['type'] || week&.type || opts[:week]&.type || @type
|
71
|
+
|
72
|
+
|
73
|
+
@coverage = data['coverage']
|
74
|
+
@scheduled = Time.parse(data["scheduled"]) if data["scheduled"]
|
75
|
+
update_teams(data)
|
76
|
+
@status = data['status'] || @status
|
77
|
+
@clock = data['clock'] || @clock
|
78
|
+
@quarter = data['quarter'] || @quarter
|
79
|
+
@home_rotation = data['home_rotation']
|
80
|
+
@away_rotation = data['away_rotation']
|
81
|
+
@neutral_site = data['neutral_site']
|
82
|
+
@home_points = data['home_points']
|
83
|
+
@away_points = data['away_points']
|
84
|
+
@venue = Venue.new(data["venue"]) if data["venue"]
|
85
|
+
@weather = data['weather']
|
86
|
+
@broadcast = Broadcast.new(data['broadcast']) if !data['broadcast'].to_h.empty?
|
87
|
+
@attendance = data['attendance']
|
88
|
+
@title = data['title'] || @title || generate_title
|
89
|
+
|
90
|
+
# @links = data['links'] ? structure_links(data['links']) : {}
|
91
|
+
|
92
|
+
@teams_hash = { @home.id => @home, @away.id => @away } if @home && @away
|
93
|
+
@team_ids = { home: (@home&.id || home_alias), away: (@away&.id || away_alias) }
|
94
|
+
|
95
|
+
@scoring_raw.update(data, source: source)
|
96
|
+
if data['statistics']
|
97
|
+
@home.update({ 'statistics' => data.dig('statistics', 'home')}, game: self)
|
98
|
+
@away.update({ 'statistics' => data.dig('statistics', 'away')}, game: self)
|
99
|
+
end
|
100
|
+
|
101
|
+
create_data(@teams_hash, data['team'], klass: team_class, api: api, game: self) if data['team']
|
102
|
+
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
def generate_title
|
107
|
+
(home && away && "#{home.full_name} vs #{away.full_name}")
|
108
|
+
end
|
109
|
+
|
110
|
+
def update_teams(data)
|
111
|
+
if data['summary']
|
112
|
+
@home.update(data.dig('summary', 'home'), game: self)
|
113
|
+
@away.update(data.dig('summary', 'away'), game: self)
|
114
|
+
else
|
115
|
+
@home.update(data['home_team'], game: self) if data['home_team'].is_a?(Hash)
|
116
|
+
@away.update(data['away_team'], game: self) if data['away_team'].is_a?(Hash)
|
117
|
+
@home_alias = data['home'] if data['home'].is_a?(String) # this might actually be team ID and not alias. check in NFL
|
118
|
+
@away_alias = data['away'] if data['away'].is_a?(String) # this might actually be team ID and not alias. check in NFL
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# def update_from_team(id, data)
|
123
|
+
# end
|
124
|
+
|
125
|
+
def home
|
126
|
+
@teams_hash[@home_id] || @home
|
127
|
+
end
|
128
|
+
|
129
|
+
def home_alias
|
130
|
+
@home_alias || @home&.alias
|
131
|
+
end
|
132
|
+
|
133
|
+
def away
|
134
|
+
@teams_hash[@away_id] || @away
|
135
|
+
end
|
136
|
+
|
137
|
+
def away_alias
|
138
|
+
@away_alias || @away&.alias
|
139
|
+
end
|
140
|
+
|
141
|
+
def tied?
|
142
|
+
@score[away_id].to_i == @score[home_id].to_i
|
143
|
+
end
|
144
|
+
def scoring
|
145
|
+
@scoring_raw.scores
|
146
|
+
end
|
147
|
+
def update_score(score)
|
148
|
+
@score.merge!(score)
|
149
|
+
end
|
150
|
+
|
151
|
+
def leading_team_id
|
152
|
+
return nil if tied?
|
153
|
+
score.max_by(&:last).first
|
154
|
+
end
|
155
|
+
|
156
|
+
def leading_team
|
157
|
+
@teams_hash[leading_team_id] || (@away_id == leading_team_id && away) || (@home_id == leading_team_id && home)
|
158
|
+
end
|
159
|
+
|
160
|
+
def team(team_id)
|
161
|
+
@teams_hash[team_id]
|
162
|
+
end
|
163
|
+
|
164
|
+
def assign_home(team)
|
165
|
+
@home_id = team.id
|
166
|
+
@teams_hash[team.id] = team
|
167
|
+
end
|
168
|
+
|
169
|
+
def assign_away(team)
|
170
|
+
@away_id = team.id
|
171
|
+
@teams_hash[team.id] = team
|
172
|
+
end
|
173
|
+
|
174
|
+
def box
|
175
|
+
@box ||= get_box
|
176
|
+
end
|
177
|
+
|
178
|
+
def pbp
|
179
|
+
if !future? && quarters.empty?
|
180
|
+
get_pbp
|
181
|
+
end
|
182
|
+
@pbp ||= quarters
|
183
|
+
end
|
184
|
+
|
185
|
+
def drives
|
186
|
+
quarters.flat_map(&:drives).compact
|
187
|
+
end
|
188
|
+
|
189
|
+
def plays
|
190
|
+
drives.flat_map(&:plays).compact
|
191
|
+
end
|
192
|
+
|
193
|
+
def events
|
194
|
+
drives.flat_map(&:events).compact
|
195
|
+
end
|
196
|
+
|
197
|
+
# def summary
|
198
|
+
# @summary ||= get_summary
|
199
|
+
# end
|
200
|
+
|
201
|
+
def quarters
|
202
|
+
@quarters_hash.values
|
203
|
+
end
|
204
|
+
def half_quarters
|
205
|
+
quarters.flat_map(&:half_quarters)
|
206
|
+
end
|
207
|
+
|
208
|
+
# tracking updates
|
209
|
+
def remember(key, object)
|
210
|
+
@updates[key] = object&.dup
|
211
|
+
end
|
212
|
+
|
213
|
+
def not_updated?(key, object)
|
214
|
+
@updates[key] == object
|
215
|
+
end
|
216
|
+
|
217
|
+
def changed?(key)
|
218
|
+
@changes[key]
|
219
|
+
end
|
220
|
+
|
221
|
+
def check_newness(key, new_object)
|
222
|
+
@changes[key] = !not_updated?(key, new_object)
|
223
|
+
remember(key, new_object)
|
224
|
+
end
|
225
|
+
|
226
|
+
# status helpers
|
227
|
+
def realtime_state
|
228
|
+
if future?
|
229
|
+
'Scheduled'
|
230
|
+
elsif delayed?
|
231
|
+
'Delayed'
|
232
|
+
elsif finished?
|
233
|
+
'Final'
|
234
|
+
elsif postponed?
|
235
|
+
'Postponed'
|
236
|
+
elsif halftime?
|
237
|
+
'Halftime'
|
238
|
+
else
|
239
|
+
clock_display
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def clock_display
|
244
|
+
if clock && quarter
|
245
|
+
"#{clock} #{quarter_display}"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
def quarter_display
|
249
|
+
if quarter > 5
|
250
|
+
"#{quarter - 4}OT"
|
251
|
+
elsif quarter == 5
|
252
|
+
'OT'
|
253
|
+
else
|
254
|
+
"Q#{quarter}"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def postponed?
|
259
|
+
'postponed' == status
|
260
|
+
end
|
261
|
+
|
262
|
+
def unnecessary?
|
263
|
+
'unnecessary' == status
|
264
|
+
end
|
265
|
+
|
266
|
+
def cancelled?
|
267
|
+
['unnecessary', 'postponed'].include? status
|
268
|
+
end
|
269
|
+
|
270
|
+
def delayed?
|
271
|
+
'delayed' == status
|
272
|
+
end
|
273
|
+
|
274
|
+
def future?
|
275
|
+
['scheduled', 'created', 'time-tbd'].include? status
|
276
|
+
end
|
277
|
+
|
278
|
+
def started?
|
279
|
+
['inprogress', 'halftime', 'wdelay', 'delayed'].include? status
|
280
|
+
end
|
281
|
+
|
282
|
+
def halftime?
|
283
|
+
'halftime' == status
|
284
|
+
end
|
285
|
+
|
286
|
+
def finished?
|
287
|
+
['complete', 'closed'].include? status
|
288
|
+
end
|
289
|
+
|
290
|
+
def completed?
|
291
|
+
'complete' == status
|
292
|
+
end
|
293
|
+
|
294
|
+
def closed?
|
295
|
+
'closed' == status
|
296
|
+
end
|
297
|
+
|
298
|
+
# url path helpers
|
299
|
+
def path_box
|
300
|
+
"#{ path_base }/boxscore"
|
301
|
+
end
|
302
|
+
def path_extended_box
|
303
|
+
"#{ path_base }/extended-boxscore"
|
304
|
+
end
|
305
|
+
def path_pbp
|
306
|
+
"#{ path_base }/pbp"
|
307
|
+
end
|
308
|
+
def path_roster
|
309
|
+
"#{ path_base }/roster"
|
310
|
+
end
|
311
|
+
def path_statistics
|
312
|
+
"#{ path_base }/statistics"
|
313
|
+
end
|
314
|
+
def path_summary
|
315
|
+
"#{ path_base }/summary"
|
316
|
+
end
|
317
|
+
|
318
|
+
# data retrieval
|
319
|
+
|
320
|
+
def get_box
|
321
|
+
data = api.get_data(path_box).to_h
|
322
|
+
ingest_box(data)
|
323
|
+
end
|
324
|
+
|
325
|
+
def ingest_box(data)
|
326
|
+
data = data
|
327
|
+
update(data, source: :box)
|
328
|
+
check_newness(:box, @clock)
|
329
|
+
data
|
330
|
+
# rescue => e
|
331
|
+
# binding.pry
|
332
|
+
end
|
333
|
+
|
334
|
+
def queue_pbp
|
335
|
+
url, headers, options, timeout = api.get_request_info(path_pbp)
|
336
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_pbp)}
|
337
|
+
end
|
338
|
+
|
339
|
+
def get_pbp
|
340
|
+
data = api.get_data(path_pbp).to_h
|
341
|
+
ingest_pbp(data)
|
342
|
+
end
|
343
|
+
|
344
|
+
def ingest_pbp(data)
|
345
|
+
data = data
|
346
|
+
update(data, source: :pbp)
|
347
|
+
create_data(@quarters_hash, data[period_key], klass: quarter_class, identifier: 'number', api: api, game: self) if data[period_key]
|
348
|
+
check_newness(:pbp, plays.last&.description)
|
349
|
+
check_newness(:score, @score)
|
350
|
+
@pbp = @quarters_hash.values
|
351
|
+
data
|
352
|
+
# rescue => e
|
353
|
+
# binding.pry
|
354
|
+
end
|
355
|
+
|
356
|
+
def period_key
|
357
|
+
'quarters'
|
358
|
+
end
|
359
|
+
|
360
|
+
def get_statistics
|
361
|
+
data = api.get_data(path_statistics).to_h
|
362
|
+
ingest_statistics(data)
|
363
|
+
end
|
364
|
+
|
365
|
+
def queue_statistics
|
366
|
+
url, headers, options, timeout = api.get_request_info(path_statistics)
|
367
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_statistics)}
|
368
|
+
end
|
369
|
+
|
370
|
+
def ingest_statistics(data)
|
371
|
+
update(data, source: :statistics)
|
372
|
+
check_newness(:statistics, @clock)
|
373
|
+
data
|
374
|
+
# rescue => e
|
375
|
+
# binding.pry
|
376
|
+
end
|
377
|
+
|
378
|
+
def quarter_class
|
379
|
+
Sportradar::Api::Football::Quarter
|
380
|
+
end
|
381
|
+
|
382
|
+
def team_class
|
383
|
+
Team
|
384
|
+
end
|
385
|
+
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
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["possession_time"]
|
21
|
+
@avg_gain = data["avg_gain"]
|
22
|
+
@safeties = data["safeties"]
|
23
|
+
@turnovers = data["turnovers"]
|
24
|
+
@play_count = data["play_count"]
|
25
|
+
@rush_plays = data["rush_plays"]
|
26
|
+
@total_yards = data["total_yards"]
|
27
|
+
@lost_fumbles = data["lost_fumbles"]
|
28
|
+
@penalty_yards = data["penalty_yards"]
|
29
|
+
@return_yards = data["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,76 @@
|
|
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 = 't')
|
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 default_year
|
15
|
+
default_date.year
|
16
|
+
end
|
17
|
+
def default_date
|
18
|
+
Date.today - 90
|
19
|
+
end
|
20
|
+
def default_season
|
21
|
+
'reg'
|
22
|
+
end
|
23
|
+
def default_access_level
|
24
|
+
if (ENV['SPORTRADAR_ENV'] || ENV['SPORTRADAR_ENV_MLB'] || ENV['RACK_ENV'] || ENV['RAILS_ENV']) == 'production'
|
25
|
+
'p'
|
26
|
+
else
|
27
|
+
't'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def content_format
|
34
|
+
'json'
|
35
|
+
end
|
36
|
+
|
37
|
+
def request_url(path)
|
38
|
+
"/ncaafb-#{access_level}#{version}/#{path}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def api_key
|
42
|
+
if !['t', 'sim-t'].include?(access_level)
|
43
|
+
::Sportradar::Api.api_key_params('ncaafb', 'production')
|
44
|
+
else
|
45
|
+
::Sportradar::Api.api_key_params('ncaafb')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def version
|
50
|
+
::Sportradar::Api.version('ncaafb')
|
51
|
+
end
|
52
|
+
|
53
|
+
def allowed_access_levels
|
54
|
+
%w[rt p s b t sim-t]
|
55
|
+
end
|
56
|
+
|
57
|
+
def allowed_seasons
|
58
|
+
["pre", "reg", "pst"]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
__END__
|
68
|
+
|
69
|
+
ncaafb = Sportradar::Api::Ncaafb.new
|
70
|
+
sw = ncaafb.weekly_schedule;
|
71
|
+
ss = ncaafb.schedule;
|
72
|
+
|
73
|
+
ss.games.count
|
74
|
+
ss.weeks.count
|
75
|
+
ss.weeks.first.response['game'].count
|
76
|
+
|
@@ -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"]
|
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
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Api
|
3
|
+
module Football
|
4
|
+
class Ncaafb
|
5
|
+
class Division < 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"]
|
15
|
+
update(data, **opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
def update(data, **opts)
|
19
|
+
@conferences_hash = create_data({}, data["conferences"], klass: Conference, division: self, api: @api) if data["conferences"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def conferences
|
23
|
+
@conferences_hash.values
|
24
|
+
end
|
25
|
+
|
26
|
+
def conference(code_name)
|
27
|
+
conferences_by_name[code_name]
|
28
|
+
end
|
29
|
+
|
30
|
+
def conferences_by_name
|
31
|
+
@conferences_by_name ||= conferences.map { |c| [c.alias, c] }.to_h
|
32
|
+
end
|
33
|
+
|
34
|
+
def teams
|
35
|
+
conferences.flat_map(&:teams)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|