sports_data_api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ # YARD artifacts
20
+ .yardoc
21
+ _yardoc
22
+ doc/
23
+
24
+ # OSX artifacts
25
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.rvmrc ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p194@sports-data"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.14.11 (stable)" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
+ \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
+ if [[ $- == *i* ]] # check for interactive shells
29
+ then echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green
30
+ else echo "Using: $GEM_HOME" # don't use colors in non-interactive shells
31
+ fi
32
+ else
33
+ # If the environment file has not yet been created, use the RVM CLI to select.
34
+ rvm --create use "$environment_id" || {
35
+ echo "Failed to create RVM environment '${environment_id}'."
36
+ return 1
37
+ }
38
+ fi
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sports_data_api.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/LICENSE.md ADDED
@@ -0,0 +1,24 @@
1
+
2
+ Copyright (c) 2012 Ryan Lovelett ( [@rlovelett](http://twitter.com/#!/rlovelett) )
3
+ =================================================================================================
4
+
5
+ The "SportsDataApi" RubyGem is released under the **MIT LICENSE**
6
+ ----------------------------------------------------------
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in
16
+ all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # SportsDataApi [![Build Status](https://travis-ci.org/RLovelett/sports_data_api.png?branch=master)](https://travis-ci.org/RLovelett/sports_data_api)
2
+
3
+ SportsDataApi is an attempt to make a Ruby interface to the
4
+ [SportsData](http://www.sportsdatallc.com/) API. The goal is to
5
+ eventaully support the full API. Pull requests that extend the API
6
+ support are always welcome.
7
+
8
+ [SportsData](http://www.sportsdatallc.com/)’s comprehensive data coverage includes all major U.S. sports,
9
+ plus hundreds of leagues throughout the world. Their live game analysts
10
+ capture every possible event of every game, in real time and with
11
+ accuracy standards developed from years of experience.
12
+
13
+ ## Author
14
+
15
+ [Ryan Lovelett](http://ryan.lovelett.me/) ( [@rlovelett](http://twitter.com/#!/rlovelett) )
16
+
17
+ Drop me a message for any questions, suggestions, requests, bugs or
18
+ submit them to the [issue
19
+ log](https://github.com/rlovelett/sports_data_api/issues).
20
+
21
+ ## API Support
22
+
23
+ * [NFL](http://developer.sportsdatallc.com/docs/NFL_API)
24
+ * TODO
25
+ 1. [MLB](http://developer.sportsdatallc.com/docs/MLB_API)
26
+ 2. [NHL](http://developer.sportsdatallc.com/docs/NHL_API)
27
+ 3. [NBA](http://developer.sportsdatallc.com/docs/NBA_API)
28
+ 4. [NCAA Basketball](http://developer.sportsdatallc.com/docs/NCAA_Mens_Backetball)
29
+ 5. [NCAA Football](http://developer.sportsdatallc.com/docs/NCAA_Football_API)
30
+
31
+ ## Installation
32
+
33
+ Add this line to your application's Gemfile:
34
+
35
+ gem 'sports_data_api'
36
+
37
+ And then execute:
38
+
39
+ $ bundle
40
+
41
+ Or install it yourself as:
42
+
43
+ $ gem install sports_data_api
44
+
45
+ ## Usage
46
+
47
+ The specs for this Gem should give you some idea of how to make use of
48
+ the API. For now they will be the usage information. As always Pull
49
+ Requests for better documentation are always welcome.
50
+
51
+ ## Contributing
52
+
53
+ 1. Fork it
54
+ 2. Create a topic branch (`git checkout -b topic`)
55
+ 3. Make your changes
56
+ 4. Squash your changes into one commit
57
+ 5. Create new Pull Request against this squashed commit
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
data/lib/nfl.rb ADDED
@@ -0,0 +1,90 @@
1
+ module SportsDataApi
2
+ module Nfl
3
+
4
+ class Exception < ::Exception
5
+ end
6
+
7
+ class Season
8
+ attr_reader :year, :type, :weeks
9
+
10
+ def initialize(xml)
11
+ @weeks = []
12
+ if xml.is_a? Nokogiri::XML::NodeSet
13
+ @year = xml.first["season"].to_i
14
+ @type = xml.first["type"].to_sym
15
+ @weeks = xml.first.xpath("week").map do |week_xml|
16
+ Week.new(week_xml)
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ class Week
23
+ attr_reader :number, :games
24
+
25
+ def initialize(xml)
26
+ @games = []
27
+ if xml.is_a? Nokogiri::XML::Element
28
+ @number = xml["week"].to_i
29
+ @games = xml.xpath("game").map do |game_xml|
30
+ Game.new(game_xml)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ class Game
37
+ attr_reader :id, :scheduled, :home, :away, :status
38
+
39
+ def initialize(xml)
40
+ if xml.is_a? Nokogiri::XML::Element
41
+ @id = xml["id"]
42
+ @scheduled = Time.parse xml["scheduled"]
43
+ @home = xml["home"]
44
+ @away = xml["away"]
45
+ @status = xml["status"]
46
+ end
47
+ end
48
+ end
49
+
50
+ BASE_URL = "http://api.sportsdatallc.org/nfl-%{access_level}%{version}"
51
+ SEASONS = [:PRE, :REG, :PST]
52
+
53
+ def self.schedule(year, season, version = 1)
54
+ base_url = BASE_URL % { access_level: SportsDataApi.access_level, version: version }
55
+ season = season.to_s.upcase.to_sym
56
+ raise SportsDataApi::Nfl::Exception.new("#{season} is not a valid season") unless season?(season)
57
+ url = "#{base_url}/#{year}/#{season}/schedule.xml"
58
+
59
+ begin
60
+ # Perform the request
61
+ response = RestClient.get(url, params: { api_key: SportsDataApi.key })
62
+
63
+ # Load the XML and ignore namespaces in Nokogiri
64
+ schedule = Nokogiri::XML(response.to_s)
65
+ schedule.remove_namespaces!
66
+
67
+ return Season.new(schedule.xpath("/season"))
68
+ rescue RestClient::Exception => e
69
+ message = if e.response.headers.key? :x_server_error
70
+ JSON.parse(error_json, { symbolize_names: true })[:message]
71
+ elsif e.response.headers.key? :x_mashery_error_code
72
+ e.response.headers[:x_mashery_error_code]
73
+ else
74
+ "The server did not specify a message"
75
+ end
76
+ raise SportsDataApi::Exception, message
77
+ end
78
+ end
79
+
80
+ ##
81
+ # Check if the requested season is a valid
82
+ # NFL season type.
83
+ #
84
+ # The only valid types are: :PRE, :REG, :PST
85
+ def self.season?(season)
86
+ SEASONS.include?(season)
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,3 @@
1
+ module SportsDataApi
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,18 @@
1
+ require "sports_data_api/version"
2
+ require "nokogiri"
3
+ require "rest_client"
4
+ require "time"
5
+
6
+ module SportsDataApi
7
+ def self.key
8
+ "garbage"
9
+ end
10
+
11
+ def self.access_level
12
+ "t"
13
+ end
14
+
15
+ autoload :Nfl, File.join(File.dirname(__FILE__), 'nfl')
16
+
17
+ class Exception < ::Exception; end
18
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe SportsDataApi::Nfl do
4
+ let(:key) { "1234567890abcdef" }
5
+ describe ".schedule" do
6
+ it "creates a valid Sports Data LLC url" do
7
+ SportsDataApi.stub(:key).and_return(key)
8
+ RestClient.stub(:get).with("http://api.sportsdatallc.org/nfl-t1/2012/REG/schedule.xml", params: { api_key: key }).and_return(schedule_xml)
9
+ subject.schedule(2012, :REG)
10
+ end
11
+ it "creates a SportsDataApi::Exception when there is no response from the api" do
12
+ error = RestClient::ResourceNotFound.new
13
+ error.stub_chain(:response, :headers).and_return(Hash.new)
14
+ SportsDataApi.stub(:key).and_return(key)
15
+ RestClient.stub(:get).and_raise(error)
16
+ expect { subject.schedule(2999, :REG) }.to raise_error(SportsDataApi::Exception)
17
+ end
18
+
19
+ describe "returned data structures" do
20
+ before(:each) { RestClient.stub(:get).and_return(schedule_xml) }
21
+ let(:season) { SportsDataApi::Nfl.schedule(2012, :REG) }
22
+ describe "SportsDataApi::Nfl::Season" do
23
+ subject { season }
24
+ it { should be_an_instance_of(SportsDataApi::Nfl::Season) }
25
+ its(:year) { should eq 2012 }
26
+ its(:type) { should eq :REG }
27
+ its(:weeks) { should have(17).weeks }
28
+ end
29
+ describe "SportsDataApi::Nfl::Week" do
30
+ subject { season.weeks.first }
31
+ it { should be_an_instance_of(SportsDataApi::Nfl::Week) }
32
+ its(:number) { should eq 1 }
33
+ its(:games) { should have(16).games }
34
+ end
35
+ describe "SportsDataApi::Nfl::Game" do
36
+ subject { season.weeks.first.games.first }
37
+ it { should be_an_instance_of(SportsDataApi::Nfl::Game) }
38
+ its(:id) { should eq "8c0bce5a-7ca2-41e5-9838-d1b8c356ddc3" }
39
+ its(:scheduled) { should eq Time.new(2012, 9, 5, 19, 30, 00, "-05:00") }
40
+ its(:home) { should eq "NYG" }
41
+ its(:away) { should eq "DAL" }
42
+ its(:status) { should eq "closed" }
43
+ end
44
+ end
45
+ end
46
+
47
+ describe ".season?" do
48
+ context :PRE do
49
+ it { subject.season?(:PRE).should be_true }
50
+ end
51
+ context :REG do
52
+ it { subject.season?(:REG).should be_true }
53
+ end
54
+ context :PST do
55
+ it { subject.season?(:PST).should be_true }
56
+ end
57
+ context :pre do
58
+ it { subject.season?(:pre).should be_false }
59
+ end
60
+ context :reg do
61
+ it { subject.season?(:reg).should be_false }
62
+ end
63
+ context :pst do
64
+ it { subject.season?(:pst).should be_false }
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,28 @@
1
+ require "sports_data_api"
2
+
3
+ # This file was generated by the `rspec --init` command. Conventionally, all
4
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
+ # Require this file using `require "spec_helper"` to ensure that it is only
6
+ # loaded once.
7
+ #
8
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
9
+
10
+ def load_xml(filename)
11
+ File.read("#{File.dirname(__FILE__)}/xml/#{filename}.xml")
12
+ end
13
+
14
+ def schedule_xml
15
+ load_xml("schedule")
16
+ end
17
+
18
+ RSpec.configure do |config|
19
+ config.treat_symbols_as_metadata_keys_with_true_values = true
20
+ config.run_all_when_everything_filtered = true
21
+ config.filter_run :focus
22
+
23
+ # Run specs in random order to surface order dependencies. If you find an
24
+ # order dependency and want to debug it, you can fix the order by providing
25
+ # the seed, which is printed after each run.
26
+ # --seed 1234
27
+ config.order = 'random'
28
+ end
data/spec/xml/game.xml ADDED
@@ -0,0 +1,69 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- Generation started at Fri Nov 02 02:27:02 +0000 2012 -->
3
+ <game xmlns="http://feed.elasticstats.com/schema/nfl/boxscore-v1.0.xsd" id="82748625-c24e-437a-b991-cab7f766c249" scheduled="2012-11-02T00:20:00+00:00" home="SD" away="KC" status="inprogress" quarter="3" clock=":53">
4
+ <team id="SD" name="Chargers" market="San Diego" remaining_challenges="2" remaining_timeouts="3">
5
+ <scoring points="10">
6
+ <quarter number="1" points="7"/>
7
+ <quarter number="2" points="3"/>
8
+ <quarter number="3" points="0"/>
9
+ </scoring>
10
+ </team>
11
+ <team id="KC" name="Chiefs" market="Kansas City" remaining_challenges="2" remaining_timeouts="3">
12
+ <scoring points="6">
13
+ <quarter number="1" points="0"/>
14
+ <quarter number="2" points="3"/>
15
+ <quarter number="3" points="3"/>
16
+ </scoring>
17
+ </team>
18
+ <scoring_drives>
19
+ <drive sequence="1" clock="15:00" quarter="1" team="SD">
20
+ <score type="touchdown" clock="10:31" quarter="1" points="6">
21
+ <summary>
22
+ <![CDATA[17-P.Rivers complete to 85-A.Gates. 85-A.Gates runs 14 yards for a touchdown.]]>
23
+ </summary>
24
+ <links>
25
+ <link rel="summary" href="/2012/REG/9/KC/SD/plays/fb5c3b6f-be0a-4f3f-819e-f1134204e312.xml" type="application/xml"/>
26
+ </links>
27
+ </score>
28
+ <score type="extrapoint" clock="10:24" quarter="1" points="1">
29
+ <summary>
30
+ <![CDATA[9-N.Novak extra point is good.]]>
31
+ </summary>
32
+ <links>
33
+ <link rel="summary" href="/2012/REG/9/KC/SD/plays/cecb31f7-febb-470d-b833-b32b9411fa95.xml" type="application/xml"/>
34
+ </links>
35
+ </score>
36
+ </drive>
37
+ <drive sequence="2" clock="02:18" quarter="1" team="SD">
38
+ <score type="fieldgoal" clock="09:13" quarter="2" points="3">
39
+ <summary>
40
+ <![CDATA[9-N.Novak 25 yards Field Goal is Good.]]>
41
+ </summary>
42
+ <links>
43
+ <link rel="summary" href="/2012/REG/9/KC/SD/plays/2036be2d-f58b-4290-9e45-2e171c37588e.xml" type="application/xml"/>
44
+ </links>
45
+ </score>
46
+ </drive>
47
+ <drive sequence="3" clock="09:10" quarter="2" team="KC">
48
+ <score type="fieldgoal" clock="02:56" quarter="2" points="3">
49
+ <summary>
50
+ <![CDATA[6-R.Succop 49 yards Field Goal is Good.]]>
51
+ </summary>
52
+ <links>
53
+ <link rel="summary" href="/2012/REG/9/KC/SD/plays/68de7467-99b7-4e87-939d-7dc9b90c0462.xml" type="application/xml"/>
54
+ </links>
55
+ </score>
56
+ </drive>
57
+ <drive sequence="4" clock="07:09" quarter="3" team="KC">
58
+ <score type="fieldgoal" clock=":58" quarter="3" points="3">
59
+ <summary>
60
+ <![CDATA[6-R.Succop 41 yards Field Goal is Good.]]>
61
+ </summary>
62
+ <links>
63
+ <link rel="summary" href="/2012/REG/9/KC/SD/plays/35b31551-62ce-430b-8d1e-4153a1e81483.xml" type="application/xml"/>
64
+ </links>
65
+ </score>
66
+ </drive>
67
+ </scoring_drives>
68
+ </game>
69
+ <!-- Generation finished at Fri Nov 02 02:27:02 +0000 2012 -->