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.
@@ -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