mlb_terminal 0.0.3 → 0.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/Gemfile.lock +1 -1
- data/README.md +76 -5
- data/bin/mlb +92 -1
- data/lib/mlb_terminal.rb +2 -0
- data/lib/mlb_terminal/game.rb +18 -8
- data/lib/mlb_terminal/globals.rb +57 -0
- data/lib/mlb_terminal/pitcher.rb +44 -0
- data/lib/mlb_terminal/version.rb +1 -1
- metadata +4 -2
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
-
|
1
|
+
nal
|
2
2
|
|
3
3
|
Access to MLB baseball scores in the terminal.
|
4
4
|
|
5
5
|
## Overview
|
6
6
|
|
7
|
-
Don't you just wish you could have a little terminal app to stream out real-time stats for a MLB baseball game? Look no further!
|
7
|
+
Don't you just wish you could have a little terminal app to stream out real-time stats for a MLB baseball game? Look no further! _Please note, the use of this data is subjected to the terms put forth by the MLB. More information can be found here: [http://gdx.mlb.com/components/copyright.txt](http://gdx.mlb.com/components/copyright.txt). You're okay if you're using this data for individual use!_
|
8
8
|
|
9
9
|
### Syntax
|
10
10
|
|
11
11
|
#### Commands
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
*
|
13
|
+
To find out more about a specific command, use `mlb [command] --help` to view the appropriate documentation.
|
14
|
+
|
15
|
+
* `help`: Display global or [command] help documentation.
|
16
|
+
* `games [options]`: Print out a list of scheduled games for the specified date
|
17
|
+
* `game [options] [game_number]`: Print out play-by-play events for a specific game. Use `--pitches` to output realtime pitch trajectory data.
|
16
18
|
|
17
19
|
#### Global options
|
18
20
|
|
@@ -22,6 +24,75 @@ Don't you just wish you could have a little terminal app to stream out real-time
|
|
22
24
|
|
23
25
|
* -t, --trace: Display backtrace when an error occurs
|
24
26
|
|
27
|
+
### Data Output Format
|
28
|
+
|
29
|
+
Each command outputs data in tab-separated format. When outputting data for a game in progress, the application will continue to pipe in data as it is made available.
|
30
|
+
|
31
|
+
#### `games` (Game listings)
|
32
|
+
|
33
|
+
1. Game index. A numbered value unique to the specified date that is referenced in the `game` command.
|
34
|
+
2. Opposing teams. A string containing: `<Away Team> (Wins - Losses) @ <Home Team> (Wins - Losses).
|
35
|
+
3. Starting time and status.
|
36
|
+
4. Current score.
|
37
|
+
|
38
|
+
#### `game` (Game events)
|
39
|
+
|
40
|
+
1. Event time.
|
41
|
+
2. Inning.
|
42
|
+
3. Event number.
|
43
|
+
4. Event description.
|
44
|
+
|
45
|
+
#### `game --pitches` (Pitch events)
|
46
|
+
|
47
|
+
1. Pitch time.
|
48
|
+
2. Inning.
|
49
|
+
3. Top/Bottom of inning.
|
50
|
+
4. Pitcher name.
|
51
|
+
5. Batter name.
|
52
|
+
6. Pitch type. (S-Strike, B-Ball, X-hit)
|
53
|
+
7. X (x). The horizontal location of the pitch as it crosses the home plate. Units: Old Gameday coordinate system
|
54
|
+
8. Y (y). The vertical location of the pitch as it crosses the home plate. Units: Old Gameday coordinate system
|
55
|
+
9. Start speed (start_speed). The initial speed of the pitch. Units: miles per hour
|
56
|
+
10. End speed (end_speed). The speed measured as it crosses the home plate. Units: miles per hour
|
57
|
+
11. Top of Strike Zone (sz_top). The distance from the ground to the top of the strike zone. Units: feet
|
58
|
+
12. Bottom of Strike Zone (sz_bot). The distance from the ground to the bottom of the strike zone. Units: feet
|
59
|
+
13. Horizontal movement (pfx_x). The horizontal movement of a pitch relative to a theoretical pitch thrown at the same speed with no spin-induced movement. Measured at 40 feet from the home plate. Units: inches
|
60
|
+
14. Vertical movement (pfx_z). The vertical movement of a pitch relative to a theoretical pitch thrown at the same speed with no spin-induced movement. Measured at 40 feet from the home plate. Units: inches
|
61
|
+
15. Horizontal pitch location at home plate (px). The horizontal location of the pitch as it crosses home plate from the perspective of the umpire. Units: feet
|
62
|
+
16. Vertical pitch location at home plate (pz). The height of the pitch as it crosses the front of home plate. Units: feet
|
63
|
+
17. Initial horizontal measurement for pitch (x0). Initial horizontal measurement of pitch as measured by PITCHf/x. Units: feet
|
64
|
+
18. Initial depth measurement for pitch (y0). Initial deptch measurement of pitch as measured by PITCHf/x. Note that this is fixed per stadium and typically located around 40-50 feet from home plate. Units: feet
|
65
|
+
19. Initial height measurement for pitch (z0). Initial height measurement of pitch as measured by PITCHf/x. Units: feet
|
66
|
+
20. Initial x velocity (vxo). Initial velocity in the horizontal direction at the initial point. Units: feet per second
|
67
|
+
21. Initial y velocity (vxo). Initial velocity in the depth-wise direction at the initial point. Units: feet per second
|
68
|
+
22. Initial z velocity (vxo). Initial velocity in the vertical direction at the initial point. Units: feet per second
|
69
|
+
23. Breaking point (break_y). The distance from the home plate in which the pitch achieved its greatest deviation from the straight line path between the release point and the front of home plate. Units: feet
|
70
|
+
24. Breaking angle (break_angle). The angle at which the pitch crossed the front of home plate as seen by the umpire. Units: degrees
|
71
|
+
25. Breaking length (break_length). The greatest distance between the pitch's trajectory and the straight path between release and home plate. Units: inches
|
72
|
+
26. Pitch type (pitch_type). Pitch type as classified by the PITCHf/x system.
|
73
|
+
* FA = Fastball
|
74
|
+
* FF = Four-seam fastball
|
75
|
+
* FT = Two-seam fastball
|
76
|
+
* FC = Fastball (cutter)
|
77
|
+
* FS / SI / SF = Fastball (sinker, split-fingered)
|
78
|
+
* SL = Slider
|
79
|
+
* CH = Changeup
|
80
|
+
* CB / CU = Curveball
|
81
|
+
* KC = Knuckle-curve
|
82
|
+
* KN = Knuckleball
|
83
|
+
* EP = Eephus
|
84
|
+
* UN / XX = Unidentified
|
85
|
+
* PO / FO = Pitch out
|
86
|
+
27. Pitch type confidence (type_confidence). A rating corresponding to the liklihood of the pitch type classification.
|
87
|
+
28. Pitch zone (zone).
|
88
|
+
29. Nasty factor (nasty). A auto-generated factor that describes the difficulty in hitting the pitch.
|
89
|
+
30. Spin direction (spin_dir).
|
90
|
+
31. Spin rate (spin_rate).
|
91
|
+
32. Comments (cc).
|
92
|
+
33. Unknown (mt).
|
93
|
+
|
94
|
+
For more information regarding PITCHf/x tracjectory data, please visit [http://fastballs.wordpress.com/category/pitchfx-glossary/](http://fastballs.wordpress.com/category/pitchfx-glossary/).
|
95
|
+
|
25
96
|
### Examples
|
26
97
|
|
27
98
|
> # List todays games
|
data/bin/mlb
CHANGED
@@ -10,7 +10,7 @@ program :description, 'Stream MLB games into the terminal'
|
|
10
10
|
|
11
11
|
command :games do |c|
|
12
12
|
c.syntax = 'mlb games [options] [date]'
|
13
|
-
c.summary = 'Print out a list of scheduled games for the specified date'
|
13
|
+
c.summary = 'Print out a list of scheduled games for the specified date.'
|
14
14
|
c.description = 'Print out a tab-seperated value list to STDOUT wih columns ' \
|
15
15
|
'for index, team names, game status, and current score.'
|
16
16
|
c.example 'description', 'mlb --date "2012-09-28" | grep Nationals'
|
@@ -30,6 +30,97 @@ command :games do |c|
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
command :pitchers do |c|
|
34
|
+
c.syntax = 'mlb pitchers [options] [game-number]'
|
35
|
+
c.summary = 'Print out a list of pitchers for the specified date and game index.'
|
36
|
+
c.description = 'Print out a tab-seperated value list to STDOUT wih columns ' \
|
37
|
+
'for team, pitcher id, and pitcher name. Note, this prints out ' \
|
38
|
+
'the full line-up on the team.'
|
39
|
+
c.example 'description', 'mlb pitchers 11 | grep "Edwin Jackson"'
|
40
|
+
c.option '--date STRING', String, 'List pitchers for specified date (Default: today)'
|
41
|
+
c.action do |args, options|
|
42
|
+
options.default :date => Time.now.to_date.to_s
|
43
|
+
|
44
|
+
# Validate input
|
45
|
+
if (Float(args.first) rescue nil).nil?
|
46
|
+
puts "Error: Game number must be a valid integer"
|
47
|
+
break
|
48
|
+
elsif (args.first.to_i < 0)
|
49
|
+
puts "Error: Game number must be greater than or equal to 0"
|
50
|
+
break
|
51
|
+
end
|
52
|
+
|
53
|
+
game_number = args.first.to_i
|
54
|
+
|
55
|
+
gameday_id = MLBTerminal::Game.list(Date.parse options.date)[game_number][:game_id]
|
56
|
+
|
57
|
+
MLBTerminal::Pitcher.list(gameday_id).each_pair do |pitcher_id, pitcher_info|
|
58
|
+
puts [
|
59
|
+
pitcher_info[:team],
|
60
|
+
pitcher_id,
|
61
|
+
pitcher_info[:name]].join("\t")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
command :pitcher do |c|
|
67
|
+
c.syntax = 'mlb pitcher [options] [game-number] [pitcher-id]'
|
68
|
+
c.summary = 'Print out a list of summary statistics for pitcher tendencies.'
|
69
|
+
c.description = 'Print out a tab-seperated value list to STDOUT wih columns ' \
|
70
|
+
'for pitcher name, pitcher team, date, away team, home team, ' \
|
71
|
+
'pitch count, average speed, pitch type, pitch count, average ' \
|
72
|
+
'movement, pfx, velocity, average initial x-position, and ' \
|
73
|
+
'average initial z-position.'
|
74
|
+
c.example 'description', 'mlb pitchers --date 2012-09-30 11 | grep "Ross Detwiler" ' \
|
75
|
+
'| cut -f 2 | xargs mlb pitcher --date 2012-09-30 11'
|
76
|
+
c.option '--date STRING', String, 'List pitchers for specified date (Default: today)'
|
77
|
+
c.action do |args, options|
|
78
|
+
game_number, pitcher_id = args
|
79
|
+
options.default :date => Time.now.to_date.to_s
|
80
|
+
|
81
|
+
# Validate input
|
82
|
+
if (Float(game_number) rescue nil).nil?
|
83
|
+
puts "Error: Game number must be a valid integer"
|
84
|
+
break
|
85
|
+
elsif (game_number.to_i < 0)
|
86
|
+
puts "Error: Game number must be greater than or equal to 0"
|
87
|
+
break
|
88
|
+
end
|
89
|
+
|
90
|
+
if (Float(pitcher_id) rescue nil).nil?
|
91
|
+
puts "Error: Pitcher ID must be a valid integer"
|
92
|
+
break
|
93
|
+
elsif (pitcher_id.to_i < 0)
|
94
|
+
puts "Error: Pitcher ID must be greater than or equal to 0"
|
95
|
+
break
|
96
|
+
end
|
97
|
+
|
98
|
+
game_number = game_number.to_i
|
99
|
+
games = MLBTerminal::Game.list(Date.parse options.date)
|
100
|
+
gameday_id = games[game_number][:game_id]
|
101
|
+
pitcher = MLBTerminal::Pitcher.new(gameday_id, pitcher_id)
|
102
|
+
|
103
|
+
pitcher.pitch_tendency_history.each do |game|
|
104
|
+
game_info = MLBTerminal::Game.parse_gameday_id(game[:gameday_id])
|
105
|
+
puts [
|
106
|
+
game[:pitcher_name],
|
107
|
+
game[:pitcher_team],
|
108
|
+
Date.new(game_info[:year].to_i, game_info[:month].to_i, game_info[:day].to_i),
|
109
|
+
MLBTerminal::TEAMS[game_info[:away_team].to_sym],
|
110
|
+
MLBTerminal::TEAMS[game_info[:home_team].to_sym],
|
111
|
+
game[:pitch_count],
|
112
|
+
game[:avg_speed],
|
113
|
+
game[:pitch_type],
|
114
|
+
game[:pitch_number],
|
115
|
+
game[:movement],
|
116
|
+
game[:pfx],
|
117
|
+
game[:vel],
|
118
|
+
game[:avg_x0],
|
119
|
+
game[:avg_z0]].join("\t")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
33
124
|
command :game do |c|
|
34
125
|
c.syntax = 'mlb game [options] [game-number]'
|
35
126
|
c.summary = 'Print game events'
|
data/lib/mlb_terminal.rb
CHANGED
data/lib/mlb_terminal/game.rb
CHANGED
@@ -4,7 +4,6 @@ require 'open-uri'
|
|
4
4
|
require 'active_support/core_ext/integer/inflections'
|
5
5
|
|
6
6
|
module MLBTerminal
|
7
|
-
MLB_BASE_URL = 'http://gd2.mlb.com/components/game/mlb'
|
8
7
|
|
9
8
|
class Game
|
10
9
|
def self.list(date = Time.now.to_date)
|
@@ -31,9 +30,7 @@ module MLBTerminal
|
|
31
30
|
end
|
32
31
|
|
33
32
|
def initialize(gameday)
|
34
|
-
@
|
35
|
-
year, month, day, game_name = /([0-9]{4})_([0-9]{2})_([0-9]{2})_(.*)/.match(@gameday).to_a.slice(1,4)
|
36
|
-
@base_url = "#{Game.base_url_for_date(Date.new(year.to_i, month.to_i, day.to_i))}/gid_#{@gameday}"
|
33
|
+
@base_url = Game.parse_gameday_id_to_url gameday
|
37
34
|
end
|
38
35
|
|
39
36
|
def events(delay = 5, &block)
|
@@ -59,9 +56,8 @@ module MLBTerminal
|
|
59
56
|
|
60
57
|
last_atbat = doc.xpath("//game/inning/*/atbat/@num").map(&:value).map(&:to_i).max
|
61
58
|
|
62
|
-
sleep delay
|
63
|
-
|
64
59
|
if doc.xpath("//game").first["ind"] != "F"
|
60
|
+
sleep delay
|
65
61
|
doc = Nokogiri::HTML(open "#{@base_url}/inning/inning_all.xml")
|
66
62
|
end
|
67
63
|
end while game_status != "F"
|
@@ -125,9 +121,8 @@ module MLBTerminal
|
|
125
121
|
|
126
122
|
last_pitch = doc.xpath("//game/inning/*/*/pitch/@id").map(&:value).map(&:to_i).max
|
127
123
|
|
128
|
-
sleep delay
|
129
|
-
|
130
124
|
if doc.xpath("//game").first["ind"] != "F"
|
125
|
+
sleep delay
|
131
126
|
doc = Nokogiri::HTML(open "#{@base_url}/inning/inning_all.xml")
|
132
127
|
end
|
133
128
|
end while game_status != "F"
|
@@ -138,6 +133,21 @@ module MLBTerminal
|
|
138
133
|
"#{MLB_BASE_URL}/year_#{date.year}/month_#{"%02d" % date.month}/day_#{"%02d" % date.day}"
|
139
134
|
end
|
140
135
|
|
136
|
+
def self.parse_gameday_id_to_url(gameday)
|
137
|
+
game_info = Game.parse_gameday_id gameday
|
138
|
+
"#{Game.base_url_for_date(Date.new(game_info[:year].to_i, game_info[:month].to_i, game_info[:day].to_i))}/gid_" \
|
139
|
+
"#{game_info[:year]}_" \
|
140
|
+
"#{game_info[:month]}_" \
|
141
|
+
"#{game_info[:day]}_" \
|
142
|
+
"#{game_info[:away_team]}mlb_" \
|
143
|
+
"#{game_info[:home_team]}mlb_" \
|
144
|
+
"#{game_info[:game_number]}"
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.parse_gameday_id(gameday)
|
148
|
+
Hash[[:year, :month, :day, :away_team, :home_team, :game_number].zip(/[gid_]*([0-9]{4})_([0-9]{2})_([0-9]{2})_([a-z]{3})mlb_([a-z]{3})mlb_([0-9])/.match(gameday).to_a.slice(1,6))]
|
149
|
+
end
|
150
|
+
|
141
151
|
private
|
142
152
|
|
143
153
|
def player_lookup
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module MLBTerminal
|
2
|
+
|
3
|
+
MLB_BASE_URL = 'http://gd2.mlb.com/components/game/mlb'
|
4
|
+
|
5
|
+
TEAMS = {
|
6
|
+
:ana => "Los Angeles Angels",
|
7
|
+
:ari => "Arizona Diamondbacks",
|
8
|
+
:atl => "Atlanta Braves",
|
9
|
+
:bal => "Baltimore Orioles",
|
10
|
+
:bos => "Boston Red Sox",
|
11
|
+
:cha => "Chicago White Sox",
|
12
|
+
:chn => "Chicago Cubs",
|
13
|
+
:cin => "Cincinnati Reds",
|
14
|
+
:cle => "Cleveland Indians",
|
15
|
+
:col => "Colorado Rockies",
|
16
|
+
:det => "Detroit Tigers",
|
17
|
+
:hou => "Houston Astros",
|
18
|
+
:kca => "Kansas City Royals",
|
19
|
+
:lan => "Los Angeles Dodgers",
|
20
|
+
:mia => "Miami Marlins",
|
21
|
+
:mil => "Milwaukee Brewers",
|
22
|
+
:min => "Minnesota Twins",
|
23
|
+
:nya => "New York Yankees",
|
24
|
+
:nyn => "New York Mets",
|
25
|
+
:oak => "Oakland Athletics",
|
26
|
+
:phi => "Philadelphia Phillies",
|
27
|
+
:pit => "Pittsburgh Pirates",
|
28
|
+
:sdn => "San Diego Padres",
|
29
|
+
:sea => "Seattle Mariners",
|
30
|
+
:sfn => "San Francisco Giants",
|
31
|
+
:sln => "Saint Louis Cardinals",
|
32
|
+
:tba => "Tampa Bay Rays",
|
33
|
+
:tex => "Texas Rangers",
|
34
|
+
:tor => "Toronto Blue Jays",
|
35
|
+
:was => "Washington Nationals"}
|
36
|
+
|
37
|
+
PITCH_TYPES = {
|
38
|
+
"FA" => "Fastball",
|
39
|
+
"FF" => "Four-seam Fastball",
|
40
|
+
"FT" => "Two-seam Fastball",
|
41
|
+
"FC" => "Fastball / Cutter",
|
42
|
+
"FS" => "Fastball / Sinker",
|
43
|
+
"SI" => "Sinker",
|
44
|
+
"SF" => "Split-Fingered Fastball",
|
45
|
+
"SL" => "Slider",
|
46
|
+
"CH" => "Changeup",
|
47
|
+
"CB" => "Curveball",
|
48
|
+
"CU" => "Curveball",
|
49
|
+
"KC" => "Kunckle-curve",
|
50
|
+
"KN" => "Kunckleball",
|
51
|
+
"EP" => "Eephus",
|
52
|
+
"UN" => "Unidentified",
|
53
|
+
"XX" => "Unidentified",
|
54
|
+
"PO" => "Pitch out",
|
55
|
+
"FO" => "Pitch out"}
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module MLBTerminal
|
5
|
+
class Pitcher
|
6
|
+
|
7
|
+
def self.list(gameday)
|
8
|
+
base_url = MLBTerminal::Game.parse_gameday_id_to_url gameday
|
9
|
+
doc = Nokogiri::HTML(open( "#{base_url}/players.xml"))
|
10
|
+
Hash[doc.xpath("//game/team/player[@position='P']").map{|x| [x["id"], {:team => x.xpath("..").first["name"], :name => "#{x["first"]} #{x["last"]}"}]}]
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(gameday, pitcher_id)
|
14
|
+
@base_url = "#{MLBTerminal::Game.parse_gameday_id_to_url gameday}/premium/pitchers/#{pitcher_id}"
|
15
|
+
pitcher = Pitcher.list(gameday)[pitcher_id]
|
16
|
+
@team = pitcher[:team]
|
17
|
+
@name = pitcher[:name]
|
18
|
+
end
|
19
|
+
|
20
|
+
def pitch_tendency_history(&block)
|
21
|
+
doc = Nokogiri::HTML(open( "#{@base_url}/pitchtendencies_history.xml"))
|
22
|
+
|
23
|
+
Enumerator.new do |y|
|
24
|
+
doc.xpath("//pitchtendencies/games/game").each do |game|
|
25
|
+
game.xpath("types/type").each do |type|
|
26
|
+
y.yield({
|
27
|
+
:pitcher_name => @name,
|
28
|
+
:pitcher_team => @team,
|
29
|
+
:gameday_id => game["id"],
|
30
|
+
:pitch_count => game["num"],
|
31
|
+
:avg_speed => game["vel"],
|
32
|
+
:pitch_type => PITCH_TYPES[type["id"]],
|
33
|
+
:pitch_number => type["num"],
|
34
|
+
:movement => type["movement"],
|
35
|
+
:pfx => type["pfx"],
|
36
|
+
:vel => type["vel"],
|
37
|
+
:avg_x0 => type["avg_x0"],
|
38
|
+
:avg_z0 => type["avg_z0"] })
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end.each(&block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/mlb_terminal/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mlb_terminal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: commander
|
@@ -77,6 +77,8 @@ files:
|
|
77
77
|
- bin/mlb
|
78
78
|
- lib/mlb_terminal.rb
|
79
79
|
- lib/mlb_terminal/game.rb
|
80
|
+
- lib/mlb_terminal/globals.rb
|
81
|
+
- lib/mlb_terminal/pitcher.rb
|
80
82
|
- lib/mlb_terminal/version.rb
|
81
83
|
- mlb_terminal.gemspec
|
82
84
|
homepage: https://github.com/slnovak/mlb_terminal
|