hoopscrape 1.0.4

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.
data/README.md ADDED
@@ -0,0 +1,390 @@
1
+ <img style='width:100%' src='./readme/logo-hoopscrape.png' />
2
+ hoopscrape is not associated with ESPN or the NBA
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/hoopscrape.svg)](https://badge.fury.io/rb/hoopscrape)
5
+ [![Code Climate](https://codeclimate.com/github/meissadia/hoopscrape/badges/gpa.svg)](https://codeclimate.com/github/meissadia/hoopscrape)
6
+ [![Build Status](https://travis-ci.org/meissadia/hoopscrape.svg?branch=master)](https://travis-ci.org/meissadia/hoopscrape)
7
+ [![Test Coverage](https://codeclimate.com/github/meissadia/hoopscrape/badges/coverage.svg)](https://codeclimate.com/github/meissadia/hoopscrape/coverage)
8
+
9
+ ## Table of Contents
10
+ + [Introduction](#introduction)
11
+ + [Installation](#installation)
12
+ + [Rails](#rails)
13
+ + [Manual](#manual)
14
+ + [Arrays, Hashes or Structs](#arrays-hashes-or-structs)
15
+ + [Working With Multiple Formats](#working-with-multiple-formats)
16
+ + [Default format](#default-format)
17
+ + [Same data using Hashes](#same-data-using-hashes)
18
+ + [Same data using Structs](#same-data-using-structs)
19
+ + [Customize Field Names for Hash and Struct Conversion](#customize-field-names-for-hash-and-struct-conversion)
20
+ + [Default As Template](#default-as-template)
21
+ + [Overwrite Default](#overwrite-default)
22
+ + [Working with Navigators](#working-with-navigators)
23
+ + [Navigator Methods](#navigator-methods)
24
+ + [Data Access](#data-access)
25
+ + [NBA Team List](#nba-team-list)
26
+ + [Boxscore](#boxscore)
27
+ + [Player Data](#player-data)
28
+ + [Team Data](#team-data)
29
+ + [Roster](#roster)
30
+ + [Player](#player)
31
+ + [Schedule](#schedule)
32
+ + [Past Schedule Games as Structs](#past-schedule-games-as-structs)
33
+ + [Future Schedule Games as Structs](#future-schedule-games-as-structs)
34
+ + [Select a specific Season Type](#select-a-specific-season-type)
35
+ + [Select Historic Schedule data](#select-historic-schedule-data)
36
+ + [Chaining it all together](#chaining-it-all-together)
37
+ + [Documentation](#documentation)
38
+ + [Requirements](#requirements)
39
+ + [Ruby version](#ruby-version)
40
+ + [Dependencies](#dependencies)
41
+ + [Testing](#testing)
42
+ + [Contributing](#contributing)
43
+
44
+
45
+ ## Introduction
46
+ The hoopscrape Ruby gem is a scraper for NBA data.
47
+ It provides a number of ways to simplify data interaction, including :
48
+ + Structs - Intuitively access data via dot notation.
49
+ + Hashes - Pass data directly to ActiveRecord CRUD methods for easy database interaction.
50
+ + String arrays - Raw data for you to manipulate as you see fit.
51
+
52
+ Version 1.0.4
53
+ + NbaBoxScore: Update failed tests to utilize pattern matching.
54
+
55
+ + Please report any [issues] you encounter!
56
+
57
+
58
+ ## Installation
59
+ #### Rails
60
+ In your application&#39;s Gemfile, include :
61
+
62
+ ```
63
+ gem 'hoopscrape'
64
+ ```
65
+ In your project dir, execute :
66
+
67
+ ```
68
+ $ bundle install
69
+ ```
70
+ #### Manual
71
+ ```
72
+ $ gem install hoopscrape
73
+ ```
74
+ ## Arrays, Hashes or Structs
75
+ If you intend to work with a single format, you can specify it at initialization. When working with multiple formats you should start with the default and convert as necessary using [Array#to_structs] or [Array#to_hashes].
76
+
77
+ ```ruby
78
+ require 'hoopscrape'
79
+ hs = HoopScrape.new # String Arrays
80
+ hs_h = HoopScrape.new(format: :to_hashes) # Hash Arrays
81
+ hs_s = HoopScrape.new(format: :to_structs) # Struct Arrays
82
+ ```
83
+ #### Working With Multiple Formats
84
+ Arrays can easily be converted to Hashes or Structs
85
+
86
+ ##### Default format
87
+ ```ruby
88
+ hs = HoopScrape.new
89
+ bs = es.boxscore(400828991) # Return an NbaBoxscore object
90
+ stats = bs.homePlayers # Returns a multidimensional array of Home Player stats
91
+ stats[4][2] # Player Name # => 'R. Hood'
92
+ stats[4][20] # Player Points # => '30'
93
+ ```
94
+ ##### Same data using Hashes
95
+ ```ruby
96
+ s_hashes = stats.to_hashes # Returns array of Hashes
97
+ s_hashes[4][:name] # Player Name # => 'R. Hood'
98
+ s_hashes[4][:points] # Player Points # => '30'
99
+ ```
100
+ ##### Same data using Structs
101
+ ```ruby
102
+ s_structs = stats.to_structs # Returns array of Structs
103
+ s_structs[4].name # Player Name # => 'R. Hood'
104
+ s_structs[4].points # Player Points # => '30'
105
+ ```
106
+ #### Customize Field Names for Hash and Struct Conversion
107
+ The [Array#to_hashes] and [Array#to_structs] methods can be passed an array of Symbols
108
+ to use in place of the default field names.
109
+
110
+ ```ruby
111
+ team_list = HoopScrape.teamList
112
+ team_list_s = t.to_structs([:abbrev, :long_team_name, :div, :conf]) # New Field Names
113
+ team_list_s.last.long_team_name # => 'Utah Jazz'
114
+ ```
115
+ Defaults are defined in the [SymbolDefaults] module.
116
+ You can overwrite them or use them as templates, replacing individual symbols using
117
+ the [Array#change_sym!] method.
118
+
119
+ ##### Default As Template
120
+ `Safe method`
121
+
122
+ ```ruby
123
+ my_names = S_ROSTER.dup.change_sym!(:p_name, :full_name).change_sym!(:salary, :crazy_money)
124
+ players = HoopScrape.roster('CLE').players.to_structs(my_names)
125
+ players[3].full_name # => 'LeBron James'
126
+ players[3].crazy_money # => '22970500'
127
+ ```
128
+ ##### Overwrite Default
129
+ `Note: Changes affect all instances of hoopscrape`
130
+
131
+ ```ruby
132
+ S_TEAM # => [:team, :name, :division, :conference]
133
+ S_TEAM.replace [:short, :long, :div, :conf]
134
+ t = HoopScrape.teamList.to_structs
135
+
136
+ t.first.short # => 'BOS'
137
+ t.first.long # => 'Boston Celtics'
138
+ ```
139
+ ## Working with Navigators
140
+ Table data is wrapped in a [Navigator] class which provides helper methods for moving through the table. The type of object the Navigator returns matches the format provided at hoopscrape instantiation.
141
+
142
+ Note: Data converted using [Array#to_structs] or [Array#to_hashes] is not wrapped in a Navigator.
143
+
144
+ ### Navigator Methods
145
+ ```ruby
146
+ # <Navigator> A Navigator for Home Player Stats Table
147
+ navigator = HoopScrape.boxscore(400878158).homePlayers
148
+
149
+ navigator[] # Array<Object> Returns the underlying Array of the Navigator
150
+ navigator[5] # <Object> 6th row of data
151
+ navigator.size # <Fixnum> Number of table rows
152
+ navigator.first # <Object> Access the first data row
153
+ navigator.last # <Object> Access the last data row
154
+ navigator.next # <Object> Access the next data row (nil if there is no more data)
155
+ navigator.curr # <Object> Access the current data row (nil at initialization)
156
+ navigator.prev # <Object> Access the previous data row (nil if there is no more data)
157
+ ```
158
+ ## Data Access
159
+ ### NBA Team List
160
+ ```ruby
161
+ hs = HoopScrape.new
162
+ team_list = es.teamList # multidimensional array of Team info
163
+ team_list.last # => ['UTA', 'Utah Jazz', 'Northwest', 'Western']
164
+ team_list.last[0] # => 'UTA'
165
+ team_list.last[1] # => 'Utah Jazz'
166
+ team_list.last[2] # => 'Northwest'
167
+ team_list.last[3] # => 'Western'
168
+ ```
169
+ ### Boxscore
170
+ Boxscore #homePlayers, #awayPlayers return a [Navigator]
171
+
172
+ ```ruby
173
+ hs = HoopScrape.new(format: :to_structs)
174
+ bs = es.boxscore(400875892) # Return an NbaBoxscore object
175
+
176
+ bs.id # <String> Boxscore ID # => '400875892'
177
+ bs.gameDate # <String> Game DateTime # => '2016-05-07 00:00:00'
178
+
179
+ bs.homeName # <String> Full Team Name
180
+ bs.homeScore # <String> Team Score
181
+ bs.homeTotals # <Object> Access the cumulative team totals
182
+ bs.homePlayers # <Navigator> A Navigator for Home Player Stats Table
183
+
184
+ bs.awayName # <String> Full Team Name
185
+ bs.awayScore # <String> Team Score
186
+ bs.awayTotals # <Object> Access the cumulative team totals
187
+ bs.awayPlayers # <Navigator> A Navigator for Home Player Stats Table
188
+ ```
189
+ ##### Player Data
190
+ ```ruby
191
+ wade = bs.homePlayers[4] # <Object> of data for Row 5
192
+
193
+ wade.team # <String> Team ID # => 'MIA'
194
+ wade.id # <String> Player ID # => '1987'
195
+ wade.name # <String> Short Name # => 'D. Wade'
196
+ wade.position # <String> Position # => 'SG'
197
+ wade.minutes # <String> Minutes # => '36'
198
+ wade.fgm # <String> Shots Made # => '13'
199
+ wade.fga # <String> Shots Attempted # => '25'
200
+ wade.tpm # <String> 3P Made # => '4'
201
+ wade.tpa # <String> 3P Attempted # => '6'
202
+ wade.ftm # <String> Freethrows Made # => '8'
203
+ wade.fta # <String> Freethrows Att. # => '8'
204
+ wade.oreb # <String> Offensive Reb. # => '1'
205
+ wade.dreb # <String> Defensive Reb. # => '7'
206
+ wade.rebounds # <String> Total Rebounds # => '8'
207
+ wade.assists # <String> Assists # => '4'
208
+ wade.steals # <String> Steals # => '0'
209
+ wade.blocks # <String> Blocks # => '0'
210
+ wade.tos # <String> Turnovers # => '4'
211
+ wade.fouls # <String> Personal Fouls # => '1'
212
+ wade.plusminus # <String> Plus/Minus # => '-8'
213
+ wade.points # <String> Points # => '38'
214
+ wade.starter # <String> Starter? # => 'true'
215
+ ```
216
+ ##### Team Data
217
+ ```ruby
218
+ miami = bs.homeTotals # <Object> Access the team totals
219
+ miami.team
220
+ miami.fgm
221
+ miami.fga
222
+ miami.tpm
223
+ miami.tpa
224
+ miami.ftm
225
+ miami.fta
226
+ miami.oreb
227
+ miami.dreb
228
+ miami.rebounds
229
+ miami.assists
230
+ miami.steals
231
+ miami.blocks
232
+ miami.turnovers
233
+ miami.fouls
234
+ miami.points
235
+ ```
236
+ ### Roster
237
+ Roster #players is a [Navigator].
238
+
239
+ ```ruby
240
+ roster = es.roster('UTA')
241
+ r_hash = es.roster('UTA', format: :to_hashes) # Pre-format players data
242
+ players = roster.players # Returns multidimensional array of Roster info
243
+ coach = roster.coach # Coach Name # => 'Quinn Snyder'
244
+
245
+ # Roster as an array of objects
246
+ players = players.to_structs # Returns array of Structs
247
+
248
+ players[2].team # Team ID # => 'UTA'
249
+ players[2].jersey # Jersey Number # => '11'
250
+ players[2].name # Name # => 'Alec Burks'
251
+ players[2].id # ID # => '6429'
252
+ players[2].position # Position # => 'SG'
253
+ players[2].age # Age # => '24'
254
+ players[2].height_ft # Height (ft) # => '6'
255
+ players[2].height_in # Height (in) # => '6'
256
+ players[2].salary # Salary # => '9463484'
257
+ players[2].weight # Weight # => '214'
258
+ players[2].college # College # => 'Colorado'
259
+ players[2].salary # Salary # => '9463484'
260
+ ```
261
+ ### Player
262
+ ```ruby
263
+ player = es.player(2991473) # Returns an NbaPlayer object
264
+ player.name #=> "Anthony Bennett"
265
+ player.age #=> "23"
266
+ player.weight #=> "245"
267
+ player.college #=> "UNLV"
268
+ player.height_ft #=> "6"
269
+ player.height_in #=> "8"
270
+ ```
271
+ ### Schedule
272
+ Schedule #allGames, #pastGames, #futureGames return a [Navigator]
273
+
274
+ ```ruby
275
+ schedule = es.schedule('UTA') # Gets latest available year and season type data
276
+ schedule = es.schedule('LAC', format: :to_structs) # Pre-format data (:to_hashes / :to_structs)
277
+ schedule = es.schedule('SAS', year: 2005) # Gets historical data for season ending in 2005
278
+ schedule = es.schedule('POR', season: 1) # Get specific season type (1 Pre/ 2 Regular/3 Post)
279
+
280
+ schedule.nextGame # <Object> Next unplayed game info
281
+ schedule.lastGame # <Object> Previously completed game info
282
+ schedule.nextTeamId # <String> Team ID of next opponent # => 'OKC'
283
+ schedule.nextGameId # <Fixnum> Index of next unplayed game
284
+
285
+ schedule.pastGames[] # Completed Games : [Object]
286
+ schedule.futureGames[] # Upcoming Games : [Object]
287
+
288
+ past = schedule.pastGames # Completed Games : <Navigator>
289
+ future = schedule.futureGames # Upcoming Games : <Navigator>
290
+ ```
291
+ ##### Past Schedule Games as Structs
292
+ ```ruby
293
+ past = schedule.pastGames # Completed Games : <Navigator>
294
+ game = past.next # <Object> Game info
295
+ game.team # Team ID
296
+ game.game_num # Game # in Season
297
+ game.date # Game Date
298
+ game.home # Home?
299
+ game.opponent # Opponent ID
300
+ game.win # Win?
301
+ game.team_score # Team Score
302
+ game.opp_score # Opponent Score
303
+ game.boxscore_id # Boxscore ID
304
+ game.wins # Team Win Count
305
+ game.losses # Team Loss Count
306
+ game.datetime # Game DateTime
307
+ game.season_type # Season Type
308
+ ```
309
+ ##### Future Schedule Games as Structs
310
+ ```ruby
311
+ future = schedule.futureGames # Upcoming Games : <Navigator>
312
+ game = future.next # <Object> Game info
313
+ game.team # Team ID
314
+ game.game_num # Game # in Season
315
+ game.date # Game Date
316
+ game.home # Home?
317
+ game.opponent # Opponent ID
318
+ game.time # Game Time
319
+ game.win # Win?
320
+ game.tv # Game on TV?
321
+ game.opp_score # Opponent Score
322
+ game.datetime # Game DateTime
323
+ game.season_type # Season Type
324
+ ```
325
+ ##### Select a specific Season Type
326
+ ```ruby
327
+ preseason = es.schedule('BOS', season: 1) # Get Preseason schedule
328
+ regular = es.schedule('NYK', season: 2) # Get Regular schedule
329
+ playoffs = es.schedule('OKC', season: 3) # Get Playoff schedule
330
+ ```
331
+ ##### Select Historic Schedule data
332
+ The year parameter should correspond to the year in which the season ended.
333
+
334
+ ```ruby
335
+ schedule = es.schedule('SAS', year: 2005) # Data for 2004-05 Season
336
+ ```
337
+ ## Chaining it all together
338
+ ```ruby
339
+ # Get a Boxscore from a past game
340
+ HoopScrape.schedule('OKC', season: 2).allGames[42].boxscore(:to_structs).awayPlayers.first.name
341
+
342
+ # Get a Roster from a Team ID
343
+ HoopScrape.boxscore(400827977).homeTotals[0].roster(:to_hashes).players.first[:name]
344
+
345
+ 'cle'.roster(:to_structs).players.next.position
346
+
347
+ # Get a Schedule from a Team ID
348
+ HoopScrape.teamList.last[0].schedule(:to_hashes).lastGame.boxscore
349
+
350
+ 'gsw'.schedule(:to_structs).lastGame.boxscore
351
+ ```
352
+ ## Documentation
353
+ Available on [RubyDoc.info] or locally:
354
+
355
+ ```
356
+ $ yard doc
357
+ $ yard server
358
+ ```
359
+ ## Requirements
360
+ ### Ruby version
361
+
362
+ - Ruby &gt;= 1.9.3
363
+
364
+ ### Dependencies
365
+
366
+ - Nokogiri ~> 1.6
367
+ - Rake
368
+ - minitest
369
+
370
+ ## Testing
371
+ ```
372
+ $ rake
373
+ ```
374
+
375
+ ## Contributing
376
+
377
+ Bug reports and pull requests are welcome on GitHub at https://github.com/meissadia/hoopscrape
378
+ <br>
379
+ <br>
380
+ <br>
381
+ &copy; 2016 Meissa Dia
382
+
383
+ [CHANGELOG]: ./CHANGELOG.md
384
+ [RubyDoc.info]: http://www.rubydoc.info/gems/hoopscrape/1.0.0
385
+ [Navigator]: http://www.rubydoc.info/gems/hoopscrape/1.0.0/Navigator
386
+ [Array#to_structs]: http://www.rubydoc.info/gems/hoopscrape/1.0.0/Array#to_structs-instance_method
387
+ [Array#to_hashes]: http://www.rubydoc.info/gems/hoopscrape/1.0.0/Array#to_hashes-instance_method
388
+ [Array#change_sym!]: http://www.rubydoc.info/gems/hoopscrape/1.0.0/Array#change_sym%21-instance_method
389
+ [SymbolDefaults]: ./lib/hoopscrape/SymbolDefaults.rb
390
+ [issues]: https://github.com/meissadia/hoopscrape/issues
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake/testtask'
2
+ Dir.glob('lib/tasks/*.rake').each { |r| load r }
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ end
7
+
8
+ desc 'Run tests'
9
+ task default: :test
10
+
11
+ desc 'Open documentation'
12
+ task :show_docs do
13
+ ['README.md', 'CHANGELOG.md', 'coverage/index.html', 'rubocop/report.html'].each do |doc|
14
+ `open #{doc} -a "Google Chrome"`
15
+ end
16
+ end
17
+
18
+ desc 'Push latest version of gem to remote server'
19
+ task :deploy_gem do
20
+ gemfile = `ls -t1 *.gem | head -n 1`
21
+ puts `gem push #{gemfile}`
22
+ end
data/lib/hoopscrape.rb ADDED
@@ -0,0 +1,113 @@
1
+ require_relative 'hoopscrape/requires'
2
+
3
+ # HoopScrape main class
4
+ class HoopScrape
5
+ # Gem Version
6
+ VERSION = '1.0.4'.freeze
7
+ # initialize
8
+ def initialize(config = {})
9
+ @format = defaultFormat(config[:format])
10
+ end
11
+
12
+ # Returns an {NbaBoxScore} object
13
+ # @param game_id [Integer] Boxscore ID
14
+ # @return [NbaBoxScore] NbaBoxScore
15
+ # @example
16
+ # HoopScrape.boxscore(493848273)
17
+ def self.boxscore(game_id, f_mat = nil)
18
+ NbaBoxScore.new(game_id: game_id,
19
+ format: defaultFormat(f_mat))
20
+ end
21
+
22
+ # Returns an {NbaBoxScore} object
23
+ # @param (see .boxscore)
24
+ # @return (see .boxscore)
25
+ # @example
26
+ # es.boxscore(493848273)
27
+ def boxscore(game_id, f_mat = nil)
28
+ HoopScrape.boxscore game_id, (f_mat || @format)
29
+ end
30
+
31
+ # Returns an {NbaRoster} object
32
+ # @param team_id [String] Team ID
33
+ # @return [NbaRoster] NbaRoster
34
+ # @example
35
+ # HoopScrape.roster('UTA')
36
+ def self.roster(team_id, options = {})
37
+ NbaRoster.new(team_id: team_id,
38
+ format: defaultFormat(options.fetch(:format, nil)))
39
+ end
40
+
41
+ # Returns an {NbaRoster} object
42
+ # @param (see .roster)
43
+ # @return (see .roster)
44
+ # @example
45
+ # es.roster('UTA')
46
+ # es.roster('UTA', format: :to_structs)
47
+ def roster(team_id, options = {})
48
+ HoopScrape.roster team_id, format: (options.fetch(:format, nil) || @format)
49
+ end
50
+
51
+ # Return Array of Team Data
52
+ # @return [[[String]]] NBA Team Data
53
+ # @example
54
+ # HoopScrape.teamList(:to_structs)
55
+ def self.teamList(f_mat = nil)
56
+ NbaTeamList.new(format: defaultFormat(f_mat)).teamList
57
+ end
58
+
59
+ # Return Array of Team Data
60
+ # @return (see .teamList)
61
+ # @example
62
+ # es.teamList(:to_structs)
63
+ def teamList(f_mat = nil)
64
+ HoopScrape.teamList(f_mat || @format)
65
+ end
66
+
67
+ # Return an {NbaSchedule} object
68
+ # @param team_id [String] Team ID
69
+ # @param options[:season] [Int] Season Type
70
+ # @param options[:year] [Int] Ending Year of Season (i.e. 2016 for 2015-16)
71
+ # @param options[:format] [Sym] Table Format (:to_structs/:to_hashes)
72
+ # @return [NbaSchedule] NbaSchedule
73
+ # @example
74
+ # HoopScrape.schedule('UTA') # Schedule for Latest Season Type
75
+ # HoopScrape.schedule('TOR', s_type: 3) # Playoff Schedule
76
+ def self.schedule(team_id, options = {})
77
+ NbaSchedule.new team_id: team_id,
78
+ season_type: options[:season],
79
+ format: defaultFormat(options[:format]),
80
+ year: options[:year]
81
+ end
82
+
83
+ # Return an {NbaSchedule} object
84
+ # @param (see .schedule)
85
+ # @return (see .schedule)
86
+ # @example
87
+ # es.schedule('MIA') # Schedule for Latest Season Type
88
+ # es.schedule('DET', season: 1, year: 2016) # Preseason Schedule
89
+ def schedule(team_id, options = {})
90
+ HoopScrape.schedule team_id,
91
+ season: options[:season],
92
+ format: (options[:format] || @format),
93
+ year: options[:year]
94
+ end
95
+
96
+ # Return new {NbaPlayer} object
97
+ # @param espn_id [String] ESPN Player ID
98
+ # @return [NbaPlayer] NbaPlayer
99
+ # @example
100
+ # HoopScrape.player(2991473)
101
+ def self.player(espn_id)
102
+ NbaPlayer.new espn_id
103
+ end
104
+
105
+ # Return new {NbaPlayer} object
106
+ # @param (see .player)
107
+ # @return (see .player)
108
+ # @example
109
+ # es.player(2991473)
110
+ def player(espn_id)
111
+ HoopScrape.player espn_id
112
+ end
113
+ end