sportradar-api 0.10.13 → 0.10.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/sportradar/api/baseball/REAME.md +3 -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 +49 -0
- data/lib/sportradar/api/baseball/events/lineup.rb +36 -0
- data/lib/sportradar/api/baseball/events/warming_up.rb +32 -0
- data/lib/sportradar/api/baseball/fielder.rb +26 -0
- data/lib/sportradar/api/baseball/game.rb +385 -0
- data/lib/sportradar/api/baseball/half_inning.rb +54 -0
- data/lib/sportradar/api/baseball/inning.rb +42 -0
- data/lib/sportradar/api/baseball/mlb/division.rb +32 -0
- data/lib/sportradar/api/baseball/mlb/hierarchy.rb +267 -0
- data/lib/sportradar/api/baseball/mlb/league.rb +27 -0
- data/lib/sportradar/api/baseball/mlb.rb +87 -0
- data/lib/sportradar/api/baseball/outcome.rb +87 -0
- data/lib/sportradar/api/baseball/pitch.rb +111 -0
- data/lib/sportradar/api/baseball/player.rb +119 -0
- data/lib/sportradar/api/baseball/record.rb +46 -0
- data/lib/sportradar/api/baseball/runner.rb +30 -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 +50 -0
- data/lib/sportradar/api/baseball.rb +45 -0
- data/lib/sportradar/api/broadcast.rb +13 -0
- data/lib/sportradar/api/data.rb +1 -1
- data/lib/sportradar/api/version.rb +1 -1
- data/lib/sportradar/api.rb +4 -1
- metadata +27 -3
@@ -0,0 +1,54 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Api
|
3
|
+
module Baseball
|
4
|
+
class HalfInning < Data
|
5
|
+
attr_accessor :response, :id, :inning, :type, :half, :number
|
6
|
+
|
7
|
+
def initialize(data, **opts)
|
8
|
+
@response = data
|
9
|
+
@api = opts[:api]
|
10
|
+
@inning = opts[:inning]
|
11
|
+
@id = data["id"]
|
12
|
+
*@inning_id, @number, @half = data['id'].split('-')
|
13
|
+
|
14
|
+
@events_hash = {}
|
15
|
+
|
16
|
+
update(data)
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def update(data, **opts)
|
21
|
+
@half = data['half']
|
22
|
+
@events = data['events'].map{ |hash| Event.new(hash, half_inning: self) }
|
23
|
+
# create_data(@events_hash, data['events'], klass: Event, api: @api, half_inning: self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def over?
|
27
|
+
pitches.last.count&.dig('outs') == 3
|
28
|
+
end
|
29
|
+
|
30
|
+
def pitches
|
31
|
+
at_bats.flat_map(&:pitches)
|
32
|
+
end
|
33
|
+
|
34
|
+
def at_bats
|
35
|
+
events.map(&:at_bat).compact
|
36
|
+
end
|
37
|
+
|
38
|
+
def lineup_changes
|
39
|
+
# events_by_klass(LineupChange)
|
40
|
+
end
|
41
|
+
|
42
|
+
def events
|
43
|
+
# @events_hash.values
|
44
|
+
@events
|
45
|
+
end
|
46
|
+
|
47
|
+
# private def events_by_klass(klass)
|
48
|
+
# @events_hash.each_value.grep(klass)
|
49
|
+
# end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Api
|
3
|
+
module Baseball
|
4
|
+
class Inning < Data
|
5
|
+
attr_accessor :response, :id, :game, :number, :sequence, :scoring
|
6
|
+
|
7
|
+
def initialize(data, **opts)
|
8
|
+
@response = data
|
9
|
+
@api = opts[:api]
|
10
|
+
@game = opts[:game]
|
11
|
+
|
12
|
+
@id = data["id"]
|
13
|
+
@number = data['number']
|
14
|
+
@sequence = data['sequence']
|
15
|
+
|
16
|
+
parse_scoring(data['scoring']) if data['scoring']
|
17
|
+
|
18
|
+
@half_innings_hash = {}
|
19
|
+
|
20
|
+
update(data)
|
21
|
+
end
|
22
|
+
def update(data, **opts)
|
23
|
+
# update scoring
|
24
|
+
halfs = data['halfs'].each { |inning| inning['id'] = "#{data['id']}-#{inning['half']}" }
|
25
|
+
create_data(@half_innings_hash, halfs, klass: HalfInning, api: @api, inning: self)
|
26
|
+
end
|
27
|
+
def parse_scoring(data)
|
28
|
+
@scoring = data.each_with_object({}) { |(_, data), hash| hash[data['id']] = data['runs'].to_s } # from PBP
|
29
|
+
end
|
30
|
+
|
31
|
+
def half_innings
|
32
|
+
@half_innings_hash.values
|
33
|
+
end
|
34
|
+
|
35
|
+
def events
|
36
|
+
half_innings.flat_map(&:events)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Api
|
3
|
+
module Baseball
|
4
|
+
class Mlb
|
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
|
+
@assigned_teams = nil
|
16
|
+
@teams_hash = {}
|
17
|
+
@teams_hash = create_data({}, data["teams"], klass: Team, division: self, api: @api) if response["teams"]
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def teams
|
22
|
+
@assigned_teams || @teams_hash.values
|
23
|
+
end
|
24
|
+
def teams=(array)
|
25
|
+
@assigned_teams = array
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,267 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Api
|
3
|
+
module Baseball
|
4
|
+
class Mlb
|
5
|
+
class Hierarchy < Data
|
6
|
+
attr_accessor :response, :id, :name, :alias, :year, :type
|
7
|
+
def all_attributes
|
8
|
+
[:name, :alias, :leagues, :divisions, :teams]
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(data = {}, **opts)
|
12
|
+
# @response = data
|
13
|
+
@api = opts[:api]
|
14
|
+
@id = data.dig('league', 'id')
|
15
|
+
|
16
|
+
@leagues_hash = {}
|
17
|
+
@games_hash = {}
|
18
|
+
@teams_hash = {}
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def update(data, source: nil, **opts)
|
23
|
+
# update stuff
|
24
|
+
@name = data.dig('league', 'name') if data.dig('league', 'name')
|
25
|
+
@alias = data.dig('league', 'alias') if data.dig('league', 'alias')
|
26
|
+
|
27
|
+
@year = data.dig('season', 'year') if data.dig('season', 'year')
|
28
|
+
@type = data.dig('season', 'type') if data.dig('season', 'type')
|
29
|
+
|
30
|
+
@leagues_hash = create_data({}, data['leagues'], klass: League, hierarchy: self, api: api) if data['leagues']
|
31
|
+
@teams_hash = create_data({}, data['teams'], klass: Team, hierarchy: self, api: api) if data['teams']
|
32
|
+
if data['games']
|
33
|
+
if data['games'].first.keys == ['game']
|
34
|
+
data['games'].map! { |hash| hash['game'] }
|
35
|
+
end
|
36
|
+
@games_hash = create_data({}, data['games'], klass: Game, hierarchy: self, api: api)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def schedule
|
41
|
+
get_schedule if games.empty?
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def standings
|
46
|
+
get_standings if teams.first&.record.nil?
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def daily_schedule
|
51
|
+
# TODO
|
52
|
+
end
|
53
|
+
|
54
|
+
def games
|
55
|
+
@games_hash.values
|
56
|
+
end
|
57
|
+
|
58
|
+
def leagues
|
59
|
+
@leagues_hash.values
|
60
|
+
end
|
61
|
+
def divisions
|
62
|
+
leagues.flat_map(&:divisions)
|
63
|
+
end
|
64
|
+
def teams
|
65
|
+
teams = divisions.flat_map(&:teams)
|
66
|
+
if teams.empty?
|
67
|
+
if @teams_hash.empty?
|
68
|
+
get_hierarchy
|
69
|
+
divisions.flat_map(&:teams)
|
70
|
+
else
|
71
|
+
@teams_hash.values
|
72
|
+
end
|
73
|
+
else
|
74
|
+
teams
|
75
|
+
end
|
76
|
+
end
|
77
|
+
def team(team_id)
|
78
|
+
teams.detect { |team| team.id == team_id }
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
# api stuff
|
84
|
+
def api
|
85
|
+
@api || Sportradar::Api::Baseball::Mlb.new
|
86
|
+
end
|
87
|
+
|
88
|
+
def default_year
|
89
|
+
Date.today.year
|
90
|
+
end
|
91
|
+
def default_date
|
92
|
+
Date.today
|
93
|
+
end
|
94
|
+
def default_season
|
95
|
+
'reg'
|
96
|
+
end
|
97
|
+
def season_year
|
98
|
+
@year || default_year
|
99
|
+
end
|
100
|
+
def mlb_season
|
101
|
+
@type || default_season
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# url paths
|
106
|
+
def path_base
|
107
|
+
"league"
|
108
|
+
end
|
109
|
+
def path_schedule
|
110
|
+
"games/#{season_year}/#{mlb_season}/schedule"
|
111
|
+
end
|
112
|
+
def path_series
|
113
|
+
"series/#{season_year}/#{mlb_season}/schedule"
|
114
|
+
end
|
115
|
+
def path_rankings
|
116
|
+
"seasontd/#{season_year}/#{mlb_season}/rankings"
|
117
|
+
end
|
118
|
+
def path_hierarchy
|
119
|
+
"#{ path_base }/hierarchy"
|
120
|
+
end
|
121
|
+
def path_depth_charts
|
122
|
+
"#{ path_base }/depth_charts"
|
123
|
+
end
|
124
|
+
def path_standings
|
125
|
+
"seasontd/#{season_year}/#{mlb_season}/standings"
|
126
|
+
end
|
127
|
+
def path_daily_summary(date)
|
128
|
+
"games/#{date.year}/#{date.month}/#{date.day}/summary"
|
129
|
+
end
|
130
|
+
def path_daily_boxscore(date)
|
131
|
+
"#{ path_base }/games/#{date.year}/#{date.month}/#{date.day}/boxscore"
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
# data retrieval
|
136
|
+
|
137
|
+
## schedule
|
138
|
+
def get_schedule
|
139
|
+
data = api.get_data(path_schedule).to_h
|
140
|
+
ingest_schedule(data)
|
141
|
+
end
|
142
|
+
|
143
|
+
def ingest_schedule(data)
|
144
|
+
update(data, source: :games)
|
145
|
+
data
|
146
|
+
end
|
147
|
+
|
148
|
+
def queue_schedule
|
149
|
+
url, headers, options, timeout = api.get_request_info(path_schedule)
|
150
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_schedule)}
|
151
|
+
end
|
152
|
+
|
153
|
+
## hierarchy
|
154
|
+
def get_hierarchy
|
155
|
+
data = api.get_data(path_hierarchy).to_h
|
156
|
+
ingest_hierarchy(data)
|
157
|
+
end
|
158
|
+
|
159
|
+
def ingest_hierarchy(data)
|
160
|
+
update(data, source: :teams)
|
161
|
+
data
|
162
|
+
end
|
163
|
+
|
164
|
+
def queue_hierarchy
|
165
|
+
url, headers, options, timeout = api.get_request_info(path_hierarchy)
|
166
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_hierarchy)}
|
167
|
+
end
|
168
|
+
|
169
|
+
## depth_charts
|
170
|
+
def get_depth_charts
|
171
|
+
data = api.get_data(path_depth_charts).to_h
|
172
|
+
ingest_depth_charts(data)
|
173
|
+
end
|
174
|
+
|
175
|
+
def ingest_depth_charts(data)
|
176
|
+
update(data, source: :teams)
|
177
|
+
data
|
178
|
+
end
|
179
|
+
|
180
|
+
def queue_depth_charts
|
181
|
+
url, headers, options, timeout = api.get_request_info(path_depth_charts)
|
182
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_depth_charts)}
|
183
|
+
end
|
184
|
+
|
185
|
+
## standings
|
186
|
+
def get_standings
|
187
|
+
data = api.get_data(path_standings).to_h
|
188
|
+
ingest_standings(data)
|
189
|
+
end
|
190
|
+
|
191
|
+
def ingest_standings(data)
|
192
|
+
update(data.dig('league','season'), source: :teams)
|
193
|
+
data
|
194
|
+
end
|
195
|
+
|
196
|
+
def queue_standings
|
197
|
+
url, headers, options, timeout = api.get_request_info(path_standings)
|
198
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_standings)}
|
199
|
+
end
|
200
|
+
|
201
|
+
## depth_charts
|
202
|
+
def get_depth_charts
|
203
|
+
data = api.get_data(path_depth_charts).to_h
|
204
|
+
ingest_depth_charts(data)
|
205
|
+
end
|
206
|
+
|
207
|
+
def ingest_depth_charts(data)
|
208
|
+
update(data, source: :teams)
|
209
|
+
data
|
210
|
+
end
|
211
|
+
|
212
|
+
def queue_depth_charts
|
213
|
+
url, headers, options, timeout = api.get_request_info(path_depth_charts)
|
214
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_depth_charts)}
|
215
|
+
end
|
216
|
+
|
217
|
+
## daily summary
|
218
|
+
def get_daily_summary(date = Date.today)
|
219
|
+
data = api.get_data(path_daily_summary(date)).to_h
|
220
|
+
ingest_daily_summary(data)
|
221
|
+
end
|
222
|
+
|
223
|
+
def ingest_daily_summary(data)
|
224
|
+
update(data.dig('league'), source: :games)
|
225
|
+
data
|
226
|
+
end
|
227
|
+
|
228
|
+
def queue_daily_summary(date = Date.today)
|
229
|
+
url, headers, options, timeout = api.get_request_info(path_daily_summary(date))
|
230
|
+
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_daily_summary)}
|
231
|
+
end
|
232
|
+
|
233
|
+
## venues
|
234
|
+
# def get_venues
|
235
|
+
# data = api.get_data(path_venues).to_h
|
236
|
+
# ingest_venues(data)
|
237
|
+
# end
|
238
|
+
|
239
|
+
# def ingest_venues(data)
|
240
|
+
# update(data, source: :teams)
|
241
|
+
# data
|
242
|
+
# end
|
243
|
+
|
244
|
+
# def queue_venues
|
245
|
+
# url, headers, options, timeout = api.get_request_info(path_venues)
|
246
|
+
# {url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_venues)}
|
247
|
+
# end
|
248
|
+
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
__END__
|
256
|
+
|
257
|
+
mlb = Sportradar::Api::Baseball::Mlb::Hierarchy.new
|
258
|
+
res = mlb.get_daily_summary;
|
259
|
+
res = mlb.get_hierarchy;
|
260
|
+
t = mlb.teams.first;
|
261
|
+
t.get_season_stats;
|
262
|
+
t.players.sample
|
263
|
+
|
264
|
+
res = mlb.get_schedule;
|
265
|
+
g = mlb.games.sort_by(&:scheduled).first
|
266
|
+
|
267
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Api
|
3
|
+
module Baseball
|
4
|
+
class Mlb
|
5
|
+
class League < 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
|
+
@divisions_hash = create_data({}, data["divisions"], klass: Division, conference: self, api: @api) # if response["division"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def divisions
|
19
|
+
@divisions_hash.values
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Api
|
3
|
+
module Baseball
|
4
|
+
class Mlb < Request
|
5
|
+
attr_accessor :league, :access_level, :simulation, :error
|
6
|
+
|
7
|
+
def initialize(access_level = default_access_level)
|
8
|
+
@league = 'mlb'
|
9
|
+
raise Sportradar::Api::Error::InvalidAccessLevel unless allowed_access_levels.include? access_level
|
10
|
+
@access_level = access_level
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_data(url)
|
14
|
+
data = get request_url(url)
|
15
|
+
if data.is_a?(Sportradar::Api::Error)
|
16
|
+
puts request_url(url)
|
17
|
+
puts
|
18
|
+
puts data.inspect
|
19
|
+
raise 'Sportradar error'
|
20
|
+
end
|
21
|
+
data
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_year
|
25
|
+
Date.today.year
|
26
|
+
end
|
27
|
+
def default_date
|
28
|
+
Date.today
|
29
|
+
end
|
30
|
+
def default_season
|
31
|
+
'reg'
|
32
|
+
end
|
33
|
+
def default_access_level
|
34
|
+
if (ENV['SPORTRADAR_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV']) == 'production'
|
35
|
+
'p'
|
36
|
+
else
|
37
|
+
't'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def league_hierarchy
|
42
|
+
response = get request_url("league/hierarchy")
|
43
|
+
if response.success?
|
44
|
+
Sportradar::Api::Baseball::Mlb::Hierarchy.new(response.to_h, api: self)
|
45
|
+
else
|
46
|
+
response
|
47
|
+
end
|
48
|
+
end
|
49
|
+
alias :hierarchy :league_hierarchy
|
50
|
+
|
51
|
+
def content_format
|
52
|
+
'json'
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def request_url(path)
|
58
|
+
"/mlb-#{access_level}#{version}/#{path}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def api_key
|
62
|
+
if access_level != 't'
|
63
|
+
Sportradar::Api.api_key_params('mlb', 'production')
|
64
|
+
else
|
65
|
+
Sportradar::Api.api_key_params('mlb')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def version
|
70
|
+
Sportradar::Api.version('mlb')
|
71
|
+
end
|
72
|
+
|
73
|
+
def allowed_access_levels
|
74
|
+
%w[p t]
|
75
|
+
end
|
76
|
+
|
77
|
+
def allowed_seasons
|
78
|
+
["pre", "reg", "pst"]
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
__END__
|
87
|
+
# mlb = Sportradar::Api::Baseball::Mlb::Hierarchy.new
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Sportradar
|
2
|
+
module Api
|
3
|
+
module Baseball
|
4
|
+
class Outcome < Data
|
5
|
+
attr_accessor :response, :type, :current_inning, :current_inning_half, :count, :hitter, :pitcher, :runners
|
6
|
+
|
7
|
+
def initialize(data, **opts)
|
8
|
+
@response = data
|
9
|
+
@api = opts[:api]
|
10
|
+
@game = opts[:game]
|
11
|
+
|
12
|
+
@scores = {}
|
13
|
+
@id = data['id']
|
14
|
+
|
15
|
+
update(data, **opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
def update(data, source: nil, **opts)
|
19
|
+
update_from_outcome(data['outcome']) if data['outcome']
|
20
|
+
end
|
21
|
+
|
22
|
+
def update_from_outcome(data)
|
23
|
+
@type = data['type'] if data['type']
|
24
|
+
@current_inning = data['current_inning'] if data['current_inning']
|
25
|
+
@current_inning_half = data['current_inning_half'] if data['current_inning_half']
|
26
|
+
@count = data['count'] if data['count']
|
27
|
+
@hitter = data['hitter'] if data['hitter']
|
28
|
+
@pitcher = data['pitcher'] if data['pitcher']
|
29
|
+
@runners = data['runners'] if data['runners']
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def parse_from_pbp(data)
|
36
|
+
scoring = data['innings'].map {|i| i['scoring'] }.compact
|
37
|
+
return {} if scoring.empty?
|
38
|
+
scoring.each_with_object({}).with_index(1) do |(hash, memo), idx|
|
39
|
+
memo[idx] = {hash.dig('home', 'id') => hash.dig('home', 'runs'), hash.dig('away', 'id') => hash.dig('away', 'runs')}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_from_box(data)
|
44
|
+
id = data.dig('home', 'id')
|
45
|
+
da = data.dig('home', 'scoring')
|
46
|
+
return {} unless da
|
47
|
+
da.each { |h| h[id] = h.delete('runs') }
|
48
|
+
id = data.dig('away', 'id')
|
49
|
+
db = data.dig('away', 'scoring')
|
50
|
+
return {} unless db
|
51
|
+
db.each { |h| h[id] = h.delete('runs') }
|
52
|
+
da.zip(db).map{ |a, b| [a['sequence'].to_i, a.merge(b)] }.sort{ |(a,_), (b,_)| a <=> b }.to_h
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse_from_summary(data)
|
56
|
+
#
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# inprogress data from daily summary
|
65
|
+
{"id"=>"e1b6d4cc-74f0-4f80-b1d4-d506624d7ba0",
|
66
|
+
"status"=>"inprogress",
|
67
|
+
"coverage"=>"full",
|
68
|
+
"game_number"=>1,
|
69
|
+
"day_night"=>"D",
|
70
|
+
"scheduled"=>"2017-05-04T17:10:00+00:00",
|
71
|
+
"home_team"=>"aa34e0ed-f342-4ec6-b774-c79b47b60e2d",
|
72
|
+
"away_team"=>"27a59d3b-ff7c-48ea-b016-4798f560f5e1",
|
73
|
+
"venue"=>{"id"=>"302f8dcd-eed6-4b83-8609-81548d51e955", "name"=>"Target Field", "market"=>"Minnesota", "capacity"=>39021, "surface"=>"grass", "address"=>"353 N 5th Street", "city"=>"Minneapolis", "state"=>"MN", "zip"=>"55403", "country"=>"USA"},
|
74
|
+
"broadcast"=>{"network"=>"FS-N"},
|
75
|
+
"outcome"=>
|
76
|
+
{"type"=>"pitch",
|
77
|
+
"current_inning"=>3,
|
78
|
+
"current_inning_half"=>"B",
|
79
|
+
"count"=>{"strikes"=>2, "balls"=>0, "outs"=>1, "inning"=>3, "inning_half"=>"B", "half_over"=>false},
|
80
|
+
"hitter"=>{"id"=>"aecc630f-57da-4b23-842b-fd65394e81be", "outcome_id"=>"kF", "ab_over"=>false, "last_name"=>"Sano", "first_name"=>"Miguel", "preferred_name"=>"Miguel", "jersey_number"=>"22"},
|
81
|
+
"pitcher"=>{"id"=>"c1f19b5a-9dee-4053-9cad-ee4196f921e1", "last_name"=>"Cotton", "first_name"=>"Jharel", "preferred_name"=>"Jharel", "jersey_number"=>"45", "pitch_type"=>"FA", "pitch_speed"=>90.0, "pitch_zone"=>9, "pitch_x"=>52, "pitch_y"=>-39},
|
82
|
+
"runners"=>[{"id"=>"29a80d91-946d-4701-af7d-034850bdef00", "starting_base"=>1, "ending_base"=>1, "outcome_id"=>"", "out"=>false, "last_name"=>"Dozier", "first_name"=>"James", "preferred_name"=>"Brian", "jersey_number"=>"2"}]},
|
83
|
+
"officials"=>
|
84
|
+
[{"full_name"=>"Mike Winters", "first_name"=>"Mike", "last_name"=>"Winters", "assignment"=>"2B", "experience"=>"24", "id"=>"344565d2-3276-4948-ac8e-28e4e49be9d9"},
|
85
|
+
{"full_name"=>"Mark Wegner", "first_name"=>"Mark", "last_name"=>"Wegner", "assignment"=>"3B", "experience"=>"15", "id"=>"27109ca4-3484-45ad-a78d-1a639c1bfabd"},
|
86
|
+
{"full_name"=>"Marty Foster", "first_name"=>"Marty", "last_name"=>"Foster", "assignment"=>"1B", "experience"=>"15", "id"=>"af6b8841-0bfd-402b-88de-1439d7d4ea74"},
|
87
|
+
{"full_name"=>"Mike Muchlinski", "first_name"=>"Mike", "last_name"=>"Muchlinski", "assignment"=>"HP", "experience"=>"2", "id"=>"ef45c7e3-9136-4704-b3a6-bfbd61cf9416"}]}
|