Merge branch 'master' of git://git.assembla.com/free_poker_tools

This commit is contained in:
sqlcoder 2009-07-19 14:31:36 +01:00
commit ceaedebcd9
3 changed files with 185 additions and 287 deletions

View File

@ -23,16 +23,32 @@ import logging
from HandHistoryConverter import *
# Fulltilt HH Format converter
# TODO: cat tourno and table to make table name for tournaments
class Fulltilt(HandHistoryConverter):
# Static regexes
re_GameInfo = re.compile('- (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<LIMIT>(No Limit|Pot Limit|Limit))? (?P<GAME>(Hold\'em|Omaha Hi|Razz))')
re_GameInfo = re.compile('''(?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)?
.+
-\s(?P<CURRENCY>\$|)?
(?P<SB>[.0-9]+)/
\$?(?P<BB>[.0-9]+)\s
(Ante\s\$(?P<ANTE>[.0-9]+)\s)?-\s
(?P<LIMIT>(No\sLimit|Pot\sLimit|Limit))?\s
(?P<GAME>(Hold\'em|Omaha\sHi|Omaha\sH/L|7\sCard\sStud|Stud\sH/L|Razz))
''', re.VERBOSE)
re_SplitHands = re.compile(r"\n\n+")
re_TailSplitHands = re.compile(r"(\n\n+)")
re_HandInfo = re.compile('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[- a-zA-Z]+) (\((?P<TABLEATTRIBUTES>.+)\) )?- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<GAMETYPE>[a-zA-Z\' ]+) - (?P<DATETIME>.*)')
re_HandInfo = re.compile('''.*\#(?P<HID>[0-9]+):\s
(?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)?
Table\s(?P<TABLE>[-\s\da-zA-Z]+)\s
(\((?P<TABLEATTRIBUTES>.+)\)\s)?-\s
\$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\s(Ante\s\$(?P<ANTE>[.0-9]+)\s)?-\s
(?P<GAMETYPE>[a-zA-Z\/\'\s]+)\s-\s
(?P<DATETIME>.*)
''', re.VERBOSE)
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE)
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[,.0-9]+)\)')
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
# NB: if we ever match "Full Tilt Poker" we should also match "FullTiltPoker", which PT Stud erroneously exports.
@ -63,19 +79,24 @@ follow : whether to tail -f the input"""
self.re_BringIn = re.compile(r"^%s brings in for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE)
self.re_PostBoth = re.compile(r"^%s posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_HeroCards = re.compile(r"^Dealt to %s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE)
self.re_Action = re.compile(r"^%s(?P<ATYPE> bets| checks| raises to| completes it to| calls| folds)(\s\$(?P<BET>[.\d]+))?" % player_re, re.MULTILINE)
self.re_Action = re.compile(r"^%s(?P<ATYPE> bets| checks| raises to| completes it to| calls| folds)(\s\$?(?P<BET>[.,\d]+))?" % player_re, re.MULTILINE)
self.re_ShowdownAction = re.compile(r"^%s shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
self.re_CollectPot = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*)" % player_re, re.MULTILINE)
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE)
self.re_ShownCards = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s \(.*\) showed \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
def readSupportedGames(self):
return [["ring", "hold", "nl"],
["ring", "hold", "pl"],
["ring", "hold", "fl"],
["ring", "stud", "fl"],
["ring", "omaha", "pl"]
["tour", "hold", "nl"],
["tour", "hold", "pl"],
["tour", "hold", "fl"],
["tour", "stud", "fl"],
]
def determineGameType(self, handText):
@ -96,22 +117,22 @@ follow : whether to tail -f the input"""
games = { # base, category
"Hold'em" : ('hold','holdem'),
'Omaha Hi' : ('hold','omahahi'),
'Omaha H/L' : ('hold','omahahilo'),
'Razz' : ('stud','razz'),
'7 Card Stud' : ('stud','studhi')
'7 Card Stud' : ('stud','studhi'),
'Stud H/L' : ('stud', 'studhilo')
}
currencies = { u'':'EUR', '$':'USD', '':'T$' }
if 'LIMIT' in mg:
info['limitType'] = limits[mg['LIMIT']]
if 'GAME' in mg:
info['limitType'] = limits[mg['LIMIT']]
info['sb'] = mg['SB']
info['bb'] = mg['BB']
if mg['GAME'] != None:
(info['base'], info['category']) = games[mg['GAME']]
if 'SB' in mg:
info['sb'] = mg['SB']
if 'BB' in mg:
info['bb'] = mg['BB']
if 'CURRENCY' in mg:
if mg['CURRENCY'] != None:
info['currency'] = currencies[mg['CURRENCY']]
if mg['TOURNO'] == None: info['type'] = "ring"
else: info['type'] = "tour"
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
return info
def readHandInfo(self, hand):
@ -121,14 +142,17 @@ follow : whether to tail -f the input"""
logging.info("Didn't match re_HandInfo")
logging.info(hand.handText)
return None
hand.handid = m.group('HID')
hand.tablename = m.group('TABLE')
hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
hand.maxseats = 8 # assume 8-max until we see otherwise
if m.group('TABLEATTRIBUTES'):
m2 = re.search("(deep )?(\d+)( max)?", m.group('TABLEATTRIBUTES'))
hand.maxseats = int(m2.group(2))
hand.tourNo = m.group('TOURNO')
# if key == 'PLAY' and info['PLAY'] != None:
# hand.gametype['currency'] = 'play'
# These work, but the info is already in the Hand class - should be used for tourneys though.
# m.group('SB')
# m.group('BB')
@ -204,73 +228,40 @@ follow : whether to tail -f the input"""
hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.handText)
if(m == None):
#Not involved in hand
hand.involved = False
else:
hand.hero = m.group('PNAME')
# "2c, qh" -> set(["2c","qc"])
# Also works with Omaha hands.
cards = m.group('NEWCARDS')
cards = [c.strip() for c in cards.split(' ')]
hand.addHoleCards(cards, m.group('PNAME'))
# streets PREFLOP, PREDRAW, and THIRD are special cases beacause
# we need to grab hero's cards
for street in ('PREFLOP', 'DEAL'):
if street in hand.streets.keys():
m = self.re_HeroCards.finditer(hand.streets[street])
for found in m:
# if m == None:
# hand.involved = False
# else:
hand.hero = found.group('PNAME')
newcards = found.group('NEWCARDS').split(' ')
hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
for street, text in hand.streets.iteritems():
if not text or street in ('PREFLOP', 'DEAL'): continue # already done these
m = self.re_HeroCards.finditer(hand.streets[street])
for found in m:
player = found.group('PNAME')
if found.group('NEWCARDS') == None:
newcards = []
else:
newcards = found.group('NEWCARDS').split(' ')
if found.group('OLDCARDS') == None:
oldcards = []
else:
oldcards = found.group('OLDCARDS').split(' ')
if street == 'THIRD' and len(newcards) == 3: # hero in stud game
hand.hero = player
hand.dealt.add(player) # need this for stud??
hand.addHoleCards(street, player, closed=newcards[0:2], open=[newcards[2]], shown=False, mucked=False, dealt=False)
else:
hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False)
def readStudPlayerCards(self, hand, street):
# This could be the most tricky one to get right.
# It looks for cards dealt in 'street',
# which may or may not be in the section of the hand designated 'street' by markStreets earlier.
# Here's an example at FTP of what 'THIRD' and 'FOURTH' look like to hero PokerAscetic
#
#"*** 3RD STREET ***
#Dealt to BFK23 [Th]
#Dealt to cutiepr1nnymaid [8c]
#Dealt to PokerAscetic [7c 8s] [3h]
#..."
#
#"*** 4TH STREET ***
#Dealt to cutiepr1nnymaid [8c] [2s]
#Dealt to PokerAscetic [7c 8s 3h] [5s]
#..."
#Note that hero's first two holecards are only reported at 3rd street as 'old' cards.
logging.debug("readStudPlayerCards")
m = self.re_HeroCards.finditer(hand.streets[street])
for player in m:
logging.debug(player.groupdict())
(pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS'))
if oldcards:
oldcards = [c.strip() for c in oldcards.split(' ')]
if newcards:
newcards = [c.strip() for c in newcards.split(' ')]
# options here:
# (1) we trust the hand will know what to do -- probably check that the old cards match what it already knows, and add the newcards to this street.
# (2) we're the experts at this particular history format and we know how we're going to be called (once for each street in Hand.streetList)
# so call addPlayerCards with the appropriate information.
# I favour (2) here but I'm afraid it is rather stud7-specific.
# in the following, the final list of cards will be in 'newcards' whilst if the first list exists (most of the time it does) it will be in 'oldcards'
if street=='ANTES':
return
elif street=='THIRD':
# we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS'
# hero: [xx][o]
# others: [o]
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards)
elif street in ('FOURTH', 'FIFTH', 'SIXTH'):
# 4th:
# hero: [xxo] [o]
# others: [o] [o]
# 5th:
# hero: [xxoo] [o]
# others: [oo] [o]
# 6th:
# hero: [xxooo] [o]
# others: [ooo] [o]
hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards)
# we may additionally want to check the earlier streets tally with what we have but lets trust it for now.
elif street=='SEVENTH' and newcards:
# hero: [xxoooo] [x]
# others: not reported.
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards)
def readAction(self, hand, street):
m = self.re_Action.finditer(hand.streets[street])

