Everleaf uncalled bets; pot total; rake
This commit is contained in:
parent
7926ac9def
commit
3dbb0e8376
|
@ -75,6 +75,7 @@ class Everleaf(HandHistoryConverter):
|
||||||
self.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)')
|
self.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)')
|
||||||
self.rexx.setPostSbRegex('.*\n(?P<PNAME>.*): posts small blind \[\$? (?P<SB>[.0-9]+)')
|
self.rexx.setPostSbRegex('.*\n(?P<PNAME>.*): posts small blind \[\$? (?P<SB>[.0-9]+)')
|
||||||
self.rexx.setPostBbRegex('.*\n(?P<PNAME>.*): posts big blind \[\$? (?P<BB>[.0-9]+)')
|
self.rexx.setPostBbRegex('.*\n(?P<PNAME>.*): posts big blind \[\$? (?P<BB>[.0-9]+)')
|
||||||
|
self.rexx.setPostBothRegex('.*\n(?P<PNAME>.*): posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
|
||||||
# mct : what about posting small & big blinds simultaneously?
|
# mct : what about posting small & big blinds simultaneously?
|
||||||
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<HOLE1>\S\S), (?P<HOLE2>\S\S) \]')
|
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<HOLE1>\S\S), (?P<HOLE2>\S\S) \]')
|
||||||
self.rexx.setActionStepRegex('.*\n(?P<PNAME>.*)(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[\$ (?P<BET>[.\d]+) USD\])?')
|
self.rexx.setActionStepRegex('.*\n(?P<PNAME>.*)(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[\$ (?P<BET>[.\d]+) USD\])?')
|
||||||
|
@ -131,7 +132,8 @@ class Everleaf(HandHistoryConverter):
|
||||||
r"(\*\* Dealing Turn \*\* \[ \S\S \](?P<TURN>.+(?=\*\* Dealing River \*\*)|.+))?"
|
r"(\*\* Dealing Turn \*\* \[ \S\S \](?P<TURN>.+(?=\*\* Dealing River \*\*)|.+))?"
|
||||||
r"(\*\* Dealing River \*\* \[ \S\S \](?P<RIVER>.+))?", hand.string,re.DOTALL)
|
r"(\*\* Dealing River \*\* \[ \S\S \](?P<RIVER>.+))?", hand.string,re.DOTALL)
|
||||||
|
|
||||||
hand.streets = m
|
hand.addStreets(m)
|
||||||
|
|
||||||
|
|
||||||
def readCommunityCards(self, hand):
|
def readCommunityCards(self, hand):
|
||||||
# currently regex in wrong place pls fix my brain's fried
|
# currently regex in wrong place pls fix my brain's fried
|
||||||
|
@ -146,15 +148,13 @@ class Everleaf(HandHistoryConverter):
|
||||||
def readBlinds(self, hand):
|
def readBlinds(self, hand):
|
||||||
try:
|
try:
|
||||||
m = self.rexx.small_blind_re.search(hand.string)
|
m = self.rexx.small_blind_re.search(hand.string)
|
||||||
hand.addBlind(m.group('PNAME'), m.group('SB'))
|
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
|
||||||
#hand.posted = [m.group('PNAME')]
|
except: # no small blind
|
||||||
except:
|
hand.addBlind(None, None, None)
|
||||||
hand.addBlind(None, 0)
|
for a in self.rexx.big_blind_re.finditer(hand.string):
|
||||||
#hand.posted = ["FpdbNBP"]
|
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
|
||||||
m = self.rexx.big_blind_re.finditer(hand.string)
|
for a in self.rexx.both_blinds_re.finditer(hand.string):
|
||||||
for a in m:
|
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
|
||||||
hand.addBlind(a.group('PNAME'), a.group('BB'))
|
|
||||||
#hand.posted = hand.posted + [a.group('PNAME')]
|
|
||||||
|
|
||||||
def readHeroCards(self, hand):
|
def readHeroCards(self, hand):
|
||||||
m = self.rexx.hero_cards_re.search(hand.string)
|
m = self.rexx.hero_cards_re.search(hand.string)
|
||||||
|
@ -167,7 +167,6 @@ class Everleaf(HandHistoryConverter):
|
||||||
|
|
||||||
def readAction(self, hand, street):
|
def readAction(self, hand, street):
|
||||||
m = self.rexx.action_re.finditer(hand.streets.group(street))
|
m = self.rexx.action_re.finditer(hand.streets.group(street))
|
||||||
hand.actions[street] = []
|
|
||||||
for action in m:
|
for action in m:
|
||||||
if action.group('ATYPE') == ' raises':
|
if action.group('ATYPE') == ' raises':
|
||||||
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
|
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
|
||||||
|
@ -182,6 +181,7 @@ class Everleaf(HandHistoryConverter):
|
||||||
else:
|
else:
|
||||||
print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)
|
print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)
|
||||||
#hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE')]]
|
#hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE')]]
|
||||||
|
# TODO: Everleaf does not record uncalled bets.
|
||||||
|
|
||||||
|
|
||||||
def readShowdownActions(self, hand):
|
def readShowdownActions(self, hand):
|
||||||
|
@ -201,9 +201,6 @@ class Everleaf(HandHistoryConverter):
|
||||||
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
||||||
|
|
||||||
|
|
||||||
def getRake(self, hand):
|
|
||||||
hand.rake = hand.totalpot - hand.totalcollected # * Decimal('0.05') # probably not quite right
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
c = Configuration.Config()
|
c = Configuration.Config()
|
||||||
e = Everleaf(c, "regression-test-files/everleaf/Speed_Kuala_full.txt")
|
e = Everleaf(c, "regression-test-files/everleaf/Speed_Kuala_full.txt")
|
||||||
|
|
|
@ -88,6 +88,7 @@ class Hand:
|
||||||
self.action = []
|
self.action = []
|
||||||
self.totalpot = None
|
self.totalpot = None
|
||||||
self.totalcollected = None
|
self.totalcollected = None
|
||||||
|
|
||||||
self.rake = None
|
self.rake = None
|
||||||
|
|
||||||
self.bets = {}
|
self.bets = {}
|
||||||
|
@ -110,6 +111,17 @@ If a player has None chips he won't be added."""
|
||||||
self.bets[street][name] = []
|
self.bets[street][name] = []
|
||||||
|
|
||||||
|
|
||||||
|
def addStreets(self, match):
|
||||||
|
# go through m and initialise actions to empty list for each street.
|
||||||
|
if match is not None:
|
||||||
|
self.streets = match
|
||||||
|
for street in match.groupdict():
|
||||||
|
if match.group(street) is not None:
|
||||||
|
self.actions[street] = []
|
||||||
|
|
||||||
|
else:
|
||||||
|
print "empty markStreets match" # better to raise exception and put process hand in a try block
|
||||||
|
|
||||||
def addHoleCards(self, cards, player):
|
def addHoleCards(self, cards, player):
|
||||||
"""\
|
"""\
|
||||||
Assigns observed holecards to a player.
|
Assigns observed holecards to a player.
|
||||||
|
@ -162,12 +174,18 @@ For when a player shows cards for any reason (for showdown or out of choice).
|
||||||
c = c.replace(k,v)
|
c = c.replace(k,v)
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def addBlind(self, player, amount):
|
def addBlind(self, player, blindtype, amount):
|
||||||
# if player is None, it's a missing small blind.
|
# if player is None, it's a missing small blind.
|
||||||
if player is not None:
|
if player is not None:
|
||||||
self.bets['PREFLOP'][player].append(Decimal(amount))
|
self.bets['PREFLOP'][player].append(Decimal(amount))
|
||||||
self.lastBet['PREFLOP'] = Decimal(amount)
|
self.actions['PREFLOP'] += [(player, 'posts', blindtype, amount)]
|
||||||
|
if blindtype == 'big blind':
|
||||||
|
self.lastBet['PREFLOP'] = Decimal(amount)
|
||||||
|
elif blindtype == 'small & big blinds':
|
||||||
|
# extra small blind is 'dead'
|
||||||
|
self.lastBet['PREFLOP'] = Decimal(self.bb)
|
||||||
self.posted += [player]
|
self.posted += [player]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def addCall(self, street, player=None, amount=None):
|
def addCall(self, street, player=None, amount=None):
|
||||||
|
@ -176,7 +194,7 @@ For when a player shows cards for any reason (for showdown or out of choice).
|
||||||
if amount is not None:
|
if amount is not None:
|
||||||
self.bets[street][player].append(Decimal(amount))
|
self.bets[street][player].append(Decimal(amount))
|
||||||
#self.lastBet[street] = Decimal(amount)
|
#self.lastBet[street] = Decimal(amount)
|
||||||
self.actions[street] += [[player, 'calls', amount]]
|
self.actions[street] += [(player, 'calls', amount)]
|
||||||
|
|
||||||
def addRaiseTo(self, street, player, amountTo):
|
def addRaiseTo(self, street, player, amountTo):
|
||||||
"""\
|
"""\
|
||||||
|
@ -193,21 +211,22 @@ Add a raise on [street] by [player] to [amountTo]
|
||||||
self.lastBet[street] = Decimal(amountTo)
|
self.lastBet[street] = Decimal(amountTo)
|
||||||
amountBy = Decimal(amountTo) - amountToCall
|
amountBy = Decimal(amountTo) - amountToCall
|
||||||
self.bets[street][player].append(amountBy+amountToCall)
|
self.bets[street][player].append(amountBy+amountToCall)
|
||||||
self.actions[street] += [[player, 'raises', amountBy, amountTo]]
|
self.actions[street] += [(player, 'raises', amountBy, amountTo, amountToCall)]
|
||||||
|
|
||||||
def addBet(self, street, player, amount):
|
def addBet(self, street, player, amount):
|
||||||
self.checkPlayerExists(player)
|
self.checkPlayerExists(player)
|
||||||
self.bets[street][player].append(Decimal(amount))
|
self.bets[street][player].append(Decimal(amount))
|
||||||
self.actions[street] += [[player, 'bets', amount]]
|
self.actions[street] += [(player, 'bets', amount)]
|
||||||
|
self.lastBet[street] = Decimal(amount)
|
||||||
|
|
||||||
def addFold(self, street, player):
|
def addFold(self, street, player):
|
||||||
self.checkPlayerExists(player)
|
self.checkPlayerExists(player)
|
||||||
self.folded.add(player)
|
self.folded.add(player)
|
||||||
self.actions[street] += [[player, 'folds']]
|
self.actions[street] += [(player, 'folds')]
|
||||||
|
|
||||||
def addCheck(self, street, player):
|
def addCheck(self, street, player):
|
||||||
self.checkPlayerExists(player)
|
self.checkPlayerExists(player)
|
||||||
self.actions[street] += [[player, 'checks']]
|
self.actions[street] += [(player, 'checks')]
|
||||||
|
|
||||||
def addCollectPot(self,player, pot):
|
def addCollectPot(self,player, pot):
|
||||||
self.checkPlayerExists(player)
|
self.checkPlayerExists(player)
|
||||||
|
@ -231,12 +250,50 @@ Known bug: doesn't take into account side pots"""
|
||||||
for street in self.streetList:
|
for street in self.streetList:
|
||||||
#print street, self.bets[street][player]
|
#print street, self.bets[street][player]
|
||||||
self.totalpot += reduce(operator.add, self.bets[street][player], 0)
|
self.totalpot += reduce(operator.add, self.bets[street][player], 0)
|
||||||
|
print "conventional totalpot:", self.totalpot
|
||||||
|
self.totalpot = 0
|
||||||
|
|
||||||
|
print self.actions
|
||||||
|
for street in self.actions:
|
||||||
|
uncalled = 0
|
||||||
|
calls = [0]
|
||||||
|
for act in self.actions[street]:
|
||||||
|
if act[1] == 'bets': # [name, 'bets', amount]
|
||||||
|
self.totalpot += Decimal(act[2])
|
||||||
|
uncalled = Decimal(act[2]) # only the last bet or raise can be uncalled
|
||||||
|
calls = [0]
|
||||||
|
print "uncalled: ", uncalled
|
||||||
|
elif act[1] == 'raises': # [name, 'raises', amountby, amountto, amountcalled]
|
||||||
|
print "calls %s and raises %s to %s" % (act[4],act[2],act[3])
|
||||||
|
self.totalpot += Decimal(act[2]) + Decimal(act[4])
|
||||||
|
calls = [0]
|
||||||
|
uncalled = Decimal(act[2])
|
||||||
|
print "uncalled: ", uncalled
|
||||||
|
elif act[1] == 'calls': # [name, 'calls', amount]
|
||||||
|
self.totalpot += Decimal(act[2])
|
||||||
|
calls = calls + [Decimal(act[2])]
|
||||||
|
print "calls:", calls
|
||||||
|
if act[1] == ('posts'):
|
||||||
|
self.totalpot += Decimal(act[3])
|
||||||
|
uncalled = Decimal(act[3])
|
||||||
|
if uncalled > 0 and max(calls+[0]) < uncalled:
|
||||||
|
|
||||||
|
print "returning some bet, calls:", calls
|
||||||
|
print "returned: %.2f from %.2f" % ((uncalled - max(calls)), self.totalpot,)
|
||||||
|
self.totalpot -= (uncalled - max(calls))
|
||||||
|
print "new totalpot:", self.totalpot
|
||||||
|
|
||||||
if self.totalcollected is None:
|
if self.totalcollected is None:
|
||||||
self.totalcollected = 0;
|
self.totalcollected = 0;
|
||||||
for amount in self.collected.values():
|
for amount in self.collected.values():
|
||||||
self.totalcollected += Decimal(amount)
|
self.totalcollected += Decimal(amount)
|
||||||
|
|
||||||
|
# TODO: Some sites (Everleaf) don't record uncalled bets. Figure out if a bet is uncalled and subtract it from self.totalcollected.
|
||||||
|
# remember that portions of bets may be uncalled, so:
|
||||||
|
# bet followed by no call is an uncalled bet
|
||||||
|
# bet x followed by call y where y < x has x-y uncalled (and second player all in)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getGameTypeAsString(self):
|
def getGameTypeAsString(self):
|
||||||
"""\
|
"""\
|
||||||
|
@ -316,7 +373,8 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
||||||
print "what do they show"
|
print "what do they show"
|
||||||
|
|
||||||
print "*** SUMMARY ***"
|
print "*** SUMMARY ***"
|
||||||
print "Total pot $%s | Rake $%.2f" % (self.totalcollected, self.rake) # TODO side pots
|
print "Total pot $%s | Rake $%.2f" % (self.totalcollected, self.rake) # TODO: side pots
|
||||||
|
|
||||||
board = []
|
board = []
|
||||||
for s in self.board.values():
|
for s in self.board.values():
|
||||||
board += s
|
board += s
|
||||||
|
|
|
@ -161,7 +161,8 @@ class HandHistoryConverter:
|
||||||
def readPlayerStacks(self, hand): abstract
|
def readPlayerStacks(self, hand): abstract
|
||||||
|
|
||||||
# Needs to return a MatchObject with group names identifying the streets into the Hand object
|
# Needs to return a MatchObject with group names identifying the streets into the Hand object
|
||||||
# that is, pulls the chunks of preflop, flop, turn and river text into hand.streets MatchObject.
|
# so groups are called by street names 'PREFLOP', 'FLOP', 'STREET2' etc
|
||||||
|
# blinds are done seperately
|
||||||
def markStreets(self, hand): abstract
|
def markStreets(self, hand): abstract
|
||||||
|
|
||||||
#Needs to return a list in the format
|
#Needs to return a list in the format
|
||||||
|
@ -173,8 +174,10 @@ class HandHistoryConverter:
|
||||||
def readCollectPot(self, hand): abstract
|
def readCollectPot(self, hand): abstract
|
||||||
|
|
||||||
# Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated
|
# Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated
|
||||||
# so that an inheriting class can calculate it for the specific site if need be.
|
# an inheriting class can calculate it for the specific site if need be.
|
||||||
def getRake(self, hand): abstract
|
def getRake(self, hand):
|
||||||
|
hand.rake = hand.totalpot - hand.totalcollected # * Decimal('0.05') # probably not quite right
|
||||||
|
|
||||||
|
|
||||||
def sanityCheck(self):
|
def sanityCheck(self):
|
||||||
sane = False
|
sane = False
|
||||||
|
|
Loading…
Reference in New Issue
Block a user