bb_analytics 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +53 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +60 -0
- data/README.md +43 -0
- data/README.rdoc +0 -0
- data/Rakefile +30 -0
- data/bb_analytics.gemspec +26 -0
- data/bb_analytics.rdoc +5 -0
- data/bin/bb_analytics +132 -0
- data/lib/bb_analytics/models/baseball_player.rb +45 -0
- data/lib/bb_analytics/models/data_store.rb +61 -0
- data/lib/bb_analytics/models/importer.rb +58 -0
- data/lib/bb_analytics/models/stats_for_year.rb +218 -0
- data/lib/bb_analytics/version.rb +3 -0
- data/lib/bb_analytics.rb +24 -0
- data/results.html +472 -0
- data/spec/models/baseball_player_spec.rb +44 -0
- data/spec/models/importer_spec.rb +117 -0
- data/spec/models/stats_for_year_spec.rb +258 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/Batting-07-12.csv +1 -0
- data/spec/support/Master-small.csv +1 -0
- metadata +171 -0
@@ -0,0 +1,218 @@
|
|
1
|
+
class StatsForYear
|
2
|
+
|
3
|
+
FANTASY_HR = 4
|
4
|
+
FANTASY_RBI = 1
|
5
|
+
FANTASY_SB = 1
|
6
|
+
FANTASY_CS = -1
|
7
|
+
|
8
|
+
attr_accessor :player_external_id, :year, :team, :games, :at_bats, :runs,
|
9
|
+
:hits, :doubles, :triples, :home_runs, :runs_batted_in, :stolen_bases,
|
10
|
+
:caught_stealing, :batting_average, :slugging_percentage, :fantasy_points
|
11
|
+
|
12
|
+
def save
|
13
|
+
# first see if we can update an existing record
|
14
|
+
DataStore.instance.db.execute("select * from stats_for_years where player_external_id = ? and year = ? and team = ?",
|
15
|
+
[self.player_external_id, self.year, self.team]) do |row|
|
16
|
+
|
17
|
+
DataStore.instance.db.execute "update stats_for_years " +
|
18
|
+
"set year = ?, team = ?, games = ?, at_bats = ?, runs =?, " +
|
19
|
+
"hits = ?, doubles = ?, triples = ?, home_runs = ?, runs_batted_in = ?, " +
|
20
|
+
"stolen_bases = ?, caught_stealing = ?, batting_average = ?, slugging_percentage = ?, fantasy_points = ? " +
|
21
|
+
"where player_external_id = ?",
|
22
|
+
[(self.year.present? ? self.year : row[1]),
|
23
|
+
(self.team.present? ? self.team : row[2]),
|
24
|
+
(self.games.present? ? self.games : row[3]),
|
25
|
+
(self.at_bats.present? ? self.at_bats : row[4]),
|
26
|
+
(self.runs.present? ? self.runs : row[5]),
|
27
|
+
(self.hits.present? ? self.hits : row[6]),
|
28
|
+
(self.doubles.present? ? self.doubles : row[7]),
|
29
|
+
(self.triples.present? ? self.triples : row[8]),
|
30
|
+
(self.home_runs.present? ? self.home_runs : row[9]),
|
31
|
+
(self.runs_batted_in.present? ? self.runs_batted_in : row[10]),
|
32
|
+
(self.stolen_bases.present? ? self.stolen_bases : row[11]),
|
33
|
+
(self.caught_stealing.present? ? self.caught_stealing : row[12]),
|
34
|
+
(self.batting_average.present? ? self.batting_average : row[13]),
|
35
|
+
(self.slugging_percentage.present? ? self.slugging_percentage : row[14]),
|
36
|
+
(self.fantasy_points.present? ? self.fantasy_points : row[15]),
|
37
|
+
self.player_external_id]
|
38
|
+
return
|
39
|
+
end
|
40
|
+
|
41
|
+
# if not, just insert
|
42
|
+
DataStore.instance.db.execute "insert into stats_for_years values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
43
|
+
[self.player_external_id,
|
44
|
+
self.year,
|
45
|
+
self.team,
|
46
|
+
self.games,
|
47
|
+
self.at_bats,
|
48
|
+
self.runs,
|
49
|
+
self.hits,
|
50
|
+
self.doubles,
|
51
|
+
self.triples,
|
52
|
+
self.home_runs,
|
53
|
+
self.runs_batted_in,
|
54
|
+
self.stolen_bases,
|
55
|
+
self.caught_stealing,
|
56
|
+
self.batting_average,
|
57
|
+
self.slugging_percentage,
|
58
|
+
self.fantasy_points]
|
59
|
+
end
|
60
|
+
|
61
|
+
def reload
|
62
|
+
DataStore.instance.db.execute("select * from stats_for_years where player_external_id = ? and year = ? and team = ?", [self.player_external_id, self.year, self.team]) do |row|
|
63
|
+
self.build_from_result_row row
|
64
|
+
end
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def calculate_batting_average!
|
69
|
+
self.batting_average = (((self.hits.to_f / self.at_bats.to_f) * 1000).to_i rescue nil)
|
70
|
+
end
|
71
|
+
|
72
|
+
def calculate_slugging_percentage!
|
73
|
+
self.slugging_percentage = (((((self.hits - self.doubles - self.triples - self.home_runs) +
|
74
|
+
(2 * self.doubles) + (3 * self.triples) +
|
75
|
+
(4 * self.home_runs)).to_f / self.at_bats.to_f) * 1000).to_i rescue nil)
|
76
|
+
end
|
77
|
+
|
78
|
+
def calculate_fantasy_points!
|
79
|
+
self.fantasy_points = ((self.home_runs * FANTASY_HR) + (self.runs_batted_in * FANTASY_RBI) +
|
80
|
+
(self.stolen_bases * FANTASY_SB) + (self.caught_stealing * FANTASY_CS) rescue nil)
|
81
|
+
end
|
82
|
+
|
83
|
+
# finders
|
84
|
+
|
85
|
+
def self.find_triple_crown_winner year, min_at_bats
|
86
|
+
home_run_winners = find_highest_home_runs year, min_at_bats
|
87
|
+
rbi_winners = find_highest_rbi year, min_at_bats
|
88
|
+
batting_crown_winners = find_highest_batting_average year, min_at_bats
|
89
|
+
|
90
|
+
first_group = []
|
91
|
+
home_run_winners.each{ |hr| first_group << hr if rbi_winners.any?{ |rbi| rbi.player_external_id == hr.player_external_id } }
|
92
|
+
second_group = []
|
93
|
+
first_group.each{ |fg| second_group << fg if batting_crown_winners.any?{ |bc| bc.player_external_id == fg.player_external_id } }
|
94
|
+
second_group.first
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.find_highest_batting_average year, min_at_bats
|
98
|
+
highest_batting_average = 0
|
99
|
+
|
100
|
+
# find the max value in case there are folks who are tied
|
101
|
+
DataStore.instance.db.execute("select max(batting_average) from stats_for_years where at_bats > ? and year = ?", [min_at_bats, year]) do |row|
|
102
|
+
highest_batting_average = row[0]
|
103
|
+
end
|
104
|
+
|
105
|
+
stats_to_return = []
|
106
|
+
# now grab everyone with the high value
|
107
|
+
DataStore.instance.db.execute("select * from stats_for_years where at_bats > ? and year = ? and batting_average = ?", [min_at_bats, year, highest_batting_average]) do |row|
|
108
|
+
stats = StatsForYear.new
|
109
|
+
stats.build_from_result_row row
|
110
|
+
stats_to_return << stats
|
111
|
+
end
|
112
|
+
stats_to_return
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.find_highest_home_runs year, min_at_bats
|
116
|
+
highest_home_runs = 0
|
117
|
+
|
118
|
+
# find the max value in case there are folks who are tied
|
119
|
+
DataStore.instance.db.execute("select max(home_runs) from stats_for_years where at_bats > ? and year = ?", [min_at_bats, year]) do |row|
|
120
|
+
highest_home_runs = row[0]
|
121
|
+
end
|
122
|
+
|
123
|
+
stats_to_return = []
|
124
|
+
# now grab everyone with the high value
|
125
|
+
DataStore.instance.db.execute("select * from stats_for_years where at_bats > ? and year = ? and home_runs = ?", [min_at_bats, year, highest_home_runs]) do |row|
|
126
|
+
stats = StatsForYear.new
|
127
|
+
stats.build_from_result_row row
|
128
|
+
stats_to_return << stats
|
129
|
+
end
|
130
|
+
stats_to_return
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.find_highest_rbi year, min_at_bats
|
134
|
+
highest_rbi = 0
|
135
|
+
|
136
|
+
# find the max value in case there are folks who are tied
|
137
|
+
DataStore.instance.db.execute("select max(runs_batted_in) from stats_for_years where at_bats > ? and year = ?", [min_at_bats, year]) do |row|
|
138
|
+
highest_rbi = row[0]
|
139
|
+
end
|
140
|
+
|
141
|
+
stats_to_return = []
|
142
|
+
# now grab everyone with the high value
|
143
|
+
DataStore.instance.db.execute("select * from stats_for_years where at_bats > ? and year = ? and runs_batted_in = ?", [min_at_bats, year, highest_rbi]) do |row|
|
144
|
+
stats = StatsForYear.new
|
145
|
+
stats.build_from_result_row row
|
146
|
+
stats_to_return << stats
|
147
|
+
end
|
148
|
+
stats_to_return
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.find_team_for_year year, team
|
152
|
+
teammates = []
|
153
|
+
DataStore.instance.db.execute("select * from stats_for_years where year = ? and team = ?", [year, team]) do |row|
|
154
|
+
stats = StatsForYear.new
|
155
|
+
stats.build_from_result_row row
|
156
|
+
teammates << stats
|
157
|
+
end
|
158
|
+
teammates
|
159
|
+
end
|
160
|
+
|
161
|
+
# end finders
|
162
|
+
|
163
|
+
def build_from_result_row row
|
164
|
+
self.player_external_id = row[0]
|
165
|
+
self.year = row[1]
|
166
|
+
self.team = row[2]
|
167
|
+
self.games = row[3]
|
168
|
+
self.at_bats = row[4]
|
169
|
+
self.runs = row[5]
|
170
|
+
self.hits = row[6]
|
171
|
+
self.doubles = row[7]
|
172
|
+
self.triples = row[8]
|
173
|
+
self.home_runs = row[9]
|
174
|
+
self.runs_batted_in = row[10]
|
175
|
+
self.stolen_bases = row[11]
|
176
|
+
self.caught_stealing = row[12]
|
177
|
+
self.batting_average = row[13]
|
178
|
+
self.slugging_percentage = row[14]
|
179
|
+
self.fantasy_points = row[15]
|
180
|
+
end
|
181
|
+
|
182
|
+
def baseball_player
|
183
|
+
BaseballPlayer.find_by_external_id self.player_external_id
|
184
|
+
end
|
185
|
+
|
186
|
+
def self.most_improved_batting_average from_year, to_year
|
187
|
+
sql = 'select a.player_external_id, (a.batting_average - b.batting_average) ' +
|
188
|
+
'from stats_for_years a, stats_for_years b ' +
|
189
|
+
'where a.year = ? and b.year = ? ' +
|
190
|
+
'and a.player_external_id = b.player_external_id'
|
191
|
+
|
192
|
+
parse_most_improved sql, from_year, to_year
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.most_improved_fantasy_points from_year, to_year
|
196
|
+
sql = 'select a.player_external_id, (a.fantasy_points - b.fantasy_points) ' +
|
197
|
+
'from stats_for_years a, stats_for_years b ' +
|
198
|
+
'where a.year = ? and b.year = ? ' +
|
199
|
+
'and a.player_external_id = b.player_external_id'
|
200
|
+
|
201
|
+
|
202
|
+
parse_most_improved sql, from_year, to_year
|
203
|
+
end
|
204
|
+
|
205
|
+
private
|
206
|
+
|
207
|
+
def self.parse_most_improved sql, from_year, to_year
|
208
|
+
deltas = []
|
209
|
+
DataStore.instance.db.execute(sql,[to_year, from_year]) do |row|
|
210
|
+
deltas << [row[0], row[1]]
|
211
|
+
end
|
212
|
+
deltas.select!{ |d| d[0].present? && d[1].present? }
|
213
|
+
deltas.sort!{ |x,y| y[1] <=> x[1] }
|
214
|
+
highest = deltas.first
|
215
|
+
deltas.select{ |d| d[1] == highest[1] }.map{ |d| d[0] }
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
data/lib/bb_analytics.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'bb_analytics/version.rb'
|
2
|
+
require 'bb_analytics/models/importer.rb'
|
3
|
+
require 'bb_analytics/models/baseball_player.rb'
|
4
|
+
require 'bb_analytics/models/stats_for_year.rb'
|
5
|
+
require 'bb_analytics/models/data_store.rb'
|
6
|
+
|
7
|
+
# some ActiveSupport style monkey patching for '#present?'
|
8
|
+
class String
|
9
|
+
def present?
|
10
|
+
!self.nil? && self != ""
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class NilClass
|
15
|
+
def present?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Integer
|
21
|
+
def present?
|
22
|
+
!self.nil?
|
23
|
+
end
|
24
|
+
end
|