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 CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mlb_terminal (0.0.2)
4
+ mlb_terminal (0.0.4)
5
5
  activesupport (~> 3.2.8)
6
6
  commander (~> 4.1.2)
7
7
  nokogiri (~> 1.5.5)
data/README.md CHANGED
@@ -1,18 +1,20 @@
1
- # MLB Terminal
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
- * help: Display global or [command] help documentation.
14
- * games: Print out a list of scheduled games for the specified date
15
- * game: Print out play-by-play events for a specific game. Use `--pitches` to output realtime pitch trajectory data.
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
@@ -1,2 +1,4 @@
1
+ require 'mlb_terminal/globals'
1
2
  require 'mlb_terminal/version'
2
3
  require 'mlb_terminal/game'
4
+ require 'mlb_terminal/pitcher'
@@ -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
- @gameday = gameday
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
@@ -1,3 +1,3 @@
1
1
  module MLBTerminal
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
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.3
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-09-30 00:00:00.000000000 Z
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