diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 4abac8ec..3fba5c5e 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -146,6 +146,14 @@ class Database: ranks = ('', '', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') cards = "" for i in xrange(1, 8): +# key = 'card' + str(i) + 'Value' +# if not d.has_key(key): continue +# if d[key] == None: +# break +# elif d[key] == 0: +# cards += "xx" +# else: +# cards += ranks[d['card' + str(i) + 'Value']] + d['card' +str(i) + 'Suit'] cv = "card%dValue" % i if cv not in d or d[cv] == None: break diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py new file mode 100644 index 00000000..b526632a --- /dev/null +++ b/pyfpdb/DerivedStats.py @@ -0,0 +1,91 @@ +#!/usr/bin/python + +#Copyright 2008 Carl Gherardi +#This program is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, version 3 of the License. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with this program. If not, see . +#In the "official" distribution you can find the license in +#agpl-3.0.txt in the docs folder of the package. + +class DerivedStats(): + def __init__(self, hand): + self.hand = hand + + self.activeSeats = 0 + self.position = 0 + self.tourneyTypeId = 0 + + self.HDs = 0 + self.street0VPI = 0 + self.street0Aggr = 0 + self.street0_3B4BChance = 0 + self.street0_3B4BDone = 0 + + self.street1Seen = 0 + self.street2Seen = 0 + self.street3Seen = 0 + self.street4Seen = 0 + self.sawShowdown = 0 + + self.street1Aggr = 0 + self.street2Aggr = 0 + self.street3Aggr = 0 + self.street4Aggr = 0 + + self.otherRaisedStreet1 = 0 + self.otherRaisedStreet2 = 0 + self.otherRaisedStreet3 = 0 + self.otherRaisedStreet4 = 0 + self.foldToOtherRaisedStreet1 = 0 + self.foldToOtherRaisedStreet2 = 0 + self.foldToOtherRaisedStreet3 = 0 + self.foldToOtherRaisedStreet4 = 0 + self.wonWhenSeenStreet1 = 0 + self.wonAtSD = 0 + + self.stealAttemptChance = 0 + self.stealAttempted = 0 + self.foldBbToStealChance = 0 + self.foldedBbToSteal = 0 + self.foldSbToStealChance = 0 + self.foldedSbToSteal = 0 + + self.street1CBChance = 0 + self.street1CBDone = 0 + self.street2CBChance = 0 + self.street2CBDone = 0 + self.street3CBChance = 0 + self.street3CBDone = 0 + self.street4CBChance = 0 + self.street4CBDone = 0 + + self.foldToStreet1CBChance = 0 + self.foldToStreet1CBDone = 0 + self.foldToStreet2CBChance = 0 + self.foldToStreet2CBDone = 0 + self.foldToStreet3CBChance = 0 + self.foldToStreet3CBDone = 0 + self.foldToStreet4CBChance = 0 + self.foldToStreet4CBDone = 0 + + self.totalProfit = 0 + + self.street1CheckCallRaiseChance = 0 + self.street1CheckCallRaiseDone = 0 + self.street2CheckCallRaiseChance = 0 + self.street2CheckCallRaiseDone = 0 + self.street3CheckCallRaiseChance = 0 + self.street3CheckCallRaiseDone = 0 + self.street4CheckCallRaiseChance = 0 + self.street4CheckCallRaiseDone = 0 + + def getStats(): + pass diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index 5e4e6f3d..f7351526 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -2,18 +2,7 @@ - + @@ -60,18 +49,7 @@ - + @@ -106,41 +84,39 @@ - - - - - - - - + + + + + + + + + + - - - - - - - - - - - + + + + + + + - + - + + + + + + + + + + + + @@ -153,7 +129,7 @@ - + @@ -177,7 +153,7 @@ - + @@ -185,7 +161,7 @@ - + @@ -220,15 +196,15 @@ - + - - - + + + diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 5728e4a2..7f560ebc 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -27,11 +27,14 @@ import time from copy import deepcopy from Exceptions import * +import DerivedStats + class Hand: 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'} - def __init__(self, sitename, gametype, handText): + def __init__(self, sitename, gametype, handText, builtFrom = "HHC"): self.sitename = sitename + self.stats = DerivedStats.DerivedStats(self) self.gametype = gametype self.handText = handText self.handid = 0 @@ -58,9 +61,9 @@ class Hand: self.actions[street] = [] self.board[street] = [] - # Collections indexed by player names 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.collected = [] #list of ? self.collectees = {} # dict from player names to amounts collected (?) @@ -77,6 +80,27 @@ class Hand: self.rake = None + def insert(self, db): + """ Function to insert Hand into database +Should not commit, and do minimal selects. Callers may want to cache commits +db: a connected fpdb_db object""" + # TODO: + # Players - base playerid and siteid tuple + # HudCache data to come from DerivedStats class + # HandsActions - all actions for all players for all streets - self.actions + # BoardCards - ? + # Hands - Summary information of hand indexed by handId - gameinfo + # HandsPlayers - ? ... Do we fix winnings? + # Tourneys ? + # TourneysPlayers + + pass + + def select(self, handId): + """ Function to create Hand object from database """ + pass + + def addPlayer(self, seat, name, chips): """\ Adds a player to the hand, and initialises data structures indexed by player. @@ -89,10 +113,12 @@ If a player has None chips he won't be added.""" self.players.append([seat, name, chips]) self.stacks[name] = Decimal(chips) self.holecards[name] = [] + self.discards[name] = [] self.pot.addPlayer(name) for street in self.streetList: self.bets[street][name] = [] self.holecards[name] = {} # dict from street names. + self.discards[name] = {} # dict from street names. def addStreets(self, match): @@ -137,8 +163,8 @@ If a player has None chips he won't be added.""" # - this is a bet of 1 sb, as yet uncalled. # Player in the big blind posts # - this is a call of 1 sb and a raise to 1 bb - # - + # + logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount)) if player is not None: self.bets['PREFLOP'][player].append(Decimal(amount)) @@ -148,11 +174,11 @@ If a player has None chips he won't be added.""" self.actions['BLINDSANTES'].append(act) self.pot.addMoney(player, Decimal(amount)) if blindtype == 'big blind': - self.lastBet['PREFLOP'] = Decimal(amount) + self.lastBet['PREFLOP'] = Decimal(amount) elif blindtype == 'both': # extra small blind is 'dead' self.lastBet['PREFLOP'] = Decimal(self.bb) - self.posted = self.posted + [[player,blindtype]] + self.posted = self.posted + [[player,blindtype]] #print "DEBUG: self.posted: %s" %(self.posted) @@ -245,6 +271,12 @@ Add a raise on [street] by [player] to [amountTo] self.actions[street].append(act) self.lastBet[street] = Decimal(amount) self.pot.addMoney(player, Decimal(amount)) + + + def addStandsPat(self, street, player): + self.checkPlayerExists(player) + act = (player, 'stands pat') + self.actions[street].append(act) def addFold(self, street, player): @@ -296,14 +328,14 @@ Map the tuple self.gametype onto the pokerstars string describing it # currently it appears to be something like ["ring", "hold", "nl", sb, bb]: gs = {"holdem" : "Hold'em", "omahahi" : "Omaha", - "omahahilo" : "FIXME", + "omahahilo" : "Omaha Hi/Lo", "razz" : "Razz", "studhi" : "7 Card Stud", "studhilo" : "FIXME", "fivedraw" : "5 Card Draw", "27_1draw" : "FIXME", "27_3draw" : "Triple Draw 2-7 Lowball", - "badugi" : "FIXME" + "badugi" : "Badugi" } ls = {"nl" : "No Limit", "pl" : "Pot Limit", @@ -339,49 +371,58 @@ Map the tuple self.gametype onto the pokerstars string describing it print >>fh, _("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'posts': if(act[2] == "small blind"): - print >>fh, _("%s: posts small blind $%s" %(act[0], act[3])) + print >>fh, _("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "big blind"): - print >>fh, _("%s: posts big blind $%s" %(act[0], act[3])) + print >>fh, _("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "both"): - print >>fh, _("%s: posts small & big blinds $%s" %(act[0], act[3])) + print >>fh, _("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) elif act[1] == 'bringin': print >>fh, _("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + elif act[1] == 'discards': + print >>fh, _("%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': + print >>fh, _("%s: stands pat" %(act[0])) + + class HoldemOmahaHand(Hand): - def __init__(self, hhc, sitename, gametype, handText): + def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): if gametype['base'] != 'hold': pass # or indeed don't pass and complain instead logging.debug("HoldemOmahaHand") - self.streetList = ['BLINDSANTES', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order + self.streetList = ['BLINDSANTES', 'DEAL', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order self.communityStreets = ['FLOP', 'TURN', 'RIVER'] self.actionStreets = ['PREFLOP','FLOP','TURN','RIVER'] - Hand.__init__(self, sitename, gametype, handText) + Hand.__init__(self, sitename, gametype, handText, builtFrom = "HHC") self.sb = gametype['sb'] self.bb = gametype['bb'] #Populate a HoldemOmahaHand #Generally, we call 'read' methods here, which get the info according to the particular filter (hhc) # which then invokes a 'addXXX' callback - hhc.readHandInfo(self) - hhc.readPlayerStacks(self) - hhc.compilePlayerRegexs(self) - hhc.markStreets(self) - hhc.readBlinds(self) - hhc.readButton(self) - hhc.readHeroCards(self) - hhc.readShowdownActions(self) - # Read actions in street order - for street in self.communityStreets: - if self.streets[street]: - hhc.readCommunityCards(self, street) - for street in self.actionStreets: - if self.streets[street]: - hhc.readAction(self, street) - hhc.readCollectPot(self) - hhc.readShownCards(self) - self.totalPot() # finalise it (total the pot) - hhc.getRake(self) + if builtFrom == "HHC": + hhc.readHandInfo(self) + hhc.readPlayerStacks(self) + hhc.compilePlayerRegexs(self) + hhc.markStreets(self) + hhc.readBlinds(self) + hhc.readButton(self) + hhc.readHeroCards(self) + hhc.readShowdownActions(self) + # Read actions in street order + for street in self.communityStreets: + if self.streets[street]: + hhc.readCommunityCards(self, street) + for street in self.actionStreets: + if self.streets[street]: + hhc.readAction(self, street) + hhc.readCollectPot(self) + hhc.readShownCards(self) + self.totalPot() # finalise it (total the pot) + hhc.getRake(self) + elif builtFrom == "DB": + self.select("dummy") # Will need a handId - def addHoleCards(self, cards, player): + def addHoleCards(self, cards, player, shown=False): """\ Assigns observed holecards to a player. cards list of card bigrams e.g. ['2h','Jc'] @@ -391,6 +432,8 @@ player (string) name of player try: self.checkPlayerExists(player) cardset = set(self.card(c) for c in cards) + if shown and len(cardset) > 0: + self.shown.add(player) if 'PREFLOP' in self.holecards[player]: self.holecards[player]['PREFLOP'].update(cardset) else: @@ -410,12 +453,12 @@ Card ranks will be uppercased 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) + self.addHoleCards(holeandboard.difference(board),player,shown=True) 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, _("%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)) players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) @@ -458,10 +501,11 @@ Card ranks will be uppercased #Some sites don't have a showdown section so we have to figure out if there should be one # The logic for a showdown is: at the end of river action there are at least two players in the hand # we probably don't need a showdown section in pseudo stars format for our filtering purposes - if 'SHOWDOWN' in self.actions: + if self.shown: print >>fh, _("*** SHOW DOWN ***") - #TODO: Complete SHOWDOWN - + for name in self.shown: + print >>fh, _("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards[name]['PREFLOP']))) + # Current PS format has the lines: # Uncalled bet ($111.25) returned to s0rrow # s0rrow collected $5.15 from side pot @@ -490,32 +534,201 @@ Card ranks will be uppercased print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']), self.collectees[name])) elif name in self.collectees: print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, 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.shown: + #~ print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']))) elif name in self.folded: print >>fh, _("Seat %d: %s folded" % (seatnum, name)) else: - print >>fh, _("Seat %d: %s mucked" % (seatnum, name)) + if name in self.shown: + print >>fh, _("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']))) + else: + print >>fh, _("Seat %d: %s mucked" % (seatnum, name)) print >>fh, "\n\n" class DrawHand(Hand): - def __init__(self, hhc, sitename, gametype, handText): + def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): if gametype['base'] != 'draw': pass # or indeed don't pass and complain instead - - def discardHoleCards(self, cards, player): + self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] + self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] + self.actionStreets = ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] + Hand.__init__(self, sitename, gametype, handText) + self.sb = gametype['sb'] + self.bb = gametype['bb'] + # Populate the draw hand. + if builtFrom == "HHC": + hhc.readHandInfo(self) + hhc.readPlayerStacks(self) + hhc.compilePlayerRegexs(self) + hhc.markStreets(self) + hhc.readBlinds(self) + hhc.readButton(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.readAction(self, street) + hhc.readCollectPot(self) + hhc.readShownCards(self) + self.totalPot() # finalise it (total the pot) + hhc.getRake(self) + elif builtFrom == "DB": + self.select("dummy") # Will need a handId + + # Draw games (at least Badugi has blinds - override default Holdem addBlind + def addBlind(self, player, blindtype, amount): + # if player is None, it's a missing small blind. + # The situation we need to cover are: + # Player in small blind posts + # - this is a bet of 1 sb, as yet uncalled. + # Player in the big blind posts + # - this is a call of 1 sb and a raise to 1 bb + # + + logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount)) + if player is not None: + self.bets['DEAL'][player].append(Decimal(amount)) + self.stacks[player] -= Decimal(amount) + #print "DEBUG %s posts, stack %s" % (player, self.stacks[player]) + act = (player, 'posts', blindtype, amount, self.stacks[player]==0) + self.actions['BLINDSANTES'].append(act) + self.pot.addMoney(player, Decimal(amount)) + if blindtype == 'big blind': + self.lastBet['DEAL'] = Decimal(amount) + elif blindtype == 'both': + # extra small blind is 'dead' + self.lastBet['DEAL'] = Decimal(self.bb) + self.posted = self.posted + [[player,blindtype]] + #print "DEBUG: self.posted: %s" %(self.posted) + + + + 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) - for card in cards: - self.holecards[player].remove(card) +# if shown and len(cardset) > 0: +# self.shown.add(player) + self.holecards[player][street] = (newcards,oldcards) except FpdbParseError, e: - pass - except ValueError: - print "[ERROR] discardHoleCard tried to discard a card %s didn't have" % (player,) + 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[player][street] = set([cards]) + + + def addDiscard(self, street, player, num, cards): + self.checkPlayerExists(player) + if cards: + act = (player, 'discards', num, cards) + self.discardDrawHoleCards(cards, player, street) + else: + act = (player, 'discards', num) + self.actions[street].append(act) + + + def addShownCards(self, cards, player, holeandboard=None): + """\ +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 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, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) + + 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])) + + 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])) + + if 'DEAL' in self.actions: + print >>fh, _("*** DEALING HANDS ***") + for player in [x[1] for x in self.players if x[1] in players_who_act_ondeal]: + if 'DEAL' in self.holecards[player]: + (nc,oc) = self.holecards[player]['DEAL'] + print >>fh, _("Dealt to %s: [%s]") % (player, " ".join(nc)) + for act in self.actions['DEAL']: + self.printActionLine(act, fh) + + if 'DRAWONE' in self.actions: + print >>fh, _("*** FIRST DRAW ***") + for act in self.actions['DRAWONE']: + self.printActionLine(act, fh) + if act[0] == self.hero and act[1] == 'discards': + (nc,oc) = self.holecards[act[0]]['DRAWONE'] + dc = self.discards[act[0]]['DRAWONE'] + kc = oc - dc + print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) + + if 'DRAWTWO' in self.actions: + print >>fh, _("*** SECOND DRAW ***") + for act in self.actions['DRAWTWO']: + self.printActionLine(act, fh) + if act[0] == self.hero and act[1] == 'discards': + (nc,oc) = self.holecards[act[0]]['DRAWTWO'] + dc = self.discards[act[0]]['DRAWTWO'] + kc = oc - dc + print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) + + if 'DRAWTHREE' in self.actions: + print >>fh, _("*** THIRD DRAW ***") + for act in self.actions['DRAWTHREE']: + self.printActionLine(act, fh) + if act[0] == self.hero and act[1] == 'discards': + (nc,oc) = self.holecards[act[0]]['DRAWTHREE'] + dc = self.discards[act[0]]['DRAWTHREE'] + kc = oc - dc + print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) + + if 'SHOWDOWN' in self.actions: + print >>fh, _("*** SHOW DOWN ***") + #TODO: Complete SHOWDOWN + + # Current PS format has the lines: + # Uncalled bet ($111.25) returned to s0rrow + # s0rrow collected $5.15 from side pot + # stervels: shows [Ks Qs] (two pair, Kings and Queens) + # stervels collected $45.35 from main pot + # 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)) + for entry in self.collected: + print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1])) + + print >>fh, _("*** SUMMARY ***") + print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) + print >>fh, "\n\n" + + class StudHand(Hand): - def __init__(self, hhc, sitename, gametype, handText): + def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): if gametype['base'] != 'stud': pass # or indeed don't pass and complain instead self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order @@ -526,24 +739,27 @@ class StudHand(Hand): #Populate the StudHand #Generally, we call a 'read' method here, which gets the info according to the particular filter (hhc) # which then invokes a 'addXXX' callback - hhc.readHandInfo(self) - hhc.readPlayerStacks(self) - hhc.compilePlayerRegexs(self) - hhc.markStreets(self) - hhc.readAntes(self) - hhc.readBringIn(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 - self.totalPot() # finalise it (total the pot) - hhc.getRake(self) + if builtFrom == "HHC": + hhc.readHandInfo(self) + hhc.readPlayerStacks(self) + hhc.compilePlayerRegexs(self) + hhc.markStreets(self) + hhc.readAntes(self) + hhc.readBringIn(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 + self.totalPot() # finalise it (total the pot) + hhc.getRake(self) + elif builtFrom == "DB": + self.select("dummy") # Will need a handId def addPlayerCards(self, player, street, open=[], closed=[]): """\ diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 23688700..98a96638 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -204,12 +204,17 @@ Tail the in_path file and yield handTexts separated by re_SplitHands""" def processHand(self, handText): gametype = self.determineGameType(handText) logging.debug("gametype %s" % gametype) - - # See if gametype is supported. - type = gametype['type'] - base = gametype['base'] - limit = gametype['limitType'] - l = [type] + [base] + [limit] + if gametype is None: + l = None + gametype = "unmatched" + # TODO: not ideal, just trying to not error. + # TODO: Need to count failed hands. + else: + # See if gametype is supported. + type = gametype['type'] + base = gametype['base'] + limit = gametype['limitType'] + l = [type] + [base] + [limit] hand = None if l in self.readSupportedGames(): hand = None diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index c9e0ea07..f47d93e9 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -44,12 +44,11 @@ import Stats import Mucked import Database import HUD_main -import Utils -def importName(module_name, name, params): +def importName(module_name, name): """Import a named object 'name' from module 'module_name'.""" # Recipe 16.3 in the Python Cookbook, 2nd ed. Thanks!!!! -# Modded by Carl G to support additional params + try: module = __import__(module_name, globals(), locals(), [name]) except: @@ -220,8 +219,9 @@ class Hud: self.config.save() def adj_seats(self, hand, config): - - adj = xrange(0, self.max + 1) # default seat adjustments = no adjustment + +# Need range here, not xrange -> need the actual list + adj = range(0, self.max + 1) # default seat adjustments = no adjustment # does the user have a fav_seat? try: sys.stderr.write("site = %s, max = %d, fav seat = %d\n" % (self.table.site, self.max, config.supported_sites[self.table.site].layout[self.max].fav_seat)) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 06a216b3..90af4b8f 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -215,7 +215,7 @@ class Stud_cards: self.config = config # self.db_name = db_name - self.card_images = self.get_card_images() + self.card_images = self.parent.get_card_images() self.seen_cards = {} self.grid_contents = {} self.eb = {} @@ -280,7 +280,7 @@ class Stud_cards: (4, cards[8:10]), (5, cards[10:12]), (6, cards[12:14])): if not i[1] == "xx": self.seen_cards[(i[0], c - 1)]. \ - set_from_pixbuf(self.card_images[self.split_cards(i[1])]) + set_from_pixbuf(self.card_images[self.parent.split_cards(i[1])]) ## action in tool tips for 3rd street cards for c in (0, 1, 2): for r in range(0, self.rows): diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 05027121..b7322a1b 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -23,53 +23,10 @@ from HandHistoryConverter import * # PokerStars HH Format -#PokerStars Game #20461877044: Hold'em No Limit ($1/$2) - 2008/09/16 18:58:01 ET -#Table 'Gianfar IV' 6-max Seat #1 is the button -#Seat 1: ZeKGB ($224 in chips) -#Seat 2: quimboavida ($107.75 in chips) -#Seat 3: tropical100 ($190 in chips) -#Seat 4: jackhama33 ($54.95 in chips) -#Seat 5: Olubanu ($196 in chips) -#Seat 6: LSgambler ($205.35 in chips) -#quimboavida: posts small blind $1 -#tropical100: posts big blind $2 -#*** HOLE CARDS *** -#jackhama33: folds -#Olubanu: folds -#LSgambler: folds -#ZeKGB: folds -#quimboavida: calls $1 -#tropical100: raises $5 to $7 -#quimboavida: calls $5 -#*** FLOP *** [3d Qs Kd] -#quimboavida: bets $10 -#tropical100: calls $10 -#*** TURN *** [3d Qs Kd] [Ah] -#quimboavida: checks -#tropical100: checks -#*** RIVER *** [3d Qs Kd Ah] [7c] -#quimboavida: bets $30 -#tropical100: folds -#quimboavida collected $32.35 from pot -#*** SUMMARY *** -#Total pot $34 | Rake $1.65 -#Board [3d Qs Kd Ah 7c] -#Seat 1: ZeKGB (button) folded before Flop (didn't bet) -#Seat 2: quimboavida (small blind) collected ($32.35) -#Seat 3: tropical100 (big blind) folded on the River -#Seat 4: jackhama33 folded before Flop (didn't bet) -#Seat 5: Olubanu folded before Flop (didn't bet) -#Seat 6: LSgambler folded before Flop (didn't bet) - - -#PokerStars Game #25381215423: HORSE (Razz Limit, $0.10/$0.20) - 2009/02/26 15:20:19 ET -#Table 'Natalie V' 8-max - - class PokerStars(HandHistoryConverter): # Static regexes - re_GameInfo = re.compile('PokerStars Game #(?P[0-9]+):\s+(HORSE)? \(?(?PHold\'em|Razz|7 Card Stud|Omaha Hi/Lo) (?PNo Limit|Limit|Pot Limit),? \(?(?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+)\) - (?P.*$)', re.MULTILINE) + re_GameInfo = re.compile("PokerStars Game #(?P[0-9]+):\s+(HORSE)? \(?(?PHold\'em|Razz|7 Card Stud|Omaha Hi/Lo|Badugi) (?PNo Limit|Limit|Pot Limit),? \(?(?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+)\) - (?P.*$)", re.MULTILINE) re_SplitHands = re.compile('\n\n+') re_HandInfo = re.compile("^Table \'(?P[- a-zA-Z]+)\'(?P.+?$)?", re.MULTILINE) re_Button = re.compile('Seat #(?P