Skip to content

Commit

Permalink
store hh._Action in hh.*_action attributes closes #2
Browse files Browse the repository at this point in the history
  • Loading branch information
kakty3 committed Jul 13, 2016
1 parent f4ec1d1 commit 45c2974
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 53 deletions.
102 changes: 97 additions & 5 deletions poker/room/pokerstars.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,96 @@ def _parse_connected(self, line):
name = splited[0]
return name, Action.CONNECTED, None


class ActionParser(object):
_player_action_re = re.compile(r'^(?P<name>.+):\s+(?P<action>.+?\b)\s*(?:[^\d]*?(?P<amount>\d+(?:\.\d+)?))?')
_uncalled_re = re.compile(r'^Uncalled bet \([^\d]*?(?P<amount>\d+(?:\.\d+)?)\) returned to\s+(?P<name>.+)$')
_collected_re = re.compile(r'^(?P<name>.+?) collected [^\d]*?(?P<amount>\d+(?:\.\d+)?)')

# @classmethod
def parse(self, action_str):
if action_str.startswith('Uncalled bet'):
action = self._parse_uncalled(action_str)
elif ' collected ' in action_str:
action = self._parse_collected(action_str)
elif "doesn't show hand" in action_str:
action = self._parse_muck(action_str)
elif ' said, "' in action_str: # skip chat lines
action = None
elif ':' in action_str:
action = self._parse_player_action(action_str)
elif 'joins the table' in action_str:
action = self._parse_join_table(action_str)
elif 'leaves the table' in action_str:
action = self._parse_leave_table(action_str)
elif 'has timed out' in action_str:
action = self._parse_timed_out(action_str)
elif 'is connected' in action_str:
action = self._parse_connected(action_str)
elif 'is disconnected' in action_str:
action = self._parse_disconnected(action_str)
else:
raise RuntimeError("Unknown action: " + action_str)

return hh._PlayerAction(*action)

def _parse_uncalled(self, line):
match = self._uncalled_re.match(line)
name = match.group('name')
amount = match.group('amount')
return name, Action.RETURN, Decimal(amount)

def _parse_collected(self, line):
match = self._collected_re.match(line)
name = match.group('name')
amount = match.group('amount')
self.pot = Decimal(amount)
return name, Action.WIN, self.pot

def _parse_muck(self, line):
colon_index = line.find(':')
name = line[:colon_index]
return name, Action.MUCK, None

def _parse_player_action(self, line):
match = self._player_action_re.match(line)
name = match.group('name')
action = Action(match.group('action'))
amount = match.group('amount')
try:
amount = Decimal(amount)
except TypeError:
pass

return name, action, amount

def _parse_join_table(self, line):
splited = line.split()
name = splited[0]
seat = splited[-1][1:]
return name, Action.JOIN, seat

def _parse_leave_table(self, line):
splited = line.split()
name = splited[0]
return name, Action.LEAVE, None

def _parse_timed_out(self, line):
splited = line.split()
name = splited[0]
return name, Action.TIMED_OUT, None

def _parse_disconnected(self, line):
splited = line.split()
name = splited[0]
return name, Action.DISCONNECTED, None

def _parse_connected(self, line):
splited = line.split()
name = splited[0]
return name, Action.CONNECTED, None


@implementer(hh.IHandHistory)
class PokerStarsHandHistory(hh._SplittableHandHistoryMixin, hh._BaseHandHistory):
"""Parses PokerStars Tournament hands."""
Expand Down Expand Up @@ -264,7 +354,8 @@ def _parse_hero(self):
def _parse_preflop(self):
start = self._sections[0] + 3
stop = self._sections[1]
self.preflop_actions = tuple(self._splitted[start:stop])
ap = ActionParser()
self.preflop_actions = tuple(ap.parse(action_str) for action_str in self._splitted[start:stop])

def _parse_flop(self):
try:
Expand All @@ -277,15 +368,16 @@ def _parse_flop(self):
self.flop = _Street(floplines)

