sports_data_api 0.1.0 → 0.2.0

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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +1 -0
  4. data/README.md +6 -6
  5. data/lib/sports_data_api.rb +2 -0
  6. data/lib/sports_data_api/nfl.rb +28 -16
  7. data/lib/sports_data_api/nfl/broadcast.rb +6 -7
  8. data/lib/sports_data_api/nfl/game.rb +17 -22
  9. data/lib/sports_data_api/nfl/games.rb +7 -8
  10. data/lib/sports_data_api/nfl/player.rb +5 -7
  11. data/lib/sports_data_api/nfl/player_season_stats.rb +3 -13
  12. data/lib/sports_data_api/nfl/season.rb +5 -7
  13. data/lib/sports_data_api/nfl/team.rb +50 -11
  14. data/lib/sports_data_api/nfl/team_roster.rb +2 -5
  15. data/lib/sports_data_api/nfl/team_season_stats.rb +4 -9
  16. data/lib/sports_data_api/nfl/teams.rb +9 -15
  17. data/lib/sports_data_api/nfl/venue.rb +12 -13
  18. data/lib/sports_data_api/nfl/weather.rb +7 -8
  19. data/lib/sports_data_api/nfl/week.rb +4 -6
  20. data/lib/sports_data_api/nhl.rb +71 -0
  21. data/lib/sports_data_api/nhl/broadcast.rb +14 -0
  22. data/lib/sports_data_api/nhl/game.rb +54 -0
  23. data/lib/sports_data_api/nhl/games.rb +26 -0
  24. data/lib/sports_data_api/nhl/player.rb +31 -0
  25. data/lib/sports_data_api/nhl/season.rb +28 -0
  26. data/lib/sports_data_api/nhl/team.rb +40 -0
  27. data/lib/sports_data_api/nhl/teams.rb +83 -0
  28. data/lib/sports_data_api/nhl/venue.rb +20 -0
  29. data/lib/sports_data_api/stats.rb +6 -2
  30. data/lib/sports_data_api/version.rb +1 -1
  31. data/spec/cassettes/sports_data_api_mlb_game.yml +19926 -19688
  32. data/spec/cassettes/sports_data_api_mlb_game_boxscore.yml +24 -18
  33. data/spec/cassettes/sports_data_api_mlb_game_stats.yml +576 -574
  34. data/spec/cassettes/sports_data_api_mlb_games.yml +152 -147
  35. data/spec/cassettes/sports_data_api_mlb_player.yml +8459 -10660
  36. data/spec/cassettes/sports_data_api_mlb_season.yml +19926 -19688
  37. data/spec/cassettes/sports_data_api_mlb_team.yml +47 -44
  38. data/spec/cassettes/sports_data_api_mlb_team_roster.yml +8459 -10660
  39. data/spec/cassettes/sports_data_api_mlb_teams.yml +94 -130
  40. data/spec/cassettes/sports_data_api_mlb_venues.yml +16 -16
  41. data/spec/cassettes/sports_data_api_nfl.yml +5331 -18893
  42. data/spec/cassettes/sports_data_api_nfl_broadcast.yml +35 -84
  43. data/spec/cassettes/sports_data_api_nfl_game.yml +7702 -15956
  44. data/spec/cassettes/sports_data_api_nfl_games.yml +211 -884
  45. data/spec/cassettes/sports_data_api_nfl_player_season_stats.yml +1002 -959
  46. data/spec/cassettes/sports_data_api_nfl_season.yml +3168 -14065
  47. data/spec/cassettes/sports_data_api_nfl_team.yml +1264 -715
  48. data/spec/cassettes/sports_data_api_nfl_team_hierarchy.yml +462 -846
  49. data/spec/cassettes/sports_data_api_nfl_team_roster.yml +796 -580
  50. data/spec/cassettes/sports_data_api_nfl_team_season_stats.yml +1004 -945
  51. data/spec/cassettes/sports_data_api_nfl_venue.yml +35 -84
  52. data/spec/cassettes/sports_data_api_nfl_weather.yml +35 -84
  53. data/spec/cassettes/sports_data_api_nfl_week.yml +3168 -14065
  54. data/spec/cassettes/sports_data_api_nhl.yml +18999 -0
  55. data/spec/cassettes/sports_data_api_nhl_broadcast.yml +226 -0
  56. data/spec/cassettes/sports_data_api_nhl_game.yml +23261 -0
  57. data/spec/cassettes/sports_data_api_nhl_games.yml +226 -0
  58. data/spec/cassettes/sports_data_api_nhl_league_hierarchy.yml +535 -0
  59. data/spec/cassettes/sports_data_api_nhl_player.yml +396 -0
  60. data/spec/cassettes/sports_data_api_nhl_season.yml +18961 -0
  61. data/spec/cassettes/sports_data_api_nhl_team.yml +1962 -0
  62. data/spec/cassettes/sports_data_api_nhl_venue.yml +226 -0
  63. data/spec/lib/sports_data_api/mlb/players_spec.rb +1 -1
  64. data/spec/lib/sports_data_api/nfl/game_spec.rb +33 -9
  65. data/spec/lib/sports_data_api/nfl/team_spec.rb +62 -32
  66. data/spec/lib/sports_data_api/nfl/teams_spec.rb +5 -6
  67. data/spec/lib/sports_data_api/nfl/venue_spec.rb +3 -3
  68. data/spec/lib/sports_data_api/nfl_spec.rb +3 -3
  69. data/spec/lib/sports_data_api/nhl/broadcast_spec.rb +18 -0
  70. data/spec/lib/sports_data_api/nhl/game_spec.rb +87 -0
  71. data/spec/lib/sports_data_api/nhl/games_spec.rb +19 -0
  72. data/spec/lib/sports_data_api/nhl/player_spec.rb +56 -0
  73. data/spec/lib/sports_data_api/nhl/season_spec.rb +41 -0
  74. data/spec/lib/sports_data_api/nhl/team_spec.rb +240 -0
  75. data/spec/lib/sports_data_api/nhl/teams_spec.rb +76 -0
  76. data/spec/lib/sports_data_api/nhl/venue_spec.rb +24 -0
  77. data/spec/lib/sports_data_api/nhl_spec.rb +41 -0
  78. data/spec/spec_helper.rb +2 -0
  79. data/sports_data_api.gemspec +1 -0
  80. metadata +62 -3
