nba 0.0.3 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -5
- data/README.md +31 -18
- data/Rakefile +1 -0
- data/bin/nba +7 -0
- data/lib/faraday_middleware/scrape_game.rb +14 -2
- data/lib/nba.rb +1 -0
- data/lib/nba/cli.rb +35 -0
- data/lib/nba/game.rb +22 -6
- data/lib/nba/player.rb +10 -6
- data/lib/nba/team.rb +95 -63
- data/lib/nba/version.rb +1 -1
- data/nba.gemspec +2 -1
- data/spec/fixtures/games.html +785 -0
- data/spec/fixtures/teams.json +16529 -0
- data/spec/game_spec.rb +40 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/team_spec.rb +93 -0
- metadata +29 -6
- data/spec/nba_spec.rb +0 -73
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b953637ba9292b6414aec1db167b451df894d354
|
4
|
+
data.tar.gz: 4d7ba14450b621e09958d41009d7e883a04ab6fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc1baeadf0c937313ac2053e5c53758ee69f30713d6f772b5818ef673855275a20720452d573c21adb7ca04ac9d470253e54ba73a3f26a4d32e6828fa642fa35
|
7
|
+
data.tar.gz: e8a6da21617c53615298400d32ef93f01633933c1ed5fbe4709c42358d9501ff31003a314b3b16941e71fe9ab84cf82cd90abdcf866959090e78c6fb66408cc6
|
data/.travis.yml
CHANGED
@@ -6,17 +6,12 @@ before_install:
|
|
6
6
|
bundler_args: --without development
|
7
7
|
language: ruby
|
8
8
|
rvm:
|
9
|
-
- 1.8.7
|
10
|
-
- 1.9.2
|
11
9
|
- 1.9.3
|
12
10
|
- 2.0.0
|
13
11
|
- 2.1.0
|
14
|
-
- rbx
|
15
12
|
- ruby-head
|
16
13
|
matrix:
|
17
14
|
include:
|
18
|
-
- rvm: jruby-18mode
|
19
|
-
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
20
15
|
- rvm: jruby-19mode
|
21
16
|
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
22
17
|
- rvm: jruby-head
|
data/README.md
CHANGED
@@ -17,6 +17,36 @@ Insipred by [@sferik][sferik]'s [MLB.rb][mlb].
|
|
17
17
|
gem install nba
|
18
18
|
|
19
19
|
## Usage Examples
|
20
|
+
You could use `nba` command-line tool directly in your terminal.
|
21
|
+
|
22
|
+
$ nba games --date=20140102
|
23
|
+
Final/OT - Cavaliers 87 : 81 Magic
|
24
|
+
Final - Heat 114 : 123 Warriors
|
25
|
+
Final - Bulls 94 : 82 Celtics
|
26
|
+
Final - Thunder 93 : 95 Nets
|
27
|
+
Final - Spurs 101 : 105 Knicks
|
28
|
+
Final - Suns 91 : 99 Grizzlies
|
29
|
+
Final - Jazz 96 : 87 Bucks
|
30
|
+
Final - Trail Blazers 134 : 104 Bobcats
|
31
|
+
Final - Kings 104 : 113 76ers
|
32
|
+
$ nba teams --name 'Lakers'
|
33
|
+
Name: Los Angeles Lakers
|
34
|
+
Founded: 1947
|
35
|
+
Conference: Western Conference
|
36
|
+
Division: Pacific Division
|
37
|
+
Coach: Mike D'Antoni
|
38
|
+
Championships: 2010 NBA Finals, 2009 NBA Finals
|
39
|
+
2002 NBA Finals, 2001 NBA Finals
|
40
|
+
2000 NBA Finals, 1988 NBA Finals
|
41
|
+
1987 NBA Finals, 1985 NBA Finals
|
42
|
+
1982 NBA Finals, 1980 NBA Finals
|
43
|
+
1972 NBA Finals, 1954 NBA Finals
|
44
|
+
1953 NBA Finals, 1952 NBA Finals
|
45
|
+
1950 NBA Finals, 1949 BAA Finals
|
46
|
+
1948 NBL Finals
|
47
|
+
|
48
|
+
Or you could use it in `irb`, which is an Interactive Ruby Shell
|
49
|
+
|
20
50
|
$ irb
|
21
51
|
>> require 'nba'
|
22
52
|
>> NBA::Game.all '20140102'
|
@@ -39,30 +69,13 @@ Insipred by [@sferik][sferik]'s [MLB.rb][mlb].
|
|
39
69
|
This library aims to support and is [tested against][travis] the following Ruby
|
40
70
|
implementations:
|
41
71
|
|
42
|
-
* Ruby 1.8.7
|
43
|
-
* Ruby 1.9.2
|
44
72
|
* Ruby 1.9.3
|
45
73
|
* Ruby 2.0.0
|
46
74
|
* Ruby 2.1.0
|
47
|
-
* [Rubinius][]
|
48
75
|
* [JRuby][]
|
49
76
|
|
50
|
-
[rubinius]: http://rubini.us/
|
51
77
|
[jruby]: http://jruby.org/
|
52
78
|
|
53
|
-
If something doesn't work on one of these interpreters, it's a bug.
|
54
|
-
|
55
|
-
This library may inadvertently work (or seem to work) on other Ruby
|
56
|
-
implementations, however support will only be provided for the versions listed
|
57
|
-
above.
|
58
|
-
|
59
|
-
If you would like this library to support another Ruby version, you may
|
60
|
-
volunteer to be a maintainer. Being a maintainer entails making sure all tests
|
61
|
-
run and pass on that implementation. When something breaks on your
|
62
|
-
implementation, you will be responsible for providing patches in a timely
|
63
|
-
fashion. If critical issues for a particular implementation exist at the time
|
64
|
-
of a major release, support for that Ruby version may be dropped.
|
65
|
-
|
66
79
|
## Colophon
|
67
80
|
NBA was built with the following tools:
|
68
81
|
|
@@ -86,7 +99,7 @@ And, special thanks to [@sfeirk][sferik]!
|
|
86
99
|
|
87
100
|
## Contributing
|
88
101
|
|
89
|
-
1. Fork it
|
102
|
+
1. [Fork it](http://github.com/larrylv/nba/fork)
|
90
103
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
91
104
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
92
105
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/Rakefile
CHANGED
data/bin/nba
ADDED
@@ -7,12 +7,24 @@ module FaradayMiddleware
|
|
7
7
|
doc = Nokogiri::HTML.parse body
|
8
8
|
doc.css('.score-row .mod-content').inject([]) do |results, game_node|
|
9
9
|
home_team_node = game_node.css('.home').first
|
10
|
-
home_team = home_team_node.css('p.team-name').first.search('a').first.content
|
11
10
|
home_score = home_team_node.css('.finalScore').first.content
|
11
|
+
home_team_name_node = home_team_node.css('p.team-name').first
|
12
|
+
begin
|
13
|
+
home_team = home_team_name_node.search('a').first.content
|
14
|
+
rescue
|
15
|
+
# some teams may change their name, so the old team has no links.
|
16
|
+
home_team = home_team_name_node.search('span').first.content
|
17
|
+
end
|
12
18
|
|
13
19
|
away_team_node = game_node.css('.away').first
|
14
|
-
away_team = away_team_node.css('p.team-name').first.search('a').first.content
|
15
20
|
away_score = away_team_node.css('.finalScore').first.content
|
21
|
+
away_team_name_node = away_team_node.css('p.team-name').first
|
22
|
+
begin
|
23
|
+
away_team = away_team_name_node.search('a').first.content
|
24
|
+
rescue
|
25
|
+
# some teams may change their name, so the old team has no links.
|
26
|
+
away_team = away_team_name_node.search('span').first.content
|
27
|
+
end
|
16
28
|
|
17
29
|
status = game_node.css('.game-status').first.search('p').first.content
|
18
30
|
|
data/lib/nba.rb
CHANGED
data/lib/nba/cli.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module NBA
|
4
|
+
class CLI < Thor
|
5
|
+
desc "games DATE", "Retrieve games' scoreboard of date"
|
6
|
+
method_option :date, :aliases => '-d', :desc => "format: YYYYMMDD"
|
7
|
+
def games
|
8
|
+
if options[:date].nil? || options[:date] == 'today'
|
9
|
+
game_date_in_et = (Time.now.utc - 5 * 60 * 60).strftime("%Y%m%d")
|
10
|
+
elsif options[:date] == 'yesterday'
|
11
|
+
game_date_in_et = (Time.now.utc - (5 + 24) * 60 * 60).strftime("%Y%m%d")
|
12
|
+
else
|
13
|
+
game_date_in_et = options[:date]
|
14
|
+
end
|
15
|
+
|
16
|
+
Game.all(game_date_in_et)
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "teams", "Retrieve teams' info, with players' info if `-p` arg is passed"
|
20
|
+
method_option :name, :type => :string, :aliases => "-n", :required => true
|
21
|
+
method_option :players, :type => :boolean, :aliases => "-p", :default => false
|
22
|
+
def teams
|
23
|
+
team_results = Team.all.select { |team| team.name =~ %r|#{options[:name]}|i }
|
24
|
+
|
25
|
+
if team_results.count == 0
|
26
|
+
puts "No team founded with name #{options[:name]}"
|
27
|
+
else
|
28
|
+
team_results.each do |team|
|
29
|
+
team.pretty_print
|
30
|
+
puts "-" * 42
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/nba/game.rb
CHANGED
@@ -16,19 +16,33 @@ module NBA
|
|
16
16
|
# >> Final - Trail Blazers 134 : 104 Bobcats
|
17
17
|
# >> Final - Kings 104 : 113 76ers
|
18
18
|
def self.all(date = (Time.now.utc - 5 * 60 * 60).strftime("%Y%m%d"))
|
19
|
-
|
20
|
-
|
19
|
+
results = scoreboard(date)
|
20
|
+
|
21
|
+
if results == 'fail'
|
22
|
+
puts "Fail to fetch game scoreboard/schedule!"
|
23
|
+
else
|
24
|
+
puts scoreboard(date).join("\n")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.scoreboard(date = (Time.now.utc - 5 * 60 * 60).strftime("%Y%m%d"))
|
29
|
+
begin
|
30
|
+
format_games(results_to_game(results_from_espn(date)))
|
31
|
+
rescue Faraday::Error::ConnectionFailed, Faraday::Error::TimeoutError, Errno::EHOSTUNREACH
|
32
|
+
"fail"
|
33
|
+
end
|
21
34
|
end
|
22
35
|
|
23
36
|
def pretty_format(options = {})
|
24
37
|
self.status.center(options[:status_length].to_i + 1) + " - " + \
|
25
38
|
self.home_team.center(options[:home_length].to_i + 1) + " " + \
|
26
|
-
|
27
|
-
|
39
|
+
self.home_score.center(options[:home_score].to_i + 1) + " : " + \
|
40
|
+
self.away_score.center(options[:away_score].to_i + 1) + " " + \
|
28
41
|
self.away_team.center(options[:away_length].to_i + 1)
|
29
42
|
end
|
30
43
|
|
31
44
|
private
|
45
|
+
|
32
46
|
def initialize(attributes = {})
|
33
47
|
attributes.each do |key, value|
|
34
48
|
instance_variable_set("@#{key}", value) if self.respond_to?(key)
|
@@ -39,13 +53,15 @@ module NBA
|
|
39
53
|
{
|
40
54
|
:status_length => games.map(&:status).map(&:length).max,
|
41
55
|
:home_length => games.map(&:home_team).map(&:length).max,
|
56
|
+
:home_score => games.map(&:home_score).map(&:length).max,
|
42
57
|
:away_length => games.map(&:away_team).map(&:length).max,
|
58
|
+
:away_score => games.map(&:away_score).map(&:length).max
|
43
59
|
}
|
44
60
|
end
|
45
61
|
|
46
|
-
def self.
|
62
|
+
def self.format_games(games)
|
47
63
|
length_options = length_options_of(games)
|
48
|
-
|
64
|
+
games.map { |game| game.pretty_format(length_options) }
|
49
65
|
end
|
50
66
|
|
51
67
|
def self.results_to_game(results)
|
data/lib/nba/player.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module NBA
|
2
2
|
class Player
|
3
|
-
attr_reader :name, :number, :
|
3
|
+
attr_reader :name, :number, :positions, :from, :to
|
4
4
|
|
5
5
|
def initialize(attributes = {})
|
6
6
|
attributes.each do |key, value|
|
@@ -8,15 +8,19 @@ module NBA
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
def pretty_print
|
12
|
+
"#{self.name}, number #{self.number}, position: #{self.positions.join(', ')}"
|
13
|
+
end
|
14
|
+
|
11
15
|
# Returns an array of Player objects given a team roster
|
12
16
|
def self.all_from_roster(players)
|
13
17
|
players.select{ |player| player['to'].nil? }.map do |player|
|
14
18
|
new(
|
15
|
-
:name
|
16
|
-
:number
|
17
|
-
:
|
18
|
-
:from
|
19
|
-
:to
|
19
|
+
:name => player['player'],
|
20
|
+
:number => player['number'].to_i,
|
21
|
+
:positions => player['position'],
|
22
|
+
:from => player['from'].to_i,
|
23
|
+
:to => "Present"
|
20
24
|
)
|
21
25
|
end
|
22
26
|
end
|
data/lib/nba/team.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
|
1
4
|
module NBA
|
2
5
|
class Team
|
3
6
|
attr_reader :name, :founded, :conference, :division, :championships, :players, :head_coach, :team_stats
|
@@ -27,77 +30,106 @@ module NBA
|
|
27
30
|
@all = nil
|
28
31
|
end
|
29
32
|
|
30
|
-
|
33
|
+
ADJUST_WIDTH = 16
|
34
|
+
def pretty_print
|
35
|
+
puts "%#{ADJUST_WIDTH}s: #{self.name}" % "Name"
|
36
|
+
puts "%#{ADJUST_WIDTH}s: #{self.founded}" % "Founded"
|
37
|
+
puts "%#{ADJUST_WIDTH}s: #{self.conference}" % "Conference"
|
38
|
+
puts "%#{ADJUST_WIDTH}s: #{self.division}" % "Division"
|
39
|
+
puts "%#{ADJUST_WIDTH}s: #{self.coach}" % "Coach"
|
40
|
+
puts "%#{ADJUST_WIDTH}s: #{pretty_print_championships}" % "Championships"
|
41
|
+
puts "%#{ADJUST_WIDTH}s: #{pretty_print_players}" % "Players"
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
31
45
|
|
32
|
-
|
33
|
-
|
34
|
-
|
46
|
+
def initialize(attributes = {})
|
47
|
+
attributes.each do |key, value|
|
48
|
+
instance_variable_set("@#{key}", value) if self.respond_to?(key)
|
49
|
+
end
|
35
50
|
end
|
36
|
-
end
|
37
51
|
|
38
|
-
|
39
|
-
|
40
|
-
Request.get_teams('/freebase/v1/mqlread', options)
|
41
|
-
end
|
52
|
+
def pretty_print_championships
|
53
|
+
idx = 0
|
42
54
|
|
43
|
-
|
44
|
-
|
45
|
-
|
55
|
+
self.championships.sort.reverse.each_slice(2).inject("") do |string, chams|
|
56
|
+
string << "\n" + (" " * (ADJUST_WIDTH + 2)) if (idx += 1) != 1
|
57
|
+
string << chams.join(", ")
|
58
|
+
end
|
59
|
+
end
|
46
60
|
|
47
|
-
|
48
|
-
|
49
|
-
end
|
61
|
+
def pretty_print_players
|
62
|
+
idx = 0
|
50
63
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
64
|
+
self.players.sort_by{|p| -p.number}.reverse.inject("") do |string, player|
|
65
|
+
string << "\n" + (" " * (ADJUST_WIDTH + 2)) if (idx += 1) != 1
|
66
|
+
string << player.pretty_print
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.results_from_freebase
|
71
|
+
options = {:query => mql_query}
|
72
|
+
Request.get_teams('/freebase/v1/mqlread', options)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.results_from_cache
|
76
|
+
JSON.load(file_from_cache('teams.json').read)
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.file_from_cache(file_name)
|
80
|
+
File.new(File.expand_path('../../../cache', __FILE__) + '/' + file_name)
|
65
81
|
end
|
66
|
-
end
|
67
82
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
"
|
90
|
-
"
|
91
|
-
"
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
"
|
83
|
+
def self.results_to_team(results)
|
84
|
+
results['result'].map do |result|
|
85
|
+
players = result['/sports/sports_team/roster']
|
86
|
+
|
87
|
+
new(
|
88
|
+
:name => result['name'],
|
89
|
+
:conference => result['/basketball/basketball_team/conference'],
|
90
|
+
:division => result['/basketball/basketball_team/division'],
|
91
|
+
:head_coach => result['/basketball/basketball_team/head_coach'],
|
92
|
+
:team_stats => result['/basketball/basketball_team/team_stats'],
|
93
|
+
:founded => result['/sports/sports_team/founded'].to_i,
|
94
|
+
:championships => result['/sports/sports_team/championships'],
|
95
|
+
:players => (players ? Player.all_from_roster(players) : [])
|
96
|
+
)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns the MQL query for teams, as a Ruby hash
|
101
|
+
def self.mql_query
|
102
|
+
query = <<-eos
|
103
|
+
[{
|
104
|
+
"name": null,
|
105
|
+
"mid": null,
|
106
|
+
"/basketball/basketball_team/head_coach": null,
|
107
|
+
"/basketball/basketball_team/conference": null,
|
108
|
+
"/basketball/basketball_team/division": null,
|
109
|
+
"/sports/sports_team/founded": null,
|
110
|
+
"/sports/sports_team/championships": [],
|
111
|
+
"/sports/sports_team/roster": [{
|
112
|
+
"number": null,
|
113
|
+
"player": null,
|
114
|
+
"from": null,
|
115
|
+
"to": null,
|
116
|
+
"position": [],
|
117
|
+
"sort": "player"
|
118
|
+
}],
|
119
|
+
"/basketball/basketball_team/team_stats": [{
|
120
|
+
"optional": true,
|
121
|
+
"season": null,
|
122
|
+
"wins": null,
|
123
|
+
"losses": null
|
124
|
+
}],
|
125
|
+
"sort": "name",
|
126
|
+
"type": "/basketball/basketball_team",
|
127
|
+
"/sports/sports_team/league": [{
|
128
|
+
"league": "National Basketball Association"
|
129
|
+
}]
|
97
130
|
}]
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
131
|
+
eos
|
132
|
+
query.gsub!("\n", '')
|
133
|
+
end
|
102
134
|
end
|
103
135
|
end
|