def _parse_street(self, street):
street_attr = '%s_actions' % street.lower()
try:
start = self._splitted.index(street.upper()) + 2
stop = self._splitted.index('', start)
street_actions = self._splitted[start:stop]
setattr(self, "{}_actions".format(street.lower()),
tuple(street_actions) if street_actions else None)
ap = ActionParser()
street_actions = [ap.parse(action_str) for action_str in self._splitted[start:stop]]
setattr(self, street_attr, tuple(street_actions) if street_actions else None)
except ValueError:
setattr(self, street, None)
setattr(self, '{}_actions'.format(street.lower()), None)
setattr(self, street_attr, None)

def _parse_showdown(self):
self.show_down = 'SHOW DOWN' in self._splitted
Expand Down
99 changes: 51 additions & 48 deletions tests/handhistory/test_stars.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,15 @@ def test_values_after_header_parsed(self, hand_header, attribute, expected_value
('river', None),
('board', (Card('2s'), Card('6d'), Card('6h'))),
('preflop_actions', (
"strongi82: folds",
"W2lkm2n: raises 40 to 60",
"MISTRPerfect: calls 60",
"blak_douglas: folds",
"sinus91: folds",
"STBIJUJA: folds",
"flettl2: folds",
"santy312: folds",
"flavio766: folds"
_PlayerAction(name=u'strongi82', action=Action('fold'), amount=None),
_PlayerAction(name=u'W2lkm2n', action=Action('raise'), amount=Decimal(40)),
_PlayerAction(name=u'MISTRPerfect', action=Action('calls'), amount=Decimal(60)),
_PlayerAction(name=u'blak_douglas', action=Action('folds'), amount=None),
_PlayerAction(name=u'sinus91', action=Action('folds'), amount=None),
_PlayerAction(name=u'STBIJUJA', action=Action('folds'), amount=None),
_PlayerAction(name=u'flettl2', action=Action('folds'), amount=None),
_PlayerAction(name=u'santy312', action=Action('folds'), amount=None),
_PlayerAction(name=u'flavio766', action=Action('folds'), amount=None),
)),
('turn_actions', None),
('river_actions', None),
Expand Down Expand Up @@ -305,16 +305,17 @@ def test_values_after_header_parsed(self, hand_header, attribute, expected_value
('river', Card('Ks')),
('board', (Card('3c'), Card('6s'), Card('9d'), Card('8d'), Card('Ks'))),
('preflop_actions', (
"lkenny44: folds",
"Newfie_187: raises 155 to 955 and is all-in",
"Hokolix: folds",
"pmmr: folds",
"costamar: raises 12040 to 12995 and is all-in",
"RichFatWhale: folds",
"W2lkm2n: calls 11740 and is all-in",
"Labahra: folds",
"Lean Abadia: folds",
"Uncalled bet (1255) returned to costamar")),
_PlayerAction(name=u'lkenny44', action=Action('fold'), amount=None),
_PlayerAction(name=u'Newfie_187', action=Action('raise'), amount=Decimal(155)),
_PlayerAction(name=u'Hokolix', action=Action('fold'), amount=None),
_PlayerAction(name=u'pmmr', action=Action('fold'), amount=None),
_PlayerAction(name=u'costamar', action=Action('raise'), amount=Decimal(12040)),
_PlayerAction(name=u'RichFatWhale', action=Action('fold'), amount=None),
_PlayerAction(name=u'W2lkm2n', action=Action('call'), amount=Decimal(11740)),
_PlayerAction(name=u'Labahra', action=Action('fold'), amount=None),
_PlayerAction(name=u'Lean Abadia', action=Action('fold'), amount=None),
_PlayerAction(name=u'costamar', action=Action('return'), amount=Decimal(1255))
)),
('turn_actions', None),
('river_actions', None),
('total_pot', Decimal(26310)),
Expand Down Expand Up @@ -398,17 +399,17 @@ def test_values_after_header_parsed(self, hand_header, attribute, expected_value
('river', None),
('board', None),
('preflop_actions', (
'EuSh0wTelm0: folds',
'panost3: folds',
'Samovlyblen: folds',
'Theralion: raises 600 to 1200',
'wrsport1015: folds',
'W2lkm2n: folds',
'fischero68: folds',
'snelle_jel: folds',
'Uncalled bet (600) returned to Theralion',
'Theralion collected 1900 from pot',
"Theralion: doesn't show hand"
_PlayerAction(name=u'EuSh0wTelm0', action=Action('fold'), amount=None),
_PlayerAction(name=u'panost3', action=Action('fold'), amount=None),
_PlayerAction(name=u'Samovlyblen', action=Action('fold'), amount=None),
_PlayerAction(name=u'Theralion', action=Action('raise'), amount=Decimal(600)),
_PlayerAction(name=u'wrsport1015', action=Action('fold'), amount=None),
_PlayerAction(name=u'W2lkm2n', action=Action('fold'), amount=None),
_PlayerAction(name=u'fischero68', action=Action('fold'), amount=None),
_PlayerAction(name=u'snelle_jel', action=Action('fold'), amount=None),
_PlayerAction(name=u'Theralion', action=Action('return'), amount=Decimal(600)),
_PlayerAction(name=u'Theralion', action=Action('collected'), amount=Decimal(1900)),
_PlayerAction(name=u'Theralion', action=Action('did not show'), amount=None),
)),
('turn_actions', None),
('river_actions', None),
Expand Down Expand Up @@ -463,26 +464,28 @@ def test_values_after_header_parsed(self, hand_header, attribute, expected_value
('river', Card('Kd')),
('board', (Card('6s'), Card('4d'), Card('3s'), Card('8c'), Card('Kd'))),
('preflop_actions', (
'sinus91: folds',
'STBIJUJA: folds',
'flettl2: raises 125 to 225',
'santy312: folds',
'flavio766: folds',
'strongi82: folds',
'W2lkm2n: folds',
'MISTRPerfect: folds',
'blak_douglas: calls 125')),
_PlayerAction('sinus91', Action.FOLD, None),
_PlayerAction('STBIJUJA', Action.FOLD, None),
_PlayerAction('flettl2', Action.RAISE, Decimal(125)),
_PlayerAction('santy312', Action.FOLD, None),
_PlayerAction('flavio766', Action.FOLD, None),
_PlayerAction('strongi82', Action.FOLD, None),
_PlayerAction('W2lkm2n', Action.FOLD, None),
_PlayerAction('MISTRPerfect', Action.FOLD, None),
_PlayerAction('blak_douglas', Action.CALL, Decimal(125)),
)),
('turn_actions', (
'blak_douglas: checks',
'flettl2: bets 250',
'blak_douglas: calls 250')),
_PlayerAction('blak_douglas', Action.CHECK, None),
_PlayerAction('flettl2', Action.BET, Decimal(250)),
_PlayerAction('blak_douglas', Action.CALL, Decimal(250))
)),
('river_actions', (
'blak_douglas: checks',
'flettl2: bets 1300',
'blak_douglas: folds',
'Uncalled bet (1300) returned to flettl2',
'flettl2 collected 1300 from pot',
"flettl2: doesn't show hand"
_PlayerAction('blak_douglas', Action.CHECK, None),
_PlayerAction('flettl2', Action.BET, Decimal(1300)),
_PlayerAction('blak_douglas', Action.FOLD, None),
_PlayerAction('flettl2', Action.RETURN, Decimal(1300)),
_PlayerAction('flettl2', Action.WIN, Decimal(1300)),
_PlayerAction('flettl2', Action.MUCK, None),
)),
('total_pot', Decimal(1300)),
('show_down', False),
Expand Down

0 comments on commit 45c2974

Please sign in to comment.