@@ -5,23 +5,18 @@ module SportsDataApi
5
5
 
6
6
  attr_reader :conferences, :divisions
7
7
 
8
- ##
9
- # Initialize by passing the raw XML returned from the API
10
- def initialize(xml)
8
+ def initialize(teams_hash)
11
9
  @teams = []
12
- xml = xml.first if xml.is_a? Nokogiri::XML::NodeSet
13
- if xml.is_a? Nokogiri::XML::Element
14
- xml.xpath('conference').each do |conference|
15
- # Conference ID, e.g., AFC or NFC
16
- cid = conference['id']
10
+ teams_hash['conferences'].each do |conference_hash|
11
+ # Conference ID, e.g., AFC or NFC
12
+ cid = conference_hash['id']
17
13
 
18
- conference.xpath('division').each do |division|
19
- # Division ID, e.g., AFC_EAST, NFC_NORTH
20
- did = division['id']
14
+ conference_hash['divisions'].each do |division_hash|
15
+ # Division ID, e.g., AFC_EAST, NFC_NORTH
16
+ did = division_hash['id']
21
17
 
22
- # Create a new team
23
- @teams << division.xpath('team').map { |team| Team.new(team, cid, did) }
24
- end
18
+ # Create a new team
19
+ @teams << division_hash['teams'].map { |team_hash| Team.new(team_hash, cid, did) }
25
20
  end
