summaryrefslogtreecommitdiff
path: root/plugin.video.mlbbasesloaded/leverage_index.py
diff options
context:
space:
mode:
authorjakecar <jakeskramer@gmail.com>2017-04-09 17:15:29 -0400
committerenen92 <enen92@users.noreply.github.com>2017-04-09 22:15:29 +0100
commit42422d801dfb9491b820fcbcfc411dc242279d68 (patch)
treeba3d49ba0ee03a552c45e92455eb05bf10346c15 /plugin.video.mlbbasesloaded/leverage_index.py
parent479a368e3491d81d93f70488becec23e078448e8 (diff)
[plugin.video.mlbbasesloaded] v0.2 (#1107)
* [plugin.video.mlbbasesloaded] 0.2 * Address comments * Remove old strings file * Address more comments
Diffstat (limited to 'plugin.video.mlbbasesloaded/leverage_index.py')
-rw-r--r--plugin.video.mlbbasesloaded/leverage_index.py80
1 files changed, 80 insertions, 0 deletions
diff --git a/plugin.video.mlbbasesloaded/leverage_index.py b/plugin.video.mlbbasesloaded/leverage_index.py
new file mode 100644
index 0000000..4f15b79
--- /dev/null
+++ b/plugin.video.mlbbasesloaded/leverage_index.py
@@ -0,0 +1,80 @@
+from __future__ import with_statement
+from __future__ import absolute_import
+import csv
+from collections import defaultdict
+from io import open
+from itertools import imap
+
+class StaticTableLeverageIndex(object):
+ u""" Uses a static CSV file to compute leverage index
+
+ >>> # Happy path test
+ >>> index = StaticTableLeverageIndex('resources/li.csv')
+ >>> index.get(7, 'bot', [u'3'], 2, 5, 5)
+ 2.6
+ >>> # Test when run differential is outside range [-4, +4]
+ >>> index.get(7, 'bot', [u'3'], 2, 1, 12) == index.get(7, 'bot', [u'3'], 2, 1, 5)
+ True
+ >>> index.get(7, 'bot', [u'3'], 2, 12, 1) == index.get(7, 'bot', [u'3'], 2, 5, 1)
+ True
+ >>> # Test no one on
+ >>> index.get(7, 'bot', [], 0, 1, 1)
+ 1.5
+ >>> # Test extra innings
+ >>> index.get(9, 'bot', [], 0, 1, 1) == index.get(12, 'bot', [], 0, 1, 1)
+ True
+ """
+ def __init__(self, li_table_filepath):
+ # Structure of self.li_table is:
+ # self.li_table[inning_num][inning_half][runners_on][outs][run_differential] = leverage_index
+ # where runners_on looks like "_ 2 _" or "_ _ _" or "1 2 _"
+ self.li_table = self._init_li_table(li_table_filepath)
+
+ def _init_li_table(self, li_table_filepath):
+ # Fields are: inning_num,inning_half,runners_on,outs,-4,-3,-2,-1,0,+1,+2,+3,+4 where "-3" means home team is down by 3
+ li_table = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(list))))
+ with open(li_table_filepath, 'r', encoding='utf-8') as f:
+ # Skip comment lines starting with '#'
+ li_table_csv = csv.reader(filter(lambda row: row[0] != '#', f))
+ for row in li_table_csv:
+ _3to2list = list(row)
+ inning_num, inning_half, runners_on, outs, run_differential, = _3to2list[:4] + [_3to2list[4:]]
+ # Convert each run differential key from str to float
+ run_differential = list(imap(float, run_differential))
+ li_table[int(inning_num)][inning_half][runners_on][int(outs)] = run_differential
+ return li_table
+
+ def get(self, inning_num, inning_half, runners_on, num_outs, away_score, home_score):
+ assert inning_half == u'top' or inning_half == u'bot'
+ assert inning_num > 0
+ assert len(runners_on) <= 3
+ assert 0 <= num_outs and num_outs < 3
+ assert away_score >= 0 and home_score >= 0
+ return self._get_impl(inning_num, inning_half, runners_on, num_outs, away_score, home_score)
+
+ def _get_impl(self, inning_num, inning_half, runners_on, num_outs, away_score, home_score):
+ run_differential_index = self._get_run_differential(away_score, home_score) + 4
+ runners_on_str = self._convert_runners_on(runners_on)
+ inning_num_index = min(inning_num, 9)
+
+ return self.li_table[inning_num_index][inning_half][runners_on_str][num_outs][run_differential_index]
+
+ def _get_run_differential(self, away_score, home_score):
+ MINIMUM = -4
+ MAXIMUM = 4
+ differential = home_score - away_score
+ clamped_differential = max(MINIMUM, min(differential, MAXIMUM))
+ return clamped_differential
+
+ def _convert_runners_on(self, runners_on):
+ assert all(type(x) is unicode for x in runners_on)
+
+ runners_on_str = unicode()
+ runners_on_str += u'1 ' if u'1' in runners_on else u'_ '
+ runners_on_str += u'2 ' if u'2' in runners_on else u'_ '
+ runners_on_str += u'3' if u'3' in runners_on else u'_'
+ return runners_on_str
+
+if __name__ == u'__main__':
+ import doctest
+ doctest.testmod()