gameday_api 0.5.0 → 0.5.1
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/lib/at_bat.rb +40 -0
- data/lib/batter.rb +101 -0
- data/lib/batting_appearance.rb +55 -0
- data/lib/box_score.rb +197 -0
- data/lib/cache_fetcher.rb +31 -0
- data/lib/coach.rb +16 -0
- data/lib/data_downloader.rb +231 -0
- data/lib/db_importer.rb +205 -0
- data/lib/event.rb +14 -0
- data/lib/event_log.rb +103 -0
- data/lib/game.rb +529 -0
- data/lib/game_status.rb +6 -0
- data/lib/gameday.rb +58 -0
- data/lib/gameday_fetcher.rb +245 -0
- data/lib/gameday_local_fetcher.rb +236 -0
- data/lib/gameday_parser.rb +305 -0
- data/lib/gameday_path_builder.rb +132 -0
- data/lib/gameday_remote_fetcher.rb +292 -0
- data/lib/gameday_url_builder.rb +125 -0
- data/lib/gameday_util.rb +136 -0
- data/lib/hip.rb +18 -0
- data/lib/hitchart.rb +26 -0
- data/lib/import_data.rb +8 -0
- data/lib/inning.rb +52 -0
- data/lib/line_score.rb +38 -0
- data/lib/media.rb +35 -0
- data/lib/media_highlight.rb +33 -0
- data/lib/media_mobile.rb +13 -0
- data/lib/pitch.rb +92 -0
- data/lib/pitcher.rb +131 -0
- data/lib/pitchfx_db_manager.rb +393 -0
- data/lib/pitching_appearance.rb +118 -0
- data/lib/player.rb +145 -0
- data/lib/players.rb +42 -0
- data/lib/roster.rb +61 -0
- data/lib/schedule.rb +53 -0
- data/lib/schedule_game.rb +24 -0
- data/lib/scoreboard.rb +23 -0
- data/lib/team.rb +336 -0
- metadata +42 -3
@@ -0,0 +1,118 @@
|
|
1
|
+
|
2
|
+
# This class holds data that represents a single pitching appearance by a pitcher.
|
3
|
+
class PitchingAppearance
|
4
|
+
|
5
|
+
attr_accessor :pid, :gid, :pitcher_name, :out, :inn, :er, :r, :h, :so, :hr, :bb, :bf
|
6
|
+
attr_accessor :w, :l, :era, :note, :start, :game
|
7
|
+
attr_accessor :pitches, :b, :s, :x, :max_speed, :min_speed
|
8
|
+
|
9
|
+
# Used to initialize from box score data
|
10
|
+
def init(gid, element, count)
|
11
|
+
@pitches = []
|
12
|
+
@gid = gid
|
13
|
+
@pid = element.attributes['id']
|
14
|
+
@pitcher_name = element.attributes['name']
|
15
|
+
@out = element.attributes['out']
|
16
|
+
@inn = convert_out_to_inn(element.attributes['out'])
|
17
|
+
@bf = element.attributes['bf']
|
18
|
+
@er = element.attributes['er']
|
19
|
+
@r = element.attributes['r']
|
20
|
+
@h = element.attributes['h']
|
21
|
+
@so = element.attributes['so']
|
22
|
+
@hr = element.attributes['hr']
|
23
|
+
@bb = element.attributes['bb']
|
24
|
+
@w = element.attributes['w']
|
25
|
+
@l = element.attributes['l']
|
26
|
+
@era = element.attributes['era']
|
27
|
+
@note = element.attributes['note']
|
28
|
+
if count == 1
|
29
|
+
@start = true
|
30
|
+
else
|
31
|
+
@start = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# Returns true if this appearance is a start
|
37
|
+
def start?
|
38
|
+
start
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# Returns true if this was a quality start
|
43
|
+
# A quality start is defined as being greater than or equal to 6 innings and allowing 3 runs or less
|
44
|
+
def quality_start?
|
45
|
+
if @inn.to_i >= 6 && @r.to_i < 4
|
46
|
+
return true
|
47
|
+
end
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# Returns an array of the atbats against this pitcher during this game
|
53
|
+
def get_vs_ab
|
54
|
+
results = []
|
55
|
+
abs = get_game.get_atbats
|
56
|
+
abs.each do |ab|
|
57
|
+
if ab.pitcher_id == @pid
|
58
|
+
results << ab
|
59
|
+
end
|
60
|
+
end
|
61
|
+
results
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Returns an array of pitches thrown by this pitcher during this game
|
66
|
+
def get_pitches
|
67
|
+
@pitches = []
|
68
|
+
ab = get_vs_ab
|
69
|
+
ab.each do |ab|
|
70
|
+
@pitches << ab.pitches
|
71
|
+
end
|
72
|
+
@pitches.flatten!
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
def set_pitch_stats
|
77
|
+
@b, @s, @x, @max_speed, @min_speed = 0, 0, 0, 0, 200
|
78
|
+
pitches = get_pitches
|
79
|
+
pitches.each do |pitch|
|
80
|
+
case pitch.type
|
81
|
+
when 'B'
|
82
|
+
@b += 1
|
83
|
+
when 'S'
|
84
|
+
@s += 1
|
85
|
+
when 'X'
|
86
|
+
@x += 1
|
87
|
+
end
|
88
|
+
if pitch.start_speed.to_f > @max_speed
|
89
|
+
@max_speed = pitch.start_speed.to_f
|
90
|
+
end
|
91
|
+
if pitch.start_speed.to_f < @min_speed
|
92
|
+
@min_speed = pitch.start_speed.to_f
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def pitch_count
|
99
|
+
get_pitches.length
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def get_game
|
104
|
+
if !@game
|
105
|
+
@game = Game.new(@gid)
|
106
|
+
end
|
107
|
+
@game
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
private
|
112
|
+
def convert_out_to_inn(outs)
|
113
|
+
num_out = outs.to_i
|
114
|
+
part = num_out % 3
|
115
|
+
return (num_out/3).to_s + '.' + part.to_s
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
data/lib/player.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'gameday_fetcher'
|
2
|
+
|
3
|
+
# This class represents a single MLB player from a single MLB game
|
4
|
+
class Player
|
5
|
+
|
6
|
+
# attributes from players.xml
|
7
|
+
attr_accessor :gid, :pid, :first, :last, :num, :boxname, :rl, :position, :status, :bat_order, :game_position
|
8
|
+
attr_accessor :avg, :hr, :std_hr, :rbi, :wins, :losses, :era, :saves, :team_code
|
9
|
+
|
10
|
+
# attributes from batters/13353333.xml or pitchers/1222112.xml
|
11
|
+
attr_accessor :team_abbrev, :type, :height, :weight, :bats, :throws, :dob
|
12
|
+
|
13
|
+
# object pointers
|
14
|
+
attr_accessor :team_obj, :games, :appearances
|
15
|
+
|
16
|
+
|
17
|
+
# Initializes a Player object by reading the player data from the players.xml file for the player specified by game id and player id.
|
18
|
+
def load_from_id(gid, pid)
|
19
|
+
@gid = gid
|
20
|
+
@pid = pid
|
21
|
+
# fetch players.xml file
|
22
|
+
@xml_data = GamedayFetcher.fetch_players(gid)
|
23
|
+
@xml_doc = REXML::Document.new(@xml_data)
|
24
|
+
# find specific player in the file
|
25
|
+
pelement = @xml_doc.root.elements["team/player[@id=#{pid}]"]
|
26
|
+
init(pelement, gid)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# Initializes pitcher info from data read from the masterscoreboard.xml file
|
31
|
+
def init_pitcher_from_scoreboard(element)
|
32
|
+
@first = element.attributes['first']
|
33
|
+
@last = element.attributes['last']
|
34
|
+
@wins = element.attributes['wins']
|
35
|
+
@losses = element.attributes['losses']
|
36
|
+
@era = element.attributes['era']
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# Returns an array of all the appearances (Batting or Pitching) made by this player
|
41
|
+
# for the season specified.
|
42
|
+
def get_all_appearances(year)
|
43
|
+
if !@appearances
|
44
|
+
@appearances = []
|
45
|
+
all_appearances = []
|
46
|
+
games = get_games_for_season(year)
|
47
|
+
games.each do |game|
|
48
|
+
@team_abbrev == game.home_team_abbrev ? status = 'home' : status = 'away'
|
49
|
+
if @position == 'P'
|
50
|
+
all_appearances.push *(game.get_pitchers(status))
|
51
|
+
else
|
52
|
+
all_appearances.push *(game.get_batters(status))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
# now go through all appearances to find those for this player
|
56
|
+
all_appearances.each do |appearance|
|
57
|
+
if appearance.pid == @pid
|
58
|
+
@appearances << appearance
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@appearances
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# Returns the number of at bats over the entire season for this player
|
67
|
+
def at_bats_count
|
68
|
+
gameday_info = GamedayUtil.parse_gameday_id(@gid)
|
69
|
+
appearances = get_all_appearances(gameday_info["year"])
|
70
|
+
count = appearances.inject(0) {|sum, a| sum + a.ab.to_i }
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# Returns the Team object representing the team for which this player plays
|
75
|
+
def get_team
|
76
|
+
if !@team_obj
|
77
|
+
@team_obj = Team.new(@team_abbrev)
|
78
|
+
end
|
79
|
+
@team_obj
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# Returns an array of all the games for the team this player is on for the season specified
|
84
|
+
# currently will not handle a player who has played for multiple teams over a season
|
85
|
+
def get_games_for_season(year)
|
86
|
+
if !@games
|
87
|
+
@games = get_team.all_games(year)
|
88
|
+
end
|
89
|
+
@games
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# Initialize a player object by reading data from the players.xml file
|
94
|
+
def init(element, gid)
|
95
|
+
@gid = gid
|
96
|
+
@pid = element.attributes['id']
|
97
|
+
@first = element.attributes['first']
|
98
|
+
@last = element.attributes['last']
|
99
|
+
@num= element.attributes['num']
|
100
|
+
@boxname = element.attributes['boxname']
|
101
|
+
@rl, = element.attributes['rl']
|
102
|
+
@position = element.attributes['position']
|
103
|
+
@status = element.attributes['status']
|
104
|
+
@bat_order = element.attributes['bat_order']
|
105
|
+
@game_position = element.attributes['game_position']
|
106
|
+
@avg = element.attributes['avg']
|
107
|
+
@hr = element.attributes['hr']
|
108
|
+
@rbi = element.attributes['rbi']
|
109
|
+
@wins = element.attributes['wins']
|
110
|
+
@losses = element.attributes['losses']
|
111
|
+
@era = element.attributes['era']
|
112
|
+
set_extra_info
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
|
119
|
+
# Set data that is read from the batter or pitcher file found in the batters/xxxxxxx.xml file or pitchers/xxxxxx.xml file
|
120
|
+
def set_extra_info
|
121
|
+
begin
|
122
|
+
if @position == 'P'
|
123
|
+
xml_data = GamedayFetcher.fetch_pitcher(@gid, @pid)
|
124
|
+
else
|
125
|
+
xml_data = GamedayFetcher.fetch_batter(@gid, @pid)
|
126
|
+
end
|
127
|
+
xml_doc = REXML::Document.new(xml_data)
|
128
|
+
@team_abbrev = xml_doc.root.attributes['team']
|
129
|
+
@type = xml_doc.root.attributes['type']
|
130
|
+
@height = xml_doc.root.attributes['height']
|
131
|
+
@weight = xml_doc.root.attributes['weight']
|
132
|
+
@bats = xml_doc.root.attributes['bats']
|
133
|
+
@throws = xml_doc.root.attributes['throws']
|
134
|
+
@dob = xml_doc.root.attributes['dob']
|
135
|
+
rescue
|
136
|
+
if @postion == 'P'
|
137
|
+
puts "Pitcher file pitchers/#{@pid}.xml not found"
|
138
|
+
else
|
139
|
+
puts "Batter file batters/#{@pid}.xml not found"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
end
|
data/lib/players.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'roster'
|
2
|
+
|
3
|
+
|
4
|
+
# This class represents the players.xml file found on the gameday server for each MLB game.
|
5
|
+
# The players.xml file contains a listing of all players on the home and away teams for the specified game
|
6
|
+
class Players
|
7
|
+
|
8
|
+
attr_accessor :xml_data, :gid, :venue, :date, :rosters, :umpires
|
9
|
+
|
10
|
+
# Loads the players XML from the MLB gameday server and parses it using REXML
|
11
|
+
def load_from_id(gid)
|
12
|
+
@gid = gid
|
13
|
+
@rosters = []
|
14
|
+
@umpires = {}
|
15
|
+
@xml_data = GamedayFetcher.fetch_players(gid)
|
16
|
+
@xml_doc = REXML::Document.new(@xml_data)
|
17
|
+
if @xml_doc.root
|
18
|
+
self.set_rosters
|
19
|
+
self.set_umpires
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def set_rosters()
|
25
|
+
away_roster = Roster.new
|
26
|
+
away_roster.init(@xml_doc.root.elements["team[@type='away']"], self.gid)
|
27
|
+
self.rosters << away_roster
|
28
|
+
home_roster = Roster.new
|
29
|
+
home_roster.init(@xml_doc.root.elements["team[@type='home']"], self.gid)
|
30
|
+
@rosters << home_roster
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def set_umpires()
|
35
|
+
@umpires['home'] = @xml_doc.root.elements["umpires/umpire[@position='home']"].attributes["name"]
|
36
|
+
@umpires['first'] = @xml_doc.root.elements["umpires/umpire[@position='first']"].attributes["name"]
|
37
|
+
@umpires['second'] = @xml_doc.root.elements["umpires/umpire[@position='second']"].attributes["name"]
|
38
|
+
@umpires['third'] = @xml_doc.root.elements["umpires/umpire[@position='third']"].attributes["name"]
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
end
|
data/lib/roster.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'player'
|
2
|
+
require 'coach'
|
3
|
+
|
4
|
+
|
5
|
+
# This class represents a team's roster for a single game.
|
6
|
+
# Both players and coaches can be read from the roster.
|
7
|
+
class Roster
|
8
|
+
|
9
|
+
attr_accessor :gid, :id, :team_name, :type, :players, :coaches
|
10
|
+
# type = home or away
|
11
|
+
|
12
|
+
def init(element, gid)
|
13
|
+
self.gid = gid
|
14
|
+
self.team_name = element.attributes['name']
|
15
|
+
self.id = element.attributes['id']
|
16
|
+
self.type = element.attributes['type']
|
17
|
+
self.players = []
|
18
|
+
self.coaches = []
|
19
|
+
self.set_players(element)
|
20
|
+
self.set_coaches(element)
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def find_player_by_last_name(last_name)
|
25
|
+
players.each do |player|
|
26
|
+
if player.last == last_name
|
27
|
+
return player
|
28
|
+
end
|
29
|
+
end
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def find_player_by_id(pid)
|
35
|
+
players.each do |player|
|
36
|
+
if player.pid == pid
|
37
|
+
return player
|
38
|
+
end
|
39
|
+
end
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def set_players(element)
|
45
|
+
element.elements.each("player") { |element|
|
46
|
+
player = Player.new
|
47
|
+
player.init(element, gid)
|
48
|
+
@players << player
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def set_coaches(element)
|
54
|
+
element.elements.each("coach") { |element|
|
55
|
+
coach = Coach.new
|
56
|
+
coach.init(element)
|
57
|
+
self.coaches << coach
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
data/lib/schedule.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'schedule_game'
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
# This class is used to retrieve season schedule information and to query
|
6
|
+
# for information related to the schedule.
|
7
|
+
class Schedule
|
8
|
+
|
9
|
+
attr_accessor :games
|
10
|
+
|
11
|
+
|
12
|
+
# Loads a single season schedule from a schedule text file
|
13
|
+
def initialize(year)
|
14
|
+
@games = []
|
15
|
+
read_file(get_sked_filename(year))
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# Returns the date of opening day as a string with the format YYYYMMDD
|
20
|
+
def get_opening_day
|
21
|
+
games[0].date
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Returns an integer representing the number of games in the season specified
|
26
|
+
def get_season_length
|
27
|
+
games[games.size-1].home_game_number.to_i
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
def get_sked_filename(year)
|
33
|
+
#'schedules/' + year.to_s + 'SKED.TXT'
|
34
|
+
File.expand_path(File.dirname(__FILE__) + '/schedules/' + year.to_s + 'SKED.TXT')
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# Reads the data from a schedule file
|
39
|
+
# Each line in the schedule file represents a single game.
|
40
|
+
# here is a sample of what a single line in the file looks like:
|
41
|
+
# "20090405","0","Sun","ATL","NL",1,"PHI","NL",1,"n","",""
|
42
|
+
# this is interpreted as:
|
43
|
+
# date, 0, day, visiting team, visiting league, visiting game number, home team, home league, home game number, day or night (d or n), "", ""
|
44
|
+
def read_file(filename)
|
45
|
+
contents = ''
|
46
|
+
File.open(filename, "r") do |infile|
|
47
|
+
while (line = infile.gets)
|
48
|
+
@games << ScheduleGame.new(line)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
# This class represents a single game from a game schedule
|
3
|
+
# This class is used in conjunction with the Schedule class.
|
4
|
+
# This is not the class you would use to retrieve game statistics.
|
5
|
+
class ScheduleGame
|
6
|
+
|
7
|
+
attr_accessor :date, :day_of_week, :away_team_abbrev, :away_league, :away_game_number
|
8
|
+
attr_accessor :home_team_abbrev, :home_league, :home_game_number, :day_or_night
|
9
|
+
|
10
|
+
|
11
|
+
def initialize(line)
|
12
|
+
temp = line.split(',')
|
13
|
+
@date = temp[0].tr_s('"', '').strip
|
14
|
+
@day_of_week = temp[2].tr_s('"', '').strip
|
15
|
+
@away_team_abbrev = temp[3].tr_s('"', '').strip
|
16
|
+
@away_league = temp[4].tr_s('"', '').strip
|
17
|
+
@away_game_number = temp[5].tr_s('"', '').strip
|
18
|
+
@home_team_abbrev = temp[6].tr_s('"', '').strip
|
19
|
+
@home_league = temp[7].tr_s('"', '').strip
|
20
|
+
@home_game_number = temp[8].tr_s('"', '').strip
|
21
|
+
@day_or_night = temp[9].tr_s('"', '').strip
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/lib/scoreboard.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'gameday_fetcher'
|
2
|
+
|
3
|
+
class Scoreboard
|
4
|
+
|
5
|
+
attr_accessor :games # An array of Game objects representing all of the games played on this date
|
6
|
+
attr_accessor :year, :month, :day
|
7
|
+
|
8
|
+
def load_for_date(year, month, day)
|
9
|
+
@games = []
|
10
|
+
@year = year
|
11
|
+
@month = month
|
12
|
+
@day = day
|
13
|
+
@xml_data = GamedayFetcher.fetch_scoreboard(year, month, day)
|
14
|
+
@xml_doc = REXML::Document.new(@xml_data)
|
15
|
+
|
16
|
+
@xml_doc.elements.each("games/game") { |element|
|
17
|
+
game = Game.new(element.attributes['gameday'])
|
18
|
+
game.load_from_scoreboard(element)
|
19
|
+
@games << game
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|