26
21
  end
27
22
 
@@ -78,7 +73,6 @@ module SportsDataApi
78
73
  end
79
74
  end
80
75
  end
81
-
82
76
  end
83
77
  end
84
78
  end
@@ -2,19 +2,18 @@ module SportsDataApi
2
2
  module Nfl
3
3
  class Venue
4
4
  attr_reader :id, :name, :address, :city, :state, :zip, :country, :capacity, :type, :surface
5
- def initialize(xml)
6
- xml = xml.first if xml.is_a? Nokogiri::XML::NodeSet
7
- if xml.is_a? Nokogiri::XML::Element
8
- @id = xml['id']
9
- @name = xml['name']
10
- @address = xml['address']
11
- @city = xml['city']
12
- @state = xml['state']
13
- @zip = xml['zip']
14
- @country = xml['country']
15
- @capacity = xml['capacity']
16
- @type = xml['type']
17
- @surface = xml['surface']
5
+ def initialize(venue_hash)
6
+ if venue_hash
7
+ @id = venue_hash['id']
8
+ @name = venue_hash['name']
9
+ @address = venue_hash['address']
10
+ @city = venue_hash['city']
11
+ @state = venue_hash['state']
12
+ @zip = venue_hash['zip']
13
+ @country = venue_hash['country']
14
+ @capacity = venue_hash['capacity']
15
+ @type = venue_hash['type']
16
+ @surface = venue_hash['surface']
18
17
  end
19
18
  end
20
19
  end
@@ -2,14 +2,13 @@ module SportsDataApi
2
2
  module Nfl
3
3
  class Weather
4
4
  attr_reader :temperature, :condition, :humidity, :wind_speed, :wind_direction
5
- def initialize(xml)
6
- xml = xml.first if xml.is_a? Nokogiri::XML::NodeSet
7
- if xml.is_a? Nokogiri::XML::Element
8
- @temperature = xml['temperature'].to_i
9
- @condition = xml['condition']
10
- @humidity = xml['humidity'].to_i
11
- @wind_speed = xml.xpath('wind').first['speed'].to_i
12
- @wind_direction = xml.xpath('wind').first['direction']
5
+ def initialize(weather_hash)
6
+ if weather_hash
7
+ @temperature = weather_hash['temperature']
8
+ @condition = weather_hash['condition']
9
+ @humidity = weather_hash['humidity']
10
+ @wind_speed = weather_hash['wind']['speed']
11
+ @wind_direction = weather_hash['wind']['direction']
13
12
  end
14
13
  end
15
14
  end
@@ -3,16 +3,14 @@ module SportsDataApi
3
3
  class Week
4
4
  attr_reader :number, :games, :year, :season
5
5
 
6
- def initialize(year, season, xml)
6
+ def initialize(year, season, week_hash)
7
7
  @games = []
8
8
  @year = year
9
9
  @season = season
10
10
 
11
- if xml.is_a? Nokogiri::XML::Element
12
- @number = xml["week"].to_i
13
- @games = xml.xpath("game").map do |game_xml|
14
- Game.new(@year, @season, @number, game_xml)
15
- end
11
+ @number = week_hash['number']
12
+ @games = week_hash['games'].map do |game_hash|
13
+ Game.new(@year, @season, @number, game_hash)
16
14
  end
17
15
  end
18
16
  end
