From dd1b442122cc1686516fd4f69a338e105f392f15 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 13 Jul 2009 00:37:51 -0400 Subject: [PATCH] Rationalized holecards for stud and draw games. Cards are now lists of cards rather than sets. Removed some game-specific methods and replaced with general methods. Let the superclass handle some stuff. --- pyfpdb/Hand.py | 180 +++++++++++++++++++++---------------- pyfpdb/PokerStarsToFpdb.py | 169 ++++++++++++++++++---------------- 2 files changed, 193 insertions(+), 156 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index a9d6d49d..a2570f42 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -15,6 +15,8 @@ #In the "official" distribution you can find the license in #agpl-3.0.txt in the docs folder of the package. +# TODO: get writehand() encoding correct + import re import sys import traceback @@ -147,7 +149,7 @@ 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)) +# logging.debug("addHoleCards %s %s" % (open + closed, player)) try: self.checkPlayerExists(player) except FpdbParseError, e: @@ -158,7 +160,6 @@ dealt whether they were seen in a 'dealt to' line if shown: self.shown.add(player) if mucked: self.mucked.add(player) - print "stuff =", street, player, open, closed self.holecards[street][player] = [open, closed] def insert(self, db): @@ -808,12 +809,13 @@ class DrawHand(Hand): hhc.markStreets(self) hhc.readBlinds(self) hhc.readButton(self) + hhc.readHeroCards(self) hhc.readShowdownActions(self) # Read actions in street order for street in self.streetList: if self.streets[street]: # hhc.readCommunityCards(self, street) - hhc.readDrawCards(self, street) +# hhc.readDrawCards(self, street) hhc.readAction(self, street) hhc.readCollectPot(self) hhc.readShownCards(self) @@ -849,20 +851,28 @@ class DrawHand(Hand): #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): - """\ -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 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): @@ -872,7 +882,6 @@ player (string) name of player def addDiscard(self, street, player, num, cards): self.checkPlayerExists(player) - print "street, player, num, cards =", street, player, num, cards if cards: act = (player, 'discards', num, cards) self.discardDrawHoleCards(cards, player, street) @@ -896,32 +905,32 @@ player (string) name of player # 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 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. @@ -1023,13 +1032,14 @@ class StudHand(Hand): hhc.markStreets(self) 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.readStudPlayerCards(self, street) hhc.readAction(self, street) hhc.readCollectPot(self) hhc.readShownCards(self) # not done yet @@ -1038,6 +1048,19 @@ class StudHand(Hand): elif builtFrom == "DB": 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=[]): """\ Assigns observed cards to a player. @@ -1055,42 +1078,41 @@ closed likewise, but known only to player 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 -""" +# 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 # -# 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]]) - +# 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' diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 1be2f767..a4b5d6f8 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -18,18 +18,19 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ######################################################################## +# TODO: play money currency showing up as T$ +# TODO: straighten out discards for draw games import sys from HandHistoryConverter import * # PokerStars HH Format -# TODO: fix finding hero in stud games -# TODO: fix open/closed hole cards for stud games - class PokerStars(HandHistoryConverter): +############################################################ +# Class Variables + # Static regexes -# re_GameInfo = re.compile("PokerStars Game #(?P[0-9]+):\s+(?PHORSE|8\-Game|HOSE)? \(?(?PHold\'em|Razz|7 Card Stud|7 Card Stud Hi/Lo|Omaha|Omaha Hi/Lo|Badugi) (?PNo Limit|Limit|Pot Limit),? \(?(?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+)\) - (?P.*$)", re.MULTILINE) re_GameInfo = re.compile("""PokerStars\sGame\s\#(?P[0-9]+):\s+ (Tournament\s\#(?P\d+),\s(?P[\$\+\d\.]+)\s)? (?PHORSE|8\-Game|HOSE)?\s?\(? @@ -71,6 +72,9 @@ follow : whether to tail -f the input""" players = set([player[1] for player in hand.players]) if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' # 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 player_re = "(?P" + "|".join(map(re.escape, players)) + ")" logging.debug("player_re: " + player_re) @@ -80,14 +84,12 @@ follow : whether to tail -f the input""" self.re_BringIn = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P[.0-9]+)" % player_re, re.MULTILINE) self.re_PostBoth = re.compile(r"^%s: posts small \& big blinds \[\$? (?P[.0-9]+)" % player_re, re.MULTILINE) self.re_HeroCards = re.compile(r"^Dealt to %s(?: \[(?P.+?)\])?( \[(?P.+?)\])" % player_re, re.MULTILINE) -# self.re_DealToCards = re.compile(r"^Dealt to %s(?: \[(?P.+?)\])?( \[(?P.+?)\])" % player_re, re.MULTILINE) -# self.re_Action = re.compile(r"^%s:(?P bets| checks| raises| calls| folds| discards| stands pat)( \$?(?P[.\d]+))?( to \$?(?P[.\d]+))?( (?P\d) cards?( \[(?P.+?)\])?)?" % player_re, re.MULTILINE) self.re_Action = re.compile(r"""^%s:(?P\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat) (\s\$?(?P[.\d]+))?(\sto\s\$?(?P[.\d]+))? # the number discarded goes in (\scards?(\s\[(?P.+?)\])?)?""" % player_re, re.MULTILINE|re.VERBOSE) self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P.*)\]" % player_re, re.MULTILINE) - self.re_CollectPot = re.compile(r"Seat (?P[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P[.\d]+)\)(, mucked| with.*|)" % player_re, re.MULTILINE) + self.re_CollectPot = re.compile(r"Seat (?P[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$?(?P[.\d]+)\)(, mucked| with.*|)" % player_re, re.MULTILINE) self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE) self.re_ShownCards = re.compile("^Seat (?P[0-9]+): %s (\(.*\) )?(?Pshowed|mucked) \[(?P.*)\].*" % player_re, re.MULTILINE) @@ -280,83 +282,96 @@ follow : whether to tail -f the input""" # hand.addHoleCards(cards, m.group('PNAME'), shown=False, mucked=False, dealt=True) def readHeroCards(self, hand): -# streets PREFLOP, PREDRAW, and THIRD are special cases - for street in ('PREFLOP', 'PREDRAW'): +# 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(): - print "text =", hand.streets[street] - m = self.re_HeroCards.search(hand.streets[street]) - if m == None: - hand.involved = False - else: - hand.hero = m.group('PNAME') - newcards = m.group('NEWCARDS').split(' ') + 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) -# def readHeroCards(self, hand): -# for street, text in hand.streets.iteritems(): -# m = self.re_HeroCards.search(hand.handText) -# if(m == None): -# #Not involved in hand -# hand.involved = False -# else: - - - - 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() + for street, text in hand.streets.iteritems(): + if 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 = set(newcards.split(' ')) - if oldcards == None: - oldcards = set() + newcards = found.group('NEWCARDS').split(' ') + if found.group('OLDCARDS') == None: + oldcards = [] else: - oldcards = set(oldcards.split(' ')) - hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) + 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 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): - # See comments of reference implementation in FullTiltToFpdb.py - 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(' ')] - 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 readStudPlayerCards(self, hand, street): +# # See comments of reference implementation in FullTiltToFpdb.py +# 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(' ')] +# 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])