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

This commit is contained in:
Worros 2009-07-14 05:00:48 +08:00
commit 7683334e36
2 changed files with 406 additions and 204 deletions

View File

@ -15,6 +15,8 @@
#In the "official" distribution you can find the license in #In the "official" distribution you can find the license in
#agpl-3.0.txt in the docs folder of the package. #agpl-3.0.txt in the docs folder of the package.
# TODO: get writehand() encoding correct
import re import re
import sys import sys
import traceback import traceback
@ -31,8 +33,15 @@ import DerivedStats
import Card import Card
class Hand: class Hand:
###############################################################3
# Class Variables
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'}
LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'}
SYMBOL = {'USD': '$', 'EUR': u'E', 'T$': '', 'play': ''}
MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE'}
def __init__(self, sitename, gametype, handText, builtFrom = "HHC"): def __init__(self, sitename, gametype, handText, builtFrom = "HHC"):
self.sitename = sitename self.sitename = sitename
self.stats = DerivedStats.DerivedStats(self) self.stats = DerivedStats.DerivedStats(self)
@ -45,6 +54,10 @@ class Hand:
self.maxseats = 10 self.maxseats = 10
self.counted_seats = 0 self.counted_seats = 0
self.buttonpos = 0 self.buttonpos = 0
self.tourNo = None
self.buyin = None
self.level = None
self.mixed = None
self.seating = [] self.seating = []
self.players = [] self.players = []
self.posted = [] self.posted = []
@ -56,17 +69,19 @@ class Hand:
self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']] self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']]
self.board = {} # dict from street names to community cards self.board = {} # dict from street names to community cards
self.holecards = {} self.holecards = {}
self.discards = {}
for street in self.allStreets: for street in self.allStreets:
self.streets[street] = "" # portions of the handText, filled by markStreets() self.streets[street] = "" # portions of the handText, filled by markStreets()
self.actions[street] = []
for street in self.actionStreets:
self.bets[street] = {} self.bets[street] = {}
self.lastBet[street] = 0 self.lastBet[street] = 0
self.actions[street] = []
self.board[street] = [] self.board[street] = []
for street in self.holeStreets:
self.holecards[street] = {} # dict from player names to holecards 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 # Collections indexed by player names
# self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards # self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards
self.discards = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards
self.stacks = {} self.stacks = {}
self.collected = [] #list of ? self.collected = [] #list of ?
self.collectees = {} # dict from player names to amounts collected (?) self.collectees = {} # dict from player names to amounts collected (?)
@ -93,6 +108,10 @@ class Hand:
("TABLE NAME", self.tablename), ("TABLE NAME", self.tablename),
("HERO", self.hero), ("HERO", self.hero),
("MAXSEATS", self.maxseats), ("MAXSEATS", self.maxseats),
("TOURNAMENT NO", self.tourNo),
("BUYIN", self.buyin),
("LEVEL", self.level),
("MIXED", self.mixed),
("LASTBET", self.lastBet), ("LASTBET", self.lastBet),
("ACTION STREETS", self.actionStreets), ("ACTION STREETS", self.actionStreets),
("STREETS", self.streets), ("STREETS", self.streets),
@ -130,6 +149,28 @@ class Hand:
str = str + "\n%s =\n" % name + pprint.pformat(struct, 4) str = str + "\n%s =\n" % name + pprint.pformat(struct, 4)
return str return str
def addHoleCards(self, street, player, open=[], closed=[], shown=False, mucked=False, 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
"""
# logging.debug("addHoleCards %s %s" % (open + closed, 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)
self.holecards[street][player] = [open, closed]
def insert(self, db): def insert(self, db):
""" Function to insert Hand into database """ Function to insert Hand into database
Should not commit, and do minimal selects. Callers may want to cache commits Should not commit, and do minimal selects. Callers may want to cache commits
@ -221,10 +262,10 @@ If a player has None chips he won't be added."""
self.players.append([seat, name, chips]) self.players.append([seat, name, chips])
self.stacks[name] = Decimal(chips) self.stacks[name] = Decimal(chips)
self.pot.addPlayer(name) self.pot.addPlayer(name)
for street in self.allStreets: for street in self.actionStreets:
self.bets[street][name] = [] self.bets[street][name] = []
#self.holecards[name] = {} # dict from street names. #self.holecards[name] = {} # dict from street names.
self.discards[name] = {} # dict from street names. #self.discards[name] = {} # dict from street names.
def addStreets(self, match): def addStreets(self, match):
@ -446,7 +487,7 @@ Card ranks will be uppercased
Map the tuple self.gametype onto the pokerstars string describing it Map the tuple self.gametype onto the pokerstars string describing it
""" """
# currently it appears to be something like ["ring", "hold", "nl", sb, bb]: # currently it appears to be something like ["ring", "hold", "nl", sb, bb]:
gs = {"holdem" : "Hold'em", gs = {"holdem" : "Hold'em",
"omahahi" : "Omaha", "omahahi" : "Omaha",
"omahahilo" : "Omaha Hi/Lo", "omahahilo" : "Omaha Hi/Lo",
"razz" : "Razz", "razz" : "Razz",
@ -466,7 +507,6 @@ Map the tuple self.gametype onto the pokerstars string describing it
logging.debug("gametype: %s" %(self.gametype)) logging.debug("gametype: %s" %(self.gametype))
retstring = "%s %s" %(gs[self.gametype['category']], ls[self.gametype['limitType']]) retstring = "%s %s" %(gs[self.gametype['category']], ls[self.gametype['limitType']])
return retstring return retstring
@ -503,6 +543,33 @@ Map the tuple self.gametype onto the pokerstars string describing it
elif act[1] == 'stands pat': elif act[1] == 'stands pat':
return ("%s: stands pat" %(act[0])) 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
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,
self.buyin, self.getGameTypeAsString(), self.level, self.getStakesAsString())
elif self.mixed != None:
game_string = game_string + " %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
def writeTableLine(self):
table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats)
if self.gametype['currency'] == 'play':
table_string = table_string + " (Play Money)"
if self.buttonpos != None:
table_string = table_string + " Seat #%s is the button" % self.buttonpos
return table_string
class HoldemOmahaHand(Hand): class HoldemOmahaHand(Hand):
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None): def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None):
@ -550,35 +617,13 @@ class HoldemOmahaHand(Hand):
pass pass
def addHoleCards(self, cards, player, shown, mucked, dealt=False): def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
"""\ if player == self.hero: # we have hero's cards just update shown/mucked
Assigns observed holecards to a player. if shown: self.shown.add(player)
cards list of card bigrams e.g. ['2h','Jc'] if mucked: self.mucked.add(player)
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
"""
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
cardset = set((self.card(c) for c in cards))
if len(cardset) == 0:
return
if dealt:
self.dealt.add(player)
if shown:
self.shown.add(player)
if mucked:
self.mucked.add(player)
if player in self.holecards['PREFLOP']:
self.holecards['PREFLOP'][player].update(cardset)
else: else:
self.holecards['PREFLOP'][player] = cardset self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt)
def writeHTMLHand(self, fh=sys.__stdout__): def writeHTMLHand(self, fh=sys.__stdout__):
from nevow import tags as T from nevow import tags as T
@ -677,8 +722,11 @@ dealt whether they were seen in a 'dealt to' line
def writeHand(self, fh=sys.__stdout__): def writeHand(self, fh=sys.__stdout__):
# PokerStars format. # 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, ("%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, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) 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))
players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) 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']) logging.debug(self.actions['PREFLOP'])
@ -692,10 +740,10 @@ dealt whether they were seen in a 'dealt to' line
print >>fh, ("*** HOLE CARDS ***") print >>fh, ("*** HOLE CARDS ***")
for player in self.dealt: for player in self.dealt:
print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player]))) print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player][1])))
if self.hero == "": if self.hero == "":
for player in self.shown.difference(self.dealt): for player in self.shown.difference(self.dealt):
print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player]))) print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player][1])))
if self.actions['PREFLOP']: if self.actions['PREFLOP']:
for act in self.actions['PREFLOP']: for act in self.actions['PREFLOP']:
@ -734,7 +782,7 @@ dealt whether they were seen in a 'dealt to' line
elif self.gametype['category'] in ('holdem'): elif self.gametype['category'] in ('holdem'):
numOfHoleCardsNeeded = 2 numOfHoleCardsNeeded = 2
if len(self.holecards['PREFLOP'][name]) == numOfHoleCardsNeeded: if len(self.holecards['PREFLOP'][name]) == numOfHoleCardsNeeded:
print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards['PREFLOP'][name]))) print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards['PREFLOP'][name][1])))
# Current PS format has the lines: # Current PS format has the lines:
# Uncalled bet ($111.25) returned to s0rrow # Uncalled bet ($111.25) returned to s0rrow
@ -761,7 +809,7 @@ dealt whether they were seen in a 'dealt to' line
seatnum = player[0] seatnum = player[0]
name = player[1] name = player[1]
if name in self.collectees and name in self.shown: 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]), self.collectees[name])) print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]), self.collectees[name]))
elif name in self.collectees: elif name in self.collectees:
print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
#~ elif name in self.shown: #~ elif name in self.shown:
@ -770,9 +818,9 @@ dealt whether they were seen in a 'dealt to' line
print >>fh, ("Seat %d: %s folded" % (seatnum, name)) print >>fh, ("Seat %d: %s folded" % (seatnum, name))
else: else:
if name in self.shown: if name in self.shown:
print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]))) print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1])))
elif name in self.mucked: elif name in self.mucked:
print >>fh, ("Seat %d: %s mucked [%s] " % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]))) print >>fh, ("Seat %d: %s mucked [%s] " % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1])))
else: else:
print >>fh, ("Seat %d: %s mucked" % (seatnum, name)) print >>fh, ("Seat %d: %s mucked" % (seatnum, name))
@ -783,8 +831,10 @@ class DrawHand(Hand):
if gametype['base'] != 'draw': if gametype['base'] != 'draw':
pass # or indeed don't pass and complain instead pass # or indeed don't pass and complain instead
self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.allStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.actionStreets = ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] self.actionStreets = ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
self.communityStreets = []
Hand.__init__(self, sitename, gametype, handText) Hand.__init__(self, sitename, gametype, handText)
self.sb = gametype['sb'] self.sb = gametype['sb']
self.bb = gametype['bb'] self.bb = gametype['bb']
@ -796,12 +846,13 @@ class DrawHand(Hand):
hhc.markStreets(self) hhc.markStreets(self)
hhc.readBlinds(self) hhc.readBlinds(self)
hhc.readButton(self) hhc.readButton(self)
hhc.readHeroCards(self)
hhc.readShowdownActions(self) hhc.readShowdownActions(self)
# Read actions in street order # Read actions in street order
for street in self.streetList: for street in self.streetList:
if self.streets[street]: if self.streets[street]:
# hhc.readCommunityCards(self, street) # hhc.readCommunityCards(self, street)
hhc.readDrawCards(self, street) # hhc.readDrawCards(self, street)
hhc.readAction(self, street) hhc.readAction(self, street)
hhc.readCollectPot(self) hhc.readCollectPot(self)
hhc.readShownCards(self) hhc.readShownCards(self)
@ -837,25 +888,33 @@ class DrawHand(Hand):
#print "DEBUG: self.posted: %s" %(self.posted) #print "DEBUG: self.posted: %s" %(self.posted)
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
if player == self.hero: # we have hero's cards just update shown/mucked
if shown: self.shown.add(player)
if mucked: self.mucked.add(player)
else:
# TODO: Probably better to find the last street with action and add the hole cards to that street
self.addHoleCards('DRAWTHREE', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt)
def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False):
"""\ # def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False):
Assigns observed holecards to a player. # """\
cards list of card bigrams e.g. ['2h','Jc'] #Assigns observed holecards to a player.
player (string) name of player #cards list of card bigrams e.g. ['2h','Jc']
""" #player (string) name of player
try: #"""
self.checkPlayerExists(player) # try:
# if shown and len(cardset) > 0: # self.checkPlayerExists(player)
# self.shown.add(player) ## if shown and len(cardset) > 0:
self.holecards[player][street] = (newcards,oldcards) ## self.shown.add(player)
except FpdbParseError, e: # self.holecards[street][player] = (newcards,oldcards)
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) # except FpdbParseError, e:
# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
def discardDrawHoleCards(self, cards, player, street): def discardDrawHoleCards(self, cards, player, street):
logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street)) logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street))
self.discards[player][street] = set([cards]) self.discards[street][player] = set([cards])
def addDiscard(self, street, player, num, cards): def addDiscard(self, street, player, num, cards):
@ -868,12 +927,12 @@ player (string) name of player
self.actions[street].append(act) self.actions[street].append(act)
def addShownCards(self, cards, player, holeandboard=None): # 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). #For when a player shows cards for any reason (for showdown or out of choice).
Card ranks will be uppercased #Card ranks will be uppercased
""" #"""
logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) # logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
# if cards is not None: # if cards is not None:
# self.shown.add(player) # self.shown.add(player)
# self.addHoleCards(cards,player) # self.addHoleCards(cards,player)
@ -883,10 +942,39 @@ Card ranks will be uppercased
# self.addHoleCards(holeandboard.difference(board),player,shown=True) # 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__): def writeHand(self, fh=sys.__stdout__):
# PokerStars format. # 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, _("%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, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) 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()
players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']])) players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']]))
@ -912,8 +1000,8 @@ Card ranks will be uppercased
for act in self.actions['DRAWONE']: for act in self.actions['DRAWONE']:
print >>fh, self.actionString(act) print >>fh, self.actionString(act)
if act[0] == self.hero and act[1] == 'discards': if act[0] == self.hero and act[1] == 'discards':
(nc,oc) = self.holecards[act[0]]['DRAWONE'] (nc,oc) = self.holecards['DRAWONE'][act[0]]
dc = self.discards[act[0]]['DRAWONE'] dc = self.discards['DRAWONE'][act[0]]
kc = oc - dc kc = oc - dc
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
@ -922,8 +1010,8 @@ Card ranks will be uppercased
for act in self.actions['DRAWTWO']: for act in self.actions['DRAWTWO']:
print >>fh, self.actionString(act) print >>fh, self.actionString(act)
if act[0] == self.hero and act[1] == 'discards': if act[0] == self.hero and act[1] == 'discards':
(nc,oc) = self.holecards[act[0]]['DRAWTWO'] (nc,oc) = self.holecards['DRAWTWO'][act[0]]
dc = self.discards[act[0]]['DRAWTWO'] dc = self.discards['DRAWTWO'][act[0]]
kc = oc - dc kc = oc - dc
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
@ -932,8 +1020,8 @@ Card ranks will be uppercased
for act in self.actions['DRAWTHREE']: for act in self.actions['DRAWTHREE']:
print >>fh, self.actionString(act) print >>fh, self.actionString(act)
if act[0] == self.hero and act[1] == 'discards': if act[0] == self.hero and act[1] == 'discards':
(nc,oc) = self.holecards[act[0]]['DRAWTHREE'] (nc,oc) = self.holecards['DRAWTHREE'][act[0]]
dc = self.discards[act[0]]['DRAWTHREE'] dc = self.discards['DRAWTHREE'][act[0]]
kc = oc - dc kc = oc - dc
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
@ -983,13 +1071,14 @@ class StudHand(Hand):
hhc.markStreets(self) hhc.markStreets(self)
hhc.readAntes(self) hhc.readAntes(self)
hhc.readBringIn(self) hhc.readBringIn(self)
hhc.readHeroCards(self)
#hhc.readShowdownActions(self) # not done yet #hhc.readShowdownActions(self) # not done yet
# Read actions in street order # Read actions in street order
for street in self.streetList: for street in self.streetList:
if self.streets[street]: if self.streets[street]:
logging.debug(street) logging.debug(street)
logging.debug(self.streets[street]) logging.debug(self.streets[street])
hhc.readStudPlayerCards(self, street) # hhc.readStudPlayerCards(self, street)
hhc.readAction(self, street) hhc.readAction(self, street)
hhc.readCollectPot(self) hhc.readCollectPot(self)
hhc.readShownCards(self) # not done yet hhc.readShownCards(self) # not done yet
@ -998,6 +1087,19 @@ class StudHand(Hand):
elif builtFrom == "DB": elif builtFrom == "DB":
self.select("dummy") # Will need a handId self.select("dummy") # Will need a handId
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
if player == self.hero: # we have hero's cards just update shown/mucked
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('SEVENTH', player, open=[], closed=[cards[6]], shown=shown, mucked=mucked)
def addPlayerCards(self, player, street, open=[], closed=[]): def addPlayerCards(self, player, street, open=[], closed=[]):
"""\ """\
Assigns observed cards to a player. Assigns observed cards to a player.
@ -1015,42 +1117,41 @@ closed likewise, but known only to player
except FpdbParseError, e: except FpdbParseError, e:
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
def addHoleCards(self, cards, player, shown, mucked, dealt=False): # def addHoleCards(self, cards, player, shown, mucked, dealt=False):
"""\ # """\
Assigns observed holecards to a player. #Assigns observed holecards to a player.
cards list of card bigrams e.g. ['2h','Jc'] #cards list of card bigrams e.g. ['2h','Jc']
player (string) name of player #player (string) name of player
shown whether they were revealed at showdown #shown whether they were revealed at showdown
mucked whether they were mucked at showdown #mucked whether they were mucked at showdown
dealt whether they were seen in a 'dealt to' line #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
# #
# For stud games we just need to do the routine setting of shown/mucked/etc # if dealt:
# and then update the cards 'THIRD' and 'SEVENTH' # self.dealt.add(player)
logging.debug("addHoleCards %s %s" % (cards, player)) # if shown:
try: # self.shown.add(player)
self.checkPlayerExists(player) # if mucked:
except FpdbParseError, e: # self.mucked.add(player)
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) # if player == self.hero:
return # if len(cards) > 2:
# self.holecards['THIRD'][player] = ([cards[0:3]], [])
if dealt: # if len(cards) > 6:
self.dealt.add(player) # self.holecards['SEVENTH'][player] = ([cards[6]], [])
if shown: # else:
self.shown.add(player) # if len(cards) > 2:
if mucked: # self.holecards['THIRD'][player] = ([cards[0]], cards[1:3])
self.mucked.add(player) # if len(cards) > 6:
if player == self.hero: # self.holecards['SEVENTH'][player] = ([], [cards[6]])
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): # TODO: def addComplete(self, player, amount):
def addComplete(self, street, player, amountTo): def addComplete(self, street, player, amountTo):
# assert street=='THIRD' # assert street=='THIRD'
@ -1087,8 +1188,15 @@ Add a complete on [street] by [player] to [amountTo]
def writeHand(self, fh=sys.__stdout__): def writeHand(self, fh=sys.__stdout__):
# PokerStars format. # 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, _("%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, _("%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, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) # 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))
players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) players_who_post_antes = set([x[0] for x in self.actions['ANTES']])

