sportradar-api 0.13.0 → 0.13.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/Gemfile.lock +4 -3
- data/lib/sportradar/api/baseball/game.rb +1 -1
- data/lib/sportradar/api/baseball/mlb/api.rb +1 -1
- data/lib/sportradar/api/basketball/game.rb +5 -4
- data/lib/sportradar/api/basketball/nba/game.rb +1 -1
- data/lib/sportradar/api/basketball/nba/quarter.rb +9 -2
- data/lib/sportradar/api/basketball/ncaamb/game.rb +5 -1
- data/lib/sportradar/api/basketball/ncaamb/half.rb +9 -0
- data/lib/sportradar/api/basketball/ncaamb.rb +2 -2
- data/lib/sportradar/api/basketball/play.rb +3 -1
- data/lib/sportradar/api/basketball/plays/base.rb +8 -1
- data/lib/sportradar/api/basketball/plays/jumpball_violation.rb +11 -0
- data/lib/sportradar/api/basketball/plays.rb +1 -0
- data/lib/sportradar/api/basketball/team.rb +1 -1
- data/lib/sportradar/api/football/ncaafb/game.rb +1 -1
- data/lib/sportradar/api/football/nfl/game.rb +1 -1
- data/lib/sportradar/api/images.rb +2 -4
- data/lib/sportradar/api/soccer/README.md +4 -0
- data/lib/sportradar/api/soccer/api.rb +1 -1
- data/lib/sportradar/api/soccer/event.rb +15 -14
- data/lib/sportradar/api/soccer/match.rb +161 -6
- data/lib/sportradar/api/soccer/player.rb +16 -4
- data/lib/sportradar/api/soccer/scoring.rb +71 -0
- data/lib/sportradar/api/soccer/team.rb +25 -12
- data/lib/sportradar/api/soccer/tournament.rb +26 -3
- data/lib/sportradar/api/soccer.rb +1 -0
- data/lib/sportradar/api/version.rb +1 -1
- metadata +5 -29
- data/lib/sportradar/api/soccer-old/boxscore.rb +0 -13
- data/lib/sportradar/api/soccer-old/category.rb +0 -17
- data/lib/sportradar/api/soccer-old/fact.rb +0 -61
- data/lib/sportradar/api/soccer-old/hierarchy.rb +0 -14
- data/lib/sportradar/api/soccer-old/match.rb +0 -55
- data/lib/sportradar/api/soccer-old/player.rb +0 -88
- data/lib/sportradar/api/soccer-old/ranking.rb +0 -13
- data/lib/sportradar/api/soccer-old/schedule.rb +0 -22
- data/lib/sportradar/api/soccer-old/season.rb +0 -14
- data/lib/sportradar/api/soccer-old/standing.rb +0 -13
- data/lib/sportradar/api/soccer-old/statistic.rb +0 -14
- data/lib/sportradar/api/soccer-old/summary.rb +0 -13
- data/lib/sportradar/api/soccer-old/team.rb +0 -63
- data/lib/sportradar/api/soccer-old/tournament.rb +0 -20
- data/lib/sportradar/api/soccer-old/tournament_group.rb +0 -35
- data/lib/sportradar/api/soccer-old/venue.rb +0 -21
- data/lib/sportradar/api/soccer-old.rb +0 -158
- data/soccer-old/boxscore_test.rb +0 -14
- data/soccer-old/hierarchy_test.rb +0 -14
- data/soccer-old/match_test.rb +0 -23
- data/soccer-old/player_test.rb +0 -40
- data/soccer-old/ranking_test.rb +0 -16
- data/soccer-old/schedule_test.rb +0 -24
- data/soccer-old/standing_test.rb +0 -14
- data/soccer-old/summary_test.rb +0 -14
- data/soccer-old/team_test.rb +0 -21
- data/soccer-old_test.rb +0 -184
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b27cb8ea668a8b5d6fc88a694aceaaeff0ac0284
|
|
4
|
+
data.tar.gz: '08009571140f719d4f7c3a0337ad0a9f737a0e5c'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8c2c2c4feeccdabbd7784a49ded61c947dec73e36734f3df85dc12b64eacaa999f84d77a01908b14b370ebffd05842ffdf09d22a1cbeb6d72df134dc8048b0dc
|
|
7
|
+
data.tar.gz: 57c4b366e2a91bc03e1b9125c0ab427f3bcfa86d2f9bf29a9024840c62ff9c2ee2c3b4002cd7ca88ebe81fc8db2154cb5dfac93ec07b8cb887fc486bf49a731c
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
sportradar-api (0.13.
|
|
4
|
+
sportradar-api (0.13.21)
|
|
5
5
|
activesupport
|
|
6
6
|
httparty (>= 0.14.0)
|
|
7
7
|
|
|
@@ -47,7 +47,8 @@ GEM
|
|
|
47
47
|
hashdiff (0.3.4)
|
|
48
48
|
httparty (0.15.6)
|
|
49
49
|
multi_xml (>= 0.5.2)
|
|
50
|
-
i18n (0.
|
|
50
|
+
i18n (0.9.5)
|
|
51
|
+
concurrent-ruby (~> 1.0)
|
|
51
52
|
json (2.1.0)
|
|
52
53
|
listen (3.1.5)
|
|
53
54
|
rb-fsevent (~> 0.9, >= 0.9.4)
|
|
@@ -86,7 +87,7 @@ GEM
|
|
|
86
87
|
thor (0.19.4)
|
|
87
88
|
thread_safe (0.3.6)
|
|
88
89
|
tins (1.14.0)
|
|
89
|
-
tzinfo (1.2.
|
|
90
|
+
tzinfo (1.2.5)
|
|
90
91
|
thread_safe (~> 0.1)
|
|
91
92
|
vcr (3.0.3)
|
|
92
93
|
webmock (3.0.1)
|
|
@@ -26,7 +26,7 @@ module Sportradar
|
|
|
26
26
|
'reg'
|
|
27
27
|
end
|
|
28
28
|
def default_access_level
|
|
29
|
-
if (ENV['
|
|
29
|
+
if (ENV['SPORTRADAR_ENV_MLB'] || ENV['SPORTRADAR_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV']) == 'production'
|
|
30
30
|
'p'
|
|
31
31
|
else
|
|
32
32
|
't'
|
|
@@ -212,7 +212,7 @@ module Sportradar
|
|
|
212
212
|
end
|
|
213
213
|
|
|
214
214
|
def halftime?
|
|
215
|
-
clock == '
|
|
215
|
+
status == 'halftime' || clock == '00:00' && quarter == 2
|
|
216
216
|
end
|
|
217
217
|
def clock_display
|
|
218
218
|
if clock && period
|
|
@@ -266,7 +266,7 @@ module Sportradar
|
|
|
266
266
|
# data retrieval
|
|
267
267
|
|
|
268
268
|
def get_box
|
|
269
|
-
data = api.get_data(path_box)
|
|
269
|
+
data = api.get_data(path_box).to_h
|
|
270
270
|
ingest_box(data)
|
|
271
271
|
end
|
|
272
272
|
|
|
@@ -283,7 +283,7 @@ module Sportradar
|
|
|
283
283
|
end
|
|
284
284
|
|
|
285
285
|
def get_pbp
|
|
286
|
-
data = api.get_data(path_pbp)
|
|
286
|
+
data = api.get_data(path_pbp).to_h
|
|
287
287
|
ingest_pbp(data)
|
|
288
288
|
end
|
|
289
289
|
|
|
@@ -305,12 +305,13 @@ module Sportradar
|
|
|
305
305
|
set_pbp(period_data)
|
|
306
306
|
@pbp = @periods_hash.values
|
|
307
307
|
check_newness(:pbp, plays.last&.updated)
|
|
308
|
+
check_newness(:clock, @clock)
|
|
308
309
|
check_newness(:score, @score)
|
|
309
310
|
data
|
|
310
311
|
end
|
|
311
312
|
|
|
312
313
|
def get_summary
|
|
313
|
-
data = api.get_data(path_summary)
|
|
314
|
+
data = api.get_data(path_summary).to_h
|
|
314
315
|
ingest_summary(data)
|
|
315
316
|
end
|
|
316
317
|
|
|
@@ -33,8 +33,15 @@ module Sportradar
|
|
|
33
33
|
end
|
|
34
34
|
def update(data, **opts)
|
|
35
35
|
create_data(@plays_hash, data.dig('events'), klass: Play, api: @api, quarter: self)
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def plays_by_type(play_type, *types)
|
|
39
|
+
if types.empty?
|
|
40
|
+
plays.grep(Play.subclass(play_type.delete('_')))
|
|
41
|
+
else
|
|
42
|
+
play_classes = [play_type, *types].map { |type| Play.subclass(type.delete('_')) }
|
|
43
|
+
plays.select { |play| play_classes.any? { |klass| play.kind_of?(klass) } }
|
|
44
|
+
end
|
|
38
45
|
end
|
|
39
46
|
|
|
40
47
|
def plays
|
|
@@ -16,6 +16,10 @@ module Sportradar
|
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
def halftime?
|
|
20
|
+
status == 'halftime' || clock == '00:00' && period == 1
|
|
21
|
+
end
|
|
22
|
+
|
|
19
23
|
def team_class
|
|
20
24
|
Team
|
|
21
25
|
end
|
|
@@ -30,7 +34,7 @@ module Sportradar
|
|
|
30
34
|
alias :halfs :periods
|
|
31
35
|
|
|
32
36
|
def api
|
|
33
|
-
@api
|
|
37
|
+
@api ||= Sportradar::Api::Basketball::Ncaamb::Api.new
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
def sim!
|
|
@@ -35,6 +35,15 @@ module Sportradar
|
|
|
35
35
|
create_data(@plays_hash, data.dig('events'), klass: Play, api: @api, half: self)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
def plays_by_type(play_type, *types)
|
|
39
|
+
if types.empty?
|
|
40
|
+
plays.grep(Play.subclass(play_type.delete('_')))
|
|
41
|
+
else
|
|
42
|
+
play_classes = [play_type, *types].map { |type| Play.subclass(type.delete('_')) }
|
|
43
|
+
plays.select { |play| play_classes.any? { |klass| play.kind_of?(klass) } }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
38
47
|
def plays
|
|
39
48
|
@plays_hash.values
|
|
40
49
|
end
|
|
@@ -16,7 +16,7 @@ module Sportradar
|
|
|
16
16
|
# end
|
|
17
17
|
# end
|
|
18
18
|
def self.new(data, **opts)
|
|
19
|
-
klass = subclass(data['event_type'])
|
|
19
|
+
klass = subclass(data['event_type']) || Base
|
|
20
20
|
klass.new(data, **opts)
|
|
21
21
|
# rescue => e
|
|
22
22
|
# binding.pry
|
|
@@ -53,6 +53,7 @@ module Sportradar
|
|
|
53
53
|
"tvtimeout" => TvTimeout,
|
|
54
54
|
"clearpathfoul" => ClearPathFoul,
|
|
55
55
|
"technicalfoul" => TechnicalFoul,
|
|
56
|
+
"minortechnicalfoul" => TechnicalFoul,
|
|
56
57
|
"review" => Review,
|
|
57
58
|
"defensivethreeseconds" => DefensiveThreeSeconds,
|
|
58
59
|
"flagrantone" => FlagrantOne,
|
|
@@ -60,6 +61,7 @@ module Sportradar
|
|
|
60
61
|
"delay" => Delay,
|
|
61
62
|
"ejection" => Ejection,
|
|
62
63
|
"defaultviolation" => DefaultViolation,
|
|
64
|
+
"jumpballviolation" => JumpballViolation,
|
|
63
65
|
"defensivegoaltending" => DefensiveGoalTending,
|
|
64
66
|
"doublelane" => DoubleLane,
|
|
65
67
|
"lane" => Lane,
|
|
@@ -3,7 +3,7 @@ module Sportradar
|
|
|
3
3
|
module Basketball
|
|
4
4
|
class Play
|
|
5
5
|
class Base < Data
|
|
6
|
-
attr_accessor :response, :id, :clock, :event_type, :description, :statistics, :score, :team_id, :player_id, :quarter, :half, :updated, :location, :possession, :on_court, :game_seconds, :identifier
|
|
6
|
+
attr_accessor :response, :id, :clock, :event_type, :description, :statistics, :score, :team_id, :player_id, :quarter, :half, :updated, :location, :possession, :on_court, :on_court_ids, :game_seconds, :identifier
|
|
7
7
|
alias :type :event_type
|
|
8
8
|
|
|
9
9
|
def initialize(data, **opts)
|
|
@@ -87,11 +87,18 @@ module Sportradar
|
|
|
87
87
|
@location = data['location'] # {"coord_x"=>"0", "coord_y"=>"0"},
|
|
88
88
|
@possession = data['possession'] # {"name"=>"Knicks", "market"=>"New York", "id"=>"583ec70e-fb46-11e1-82cb-f4ce4684ea4c"},
|
|
89
89
|
# @on_court = data['on_court'] # hash
|
|
90
|
+
handle_on_court(data['on_court']) if data['on_court']
|
|
90
91
|
|
|
91
92
|
handle_time(data, **opts)
|
|
92
93
|
parse_statistics(data) if data['statistics']
|
|
93
94
|
end
|
|
94
95
|
|
|
96
|
+
def handle_on_court(data)
|
|
97
|
+
teams = [data['home'], data['away']]
|
|
98
|
+
@on_court = teams.flat_map { |hash| hash['players'].map { |pl| OpenStruct.new(pl) } }
|
|
99
|
+
@on_court_ids = @on_court.map(&:id)
|
|
100
|
+
end
|
|
101
|
+
|
|
95
102
|
def handle_time(data, **opts)
|
|
96
103
|
@game_seconds = if opts[:quarter]
|
|
97
104
|
@quarter = opts[:quarter].sequence.to_i rescue opts[:quarter].to_i
|
|
@@ -38,6 +38,7 @@ require_relative 'plays/flagrant_two'
|
|
|
38
38
|
require_relative 'plays/delay'
|
|
39
39
|
require_relative 'plays/ejection'
|
|
40
40
|
require_relative 'plays/default_violation'
|
|
41
|
+
require_relative 'plays/jumpball_violation'
|
|
41
42
|
require_relative 'plays/defensive_goal_tending'
|
|
42
43
|
require_relative 'plays/double_lane'
|
|
43
44
|
require_relative 'plays/lane'
|
|
@@ -115,7 +115,7 @@ module Sportradar
|
|
|
115
115
|
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_roster)}
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
-
def get_season_stats(year =
|
|
118
|
+
def get_season_stats(year = api.default_year)
|
|
119
119
|
data = api.get_data(path_season_stats(year)).to_h
|
|
120
120
|
ingest_season_stats(data)
|
|
121
121
|
end
|
|
@@ -39,7 +39,6 @@ module Sportradar
|
|
|
39
39
|
# Coach Manifests
|
|
40
40
|
|
|
41
41
|
def coach_manifests
|
|
42
|
-
raise Sportradar::Api::Error::InvalidLeague unless league.nil?
|
|
43
42
|
response = get request_url("coaches/#{image_type}/manifests/all_assets")
|
|
44
43
|
if response.success? && response["assetlist"]
|
|
45
44
|
Sportradar::Api::Images::AssetList.new response["assetlist"]
|
|
@@ -50,7 +49,6 @@ module Sportradar
|
|
|
50
49
|
alias_method :all_coaches, :coach_manifests
|
|
51
50
|
|
|
52
51
|
def venue_manifests
|
|
53
|
-
raise Sportradar::Api::Error::InvalidLeague unless league.nil?
|
|
54
52
|
if version == 3
|
|
55
53
|
response = get request_url("venues/manifest")
|
|
56
54
|
else
|
|
@@ -97,7 +95,7 @@ module Sportradar
|
|
|
97
95
|
private
|
|
98
96
|
|
|
99
97
|
def request_url(path)
|
|
100
|
-
"/#{sport}-images-#{access_level}#{version}/#{provider}/#{path}"
|
|
98
|
+
"/#{sport}-images-#{access_level}#{version}/#{provider}/#{( league + '/') if league}#{path}"
|
|
101
99
|
end
|
|
102
100
|
|
|
103
101
|
def api_key
|
|
@@ -169,7 +167,7 @@ module Sportradar
|
|
|
169
167
|
end
|
|
170
168
|
|
|
171
169
|
def allowed_sports
|
|
172
|
-
v2_api_sports + v3_api_sports
|
|
170
|
+
v2_api_sports + v3_api_sports + soccer_leagues
|
|
173
171
|
end
|
|
174
172
|
|
|
175
173
|
def v2_api_sports
|
|
@@ -19,7 +19,7 @@ module Sportradar
|
|
|
19
19
|
'reg'
|
|
20
20
|
end
|
|
21
21
|
def default_access_level
|
|
22
|
-
if (ENV['SPORTRADAR_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV']) == 'production'
|
|
22
|
+
if (ENV['SPORTRADAR_SOCCER_ENV'] || ENV['SPORTRADAR_ENV'] || ENV['RACK_ENV'] || ENV['RAILS_ENV']) == 'production'
|
|
23
23
|
'x'
|
|
24
24
|
else
|
|
25
25
|
'xt'
|
|
@@ -2,7 +2,7 @@ module Sportradar
|
|
|
2
2
|
module Api
|
|
3
3
|
module Soccer
|
|
4
4
|
class Event < Data
|
|
5
|
-
attr_reader :id, :type, :time, :period, :period_type, :period_name, :match_time, :team, :x, :y, :outcome, :home_score, :away_score, :goal_scorer, :stoppage_time, :player_out, :player_in, :player
|
|
5
|
+
attr_reader :id, :type, :time, :period, :period_type, :period_name, :match_time, :team, :x, :y, :outcome, :home_score, :away_score, :goal_scorer, :stoppage_time, :player_out, :player_in, :player, :commentaries
|
|
6
6
|
|
|
7
7
|
def initialize(data, **opts)
|
|
8
8
|
@response = data
|
|
@@ -12,18 +12,19 @@ module Sportradar
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def update(data, **opts)
|
|
15
|
-
@type = data['type']
|
|
16
|
-
@time = Time.parse(data['time'])
|
|
17
|
-
@period = data['period']
|
|
18
|
-
@period_type = data['period_type']
|
|
19
|
-
@period_name = data['period_name']
|
|
20
|
-
@match_time = data['match_time']
|
|
21
|
-
@team = data['team']
|
|
22
|
-
@x = data['x']
|
|
23
|
-
@y = data['y']
|
|
24
|
-
@outcome = data['outcome']
|
|
25
|
-
@home_score = data['home_score']
|
|
26
|
-
@away_score = data['away_score']
|
|
15
|
+
@type = data['type'] if data['type']
|
|
16
|
+
@time = Time.parse(data['time']) if data['time']
|
|
17
|
+
@period = data['period'] if data['period']
|
|
18
|
+
@period_type = data['period_type'] if data['period_type']
|
|
19
|
+
@period_name = data['period_name'] if data['period_name']
|
|
20
|
+
@match_time = data['match_time'] if data['match_time']
|
|
21
|
+
@team = data['team'] if data['team']
|
|
22
|
+
@x = data['x'] if data['x']
|
|
23
|
+
@y = data['y'] if data['y']
|
|
24
|
+
@outcome = data['outcome'] if data['outcome']
|
|
25
|
+
@home_score = data['home_score'] if data['home_score']
|
|
26
|
+
@away_score = data['away_score'] if data['away_score']
|
|
27
|
+
@commentaries = data['commentaries'] if data['commentaries']
|
|
27
28
|
@goal_scorer = OpenStruct.new(data['goal_scorer']) if data['goal_scorer']
|
|
28
29
|
@stoppage_time = data['stoppage_time'].to_i if data['stoppage_time']
|
|
29
30
|
@player_out = OpenStruct.new(data['player_out']) if data['player_out']
|
|
@@ -31,7 +32,7 @@ module Sportradar
|
|
|
31
32
|
@player = OpenStruct.new(data['player']) if data['player'] # red/yellow cards
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
def
|
|
35
|
+
def updated
|
|
35
36
|
@time
|
|
36
37
|
end
|
|
37
38
|
|
|
@@ -6,20 +6,29 @@ module Sportradar
|
|
|
6
6
|
attr_reader :home_score, :away_score, :winner_id, :aggregate_home_score, :aggregate_away_score, :aggregate_winner_id
|
|
7
7
|
attr_reader :referee, :weather_info, :coverage_info, :probabilities
|
|
8
8
|
attr_reader :home, :away, :tournament_id
|
|
9
|
+
attr_reader :period, :score, :broadcast, :coverage # these are for consistency with other sports
|
|
10
|
+
attr_reader :match_time, :stoppage_time
|
|
11
|
+
attr_reader :team_stats, :player_stats
|
|
9
12
|
|
|
10
13
|
def initialize(data = {}, league_group: nil, **opts)
|
|
11
14
|
@response = data
|
|
12
15
|
@id = data['id']
|
|
13
16
|
@api = opts[:api]
|
|
17
|
+
@updates = {}
|
|
18
|
+
@changes = {}
|
|
14
19
|
|
|
15
20
|
@league_group = league_group || data['league_group'] || @api&.league_group
|
|
16
21
|
|
|
17
22
|
@timeline_hash = {}
|
|
18
23
|
@lineups_hash = {}
|
|
19
24
|
get_tournament_id(data, **opts)
|
|
20
|
-
@
|
|
21
|
-
@
|
|
25
|
+
@scoring_raw = Scoring.new(data, game: self)
|
|
26
|
+
@home = Team.new(data['home'].to_h, api: api, match: self)
|
|
27
|
+
@away = Team.new(data['away'].to_h, api: api, match: self)
|
|
22
28
|
@teams_hash = { away: @away, home: @home }
|
|
29
|
+
@team_ids = { away: @away.id, home: @home.id }
|
|
30
|
+
@team_stats = {}
|
|
31
|
+
@player_stats = {}
|
|
23
32
|
|
|
24
33
|
update(data, **opts)
|
|
25
34
|
end
|
|
@@ -47,7 +56,6 @@ module Sportradar
|
|
|
47
56
|
update_teams(stats)
|
|
48
57
|
end
|
|
49
58
|
|
|
50
|
-
|
|
51
59
|
@scheduled = Time.parse(data['scheduled']) if data['scheduled']
|
|
52
60
|
@start_time_tbd = data['start_time_tbd'] if data.key?('start_time_tbd')
|
|
53
61
|
@status = data['status'] if data['status']
|
|
@@ -60,14 +68,18 @@ module Sportradar
|
|
|
60
68
|
|
|
61
69
|
@home_score = data['home_score'] if data['home_score']
|
|
62
70
|
@away_score = data['away_score'] if data['away_score']
|
|
71
|
+
@period = data['period'] if data['period']
|
|
72
|
+
@match_time = data.dig('clock', 'match_time') if data.dig('clock', 'match_time')
|
|
73
|
+
@stoppage_time = data.dig('clock', 'stoppage_time')
|
|
74
|
+
@ball_locations = data['ball_locations'] if data['ball_locations']
|
|
63
75
|
@winner_id = data['winner_id'] if data['winner_id']
|
|
64
76
|
|
|
65
77
|
@aggregate_home_score = data['aggregate_home_score'] if data['aggregate_home_score']
|
|
66
78
|
@aggregate_away_score = data['aggregate_away_score'] if data['aggregate_away_score']
|
|
67
79
|
@aggregate_winner_id = data['aggregate_winner_id'] if data['aggregate_winner_id']
|
|
80
|
+
@scoring_raw.update(data, source: opts[:source])
|
|
68
81
|
create_data(@timeline_hash, data['timeline'], klass: Event, api: api)
|
|
69
|
-
|
|
70
|
-
# @tournament
|
|
82
|
+
|
|
71
83
|
if data['competitors']
|
|
72
84
|
update_teams(data['competitors'])
|
|
73
85
|
end
|
|
@@ -75,6 +87,97 @@ module Sportradar
|
|
|
75
87
|
# parse_nested_data(data)
|
|
76
88
|
end
|
|
77
89
|
|
|
90
|
+
def title
|
|
91
|
+
[@home, @away].compact.map(&:name).join(' vs ')
|
|
92
|
+
end
|
|
93
|
+
def scoring
|
|
94
|
+
@scoring_raw.scores.each { |period, hash| hash[@home.id] = hash['home']; hash[@away.id] = hash['away'] }
|
|
95
|
+
end
|
|
96
|
+
def score
|
|
97
|
+
{@home.id => @home_score, @away.id => @away_score}
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# status helpers
|
|
101
|
+
def realtime_state_short
|
|
102
|
+
if future?
|
|
103
|
+
'Scheduled' # ??
|
|
104
|
+
elsif finished?
|
|
105
|
+
'FT'
|
|
106
|
+
elsif postponed?
|
|
107
|
+
'PPD'
|
|
108
|
+
elsif halftime?
|
|
109
|
+
'HT'
|
|
110
|
+
else
|
|
111
|
+
clock_display
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def realtime_state
|
|
116
|
+
if future?
|
|
117
|
+
'Scheduled'
|
|
118
|
+
elsif finished?
|
|
119
|
+
'Final'
|
|
120
|
+
elsif postponed?
|
|
121
|
+
'Postponed'
|
|
122
|
+
elsif halftime?
|
|
123
|
+
'Halftime'
|
|
124
|
+
else
|
|
125
|
+
clock_display
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def halftime?
|
|
130
|
+
@match_status == "halftime"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def postponed?
|
|
134
|
+
'postponed' == status
|
|
135
|
+
end
|
|
136
|
+
def unnecessary?
|
|
137
|
+
'unnecessary' == status
|
|
138
|
+
end
|
|
139
|
+
def cancelled?
|
|
140
|
+
['unnecessary', 'postponed'].include? status
|
|
141
|
+
end
|
|
142
|
+
def future?
|
|
143
|
+
['not_started', 'scheduled', 'delayed', 'created', 'time-tbd', 'if-necessary'].include? status
|
|
144
|
+
end
|
|
145
|
+
def started?
|
|
146
|
+
['live'].include?(@status) || ['halftime', '1st_half', '2nd_half'].include?(@match_status)
|
|
147
|
+
end
|
|
148
|
+
def finished?
|
|
149
|
+
['ended', 'complete', 'closed'].include?(@status) || ['ended'].include?(@match_status)
|
|
150
|
+
end
|
|
151
|
+
def completed?
|
|
152
|
+
['ended', 'complete'].include? status
|
|
153
|
+
end
|
|
154
|
+
def closed?
|
|
155
|
+
'closed' == status
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def clock_display
|
|
159
|
+
return unless @match_time
|
|
160
|
+
if @match_time == '45:00' || @match_time == '90:00' # stoppage time
|
|
161
|
+
@match_time.split(':').first + ?'
|
|
162
|
+
else
|
|
163
|
+
@match_time.split(':').first + ?'
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
alias :clock :clock_display
|
|
167
|
+
|
|
168
|
+
def match_seconds
|
|
169
|
+
return nil unless @match_time
|
|
170
|
+
mm, ss = @match_time.split(':').map(&:to_i)
|
|
171
|
+
time = mm * 60 + ss
|
|
172
|
+
if @stoppage_time && (@match_time == '45:00' || @match_time == '90:00') # stoppage time
|
|
173
|
+
mm, ss = @stoppage_time.split(':').map(&:to_i)
|
|
174
|
+
stop_time = mm * 60 + ss
|
|
175
|
+
time += stop_time
|
|
176
|
+
end
|
|
177
|
+
time
|
|
178
|
+
end
|
|
179
|
+
alias :game_seconds :match_seconds
|
|
180
|
+
|
|
78
181
|
def update_teams(data)
|
|
79
182
|
home_hash = data.detect { |team_hash| team_hash["qualifier"] == "home" || team_hash["team"] == "home" }
|
|
80
183
|
away_hash = (data - [home_hash]).first
|
|
@@ -83,9 +186,20 @@ module Sportradar
|
|
|
83
186
|
@away.update(away_hash, match: self)
|
|
84
187
|
@teams_hash[@home.id] = @home
|
|
85
188
|
@teams_hash[@away.id] = @away
|
|
189
|
+
@team_ids = { away: @away.id, home: @home.id }
|
|
86
190
|
end
|
|
87
191
|
end
|
|
88
192
|
|
|
193
|
+
def update_stats(team, stats)
|
|
194
|
+
@team_stats.merge!(team.id => stats.merge(team: team))
|
|
195
|
+
end
|
|
196
|
+
def update_player_stats(player, stats)
|
|
197
|
+
@player_stats.merge!(player.id => stats.merge!(player: player))
|
|
198
|
+
end
|
|
199
|
+
def stats(team_id)
|
|
200
|
+
team_id.is_a?(Symbol) ? @team_stats[@team_ids[team_id]] : @team_stats[team_id]
|
|
201
|
+
end
|
|
202
|
+
|
|
89
203
|
def get_tournament_id(data, **opts)
|
|
90
204
|
@tournament_id ||= if opts[:tournament]
|
|
91
205
|
opts[:tournament].id
|
|
@@ -112,6 +226,19 @@ module Sportradar
|
|
|
112
226
|
end
|
|
113
227
|
end
|
|
114
228
|
|
|
229
|
+
def timeline_by_minute(minute_start, minute_end = nil)
|
|
230
|
+
if minute_end
|
|
231
|
+
@timeline_hash.each_value.select { |ev| (minute_start..minute_end).cover?(ev.match_time.to_i) }
|
|
232
|
+
else
|
|
233
|
+
@timeline_hash.each_value.select { |ev| minute_start === ev.match_time }
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def plays_by_minute(type, minute_start, minute_end = nil)
|
|
238
|
+
timeline_by_minute(minute_start, minute_end).select { |ev| ev.type == type }
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
|
|
115
242
|
def lineups(which = nil)
|
|
116
243
|
if which
|
|
117
244
|
@lineups_hash[which.to_s]
|
|
@@ -200,7 +327,9 @@ module Sportradar
|
|
|
200
327
|
ingest_timeline(data)
|
|
201
328
|
end
|
|
202
329
|
def ingest_timeline(data)
|
|
203
|
-
update(data)
|
|
330
|
+
update(data, source: :pbp)
|
|
331
|
+
check_newness(:pbp, timeline.last&.updated)
|
|
332
|
+
check_newness(:clock, self.match_seconds.to_s)
|
|
204
333
|
data
|
|
205
334
|
end
|
|
206
335
|
def queue_timeline
|
|
@@ -208,6 +337,21 @@ module Sportradar
|
|
|
208
337
|
{url: url, headers: headers, params: options, timeout: timeout, callback: method(:ingest_timeline)}
|
|
209
338
|
end
|
|
210
339
|
|
|
340
|
+
# tracking updates
|
|
341
|
+
def remember(key, object)
|
|
342
|
+
@updates[key] = object&.dup
|
|
343
|
+
end
|
|
344
|
+
def not_updated?(key, object)
|
|
345
|
+
@updates[key] == object
|
|
346
|
+
end
|
|
347
|
+
def changed?(key)
|
|
348
|
+
@changes[key]
|
|
349
|
+
end
|
|
350
|
+
def check_newness(key, new_object)
|
|
351
|
+
@changes[key] = !not_updated?(key, new_object)
|
|
352
|
+
remember(key, new_object)
|
|
353
|
+
end
|
|
354
|
+
|
|
211
355
|
end
|
|
212
356
|
end
|
|
213
357
|
end
|
|
@@ -226,6 +370,17 @@ __END__
|
|
|
226
370
|
[{"id"=>"sr:competitor:2793", "name"=>"US Sassuolo", "country"=>"Italy", "country_code"=>"ITA", "abbreviation"=>"SAS", "qualifier"=>"home"},
|
|
227
371
|
{"id"=>"sr:competitor:2702", "name"=>"AS Roma", "country"=>"Italy", "country_code"=>"ITA", "abbreviation"=>"ROM", "qualifier"=>"away"}]
|
|
228
372
|
|
|
373
|
+
"sport_event_status"=>
|
|
374
|
+
{"status"=>"live",
|
|
375
|
+
"match_status"=>"1st_half",
|
|
376
|
+
"home_score"=>1,
|
|
377
|
+
"away_score"=>0,
|
|
378
|
+
"period"=>1,
|
|
379
|
+
"clock"=>{"match_time"=>"19:25"},
|
|
380
|
+
"clock"=>{"match_time"=>"45:00", "stoppage_time"=>"00:05"}
|
|
381
|
+
"ball_locations"=>[{"x"=>"95", "y"=>"50", "team"=>"away"}, {"x"=>"80", "y"=>"62", "team"=>"home"}, {"x"=>"82", "y"=>"60", "team"=>"home"}, {"x"=>"79", "y"=>"58", "team"=>"home"}]},
|
|
382
|
+
|
|
383
|
+
|
|
229
384
|
|
|
230
385
|
m = Sportradar::Api::Soccer::Match.new({"id"=>"sr:match:12090446"}, league_group: 'eu')
|
|
231
386
|
res = m.get_summary
|