@@ -0,0 +1,71 @@
1
+ module SportsDataApi
2
+ module Nhl
3
+
4
+ class Exception < ::Exception
5
+ end
6
+
7
+ DIR = File.join(File.dirname(__FILE__), 'nhl')
8
+ BASE_URL = 'http://api.sportsdatallc.org/nhl-%{access_level}%{version}'
9
+ DEFAULT_VERSION = 3
10
+ SPORT = :nhl
11
+
12
+ autoload :Team, File.join(DIR, 'team')
13
+ autoload :Teams, File.join(DIR, 'teams')
14
+ autoload :Player, File.join(DIR, 'player')
15
+ autoload :Game, File.join(DIR, 'game')
16
+ autoload :Games, File.join(DIR, 'games')
17
+ autoload :Season, File.join(DIR, 'season')
18
+ autoload :Venue, File.join(DIR, 'venue')
19
+ autoload :Broadcast, File.join(DIR, 'broadcast')
20
+
21
+ ##
22
+ # Fetches NHL season schedule for a given year and season
23
+ def self.schedule(year, season, version = DEFAULT_VERSION)
24
+ season = season.to_s.upcase.to_sym
25
+ raise SportsDataApi::Nhl::Exception.new("#{season} is not a valid season") unless Season.valid?(season)
26
+
27
+ response = self.response_xml(version, "/games/#{year}/#{season}/schedule.xml")
28
+
29
+ return Season.new(response.xpath("/league/season-schedule"))
30
+ end
31
+
32
+ ##
33
+ # Fetches NHL team roster
34
+ def self.team_roster(team, version = DEFAULT_VERSION)
35
+ response = self.response_xml(version, "/teams/#{team}/profile.xml")
36
+
37
+ return Team.new(response.xpath("team"))
38
+ end
39
+
40
+ ##
41
+ # Fetches NHL game summary for a given game
42
+ def self.game_summary(game, version = DEFAULT_VERSION)
43
+ response = self.response_xml(version, "/games/#{game}/summary.xml")
44
+
45
+ return Game.new(xml: response.xpath("/game"))
46
+ end
47
+
48
+ ##
49
+ # Fetches all NHL teams
50
+ def self.teams(version = DEFAULT_VERSION)
51
+ response = self.response_xml(version, "/league/hierarchy.xml")
52
+
53
+ return Teams.new(response.xpath('/league'))
54
+ end
55
+
56
+ ##
57
+ # Fetches NHL daily schedule for a given date
58
+ def self.daily(year, month, day, version = DEFAULT_VERSION)
59
+ response = self.response_xml(version, "/games/#{year}/#{month}/#{day}/schedule.xml")
60
+
61
+ return Games.new(response.xpath('league/daily-schedule'))
62
+ end
63
+
64
+ private
65
+ def self.response_xml(version, url)
66
+ base_url = BASE_URL % { access_level: SportsDataApi.access_level(SPORT), version: version }
67
+ response = SportsDataApi.generic_request("#{base_url}#{url}", SPORT)
68
+ Nokogiri::XML(response.to_s).remove_namespaces!
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,14 @@
1
+ module SportsDataApi
2
+ module Nhl
3
+ class Broadcast
4
+ attr_reader :network, :satellite
5
+ def initialize(xml)
6
+ xml = xml.first if xml.is_a? Nokogiri::XML::NodeSet
7
+ if xml.is_a? Nokogiri::XML::Element
8
+ @network = xml['network']
9
+ @satellite = xml['satellite']
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,54 @@
1
+ module SportsDataApi
2
+ module Nhl
3
+ class Game
4
+ attr_reader :id, :scheduled, :home, :home_team, :away,
5
+ :away_team, :status, :venue, :broadcast, :year, :season,
6
+ :date, :period, :clock
7
+
8
+ def initialize(args={})
9
+ xml = args.fetch(:xml)
10
+ @year = args[:year] ? args[:year].to_i : nil
11
+ @season = args[:season] ? args[:season].to_sym : nil
12
+ @date = args[:date]
13
+
14
+ xml = xml.first if xml.is_a? Nokogiri::XML::NodeSet
15
+ if xml.is_a? Nokogiri::XML::Element
16
+ @id = xml['id']
17
+ @scheduled = Time.parse xml['scheduled']
18
+ @home = xml['home_team']
19
+ @away = xml['away_team']
20
+ @status = xml['status']
21
+ @clock = xml['clock']
22
+ @period = xml['period'] ? xml['period'].to_i : nil
23
+
24
+ team_xml = xml.xpath('team')
25
+ @home_team = Team.new(team_xml.first)
26
+ @away_team = Team.new(team_xml.last)
27
+ @venue = Venue.new(xml.xpath('venue'))
28
+ @broadcast = Broadcast.new(xml.xpath('broadcast'))
29
+ end
30
+ end
31
+
32
+ ##
33
+ # Wrapper for Nhl.game_summary
34
+ # TODO
35
+ def summary
36
+ Nhl.game_summary(@id)
37
+ end
38
+
39
+ ##
40
+ # Wrapper for Nhl.pbp (Nhl.play_by_play)
41
+ # TODO
42
+ def pbp
43
+ raise NotImplementedError
44
+ end
45
+
46
+ ##
47
+ # Wrapper for Nhl.boxscore
48
+ # TODO
49
+ def boxscore
50
+ raise NotImplementedError
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,26 @@
1
+ module SportsDataApi
2
+ module Nhl
3
+ class Games
4
+ include Enumerable
5
+ attr_reader :games, :date
6
+
7
+ def initialize(xml)
8
+ @date = xml.first['date']
9
+
10
+ @games = xml.xpath("games/game").map do |game_xml|
11
+ Game.new(date: @date, xml: game_xml)
12
+ end
13
+ end
14
+
15
+ def each &block
16
+ @games.each do |game|
17
+ if block_given?
18
+ block.call game
19
+ else
20
+ yield game
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,31 @@
1
+ module SportsDataApi
2
+ module Nhl
3
+ class Player
4
+ attr_reader :stats
5
+
6
+ def initialize(xml)
7
+ if xml.is_a? Nokogiri::XML::Element
8
+ player_ivar = self.instance_variable_set("@#{xml.name}", {})
9
+ self.class.class_eval { attr_reader :"#{xml.name}" }
10
+ xml.attributes.each do |attr_name, attr_value|
11
+ player_ivar[attr_name.to_sym] = attr_value.value
12
+ end
13
+
14
+ stats_xml = xml.xpath('statistics')
15
+ if stats_xml.is_a? Nokogiri::XML::NodeSet and stats_xml.count > 0
16
+ @stats = SportsDataApi::Stats.new(stats_xml.first)
17
+ end
18
+
19
+ if @stats
20
+ goaltending_xml = xml.xpath('goaltending').first
21
+ if goaltending_xml.is_a? Nokogiri::XML::Element
22
+ goaltending_ivar = @stats.instance_variable_set("@#{goaltending_xml.name}", {})
23
+ @stats.class.class_eval { attr_reader :"#{goaltending_xml.name}" }
24
+ goaltending_xml.attributes.each { |attr_name, attr_value| goaltending_ivar[attr_name.to_sym] = attr_value.value }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ module SportsDataApi
2
+ module Nhl
3
+ class Season
4
+ attr_reader :id, :year, :type, :games
5
+
6
+ def initialize(xml)
7
+ if xml.is_a? Nokogiri::XML::NodeSet
8
+ @id = xml.first["id"]
9
+ @year = xml.first["year"].to_i
10
+ @type = xml.first["type"].to_sym
11
+
12
+ @games = xml.first.xpath("games/game").map do |game_xml|
13
+ Game.new(year: @year, season: @type, xml: game_xml)
14
+ end
15
+ end
16
+ end
17
+
18
+ ##
19
+ # Check if the requested season is a valid
20
+ # NHL season type.
21
+ #
22
+ # The only valid types are: :pre, :reg, :pst
23
+ def self.valid?(season)
24
+ [:PRE, :REG, :PST].include?(season)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,40 @@
1
+ module SportsDataApi
2
+ module Nhl
3
+ class Team
4
+ attr_reader :id, :name, :market, :alias, :conference, :division,
5
+ :stats, :players, :points
6
+
7
+ def initialize(xml, conference = nil, division = nil)
8
+ xml = xml.first if xml.is_a? Nokogiri::XML::NodeSet
9
+ if xml.is_a? Nokogiri::XML::Element
10
+ @id = xml['id']
11
+ @name = xml['name']
12
+ @market = xml['market']
13
+ @alias = xml['alias']
14
+ @points = xml['points'] ? xml['points'].to_i : nil
15
+ @conference = conference
16
+ @division = division
17
+ @players = xml.xpath("players/player").map do |player_xml|
18
+ Player.new(player_xml)
19
+ end
20
+ end
21
+ end
22
+
23
+ ##
24
+ # Compare the Team with another team
25
+ def ==(other)
26
+ # Must have an id to compare
27
+ return false if self.id.nil?
28
+
29
+ if other.is_a? SportsDataApi::Nhl::Team
30
+ return false if other.id.nil?
31
+ self.id === other.id
32
+ elsif other.is_a? Symbol
33
+ self.id.to_sym === other
34
+ else
35
+ super(other)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,83 @@
1
+ module SportsDataApi
2
+ module Nhl
3
+ class Teams
4
+ include Enumerable
5
+
6
+ attr_reader :conferences, :divisions
7
+
8
+ ##
9
+ # Initialize by passing the raw XML returned from the API
10
+ def initialize(xml)
11
+ @teams = []
12
+ xml = xml.first if xml.is_a? Nokogiri::XML::NodeSet
13
+ if xml.is_a? Nokogiri::XML::Element
14
+ xml.xpath('conference').each do |conference|
15
+ # Conference ID, e.g., EASTERN or WESTERN
16
+ cname = conference['alias']
17
+
18
+ conference.xpath('division').each do |division|
19
+ # Division ID, e.g., ATLANTIC, PACIFIC
20
+ dname = division['alias']
21
+
22
+ # Create a new team
23
+ @teams << division.xpath('team').map { |team| Team.new(team, cname, dname) }
24
+ end
25
+ end
26
+ end
27
+
28
+ @teams.flatten!
29
+
30
+ uniq_conferences = @teams.map { |team| team.conference.upcase }.uniq
31
+ @allowed_conferences = uniq_conferences.map { |str| str.to_sym }.concat(uniq_conferences.map { |str| str.downcase.to_sym })
32
+ @conferences = uniq_conferences.map { |conf| conf.to_sym }
33
+
34
+ uniq_divisions = @teams.map { |team| team.division.upcase }.uniq
35
+ @divisions = @teams.map { |team| team.division.to_sym }.uniq
36
+ @allowed_divisions = uniq_divisions.map { |str| str.to_sym }.concat(uniq_divisions.map { |str| str.downcase.to_sym })
37
+ end
38
+
39
+ def [](search_index)
40
+ found_index = @teams.index(search_index)
41
+ unless found_index.nil?
42
+ @teams[found_index]
43
+ end
44
+ end
45
+
46
+ ##
47
+ #
48
+ def respond_to?(method)
49
+ @allowed_conferences.include?(method) || @allowed_divisions.include?(method)
50
+ end
51
+
52
+ ##
53
+ #
54
+ def method_missing(method)
55
+ if @allowed_conferences.include?(method)
56
+ return @teams.select do |team|
57
+ up = team.conference.upcase.to_sym
58
+ dw = team.conference.downcase.to_sym
59
+ up === method || dw === method
60
+ end
61
+ elsif @allowed_divisions.include?(method)
62
+ return @teams.select do |team|
63
+ up = team.division.upcase.to_sym
64
+ dw = team.division.downcase.to_sym
65
+ up === method || dw === method
66
+ end
67
+ end
68
+ end
69
+
70
+ ##
71
+ # Make the class Enumerable
72
+ def each(&block)
73
+ @teams.each do |team|
74
+ if block_given?
75
+ block.call team
76
+ else
77
+ yield team
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end