View File

@ -18,6 +18,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
######################################################################## ########################################################################
# TODO: straighten out discards for draw games
import sys import sys
from HandHistoryConverter import * from HandHistoryConverter import *
@ -25,16 +26,35 @@ from HandHistoryConverter import *
class PokerStars(HandHistoryConverter): class PokerStars(HandHistoryConverter):
############################################################
# Class Variables
# Static regexes # Static regexes
re_GameInfo = re.compile("PokerStars Game #(?P<HID>[0-9]+):\s+(?P<MIXED>HORSE|8\-Game|HOSE)? \(?(?P<GAME>Hold\'em|Razz|7 Card Stud|7 Card Stud Hi/Lo|Omaha|Omaha Hi/Lo|Badugi) (?P<LIMIT>No Limit|Limit|Pot Limit),? \(?(?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\) - (?P<DATETIME>.*$)", re.MULTILINE) re_GameInfo = re.compile("""PokerStars\sGame\s\#(?P<HID>[0-9]+):\s+
(Tournament\s\#(?P<TOURNO>\d+),\s(?P<BUYIN>[\$\+\d\.]+)\s)?
(?P<MIXED>HORSE|8\-Game|HOSE)?\s?\(?
(?P<GAME>Hold\'em|Razz|7\sCard Stud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s
(?P<LIMIT>No\sLimit|Limit|Pot\sLimit),?\s
(-\sLevel\s(?P<LEVEL>[IVXLC]+)\s)?\(?
(?P<CURRENCY>\$|)?
(?P<SB>[.0-9]+)/\$?
(?P<BB>[.0-9]+)\)\s-\s
(?P<DATETIME>.*$)""",
re.MULTILINE|re.VERBOSE)
re_SplitHands = re.compile('\n\n+') re_SplitHands = re.compile('\n\n+')
re_TailSplitHands = re.compile('(\n\n\n+)') re_TailSplitHands = re.compile('(\n\n\n+)')
re_HandInfo = re.compile("^Table \'(?P<TABLE>[- a-zA-Z]+)\'(?P<TABLEATTRIBUTES>.+?$)?", re.MULTILINE) re_HandInfo = re.compile("""^Table\s\'(?P<TABLE>[-\ a-zA-Z\d]+)\'\s
((?P<MAX>\d+)-max\s)?
(?P<PLAY>\(Play\sMoney\)\s)?
(Seat\s\#(?P<BUTTON>\d+)\sis\sthe\sbutton)?""",
re.MULTILINE|re.VERBOSE)
re_Button = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE) re_Button = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE)
re_PlayerInfo = re.compile('^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[.0-9]+) in chips\)', re.MULTILINE) re_PlayerInfo = re.compile('^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[.0-9]+) in chips\)', re.MULTILINE)
re_Board = re.compile(r"\[(?P<CARDS>.+)\]") re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
# self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)') # self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'}
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True):
"""\ """\
in_path (default '-' = sys.stdin) in_path (default '-' = sys.stdin)
@ -53,6 +73,9 @@ follow : whether to tail -f the input"""
players = set([player[1] for player in hand.players]) players = set([player[1] for player in hand.players])
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
# we need to recompile the player regexs. # we need to recompile the player regexs.
# TODO: should probably rename re_HeroCards and corresponding method,
# since they are used to find all cards on lines starting with "Dealt to:"
# They still identify the hero.
self.compiledPlayers = players self.compiledPlayers = players
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")" player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
logging.debug("player_re: " + player_re) logging.debug("player_re: " + player_re)
@ -62,9 +85,12 @@ follow : whether to tail -f the input"""
self.re_BringIn = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE) self.re_BringIn = re.compile(r"^%s: brings[- ]in( low|) 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_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_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| calls| folds| discards| stands pat)( \$(?P<BET>[.\d]+))?( to \$(?P<BETTO>[.\d]+))?( (?P<NODISCARDED>\d) cards?( \[(?P<DISCARDED>.+?)\])?)?" % player_re, re.MULTILINE) self.re_Action = re.compile(r"""^%s:(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat)
(\s\$?(?P<BET>[.\d]+))?(\sto\s\$?(?P<BETTO>[.\d]+))? # the number discarded goes in <BET>
(\scards?(\s\[(?P<DISCARDED>.+?)\])?)?"""
% player_re, re.MULTILINE|re.VERBOSE)
self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % 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_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("^%s sits out" % player_re, re.MULTILINE) self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE)
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE) self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
@ -72,33 +98,46 @@ follow : whether to tail -f the input"""
return [["ring", "hold", "nl"], return [["ring", "hold", "nl"],
["ring", "hold", "pl"], ["ring", "hold", "pl"],
["ring", "hold", "fl"], ["ring", "hold", "fl"],
["ring", "stud", "fl"], ["ring", "stud", "fl"],
#["ring", "draw", "fl"],
["ring", "omaha", "pl"] ["ring", "draw", "fl"],
["tour", "hold", "nl"],
["tour", "hold", "pl"],
["tour", "hold", "fl"],
["tour", "stud", "fl"],
] ]
def determineGameType(self, handText): def determineGameType(self, handText):
info = {'type':'ring'} # inspect the handText and return the gametype dict
# gametype dict is:
# {'limitType': xxx, 'base': xxx, 'category': xxx}
info = {}
m = self.re_GameInfo.search(handText) m = self.re_GameInfo.search(handText)
if not m: if not m:
return None return None
mg = m.groupdict() mg = m.groupdict()
# translations from captured groups to fpdb info strings
# translations from captured groups to our info strings
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' }
mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} games = { # base, category
games = { # base, category "Hold'em" : ('hold','holdem'),
"Hold'em" : ('hold','holdem'), 'Omaha' : ('hold','omahahi'),
'Omaha' : ('hold','omahahi'), 'Omaha Hi/Lo' : ('hold','omahahilo'),
'Omaha Hi/Lo' : ('hold','omahahilo'), 'Razz' : ('stud','razz'),
'Razz' : ('stud','razz'), '7 Card Stud' : ('stud','studhi'),
'7 Card Stud' : ('stud','studhi'), '7 Card Stud Hi/Lo' : ('stud','studhilo'),
'7 Card Stud Hi/Lo' : ('stud','studhilo'), 'Badugi' : ('draw','badugi'),
'Badugi' : ('draw','badugi') 'Triple Draw 2-7 Lowball' : ('draw','27_3draw'),
} }
currencies = { u'':'EUR', '$':'USD', '':'T$' } currencies = { u'':'EUR', '$':'USD', '':'T$' }
# I don't think this is doing what we think. mg will always have all
# the expected keys, but the ones that didn't match in the regex will
# have a value of None. It is OK if it throws an exception when it
# runs across an unknown game or limit or whatever.
if 'LIMIT' in mg: if 'LIMIT' in mg:
info['limitType'] = limits[mg['LIMIT']] info['limitType'] = limits[mg['LIMIT']]
if 'GAME' in mg: if 'GAME' in mg:
@ -109,10 +148,13 @@ follow : whether to tail -f the input"""
info['bb'] = mg['BB'] info['bb'] = mg['BB']
if 'CURRENCY' in mg: if 'CURRENCY' in mg:
info['currency'] = currencies[mg['CURRENCY']] info['currency'] = currencies[mg['CURRENCY']]
if 'MIXED' in mg and mg['MIXED'] != None:
info['mixedType'] = mixes[mg['MIXED']] if 'TOURNO' in mg and mg['TOURNO'] == None:
info['type'] = 'ring'
else:
info['type'] = 'tour'
# NB: SB, BB must be interpreted as blinds or bets depending on limit type. # NB: SB, BB must be interpreted as blinds or bets depending on limit type.
return info return info
@ -121,14 +163,13 @@ follow : whether to tail -f the input"""
m = self.re_HandInfo.search(hand.handText,re.DOTALL) m = self.re_HandInfo.search(hand.handText,re.DOTALL)
if m: if m:
info.update(m.groupdict()) info.update(m.groupdict())
# TODO: Be less lazy and parse maxseats from the HandInfo regex # hand.maxseats = int(m2.group(1))
if m.group('TABLEATTRIBUTES'): else:
m2 = re.search("\s*(\d+)-max", m.group('TABLEATTRIBUTES')) pass # throw an exception here, eh?
hand.maxseats = int(m2.group(1))
m = self.re_GameInfo.search(hand.handText) m = self.re_GameInfo.search(hand.handText)
if m: info.update(m.groupdict()) if m: info.update(m.groupdict())
m = self.re_Button.search(hand.handText) # m = self.re_Button.search(hand.handText)
if m: info.update(m.groupdict()) # if m: info.update(m.groupdict())
# TODO : I rather like the idea of just having this dict as hand.info # TODO : I rather like the idea of just having this dict as hand.info
logging.debug("readHandInfo: %s" % info) logging.debug("readHandInfo: %s" % info)
for key in info: for key in info:
@ -145,7 +186,23 @@ follow : whether to tail -f the input"""
hand.tablename = info[key] hand.tablename = info[key]
if key == 'BUTTON': if key == 'BUTTON':
hand.buttonpos = info[key] hand.buttonpos = info[key]
if key == 'MAX':
hand.maxseats = int(info[key])
if key == 'MIXED':
if info[key] == None: hand.mixed = None
else: hand.mixed = self.mixes[info[key]]
if key == 'TOURNO':
hand.tourNo = info[key]
if key == 'BUYIN':
hand.buyin = info[key]
if key == 'LEVEL':
hand.level = info[key]
if key == 'PLAY' and info['PLAY'] != None:
# hand.currency = 'play' # overrides previously set value
hand.gametype['currency'] = 'play'
def readButton(self, hand): def readButton(self, hand):
m = self.re_Button.search(hand.handText) m = self.re_Button.search(hand.handText)
if m: if m:
@ -213,78 +270,115 @@ follow : whether to tail -f the input"""
for a in self.re_PostBoth.finditer(hand.handText): for a in self.re_PostBoth.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB')) hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB'))
# 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 = set(cards.split(' '))
# hand.addHoleCards(cards, m.group('PNAME'), shown=False, mucked=False, dealt=True)
def readHeroCards(self, hand): def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.handText) # streets PREFLOP, PREDRAW, and THIRD are special cases beacause
if(m == None): # we need to grab hero's cards
#Not involved in hand for street in ('PREFLOP', 'DEAL'):
hand.involved = False if street in hand.streets.keys():
else: m = self.re_HeroCards.finditer(hand.streets[street])
hand.hero = m.group('PNAME') for found in m:
# "2c, qh" -> set(["2c","qc"]) # if m == None:
# Also works with Omaha hands. # hand.involved = False
cards = m.group('NEWCARDS') # else:
cards = set(cards.split(' ')) hand.hero = found.group('PNAME')
hand.addHoleCards(cards, m.group('PNAME'), shown=False, mucked=False, dealt=True) newcards = found.group('NEWCARDS').split(' ')
hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
def readDrawCards(self, hand, street): for street, text in hand.streets.iteritems():
logging.debug("readDrawCards") if street in ('PREFLOP', 'DEAL'): continue # already done these
m = self.re_HeroCards.finditer(hand.streets[street]) m = self.re_HeroCards.finditer(hand.streets[street])
if m == None: for found in m:
hand.involved = False player = found.group('PNAME')
else: if found.group('NEWCARDS') == None:
for player in m: newcards = []
hand.hero = player.group('PNAME') # Only really need to do this once
newcards = player.group('NEWCARDS')
oldcards = player.group('OLDCARDS')
if newcards == None:
newcards = set()
else: else:
newcards = set(newcards.split(' ')) newcards = found.group('NEWCARDS').split(' ')
if oldcards == None: if found.group('OLDCARDS') == None:
oldcards = set() oldcards = []
else: else:
oldcards = set(oldcards.split(' ')) oldcards = found.group('OLDCARDS').split(' ')
hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street)
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 readDrawCards(self, hand, street):
# logging.debug("readDrawCards")
# m = self.re_HeroCards.finditer(hand.streets[street])
# if m == None:
# hand.involved = False
# else:
# for player in m:
# hand.hero = player.group('PNAME') # Only really need to do this once
# newcards = player.group('NEWCARDS')
# oldcards = player.group('OLDCARDS')
# if newcards == None:
# newcards = set()
# else:
# newcards = set(newcards.split(' '))
# if oldcards == None:
# oldcards = set()
# else:
# oldcards = set(oldcards.split(' '))
# hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street)
def readStudPlayerCards(self, hand, street): # def readStudPlayerCards(self, hand, street):
# See comments of reference implementation in FullTiltToFpdb.py # # See comments of reference implementation in FullTiltToFpdb.py
logging.debug("readStudPlayerCards") # logging.debug("readStudPlayerCards")
m = self.re_HeroCards.finditer(hand.streets[street]) # m = self.re_HeroCards.finditer(hand.streets[street])
for player in m: # for player in m:
#~ logging.debug(player.groupdict()) # #~ logging.debug(player.groupdict())
(pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS')) # (pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS'))
if oldcards: # if oldcards:
oldcards = [c.strip() for c in oldcards.split(' ')] # oldcards = [c.strip() for c in oldcards.split(' ')]
if newcards: # if newcards:
newcards = [c.strip() for c in newcards.split(' ')] # newcards = [c.strip() for c in newcards.split(' ')]
if street=='ANTES': # if street=='ANTES':
return # return
elif street=='THIRD': # elif street=='THIRD':
# we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS' # # we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS'
# hero: [xx][o] # # hero: [xx][o]
# others: [o] # # others: [o]
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards) # hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards)
elif street in ('FOURTH', 'FIFTH', 'SIXTH'): # elif street in ('FOURTH', 'FIFTH', 'SIXTH'):
# 4th: # # 4th:
# hero: [xxo] [o] # # hero: [xxo] [o]
# others: [o] [o] # # others: [o] [o]
# 5th: # # 5th:
# hero: [xxoo] [o] # # hero: [xxoo] [o]
# others: [oo] [o] # # others: [oo] [o]
# 6th: # # 6th:
# hero: [xxooo] [o] # # hero: [xxooo] [o]
# others: [ooo] [o] # # others: [ooo] [o]
hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards) # 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. # # 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: # elif street=='SEVENTH' and newcards:
# hero: [xxoooo] [x] # # hero: [xxoooo] [x]
# others: not reported. # # others: not reported.
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards) # hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards)
def readAction(self, hand, street): def readAction(self, hand, street):
m = self.re_Action.finditer(hand.streets[street]) m = self.re_Action.finditer(hand.streets[street])
for action in m: for action in m:
acts = action.groupdict()
if action.group('ATYPE') == ' raises': if action.group('ATYPE') == ' raises':
hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') ) hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') )
elif action.group('ATYPE') == ' calls': elif action.group('ATYPE') == ' calls':
@ -296,7 +390,7 @@ follow : whether to tail -f the input"""
elif action.group('ATYPE') == ' checks': elif action.group('ATYPE') == ' checks':
hand.addCheck( street, action.group('PNAME')) hand.addCheck( street, action.group('PNAME'))
elif action.group('ATYPE') == ' discards': elif action.group('ATYPE') == ' discards':
hand.addDiscard(street, action.group('PNAME'), action.group('NODISCARDED'), action.group('DISCARDED')) hand.addDiscard(street, action.group('PNAME'), action.group('BET'), action.group('DISCARDED'))
elif action.group('ATYPE') == ' stands pat': elif action.group('ATYPE') == ' stands pat':
hand.addStandsPat( street, action.group('PNAME')) hand.addStandsPat( street, action.group('PNAME'))
else: else:
@ -304,9 +398,9 @@ follow : whether to tail -f the input"""
def readShowdownActions(self, hand): def readShowdownActions(self, hand):
# TODO: pick up mucks also
for shows in self.re_ShowdownAction.finditer(hand.handText): for shows in self.re_ShowdownAction.finditer(hand.handText):
cards = shows.group('CARDS') cards = shows.group('CARDS').split(' ')
cards = set(cards.split(' '))
hand.addShownCards(cards, shows.group('PNAME')) hand.addShownCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand): def readCollectPot(self,hand):