View File

@ -32,7 +32,7 @@ import pprint
import DerivedStats
import Card
class Hand:
class Hand(object):
###############################################################3
# Class Variables
@ -81,7 +81,6 @@ class Hand:
self.holecards[street] = {} # dict from player names to holecards
self.discards[street] = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards
# Collections indexed by player names
# self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards
self.stacks = {}
self.collected = [] #list of ?
self.collectees = {} # dict from player names to amounts collected (?)
@ -92,12 +91,14 @@ class Hand:
self.shown = set() # cards were shown
self.mucked = set() # cards were mucked at showdown
# self.action = []
# Things to do with money
self.pot = Pot()
self.totalpot = None
self.totalcollected = None
self.rake = None
# currency symbol for this hand
self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done
self.pot.setSym(self.sym)
def __str__(self):
vars = ( ("BB", self.bb),
@ -262,6 +263,7 @@ chips (string) the chips the player has at the start of the hand (can be None)
If a player has None chips he won't be added."""
logging.debug("addPlayer: %s %s (%s)" % (seat, name, chips))
if chips is not None:
chips = re.sub(u',', u'', chips) #some sites have commas
self.players.append([seat, name, chips])
self.stacks[name] = Decimal(chips)
self.pot.addPlayer(name)
@ -289,6 +291,7 @@ If a player has None chips he won't be added."""
def setCommunityCards(self, street, cards):
logging.debug("setCommunityCards %s %s" %(street, cards))
self.board[street] = [self.card(c) for c in cards]
# print "DEBUG: self.board: %s" % self.board
def card(self,c):
"""upper case the ranks but not suits, 'atjqk' => 'ATJQK'"""
@ -299,6 +302,7 @@ If a player has None chips he won't be added."""
def addAnte(self, player, ante):
logging.debug("%s %s antes %s" % ('ANTES', player, ante))
if player is not None:
ante = re.sub(u',', u'', ante) #some sites have commas
self.bets['ANTES'][player].append(Decimal(ante))
self.stacks[player] -= Decimal(ante)
act = (player, 'posts', "ante", ante, self.stacks[player]==0)
@ -317,6 +321,7 @@ If a player has None chips he won't be added."""
logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount))
if player is not None:
amount = re.sub(u',', u'', amount) #some sites have commas
self.bets['PREFLOP'][player].append(Decimal(amount))
self.stacks[player] -= Decimal(amount)
#print "DEBUG %s posts, stack %s" % (player, self.stacks[player])
@ -334,6 +339,8 @@ If a player has None chips he won't be added."""
def addCall(self, street, player=None, amount=None):
if amount:
amount = re.sub(u',', u'', amount) #some sites have commas
logging.debug("%s %s calls %s" %(street, player, amount))
# Potentially calculate the amount of the call if not supplied
# corner cases include if player would be all in
@ -361,6 +368,7 @@ Add a raise by amountBy on [street] by [player]
# then: C = Bp - Bc (amount to call)
# Rt = Bp + Rb (raise to)
#
amountBy = re.sub(u',', u'', amountBy) #some sites have commas
self.checkPlayerExists(player)
Rb = Decimal(amountBy)
Bp = self.lastBet[street]
@ -378,6 +386,7 @@ Add a raise by amountBy on [street] by [player]
"""\
For sites which by "raises x" mean "calls and raises putting a total of x in the por". """
self.checkPlayerExists(player)
amount = re.sub(u',', u'', amount) #some sites have commas
CRb = Decimal(amount)
Bp = self.lastBet[street]
Bc = reduce(operator.add, self.bets[street][player], 0)
@ -393,6 +402,7 @@ Add a raise on [street] by [player] to [amountTo]
"""
#CG - No idea if this function has been test/verified
self.checkPlayerExists(player)
amountTo = re.sub(u',', u'', amountTo) #some sites have commas
Bp = self.lastBet[street]
Bc = reduce(operator.add, self.bets[street][player], 0)
Rt = Decimal(amountTo)
@ -413,6 +423,7 @@ Add a raise on [street] by [player] to [amountTo]
def addBet(self, street, player, amount):
logging.debug("%s %s bets %s" %(street, player, amount))
amount = re.sub(u',', u'', amount) #some sites have commas
self.checkPlayerExists(player)
self.bets[street][player].append(Decimal(amount))
self.stacks[player] -= Decimal(amount)
@ -525,44 +536,47 @@ Map the tuple self.gametype onto the pokerstars string describing it
elif act[1] == 'checks':
return ("%s: checks " %(act[0]))
elif act[1] == 'calls':
return ("%s: calls $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
return ("%s: calls %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'bets':
return ("%s: bets $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
return ("%s: bets %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'raises':
return ("%s: raises $%s to $%s%s" %(act[0], act[2], act[3], ' and is all-in' if act[5] else ''))
return ("%s: raises %s%s to %s%s%s" %(act[0], self.sym, act[2], self.sym, act[3], ' and is all-in' if act[5] else ''))
elif act[1] == 'completea':
return ("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
return ("%s: completes to %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'posts':
if(act[2] == "small blind"):
return ("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else ''))
return ("%s: posts small blind %s%s%s" %(act[0], self.sym, act[3], ' and is all-in' if act[4] else ''))
elif(act[2] == "big blind"):
return ("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else ''))
return ("%s: posts big blind %s%s%s" %(act[0], self.sym, act[3], ' and is all-in' if act[4] else ''))
elif(act[2] == "both"):
return ("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else ''))
return ("%s: posts small & big blinds %s%s%s" %(act[0], self.sym, act[3], ' and is all-in' if act[4] else ''))
elif act[1] == 'bringin':
return ("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
return ("%s: brings in for %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else ''))
elif act[1] == 'discards':
return ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else ''))
elif act[1] == 'stands pat':
return ("%s: stands pat" %(act[0]))
def getStakesAsString(self):
retstring = "%s%s/%s%s" % (self.SYMBOL[self.gametype['currency']], self.sb, self.SYMBOL[self.gametype['currency']], self.bb)
return retstring
"""Return a string of the stakes of the current hand."""
return "%s%s/%s%s" % (self.sym, self.sb, self.sym, self.bb)
def writeGameLine(self):
# print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')))
game_string = "PokerStars Game #%s: " % self.handid
if self.tourNo != None:
game_string = game_string + "Tournament #%s, %s %s - Level %s (%s) - " % (self.tourNo,
"""Return the first HH line for the current hand."""
gs = "PokerStars Game #%s: " % self.handid
if self.tourNo != None and self.mixed != None: # mixed tournament
gs = gs + "Tournament #%s, %s %s (%s) - Level %s (%s) - " % (self.tourNo, self.buyin, self.MS[self.mixed], self.getGameTypeAsString(), self.level, self.getStakesAsString())
elif self.tourNo != None: # all other tournaments
gs = gs + "Tournament #%s, %s %s - Level %s (%s) - " % (self.tourNo,
self.buyin, self.getGameTypeAsString(), self.level, self.getStakesAsString())
elif self.mixed != None:
game_string = game_string + " %s (%s, %s) - " % (self.MS[self.mixed],
elif self.mixed != None: # all other mixed games
gs = gs + " %s (%s, %s) - " % (self.MS[self.mixed],
self.getGameTypeAsString(), self.getStakesAsString())
else:
game_string = game_string + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString())
game_string = game_string + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET')
return game_string
else: # non-mixed cash games
gs = gs + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString())
return gs + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET')
def writeTableLine(self):
@ -574,6 +588,12 @@ Map the tuple self.gametype onto the pokerstars string describing it
return table_string
def writeHand(self, fh=sys.__stdout__):
# PokerStars format.
print >>fh, self.writeGameLine()
print >>fh, self.writeTableLine()
class HoldemOmahaHand(Hand):
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None):
if gametype['base'] != 'hold':
@ -637,8 +657,8 @@ class HoldemOmahaHand(Hand):
def render_stack(context,data):
pat = context.tag.patternGenerator('list_item')
for player in data:
x = "Seat %s: %s ($%s in chips) " %(player[0], player[1],
player[2])
x = "Seat %s: %s (%s%s in chips) " %(player[0], player[1],
self.sym, player[2])
context.tag[ pat().fillSlots('playerStack', x)]
return context.tag
@ -725,12 +745,8 @@ class HoldemOmahaHand(Hand):
def writeHand(self, fh=sys.__stdout__):
# PokerStars format.
# print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')))
print >>fh, self.writeGameLine()
print >>fh, self.writeTableLine()
super(HoldemOmahaHand, self).writeHand(fh)
# print >>fh, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']]))
logging.debug(self.actions['PREFLOP'])
for player in [x for x in self.players if x[1] in players_who_act_preflop]:
@ -795,16 +811,16 @@ class HoldemOmahaHand(Hand):
# Immediately before the summary.
# The current importer uses those lines for importing winning rather than the summary
for name in self.pot.returned:
print >>fh, ("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name))
print >>fh, ("Uncalled bet (%s%s) returned to %s" %(self.sym, self.pot.returned[name],name))
for entry in self.collected:
print >>fh, ("%s collected $%s from x pot" %(entry[0], entry[1]))
print >>fh, ("%s collected %s%s from x pot" %(entry[0], self.sym, entry[1]))
print >>fh, ("*** SUMMARY ***")
print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake)
print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake)
board = []
for s in self.board.values():
board += s
for street in ["FLOP", "TURN", "RIVER"]:
board += self.board[street]
if board: # sometimes hand ends preflop without a board
print >>fh, ("Board [%s]" % (" ".join(board)))
@ -812,9 +828,9 @@ class HoldemOmahaHand(Hand):
seatnum = player[0]
name = player[1]
if name in self.collectees and name in self.shown:
print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]), self.collectees[name]))
print >>fh, ("Seat %d: %s showed [%s] and won (%s%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]), self.sym, self.collectees[name]))
elif name in self.collectees:
print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
print >>fh, ("Seat %d: %s collected (%s%s)" % (seatnum, name, self.sym, self.collectees[name]))
#~ elif name in self.shown:
#~ print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP'])))
elif name in self.folded:
@ -854,8 +870,6 @@ class DrawHand(Hand):
# Read actions in street order
for street in self.streetList:
if self.streets[street]:
# hhc.readCommunityCards(self, street)
# hhc.readDrawCards(self, street)
hhc.readAction(self, street)
hhc.readCollectPot(self)
hhc.readShownCards(self)
@ -900,21 +914,6 @@ class DrawHand(Hand):
self.addHoleCards('DRAWTHREE', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt)
# def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False):
# """\
#Assigns observed holecards to a player.
#cards list of card bigrams e.g. ['2h','Jc']
#player (string) name of player
#"""
# try:
# self.checkPlayerExists(player)
## if shown and len(cardset) > 0:
## self.shown.add(player)
# self.holecards[street][player] = (newcards,oldcards)
# except FpdbParseError, e:
# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
def discardDrawHoleCards(self, cards, player, street):
logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street))
self.discards[street][player] = set([cards])
@ -930,64 +929,19 @@ class DrawHand(Hand):
self.actions[street].append(act)
# def addShownCards(self, cards, player, holeandboard=None, shown=False, mucked=False):
# """\
#For when a player shows cards for any reason (for showdown or out of choice).
#Card ranks will be uppercased
#"""
# logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
# if cards is not None:
# self.shown.add(player)
# self.addHoleCards(cards,player)
# elif holeandboard is not None:
# holeandboard = set([self.card(c) for c in holeandboard])
# board = set([c for s in self.board.values() for c in s])
# self.addHoleCards(holeandboard.difference(board),player,shown=True)
# def addHoleCards(self, cards, player, shown, mucked, dealt=False):
# """\
#Assigns observed holecards to a player.
#cards list of card bigrams e.g. ['2h','Jc']
#player (string) name of player
#shown whether they were revealed at showdown
#mucked whether they were mucked at showdown
#dealt whether they were seen in a 'dealt to' line
#"""
## I think this only gets called for shown cards.
# logging.debug("addHoleCards %s %s" % (cards, player))
# try:
# self.checkPlayerExists(player)
# except FpdbParseError, e:
# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
# return
#
# if dealt:
# self.dealt.add(player)
# if shown:
# self.shown.add(player)
# if mucked:
# self.mucked.add(player)
# if player != self.hero: #skip hero, we know his cards
# print "player, cards =", player, cards
# self.holecards[self.holeStreets[-1]][player] = (cards, set([]))
def writeHand(self, fh=sys.__stdout__):
# PokerStars format.
# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d %H:%M:%S ET', self.starttime)))
print >>fh, self.writeGameLine()
# print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
print >>fh, self.writeTableLine()
super(DrawHand, self).writeHand(fh)
players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']]))
for player in [x for x in self.players if x[1] in players_who_act_ondeal]:
#Only print stacks of players who do something on deal
print >>fh, _("Seat %s: %s ($%s in chips) " %(player[0], player[1], player[2]))
print >>fh, _("Seat %s: %s (%s%s in chips) " %(player[0], player[1], self.sym, player[2]))
if 'BLINDSANTES' in self.actions:
for act in self.actions['BLINDSANTES']:
print >>fh, _("%s: %s %s $%s" %(act[0], act[1], act[2], act[3]))
print >>fh, _("%s: %s %s %s%s" %(act[0], act[1], act[2], self.sym, act[3]))
if 'DEAL' in self.actions:
print >>fh, _("*** DEALING HANDS ***")
@ -1040,12 +994,12 @@ class DrawHand(Hand):
# Immediately before the summary.
# The current importer uses those lines for importing winning rather than the summary
for name in self.pot.returned:
print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name))
print >>fh, _("Uncalled bet (%s%s) returned to %s" %(self.sym, self.pot.returned[name],name))
for entry in self.collected:
print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1]))
print >>fh, _("%s collected %s%s from x pot" %(entry[0], self.sym, entry[1]))
print >>fh, _("*** SUMMARY ***")
print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake)
print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake)
print >>fh, "\n\n"
@ -1060,7 +1014,7 @@ class StudHand(Hand):
self.actionStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH']
self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
self.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH']
self.holeStreets = ['THIRD','FOURTH','FIFTH','SIXTH','SEVENTH']
Hand.__init__(self, sitename, gametype, handText)
self.sb = gametype['sb']
self.bb = gametype['bb']
@ -1075,13 +1029,11 @@ class StudHand(Hand):
hhc.readAntes(self)
hhc.readBringIn(self)
hhc.readHeroCards(self)
#hhc.readShowdownActions(self) # not done yet
# Read actions in street order
for street in self.streetList:
if self.streets[street]:
logging.debug(street)
logging.debug(self.streets[street])
# hhc.readStudPlayerCards(self, street)
hhc.readAction(self, street)
hhc.readCollectPot(self)
hhc.readShownCards(self) # not done yet
@ -1095,11 +1047,10 @@ class StudHand(Hand):
if shown: self.shown.add(player)
if mucked: self.mucked.add(player)
else:
# self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt)
self.addHoleCards('THIRD', player, open=[cards[2]], closed=cards[0:2], shown=shown, mucked=mucked)
self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[], shown=shown, mucked=mucked)
self.addHoleCards('FIFTH', player, open=[cards[4]], closed=[], shown=shown, mucked=mucked)
self.addHoleCards('SIXTH', player, open=[cards[5]], closed=[], shown=shown, mucked=mucked)
self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[cards[2]], shown=shown, mucked=mucked)
self.addHoleCards('FIFTH', player, open=[cards[4]], closed=cards[2:4], shown=shown, mucked=mucked)
self.addHoleCards('SIXTH', player, open=[cards[5]], closed=cards[2:5], shown=shown, mucked=mucked)
self.addHoleCards('SEVENTH', player, open=[], closed=[cards[6]], shown=shown, mucked=mucked)
@ -1115,46 +1066,9 @@ closed likewise, but known only to player
try:
self.checkPlayerExists(player)
self.holecards[street][player] = (open, closed)
# cards = set([self.card(c) for c in cards])
# self.holecards[player].update(cards)
except FpdbParseError, e:
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
# def addHoleCards(self, cards, player, shown, mucked, dealt=False):
# """\
#Assigns observed holecards to a player.
#cards list of card bigrams e.g. ['2h','Jc']
#player (string) name of player
#shown whether they were revealed at showdown
#mucked whether they were mucked at showdown
#dealt whether they were seen in a 'dealt to' line
#"""
##
## For stud games we just need to do the routine setting of shown/mucked/etc
## and then update the cards 'THIRD' and 'SEVENTH'
# logging.debug("addHoleCards %s %s" % (cards, player))
# try:
# self.checkPlayerExists(player)
# except FpdbParseError, e:
# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
# return
#
# if dealt:
# self.dealt.add(player)
# if shown:
# self.shown.add(player)
# if mucked:
# self.mucked.add(player)
# if player == self.hero:
# if len(cards) > 2:
# self.holecards['THIRD'][player] = ([cards[0:3]], [])
# if len(cards) > 6:
# self.holecards['SEVENTH'][player] = ([cards[6]], [])
# else:
# if len(cards) > 2:
# self.holecards['THIRD'][player] = ([cards[0]], cards[1:3])
# if len(cards) > 6:
# self.holecards['SEVENTH'][player] = ([], [cards[6]])
# TODO: def addComplete(self, player, amount):
def addComplete(self, street, player, amountTo):
# assert street=='THIRD'
@ -1190,26 +1104,18 @@ Add a complete on [street] by [player] to [amountTo]
def writeHand(self, fh=sys.__stdout__):
# PokerStars format.
# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime)))
# TODO:
# Hole cards are not currently correctly written. Currently the down cards for non-heros
# are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix
# but mind got boggled, will try again.
# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')))
print >>fh, self.writeGameLine()
print >>fh, self.writeTableLine()
# print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
super(StudHand, self).writeHand(fh)
players_who_post_antes = set([x[0] for x in self.actions['ANTES']])
for player in [x for x in self.players if x[1] in players_who_post_antes]:
#Only print stacks of players who do something preflop
print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2]))
print >>fh, _("Seat %s: %s (%s%s in chips)" %(player[0], player[1], self.sym, player[2]))
if 'ANTES' in self.actions:
for act in self.actions['ANTES']:
print >>fh, _("%s: posts the ante $%s" %(act[0], act[3]))
print >>fh, _("%s: posts the ante %s%s" %(act[0], self.sym, act[3]))
if 'THIRD' in self.actions:
dealt = 0
@ -1220,7 +1126,8 @@ Add a complete on [street] by [player] to [amountTo]
dealt+=1
if dealt==1:
print >>fh, _("*** 3RD STREET ***")
print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "] " if closed else " ", "[" + " ".join(open) + "]" if open else "")
# print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "] " if closed else " ", "[" + " ".join(open) + "]" if open else "")
print >>fh, self.writeHoleCards('THIRD', player)
for act in self.actions['THIRD']:
#FIXME: Need some logic here for bringin vs completes
print >>fh, self.actionString(act)
@ -1230,15 +1137,10 @@ Add a complete on [street] by [player] to [amountTo]
#~ print >>fh, _("*** 4TH STREET ***")
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
if player in self.holecards['FOURTH']:
old = []
(o,c) = self.holecards['THIRD'][player]
if o:old.extend(o)
if c:old.extend(c)
new = self.holecards['FOURTH'][player][0]
dealt+=1
if dealt==1:
print >>fh, _("*** 4TH STREET ***")
print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "")
print >>fh, self.writeHoleCards('FOURTH', player)
for act in self.actions['FOURTH']:
print >>fh, self.actionString(act)
@ -1247,16 +1149,10 @@ Add a complete on [street] by [player] to [amountTo]
#~ print >>fh, _("*** 5TH STREET ***")
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
if self.holecards['FIFTH'].has_key(player):
old = []
for street in ('THIRD','FOURTH'):
(o,c) = self.holecards[street][player]
if o:old.extend(o)
if c:old.extend(c)
new = self.holecards['FIFTH'][player][0]
dealt+=1
if dealt==1:
print >>fh, _("*** 5TH STREET ***")
print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "")
print >>fh, self.writeHoleCards('FIFTH', player)
for act in self.actions['FIFTH']:
print >>fh, self.actionString(act)
@ -1265,16 +1161,10 @@ Add a complete on [street] by [player] to [amountTo]
#~ print >>fh, _("*** 6TH STREET ***")
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
if self.holecards['SIXTH'].has_key(player):
old = []
for street in ('THIRD','FOURTH','FIFTH'):
(o,c) = self.holecards[street][player]
if o:old.extend(o)
if c:old.extend(c)
new = self.holecards['SIXTH'][player][0]
dealt += 1
if dealt == 1:
print >>fh, _("*** 6TH STREET ***")
print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "")
print >>fh, self.writeHoleCards('SIXTH', player)
for act in self.actions['SIXTH']:
print >>fh, self.actionString(act)
@ -1283,17 +1173,11 @@ Add a complete on [street] by [player] to [amountTo]
# Then we have no 'dealt to' lines, no action lines, but still 7th street should appear.
# The only way I can see to know whether to print this line is by knowing the state of the hand
# i.e. are all but one players folded; is there an allin showdown; and all that.
print >>fh, _("*** 7TH STREET ***")
print >>fh, _("*** RIVER ***")
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
if self.holecards['SEVENTH'].has_key(player):
old = []
for street in ('THIRD','FOURTH','FIFTH','SIXTH'):
(o,c) = self.holecards[street][player]
if o:old.extend(o)
if c:old.extend(c)
new = self.holecards['SEVENTH'][player][0]
if new:
print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "")
if self.writeHoleCards('SEVENTH', player):
print >>fh, self.writeHoleCards('SEVENTH', player)
for act in self.actions['SEVENTH']:
print >>fh, self.actionString(act)
@ -1312,13 +1196,13 @@ Add a complete on [street] by [player] to [amountTo]
# Immediately before the summary.
# The current importer uses those lines for importing winning rather than the summary
for name in self.pot.returned:
print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name))
print >>fh, _("Uncalled bet (%s%s) returned to %s" %(self.sym, self.pot.returned[name],name))
for entry in self.collected:
print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1]))
print >>fh, _("%s collected %s%s from x pot" %(entry[0], self.sym, entry[1]))
print >>fh, _("*** SUMMARY ***")
print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake)
#print >>fh, _("Total pot $%s | Rake $%.2f" % (self.totalpot, self.rake)) # TODO: side pots
print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake)
# TODO: side pots
board = []
for s in self.board.values():
@ -1330,9 +1214,9 @@ Add a complete on [street] by [player] to [amountTo]
seatnum = player[0]
name = player[1]
if name in self.collectees and name in self.shown:
print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, self.join_holecards(name), self.collectees[name]))
print >>fh, _("Seat %d: %s showed [%s] and won (%s%s)" % (seatnum, name, self.join_holecards(name), self.sym, self.collectees[name]))
elif name in self.collectees:
print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
print >>fh, _("Seat %d: %s collected (%s%s)" % (seatnum, name, self.sym, self.collectees[name]))
elif name in self.shown:
print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, self.join_holecards(name)))
elif name in self.mucked:
@ -1345,11 +1229,30 @@ Add a complete on [street] by [player] to [amountTo]
print >>fh, "\n\n"
def writeHoleCards(self, street, player):
hc = "Dealt to %s [" % player
if street == 'THIRD':
if player == self.hero:
return hc + " ".join(self.holecards[street][player][1]) + " " + " ".join(self.holecards[street][player][0]) + ']'
else:
return hc + " ".join(self.holecards[street][player][0]) + ']'
if street == 'SEVENTH' and player != self.hero: return # only write 7th st line for hero, LDO
return hc + " ".join(self.holecards[street][player][1]) + "] [" + " ".join(self.holecards[street][player][0]) + "]"
def join_holecards(self, player):
holecards = []
for street in self.holeStreets:
if self.holecards[street].has_key(player):
holecards = holecards + self.holecards[street][player][0]
if street == 'THIRD':
holecards = holecards + self.holecards[street][player][1] + self.holecards[street][player][0]
elif street == 'SEVENTH':
if player == self.hero:
holecards = holecards + self.holecards[street][player][0]
else:
holecards = holecards + self.holecards[street][player][1]
else:
holecards = holecards + self.holecards[street][player][0]
return " ".join(holecards)
class Pot(object):
@ -1360,6 +1263,10 @@ class Pot(object):
self.committed = {}
self.total = None
self.returned = {}
self.sym = u'$' # this is the default currency symbol
def setSym(self, sym):
self.sym = sym
def addPlayer(self,player):
self.committed[player] = Decimal(0)
@ -1411,16 +1318,16 @@ class Pot(object):
raise FpdbParseError
# TODO: This really neeads to be a loop to handle multiple side pots
if len(self.pots) == 1: # (only use Total pot)
return "Total pot $%.2f" % (self.total,)
return "Total pot %s%.2f" % (self.sym, self.total,)
elif len(self.pots) == 2:
return "Total pot $%.2f Main pot $%.2f. Side pot $%2.f." % (self.total, self.pots[0], self.pots[1])
return "Total pot %s%.2f Main pot %s%.2f. Side pot %s%2.f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1])
elif len(self.pots) == 3:
return "Total pot $%.2f Main pot $%.2f. Side pot-1 $%2.2f. Side pot-2 $%.2f." % (self.total, self.pots[0], self.pots[1], self.pots[2])
return "Total pot %s%.2f Main pot $%.2f. Side pot-1 %s%2.2f. Side pot-2 %s%.2f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1], self.sym, self.pots[2])
elif len(self.pots) == 0:
# no small blind and walk in bb (hopefully)
return "Total pot $%.2f" % (self.total,)
return "Total pot %s%.2f" % (self.sym, self.total,)
else:
return ("too many pots.. no small blind and walk in bb?. self.pots: %s" %(self.pots))
# I don't know stars format for a walk in the bb when sb doesn't post.

View File

@ -398,7 +398,7 @@ follow : whether to tail -f the input"""
def readShowdownActions(self, hand):
# TODO: pick up mucks also
# TODO: pick up mucks also??
for shows in self.re_ShowdownAction.finditer(hand.handText):
cards = shows.group('CARDS').split(' ')
hand.addShownCards(cards, shows.group('PNAME'))