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
data/lib/at_bat.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'pitch'
|
2
|
+
|
3
|
+
|
4
|
+
# This class represents a single atbat during a single game
|
5
|
+
class AtBat
|
6
|
+
|
7
|
+
attr_accessor :gid, :inning, :away_team, :home_team
|
8
|
+
attr_accessor :num, :b, :s, :o, :batter_id, :stand, :b_height, :pitcher_id, :p_throws, :des, :event
|
9
|
+
attr_accessor :pitches
|
10
|
+
|
11
|
+
def init(element, gid, inning)
|
12
|
+
@inning = inning
|
13
|
+
@xml_doc = element
|
14
|
+
@gid = gid
|
15
|
+
@num = element.attributes["num"]
|
16
|
+
@b = element.attributes["b"]
|
17
|
+
@s = element.attributes["s"]
|
18
|
+
@o = element.attributes["o"]
|
19
|
+
@batter_id = element.attributes["batter"]
|
20
|
+
@stand = element.attributes["stand"]
|
21
|
+
@b_height = element.attributes["b_height"]
|
22
|
+
@pitcher_id = element.attributes["pitcher"]
|
23
|
+
@p_throws = element.attributes["p_throws"]
|
24
|
+
@des = element.attributes["des"]
|
25
|
+
@event = element.attributes["event"]
|
26
|
+
set_pitches(element)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def set_pitches(element)
|
31
|
+
@pitches = []
|
32
|
+
element.elements.each("pitch") do |element|
|
33
|
+
pitch = Pitch.new
|
34
|
+
pitch.init(element)
|
35
|
+
@pitches << pitch
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
data/lib/batter.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'player'
|
2
|
+
|
3
|
+
# This class represents a single batter whom appeared in an MLB game
|
4
|
+
class Batter < Player
|
5
|
+
|
6
|
+
# attributes read from the batters/(pid).xml file
|
7
|
+
attr_accessor :team_abbrev, :pid, :pos, :first_name, :last_name, :jersey_number
|
8
|
+
attr_accessor :height, :weight, :bats, :throws, :dob
|
9
|
+
attr_accessor :season_stats, :career_stats, :month_stats, :empty_stats
|
10
|
+
attr_accessor :men_on_stats, :risp_stats, :loaded_stats, :vs_lhp_stats, :vs_rhp_stats
|
11
|
+
|
12
|
+
|
13
|
+
def load_from_id(gid, pid)
|
14
|
+
@gid = gid
|
15
|
+
@pid = pid
|
16
|
+
@xml_data = GamedayFetcher.fetch_batter(gid, pid)
|
17
|
+
@xml_doc = REXML::Document.new(@xml_data)
|
18
|
+
@team_abbrev = @xml_doc.root.attributes["team"]
|
19
|
+
@first_name = @xml_doc.root.attributes["first_name"]
|
20
|
+
@last_name = @xml_doc.root.attributes["last_name"]
|
21
|
+
@jersey_number = @xml_doc.root.attributes["jersey_number"]
|
22
|
+
@height = @xml_doc.root.attributes["height"]
|
23
|
+
@weight = @xml_doc.root.attributes["weight"]
|
24
|
+
@bats = @xml_doc.root.attributes["bats"]
|
25
|
+
@throws = @xml_doc.root.attributes["throws"]
|
26
|
+
@dob = @xml_doc.root.attributes['dob']
|
27
|
+
set_batting_stats
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
# Returns an array of all the appearances (Batting) made by this player
|
32
|
+
# for the season specified, in which the player had more than 1 hit.
|
33
|
+
def get_multihit_appearances(year)
|
34
|
+
appearances = get_all_appearances(year)
|
35
|
+
mh_appearances = []
|
36
|
+
# now go through all appearances to find those for this player
|
37
|
+
appearances.each do |appearance|
|
38
|
+
if appearance.h.to_i > 1 #add only multihit games
|
39
|
+
mh_appearances << appearance
|
40
|
+
end
|
41
|
+
end
|
42
|
+
mh_appearances
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
# Returns an array of batter ids for the game specified
|
47
|
+
# batters are found by looking in the gid/batters directory on gameday
|
48
|
+
def self.get_all_ids_for_game(gid)
|
49
|
+
batters_page = GamedayFetcher.fetch_batters_page(gid)
|
50
|
+
results = []
|
51
|
+
if batters_page
|
52
|
+
doc = Hpricot(batters_page)
|
53
|
+
a = doc.at('ul')
|
54
|
+
if a
|
55
|
+
(a/"a").each do |link|
|
56
|
+
# look at each link inside of a ul tag
|
57
|
+
if link.inner_html.include?(".xml") == true
|
58
|
+
# if the link contains the text '.xml' then it is a batter
|
59
|
+
str = link.inner_html
|
60
|
+
str.strip!
|
61
|
+
batter_id = str[0..str.length-5]
|
62
|
+
results << batter_id
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
results
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def set_batting_stats
|
74
|
+
@season_stats = BattingStats.new(@xml_doc.root.elements["season"])
|
75
|
+
@career_stats = BattingStats.new(@xml_doc.root.elements["career"])
|
76
|
+
@month_stats = BattingStats.new(@xml_doc.root.elements["month"])
|
77
|
+
@empty_stats = BattingStats.new(@xml_doc.root.elements["Empty"])
|
78
|
+
@men_on_stats = BattingStats.new(@xml_doc.root.elements["Men_On"])
|
79
|
+
@risp_stats = BattingStats.new(@xml_doc.root.elements["RISP"])
|
80
|
+
@loaded_stats = BattingStats.new(@xml_doc.root.elements["Loaded"])
|
81
|
+
@vs_lhp_stats = BattingStats.new(@xml_doc.root.elements["vs_LHP"])
|
82
|
+
@vs_rhp_stats = BattingStats.new(@xml_doc.root.elements["vs_RHP"])
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
class BattingStats
|
89
|
+
attr_accessor :des, :avg, :ab, :hr, :bb, :so
|
90
|
+
|
91
|
+
def initialize(element)
|
92
|
+
if element.attributes['des']
|
93
|
+
@des = element.attributes['des']
|
94
|
+
end
|
95
|
+
@avg = element.attributes['avg']
|
96
|
+
@ab = element.attributes['ab']
|
97
|
+
@hr = element.attributes['hr']
|
98
|
+
@bb = element.attributes['bb']
|
99
|
+
@so = element.attributes['so']
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'player'
|
2
|
+
|
3
|
+
|
4
|
+
# This class represents a batting record for a single player for a single game
|
5
|
+
# Note that this does NOT represent a single atbat of a player, but rather an appearance is a player's stats over an entire game.
|
6
|
+
class BattingAppearance
|
7
|
+
|
8
|
+
attr_accessor :pid, :batter_name, :pos, :bo, :ab, :po, :r, :bb, :a, :t, :sf, :h, :e, :d, :hbp, :so, :hr, :rbi, :lob, :sb, :avg, :fldg
|
9
|
+
attr_accessor :player, :atbats
|
10
|
+
|
11
|
+
# Used to initialize from box score data
|
12
|
+
def init(element)
|
13
|
+
self.pid = element.attributes['id']
|
14
|
+
self.batter_name = element.attributes['name']
|
15
|
+
self.pos = element.attributes['pos']
|
16
|
+
self.bo = element.attributes['bo']
|
17
|
+
self.ab = element.attributes['ab']
|
18
|
+
self.po = element.attributes['po']
|
19
|
+
self.r = element.attributes['r']
|
20
|
+
self.bb = element.attributes['bb']
|
21
|
+
self.a = element.attributes['a']
|
22
|
+
self.t = element.attributes['t']
|
23
|
+
self.sf = element.attributes['sf']
|
24
|
+
self.h = element.attributes['h']
|
25
|
+
self.e = element.attributes['e']
|
26
|
+
self.d = element.attributes['d']
|
27
|
+
self.hbp = element.attributes['hbp']
|
28
|
+
self.so = element.attributes['so']
|
29
|
+
self.hr = element.attributes['hr']
|
30
|
+
self.rbi = element.attributes['rbi']
|
31
|
+
self.lob = element.attributes['lob']
|
32
|
+
self.sb = element.attributes['sb']
|
33
|
+
self.avg = element.attributes['avg'] # season avg
|
34
|
+
self.fldg = element.attributes['fldg']
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# Looks up the player record using the players.xml file for the player in this appearance
|
39
|
+
def get_player
|
40
|
+
if !self.player
|
41
|
+
# retrieve player object
|
42
|
+
player = Player.new
|
43
|
+
player.init()
|
44
|
+
self.player = player
|
45
|
+
end
|
46
|
+
self.player
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# get the atbats associated with this appearance
|
51
|
+
def get_atbats
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/lib/box_score.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'team'
|
2
|
+
require 'pitching_appearance'
|
3
|
+
require 'batting_appearance'
|
4
|
+
require 'gameday_fetcher'
|
5
|
+
require 'line_score'
|
6
|
+
require 'hpricot'
|
7
|
+
require 'rexml/document'
|
8
|
+
require 'gameday_util'
|
9
|
+
|
10
|
+
|
11
|
+
# Parses the MLB Gameday XML representation of a boxscore and returns data in easy to use
|
12
|
+
# arrays and hashes. Can be used along with a view template to easily create a displayable
|
13
|
+
# box score.
|
14
|
+
class BoxScore
|
15
|
+
|
16
|
+
attr_accessor :xml_data, :gid, :game, :linescore, :game_info, :home_batting_text, :away_batting_text
|
17
|
+
|
18
|
+
attr_accessor :game_id, :game_pk, :home_sport_code, :away_team_code, :home_team_code
|
19
|
+
attr_accessor :away_id, :home_id, :away_fname, :home_fname, :away_sname, :home_sname
|
20
|
+
attr_accessor :date, :away_wins, :away_loss, :home_wins, :home_loss, :status_ind
|
21
|
+
|
22
|
+
attr_accessor :home_runs, :away_runs
|
23
|
+
|
24
|
+
attr_accessor :temp, :wind_speed, :wind_dir
|
25
|
+
|
26
|
+
# complex attributes
|
27
|
+
attr_accessor :innings, :cities, :linescore_totals, :pitchers, :batters
|
28
|
+
|
29
|
+
|
30
|
+
# Loads the boxscore XML from the MLB gameday server and parses it using REXML
|
31
|
+
def load_from_id(gid)
|
32
|
+
@gid = gid
|
33
|
+
@xml_data = GamedayFetcher.fetch_boxscore(gid)
|
34
|
+
@xml_doc = REXML::Document.new(@xml_data)
|
35
|
+
if @xml_doc.root
|
36
|
+
@game = Game.new(@gid)
|
37
|
+
@game.boxscore = self
|
38
|
+
set_basic_info
|
39
|
+
@linescore = LineScore.new
|
40
|
+
@linescore.init(@xml_doc.root.elements["linescore"])
|
41
|
+
@home_runs = @linescore.home_team_runs
|
42
|
+
@away_runs = @linescore.away_team_runs
|
43
|
+
@game_info = @xml_doc.root.elements["game_info"].text
|
44
|
+
set_batting_text
|
45
|
+
set_cities
|
46
|
+
set_pitchers
|
47
|
+
set_batters
|
48
|
+
set_weather
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Saves an HTML version of the boxscore
|
54
|
+
def dump_to_file
|
55
|
+
GamedayUtil.save_file("boxscore.html", to_html('boxscore.html.erb'))
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Converts the boxscore into a formatted HTML representation.
|
60
|
+
# Relies on the boxscore.html.erb template for describing the layout
|
61
|
+
def to_html(template_filename)
|
62
|
+
gameday_info = GamedayUtil.parse_gameday_id('gid_' + gid)
|
63
|
+
template = ERB.new File.new(File.expand_path(File.dirname(__FILE__) + "/" + template_filename)).read, nil, "%"
|
64
|
+
return template.result(binding)
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# Returns a 2 element array of leadoff hitters for this game.
|
69
|
+
# [0] = visitor's leadoff hitter
|
70
|
+
# [1] = home's leadoff hitter
|
71
|
+
def get_leadoff_hitters
|
72
|
+
find_hitters("batter")
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# Returns a 2 element array of cleanup hitters for this game.
|
77
|
+
# [0] = visitor's cleanup hitter
|
78
|
+
# [1] = home's cleanup hitter
|
79
|
+
def get_cleanup_hitters
|
80
|
+
find_hitters("batter[@bo='400']")
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def find_hitters(search_string)
|
85
|
+
results = []
|
86
|
+
away = @xml_doc.elements["boxscore/batting[@team_flag='away']/#{search_string}"]
|
87
|
+
away_batter = BattingAppearance.new
|
88
|
+
away_batter.init(away)
|
89
|
+
results << away_batter
|
90
|
+
home = @xml_doc.elements["boxscore/batting[@team_flag='home']/#{search_string}"]
|
91
|
+
home_batter = BattingAppearance.new
|
92
|
+
home_batter.init(home)
|
93
|
+
results << home_batter
|
94
|
+
results
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
# Retrieves basic game data from the XML root element and sets in object
|
101
|
+
def set_basic_info
|
102
|
+
@game_id = @xml_doc.root.attributes["game_id"]
|
103
|
+
@game_pk = @xml_doc.root.attributes["game_pk"]
|
104
|
+
@home_sport_code = @xml_doc.root.attributes["home_sport_code"]
|
105
|
+
@away_team_code = @xml_doc.root.attributes["away_team_code"]
|
106
|
+
@home_team_code = @xml_doc.root.attributes["home_team_code"]
|
107
|
+
@away_id = @xml_doc.root.attributes["away_id"]
|
108
|
+
@home_id = @xml_doc.root.attributes["home_id"]
|
109
|
+
@away_fname = @xml_doc.root.attributes["away_fname"]
|
110
|
+
@home_fname = @xml_doc.root.attributes["home_fname"]
|
111
|
+
@away_sname = @xml_doc.root.attributes["away_sname"]
|
112
|
+
@home_sname = @xml_doc.root.attributes["home_sname"]
|
113
|
+
@date = @xml_doc.root.attributes["date"]
|
114
|
+
@away_wins = @xml_doc.root.attributes["away_wins"]
|
115
|
+
@away_loss = @xml_doc.root.attributes["away_loss"]
|
116
|
+
@home_wins = @xml_doc.root.attributes["home_wins"]
|
117
|
+
@home_loss = @xml_doc.root.attributes["home_loss"]
|
118
|
+
@status_ind = @xml_doc.root.attributes["status_ind"]
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
def set_batting_text
|
123
|
+
if @xml_doc.root.elements["batting[@team_flag='home']/text_data"]
|
124
|
+
@home_batting_text = @xml_doc.root.elements["batting[@team_flag='home']/text_data"].text
|
125
|
+
end
|
126
|
+
if @xml_doc.root.elements["batting[@team_flag='away']/text_data"]
|
127
|
+
@away_batting_text = @xml_doc.root.elements["batting[@team_flag='away']/text_data"].text
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
# Sets an array of the city names for the teams playing the game
|
133
|
+
# [0] = away
|
134
|
+
# [1] = home
|
135
|
+
def set_cities
|
136
|
+
@cities = []
|
137
|
+
if @xml_doc.root
|
138
|
+
@cities.push @xml_doc.root.attributes["away_sname"]
|
139
|
+
@cities.push @xml_doc.root.attributes["home_sname"]
|
140
|
+
else
|
141
|
+
@cities.push 'unknown'
|
142
|
+
@cities.push 'unknown'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
# Sets an array of hashes where each hash holds data for a pitcher whom appeared
|
148
|
+
# in the game. Specify either home or away team pitchers.
|
149
|
+
def set_pitchers
|
150
|
+
@pitchers, away_pitchers, home_pitchers = [], [], []
|
151
|
+
count = 1
|
152
|
+
@xml_doc.elements.each("boxscore/pitching[@team_flag='away']/pitcher") { |element|
|
153
|
+
pitcher = PitchingAppearance.new
|
154
|
+
pitcher.init(@gid, element, count)
|
155
|
+
count += 1
|
156
|
+
away_pitchers.push pitcher
|
157
|
+
}
|
158
|
+
count = 1
|
159
|
+
@xml_doc.elements.each("boxscore/pitching[@team_flag='home']/pitcher") { |element|
|
160
|
+
pitcher = PitchingAppearance.new
|
161
|
+
pitcher.init(@gid, element, count)
|
162
|
+
count += 1
|
163
|
+
home_pitchers.push pitcher
|
164
|
+
}
|
165
|
+
@pitchers << away_pitchers
|
166
|
+
@pitchers << home_pitchers
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
# Sets an array of hashes where each hash holds data for a batter whom appeared
|
171
|
+
# in the game. Specify either home or away team batters.
|
172
|
+
def set_batters
|
173
|
+
@batters, away_batters, home_batters = [], [], []
|
174
|
+
@xml_doc.elements.each("boxscore/batting[@team_flag='away']/batter") { |element|
|
175
|
+
batter = BattingAppearance.new
|
176
|
+
batter.init(element)
|
177
|
+
away_batters.push batter
|
178
|
+
}
|
179
|
+
@xml_doc.elements.each("boxscore/batting[@team_flag='home']/batter") { |element|
|
180
|
+
batter = BattingAppearance.new
|
181
|
+
batter.init(element)
|
182
|
+
home_batters.push batter
|
183
|
+
}
|
184
|
+
@batters << away_batters
|
185
|
+
@batters << home_batters
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
def set_weather
|
190
|
+
@game_info =~ /<br\/><b>Weather<\/b>: (\d+) degrees,.*<br\/><b>Wind<\/b>: (\d+) mph, ([\w\s]+).<br\/>/
|
191
|
+
@temp = $1
|
192
|
+
@wind_speed = $2
|
193
|
+
@wind_dir = $3
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'md5'
|
3
|
+
|
4
|
+
class CacheFetcher
|
5
|
+
|
6
|
+
def initialize(cache_dir=File.expand_path(File.dirname(__FILE__)) + '/tmp')
|
7
|
+
# this is the dir where we store our cache
|
8
|
+
@cache_dir = cache_dir
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
def fetch(url)
|
13
|
+
file = MD5.hexdigest(url)
|
14
|
+
file_path = File.join("", @cache_dir, file)
|
15
|
+
# we check if the file -- a MD5 hexdigest of the URL -- exists
|
16
|
+
# in the dir. If it does we just read data from the file and return
|
17
|
+
if !File.exists? file_path
|
18
|
+
#puts 'Not found in cache'
|
19
|
+
# if the file does not exist (or if the data is not fresh), we
|
20
|
+
# make an HTTP request and save it to a file
|
21
|
+
#puts 'Fetching file from internet...'
|
22
|
+
File.open(file_path, "w") do |data|
|
23
|
+
data << Net::HTTP.get_response(URI.parse(url)).body
|
24
|
+
end
|
25
|
+
else
|
26
|
+
#puts 'Using cache'
|
27
|
+
end
|
28
|
+
return File.new(file_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/lib/coach.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# This class represents a single MLB coach
|
2
|
+
class Coach
|
3
|
+
|
4
|
+
attr_accessor :position, :first, :last, :id, :num
|
5
|
+
|
6
|
+
|
7
|
+
def init(element)
|
8
|
+
self.id = element.attributes['id']
|
9
|
+
self.first = element.attributes['first']
|
10
|
+
self.last = element.attributes['last']
|
11
|
+
self.num= element.attributes['num']
|
12
|
+
self.position = element.attributes['position']
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'game'
|
2
|
+
require 'batter'
|
3
|
+
require 'pitcher'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
# This class is used to download data files from the MLB Gameday site to
|
9
|
+
# local storage. The data that is downloaded will be stored into a path that
|
10
|
+
# replicates the MLB Gameday paths, for example here is a sample path for
|
11
|
+
# a specified date:
|
12
|
+
# /components/game/mlb/year_2008/month_04/day_07
|
13
|
+
#
|
14
|
+
class DataDownloader
|
15
|
+
|
16
|
+
FILE_BASE_PATH = 'components/game/mlb'
|
17
|
+
|
18
|
+
|
19
|
+
# Downloads all data files associated with the game specified by the game id passed in.
|
20
|
+
def download_all_for_game(gid)
|
21
|
+
download_xml_for_game(gid)
|
22
|
+
download_batters_for_game(gid)
|
23
|
+
download_inning_for_game(gid)
|
24
|
+
download_media_for_game(gid)
|
25
|
+
download_notification_for_game(gid)
|
26
|
+
download_onbase_for_game(gid)
|
27
|
+
download_pitchers_for_game(gid)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def download_batters_for_game(gid)
|
32
|
+
write_file(get_gid_path(gid) + "/batters.html", GamedayFetcher.fetch_batters_page(gid))
|
33
|
+
batter_path = get_gid_path(gid) + "/batters"
|
34
|
+
ids = Batter.get_all_ids_for_game(gid)
|
35
|
+
ids.each do |id|
|
36
|
+
if !File.exists? "#{batter_path}/#{id}.xml"
|
37
|
+
write_file("#{batter_path}/#{id}.xml", GamedayFetcher.fetch_batter(gid, id))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def download_pitchers_for_game(gid)
|
44
|
+
write_file(get_gid_path(gid) + "/pitchers.html", GamedayFetcher.fetch_pitchers_page(gid))
|
45
|
+
pitcher_path = get_gid_path(gid) + "/pitchers"
|
46
|
+
ids = Pitcher.get_all_ids_for_game(gid)
|
47
|
+
ids.each do |id|
|
48
|
+
if !File.exists? "#{pitcher_path}/#{id}.xml"
|
49
|
+
write_file("#{pitcher_path}/#{id}.xml", GamedayFetcher.fetch_pitcher(gid, id))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def download_inning_for_game(gid)
|
56
|
+
game = Game.new(gid)
|
57
|
+
inn_count = game.get_num_innings
|
58
|
+
inn_path = get_gid_path(gid) + "/inning"
|
59
|
+
(1..inn_count).each do |inn|
|
60
|
+
if !File.exists? "#{inn_path}/inning_#{inn}.xml"
|
61
|
+
write_file("#{inn_path}/inning_#{inn}.xml", GamedayFetcher.fetch_inningx(gid, inn))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
if !File.exists? "#{inn_path}/inning_Scores.xml"
|
65
|
+
write_file("#{inn_path}/inning_Scores.xml", GamedayFetcher.fetch_inning_scores(gid))
|
66
|
+
end
|
67
|
+
if !File.exists? "#{inn_path}/inning_hit.xml"
|
68
|
+
write_file("#{inn_path}/inning_hit.xml", GamedayFetcher.fetch_inning_hit(gid))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def download_media_for_game(gid)
|
74
|
+
media_path = get_gid_path(gid) + "/media"
|
75
|
+
if !File.exists? "#{media_path}/highlights.xml"
|
76
|
+
write_file("#{media_path}/highlights.xml", GamedayFetcher.fetch_media_highlights(gid))
|
77
|
+
end
|
78
|
+
if !File.exists? "#{media_path}/mobile.xml"
|
79
|
+
write_file("#{media_path}/mobile.xml", GamedayFetcher.fetch_media_mobile(gid))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def download_notification_for_game(gid)
|
85
|
+
game = Game.new(gid)
|
86
|
+
inn_count = game.get_num_innings
|
87
|
+
notif_path = get_gid_path(gid) + "/notifications"
|
88
|
+
(1..inn_count).each do |inn|
|
89
|
+
if !File.exists? "#{notif_path}/notifications_#{inn}.xml"
|
90
|
+
write_file("#{notif_path}/notifications_#{inn}.xml", GamedayFetcher.fetch_notifications_inning(gid, inn))
|
91
|
+
end
|
92
|
+
end
|
93
|
+
if !File.exists? "#{notif_path}/notifications_full.xml"
|
94
|
+
write_file("#{notif_path}/notifications_full.xml", GamedayFetcher.fetch_notifications_full(gid))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def download_onbase_for_game(gid)
|
100
|
+
onbase_path = get_gid_path(gid) + "/onbase"
|
101
|
+
write_file("#{onbase_path}/linescore.xml", GamedayFetcher.fetch_onbase_linescore(gid))
|
102
|
+
write_file("#{onbase_path}/plays.xml", GamedayFetcher.fetch_onbase_plays(gid))
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
# Downloads the top-level xml directories for the game specified by the passed in game id.
|
107
|
+
# The files include:
|
108
|
+
# bench.xml
|
109
|
+
# benchO.xml
|
110
|
+
# boxscore.xml
|
111
|
+
# emailSource.xml
|
112
|
+
# eventLog.xml
|
113
|
+
# game.xml
|
114
|
+
# game_events.xml
|
115
|
+
# gamecenter.xml
|
116
|
+
# gameday_Syn.xml
|
117
|
+
# linescore.xml
|
118
|
+
# miniscoreboard.xml
|
119
|
+
# players.xml
|
120
|
+
# plays.xml
|
121
|
+
def download_xml_for_game(gid)
|
122
|
+
gid_path = get_gid_path(gid)
|
123
|
+
write_file("#{gid_path}/bench.xml", GamedayFetcher.fetch_bench(gid))
|
124
|
+
write_file("#{gid_path}/benchO.xml", GamedayFetcher.fetch_bencho(gid))
|
125
|
+
write_file("#{gid_path}/boxscore.xml", GamedayFetcher.fetch_boxscore(gid))
|
126
|
+
write_file("#{gid_path}/emailSource.xml", GamedayFetcher.fetch_emailsource(gid))
|
127
|
+
write_file("#{gid_path}/eventLog.xml", GamedayFetcher.fetch_eventlog(gid))
|
128
|
+
write_file("#{gid_path}/game.xml", GamedayFetcher.fetch_game_xml(gid))
|
129
|
+
write_file("#{gid_path}/game_events.xml", GamedayFetcher.fetch_game_events(gid))
|
130
|
+
write_file("#{gid_path}/gamecenter.xml", GamedayFetcher.fetch_gamecenter_xml(gid))
|
131
|
+
write_file("#{gid_path}/gameday_Syn.xml", GamedayFetcher.fetch_gamedaysyn(gid))
|
132
|
+
write_file("#{gid_path}/linescore.xml", GamedayFetcher.fetch_linescore(gid))
|
133
|
+
write_file("#{gid_path}/miniscoreboard.xml", GamedayFetcher.fetch_miniscoreboard(gid))
|
134
|
+
write_file("#{gid_path}/players.xml", GamedayFetcher.fetch_players(gid))
|
135
|
+
write_file("#{gid_path}/plays.xml", GamedayFetcher.fetch_plays(gid))
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
def download_xml_for_date(year, month, day)
|
140
|
+
day_path = get_day_path(year, month, day)
|
141
|
+
write_file("#{day_path}/epg.xml", GamedayFetcher.fetch_epg(year, month, day))
|
142
|
+
write_file("#{day_path}/master_scoreboard.xml", GamedayFetcher.fetch_scoreboard(year, month, day))
|
143
|
+
write_file("#{day_path}/media/highlights.xml", GamedayFetcher.fetch_day_highlights(year, month, day))
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
def download_all_for_date(year, month, day)
|
148
|
+
day_path = get_day_path(year, month, day)
|
149
|
+
write_file("#{day_path}/games.html", GamedayFetcher.fetch_games_page(year, month, day))
|
150
|
+
download_xml_for_date(year, month, day)
|
151
|
+
games = Game.find_by_date(year, month, day)
|
152
|
+
games.each do |game|
|
153
|
+
download_all_for_game(game.gid)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
def download_all_for_month(year, month)
|
159
|
+
start_date = Date.new(year.to_i, month.to_i) # first day of month
|
160
|
+
end_date = (start_date >> 1)-1 # last day of month
|
161
|
+
((start_date)..(end_date)).each do |dt|
|
162
|
+
puts 'Downloading ' + year.to_s + '/' + month.to_s + '/' + dt.day.to_s
|
163
|
+
download_all_for_date(year, month, dt.day.to_s)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
def download_all_for_range(year, start_month, start_day, end_month, end_day)
|
169
|
+
start_date = Date.new(year.to_i, start_month.to_i, start_day.to_i)
|
170
|
+
end_date = Date.new(year.to_i, end_month.to_i, end_day.to_i)
|
171
|
+
((start_date)..(end_date)).each do |dt|
|
172
|
+
puts 'Downloading ' + dt.year.to_s + '/' + dt.month.to_s + '/' + dt.day.to_s
|
173
|
+
download_all_for_date(dt.year.to_s, dt.month.to_s, dt.day.to_s)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
def tmp_fetch_pages_for_month(year, month, end_day)
|
179
|
+
start_date = Date.new(year.to_i, month.to_i) # first day of month
|
180
|
+
if end_day
|
181
|
+
end_date = Date.new(year.to_i, month.to_i, end_day.to_i)
|
182
|
+
else
|
183
|
+
end_date = (start_date >> 1)-1 # last day of month
|
184
|
+
end
|
185
|
+
((start_date)..(end_date)).each do |dt|
|
186
|
+
day = dt.day.to_s
|
187
|
+
puts day
|
188
|
+
day_path = get_day_path(year, month, day)
|
189
|
+
write_file("#{day_path}/games.html", GamedayFetcher.fetch_games_page(year, month, day))
|
190
|
+
games = Game.find_by_date(year, month, day)
|
191
|
+
games.each do |game|
|
192
|
+
tmp_fetch_pages_for_game(game.gid)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def tmp_fetch_pages_for_game(gid)
|
198
|
+
write_file(get_gid_path(gid) + "/batters.html", GamedayFetcher.fetch_batters_page(gid))
|
199
|
+
write_file(get_gid_path(gid) + "/pitchers.html", GamedayFetcher.fetch_pitchers_page(gid))
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
private
|
204
|
+
|
205
|
+
|
206
|
+
def get_day_path(year, month, day)
|
207
|
+
year = GamedayUtil.convert_digit_to_string(year.to_i)
|
208
|
+
month = GamedayUtil.convert_digit_to_string(month.to_i)
|
209
|
+
day = GamedayUtil.convert_digit_to_string(day.to_i)
|
210
|
+
"#{FILE_BASE_PATH}/year_" + year + "/month_" + month + "/day_" + day
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
def get_gid_path(gid)
|
215
|
+
gameday_info = GamedayUtil.parse_gameday_id('gid_' + gid)
|
216
|
+
"#{FILE_BASE_PATH}/year_" + gameday_info['year'] + "/month_" + gameday_info['month'] + "/day_" + gameday_info['day'] + "/gid_"+gid
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
# Writes the gameday data to the file specified.
|
221
|
+
# Does not overwrite existing files.
|
222
|
+
def write_file(file_path, gd_data)
|
223
|
+
if gd_data && !File.exists?(file_path)
|
224
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
225
|
+
File.open(file_path, "w") do |data|
|
226
|
+
data << gd_data
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|