codenamev-baseball-stats 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e68b76699a7b187eca62f659bc71d0b31fb4ac06
4
+ data.tar.gz: 042a059cee664f3e48d39b540b99bd7299dba664
5
+ SHA512:
6
+ metadata.gz: dfb71a29b8e9f88d6d7dd382367204a2d3aa160613f80744adc4a7d298e0178a9220702ddaf4e0e6a1f6d7c2c6d04346d3a4ea8bf423524b1b7f8316bc376376
7
+ data.tar.gz: 8541554cefc58a772afd0ef0700e7c4004ca4ca00fc23f2ac9c52b9d0fbabfe3d50d28fe355518a82e3d3202b74fb8408eba73df631ab2369efb608300d40537
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ **/.~lock.*
2
+ **/.DS_STORE
3
+ *.gem
4
+ *.rbc
5
+ .bundle
6
+ .config
7
+ .yardoc
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
20
+ db/*.sqlite3
21
+ log/*.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.1.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in baseball-stats.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Valentino
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Valentino
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # BaseballStats
2
+
3
+ Baseball player statistical analysis
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'codenamev-baseball-stats'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install codenamev-baseball-stats
18
+
19
+ ## Usage
20
+
21
+ After installing the gem, running `baseball_stats` from the command-line will
22
+ display the results to the following excersize:
23
+
24
+ 1. Most improved batting average from 2009 to 2010
25
+ 2. Slugging percentage for all players on the Oakland A's in 2007
26
+ 3. Who was the AL and NL tripple crown winner for 2011 and 2012. If no one won
27
+ the crown should be "(No winner)"
28
+
29
+ ## NOTES
30
+
31
+ The first run of the command imports two fairly large CSV files with sample
32
+ data into an SQLite3 database. This may take up to 5 minutes depending on your machine.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+ require 'active_record'
5
+ require 'active_record_migrations'
6
+ require 'baseball_stats/database'
7
+
8
+ Dir[File.join(File.dirname(__FILE__),'lib/tasks/*.rake')].each { |f| load f }
9
+
10
+ RSpec::Core::RakeTask.new(:spec)
11
+ ActiveRecordMigrations.load_tasks
12
+
13
+ task :environment do
14
+ BaseballStats::Database.connection
15
+ end
16
+
17
+ task :default => [:spec]
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'baseball_stats/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "codenamev-baseball-stats"
8
+ spec.version = BaseballStats::VERSION
9
+ spec.authors = ["Valentino Stoll"]
10
+ spec.email = ["valentino@reenhanced.com"]
11
+ spec.description = %q{Generates baseball player statistics}
12
+ spec.summary = %q{Generates baseball player statistics}
13
+ spec.homepage = "https://github.com/codenamev/baseball-stats"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activerecord", "~> 4.1.6"
22
+ spec.add_dependency "active_record_migrations", "~> 4.1.6.1"
23
+ spec.add_dependency "colorize", "~> 0.7.3"
24
+ spec.add_dependency "sqlite3", "~> 1.3.9"
25
+ spec.add_dependency "table_print", "~> 1.1.5"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.3"
28
+ spec.add_development_dependency "database_cleaner"
29
+ spec.add_development_dependency "factory_girl"
30
+ spec.add_development_dependency "faker"
31
+ spec.add_development_dependency "pry"
32
+ spec.add_development_dependency "rake"
33
+ spec.add_development_dependency "rspec"
34
+ spec.add_development_dependency "shoulda-matchers"
35
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'baseball_stats'
4
+
5
+ puts "Analyzing sample data..."
6
+ BaseballStats.seed_data
7
+
8
+ puts "1) Most improved batting average from 2009 to 2010: ".colorize(:green)
9
+ puts "\t#{BaseballStats.most_improved_player(2010)}\n"
10
+
11
+ puts "2) Slugging percentage for all players on the Oakland A's in 2007:".colorize(:green)
12
+ tp BaseballStats.slugging_percentage_for_team_and_year('OAK', 2007)
13
+
14
+ puts "\n3) AL Tripple crown winner for 2011: ".colorize(:green)
15
+ puts "\t#{BaseballStats.tripple_crown_winner(2011, 'AL')}\n"
16
+
17
+ puts "\n3) AL Tripple crown winner for 2012: ".colorize(:green)
18
+ puts "\t#{BaseballStats.tripple_crown_winner(2012, 'AL')}\n"
19
+
20
+ puts "\n3) NL Tripple crown winner for 2011: ".colorize(:green)
21
+ puts "\t#{BaseballStats.tripple_crown_winner(2011, 'NL')}\n"
22
+
23
+ puts "\n3) NL Tripple crown winner for 2012: ".colorize(:green)
24
+ puts "\t#{BaseballStats.tripple_crown_winner(2012, 'NL')}\n"
data/db/config.yml ADDED
@@ -0,0 +1,12 @@
1
+ all: &all
2
+ adapter: sqlite3
3
+ pool: 5
4
+ timeout: 5000
5
+
6
+ development:
7
+ <<: *all
8
+ database: db/development.sqlite3
9
+
10
+ test:
11
+ <<: *all
12
+ database: db/test.sqlite3
@@ -0,0 +1,27 @@
1
+ class CreateBattings < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :battings do |t|
4
+ t.string :player_id
5
+ t.integer :year_id
6
+ t.string :league
7
+ t.string :team_id
8
+ t.string :appearances
9
+ t.integer :at_bats
10
+ t.integer :runs_scored
11
+ t.integer :hits
12
+ t.integer :doubles
13
+ t.integer :triples
14
+ t.integer :home_runs
15
+ t.integer :runs_batted_in
16
+ t.integer :stolen_bases
17
+ t.integer :times_caught_stealing
18
+ end
19
+
20
+ add_index :battings, :player_id
21
+ add_index :battings, :year_id
22
+ end
23
+
24
+ def self.down
25
+ drop_table :battings
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ class CreatePlayers < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :players do |t|
4
+ t.string :player_id
5
+ t.integer :birth_year
6
+ t.string :first_name
7
+ t.string :last_name
8
+ end
9
+
10
+ add_index :players, :player_id
11
+ end
12
+
13
+ def self.down
14
+ drop_table :players
15
+ end
16
+ end
data/db/schema.rb ADDED
@@ -0,0 +1,45 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended that you check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(version: 20141029204424) do
15
+
16
+ create_table "battings", force: true do |t|
17
+ t.string "player_id"
18
+ t.integer "year_id"
19
+ t.string "league"
20
+ t.string "team_id"
21
+ t.string "appearances"
22
+ t.integer "at_bats"
23
+ t.integer "runs_scored"
24
+ t.integer "hits"
25
+ t.integer "doubles"
26
+ t.integer "triples"
27
+ t.integer "home_runs"
28
+ t.integer "runs_batted_in"
29
+ t.integer "stolen_bases"
30
+ t.integer "times_caught_stealing"
31
+ end
32
+
33
+ add_index "battings", ["player_id"], name: "index_battings_on_player_id"
34
+ add_index "battings", ["year_id"], name: "index_battings_on_year_id"
35
+
36
+ create_table "players", force: true do |t|
37
+ t.string "player_id"
38
+ t.integer "birth_year"
39
+ t.string "first_name"
40
+ t.string "last_name"
41
+ end
42
+
43
+ add_index "players", ["player_id"], name: "index_players_on_player_id"
44
+
45
+ end
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+ require 'sqlite3'
4
+ require 'colorize'
5
+ require 'table_print'
6
+
7
+ require "baseball_stats/database"
8
+ require "baseball_stats/batting"
9
+ require "baseball_stats/player"
10
+ require "baseball_stats/import"
11
+ require "baseball_stats/version"
12
+
13
+ module BaseballStats
14
+ include Import
15
+ include Database
16
+
17
+ extend self
18
+
19
+ def most_improved_player(year)
20
+ battings_for_year = Batting.with_batting_average.where('year_id = ? AND at_bats >= 200', year).order(player_id: :asc)
21
+ battings_for_previous_year = Batting.with_batting_average.where('year_id = ? AND at_bats >= 200', year-1).order(player_id: :asc)
22
+
23
+ most_improved_batting_average = 0.0
24
+ most_improved_player = nil
25
+
26
+ battings_for_year.each do |batting|
27
+ next unless prev_year_batting = battings_for_previous_year.where(player_id: batting.player_id).first
28
+ improvement = batting.batting_average - prev_year_batting.batting_average
29
+ next unless improvement > most_improved_batting_average
30
+ most_improved_batting_average = batting.batting_average
31
+ most_improved_player = batting.player_id
32
+ end
33
+
34
+ Player.where(player_id: most_improved_player).first
35
+ end
36
+
37
+ def slugging_percentage_for_team_and_year(team_id, year)
38
+ battings_for_team = Batting.includes(:player).with_slugging_percentage.where(team_id: team_id, year_id: year)
39
+ battings_for_team.collect {|batting|
40
+ { player: batting.player_name, slugging_percentage: "#{(batting.slugging_percentage.to_f * 100).round(2)}%" }
41
+ }
42
+ end
43
+
44
+ def tripple_crown_winner(year, league)
45
+ highest_batting_average = Batting.with_batting_average.tripple_crown_eligible.where(year_id: year, league: league).order('batting_average DESC').first
46
+ most_home_runs = Batting.tripple_crown_eligible.where(year_id: year, league: league).order(home_runs: :desc).first
47
+ most_rbis = Batting.tripple_crown_eligible.where(year_id: year, league: league).order(runs_batted_in: :desc).first
48
+
49
+ if highest_batting_average and most_home_runs and most_rbis and
50
+ highest_batting_average.player_id == most_home_runs.player_id and highest_batting_average.player_id == most_rbis.player_id
51
+ most_rbis.player
52
+ else
53
+ '(No winner)'
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,16 @@
1
+ require 'baseball_stats/database'
2
+
3
+ module BaseballStats
4
+ @connection = Database.connection
5
+
6
+ class Batting < ::ActiveRecord::Base
7
+ self.table_name = 'battings'
8
+
9
+ belongs_to :player, primary_key: :player_id
10
+ delegate :name, to: :player, prefix: true, allow_nil: true
11
+
12
+ scope :tripple_crown_eligible, -> { where('battings.at_bats >= 400') }
13
+ scope :with_batting_average, -> { select('battings.*, ((battings.hits * 1.0) / battings.at_bats) AS batting_average') }
14
+ scope :with_slugging_percentage, -> { select('battings.*, ((((battings.hits - battings.doubles - battings.triples - battings.home_runs) + (2*battings.doubles) + (3*battings.triples) + (4*battings.home_runs))* 1.0) / battings.at_bats) AS slugging_percentage') }
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+ require 'sqlite3'
4
+ require 'logger'
5
+ require 'yaml'
6
+
7
+ module BaseballStats
8
+ module Database
9
+ include ActiveRecord::Tasks
10
+
11
+ DEFAULT_ENV = "development".freeze
12
+
13
+ @env = nil
14
+ @logger = nil
15
+ @connection = nil
16
+ @configuration = YAML::load(IO.read('db/config.yml')).freeze
17
+ @root_path = File.expand_path('../../..', __FILE__).freeze
18
+ @db_dir = File.join(@root_path, 'db').freeze
19
+ @migrations_paths = [File.join(@root_path, 'db/migrate')].freeze
20
+
21
+ attr_accessor :configuration, :db_dir, :migrations_paths
22
+
23
+ extend self
24
+
25
+ def env
26
+ @env = ENV['APP_ENV'] || DEFAULT_ENV
27
+ end
28
+
29
+ def connection
30
+ ::ActiveRecord::Base.logger = Logger.new("log/#{self.env}.log")
31
+ ::ActiveRecord::Base.establish_connection(configuration[self.env])
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'csv'
4
+ require "baseball_stats/batting"
5
+ require "baseball_stats/player"
6
+
7
+ # Require all migration files
8
+ Dir[File.expand_path('../../../db/migrate/*.rb', __FILE__)].each {|f| require f }
9
+
10
+ module BaseballStats::Import
11
+ extend self
12
+
13
+ SEED_BATTINGS_CSV = File.expand_path('../../../sample_data/battings.csv', __FILE__)
14
+ SEED_PLAYERS_CSV = File.expand_path('../../../sample_data/players.csv', __FILE__)
15
+
16
+ def seed_data
17
+ import_battings_from_csv(SEED_BATTINGS_CSV)
18
+ import_players_from_csv(SEED_PLAYERS_CSV)
19
+ end
20
+
21
+ def import_battings_from_csv(csv_file)
22
+ CreateBattings.up unless ActiveRecord::Base.connection.table_exists?('battings')
23
+ CSV.foreach(csv_file, headers: true, header_converters: :symbol) do |batting|
24
+ new_batting = BaseballStats::Batting.find_or_create_by(player_id: batting[:player_id], year_id: batting[:year_id])
25
+ new_batting.league = batting[:league]
26
+ new_batting.team_id = batting[:team_id]
27
+ new_batting.appearances = batting[:appearances]
28
+ new_batting.at_bats = batting[:at_bats]
29
+ new_batting.runs_scored = batting[:runs_scored]
30
+ new_batting.hits = batting[:hits]
31
+ new_batting.doubles = batting[:doubles]
32
+ new_batting.triples = batting[:triples]
33
+ new_batting.home_runs = batting[:home_runs]
34
+ new_batting.runs_batted_in = batting[:runs_batted_in]
35
+ new_batting.stolen_bases = batting[:stolen_bases]
36
+ new_batting.times_caught_stealing = batting[:times_caught_stealing]
37
+ new_batting.save!
38
+ end
39
+ end
40
+
41
+ def import_players_from_csv(csv_file)
42
+ CreatePlayers.up unless ActiveRecord::Base.connection.table_exists?('players')
43
+ CSV.foreach(csv_file, headers: true, header_converters: :symbol) do |player|
44
+ new_player = BaseballStats::Player.find_or_create_by(player_id: player[:player_id])
45
+ new_player.birth_year = player[:birth_year]
46
+ new_player.first_name = player[:name_first]
47
+ new_player.last_name = player[:name_last]
48
+ new_player.save!
49
+ end
50
+ end
51
+ end