repl.it
@SeanMcNamara1/

BaseballRunDistributionAnalysis

Ruby

No description

fork
loading
Files
  • main.rb
  • gamelog-2012-Orioles.csv
  • gamelog-2014-Orioles.csv
  • gamelog-2018-Orioles.csv
main.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
require 'bundler/inline'

def suppress_output
  original_stdout, original_stderr = $stdout.clone, $stderr.clone
  $stderr.reopen File.new('/dev/null', 'w')
  $stdout.reopen File.new('/dev/null', 'w')
  yield
ensure
  $stdout.reopen original_stdout
  $stderr.reopen original_stderr
end

suppress_output do
  gemfile true do
   source 'http://rubygems.org'
   gem 'multi_json'
  end
end

def run_stats(filename)
  metadata = {}
  inputs = Array.new
  firstLine = true
  IO.read(filename).each_line do |line|
    if firstLine
      firstLine = false
      metadata = MultiJson.load(line)
    else
      a = line.split(",")
      h = { :date => a[0], :rs => a[1].to_i(), :ra => a[2].strip.to_i(), :used_rs => false }
      h[:locked] = (h[:rs] == (h[:ra] + 1))
      inputs << h
    end
  end
  
  puts "**************START ANALYSIS OF: #{metadata['year']} #{metadata['team']}**************"
  
  oinputs = inputs
  inputs = inputs.sort_by { |h| h[:ra] }
  inputs_ra_desc = inputs.reverse
  inputs_rs_asc = inputs.sort_by { |h| h[:rs] }
  
  inputs_ra_desc.each do |h|
    cheap_game_idx = inputs.find_index { |i| i[:rs] > h[:ra] and i[:used_rs] == false and i[:locked] == false }
    cheap_game = cheap_game_idx.nil? ? nil : inputs[cheap_game_idx]
    
    if h[:rs] > h[:ra] and h[:used_rs] == false
      h[:locked] = true
      h[:borrowed_rs] = -1
      h[:used_rs] = true
    elsif !cheap_game.nil? and cheap_game != h
      h[:borrowed_rs_date] = cheap_game[:date]
      h[:borrowed_rs] = cheap_game[:rs]
      cheap_game[:used_rs] = true
    else
      h[:borrowed_rs] = -1
    end
  end
  
  sinputs = inputs.sort_by { |h| h[:borrowed_rs] }
  
  wins = 0
  losses = 0
  sinputs.sort_by { |p| p[:date] }.each do |h|
    wl = h[:rs] > h[:ra] ? 'W' : 'L'
    myput = "(#{wl}->#{(h[:borrowed_rs]==-1 and h[:locked] == false) ? 'L' : 'W'}) On #{h[:date]} the #{metadata['team']} "
    myput << "WON #{h[:rs]}-#{h[:ra]}" if wl == 'W'
    myput << "LOST #{h[:ra]}-#{h[:rs]}" if wl == 'L'
    myput << ". "
    if h[:locked] == true
      if wl == 'W'
        myput << "No need to rearrange the results of this game."
        wins+=1
      elsif wl == 'L'
        losses+=1
      else
        raise 'huh?'
      end
    else
      if h[:borrowed_rs] == -1
        if inputs.count { |z| z[:rs] > h[:ra] } == 0
          myput << "They never scored at least #{h[:ra]+1} runs this season, so this is an automatic loss."  
        else
          if h[:rs] > h[:ra]
            myput << "I've repurposed these #{h[:rs]} runs to use them more efficiently. They don't have enough games scoring at least #{h[:ra]+1} runs to win here, so this is a loss."  
          else
            myput << "They don't have enough games scoring at least #{h[:ra]+1} runs to win here, so this remains a loss."  
          end
          
        end
        losses+=1
      else
        myput << "If they borrowed the #{h[:borrowed_rs]} runs they scored on #{h[:borrowed_rs_date]}, they would've won!"
        wins+=1
      end
    end
    puts myput
  end
  
  owins = oinputs.count { |h| h[:rs] > h[:ra] }
  olosses = oinputs.count { |h| h[:rs] < h[:ra] }
  puts "ANALYSIS:"
  puts "As of #{oinputs.last[:date]} the #{metadata['team']} would have been #{wins}-#{losses} if they had optimally distributed their offensive and defensive performances."
  puts "Instead, they were #{owins}-#{olosses}. That's #{wins-owins} wins worse than they could've done with optimal run utilization."
  puts "Their actual run utilization efficiency was #{(((wins.to_f-owins.to_f)/wins.to_f)*100).to_i}% of optimal."
  ewins = ((owins.to_f+olosses.to_f)/2.0).floor.to_i
  elosses = (owins+olosses) - ewins
  ediff = ewins-owins
  optdiff = wins-owins
  epct = ((ediff.to_f/optdiff.to_f)*100).to_i
  if(owins < olosses)
    puts "The #{metadata['team']} could have a record of #{ewins}-#{elosses} if they'd distributed runs efficiently across #{ewins-owins} more games, for an efficiency of #{epct}%."
  elsif owins > olosses
    puts "To play down to a record of #{ewins}-#{elosses} the #{metadata['team']} would have to mismatch their run distribution in #{(ewins-owins).abs} more games, for an efficiency of #{epct}%."
  else
    puts "The #{metadata['team']} are exactly .500."
  end
  puts "**************FINISHED ANALYSIS OF: #{metadata['year']} #{metadata['team']}**************"
  puts
end

Dir.foreach('.') do |item|
  next unless item =~ /.*\.csv/
  run_stats(item)
end
ruby 2.5.5p157 (2019-03-15 revision 67260) [x86_64-linux]
?