bb_analytics 0.0.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.
- 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
|