470 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			470 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/python
 | 
						|
 | 
						|
#Copyright 2009 Stephane Alessio
 | 
						|
#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 <http://www.gnu.org/licenses/>.
 | 
						|
#In the "official" distribution you can find the license in
 | 
						|
#agpl-3.0.txt in the docs folder of the package.
 | 
						|
 | 
						|
# TODO: check to keep only the needed modules
 | 
						|
 | 
						|
import re
 | 
						|
import sys
 | 
						|
import traceback
 | 
						|
import logging
 | 
						|
import os
 | 
						|
import os.path
 | 
						|
from decimal import Decimal
 | 
						|
import operator
 | 
						|
import time,datetime
 | 
						|
from copy import deepcopy
 | 
						|
from Exceptions import *
 | 
						|
import pprint
 | 
						|
import DerivedStats
 | 
						|
import Card
 | 
						|
 | 
						|
log = logging.getLogger("parser")
 | 
						|
 | 
						|
class Tourney(object):
 | 
						|
 | 
						|
################################################################
 | 
						|
#    Class Variables
 | 
						|
    UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'}     # SAL- TO KEEP ??
 | 
						|
    LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'}                                                  # SAL- TO KEEP ??
 | 
						|
    SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''}
 | 
						|
    MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose'  : 'HOSE', 'ha': 'HA'}
 | 
						|
    SITEIDS = {'Fulltilt':1, 'PokerStars':2, 'Everleaf':3, 'Win2day':4, 'OnGame':5, 'UltimateBet':6, 'Betfair':7, 'Absolute':8, 'PartyPoker':9 }
 | 
						|
 | 
						|
 | 
						|
    def __init__(self, sitename, gametype, summaryText, builtFrom = "HHC"):
 | 
						|
        self.sitename           = sitename
 | 
						|
        self.siteId             = self.SITEIDS[sitename]
 | 
						|
        self.gametype           = gametype
 | 
						|
        self.starttime          = None
 | 
						|
        self.endtime            = None
 | 
						|
        self.summaryText        = summaryText
 | 
						|
        self.tourneyName        = None
 | 
						|
        self.tourNo             = None
 | 
						|
        self.buyin              = None
 | 
						|
        self.fee                = None  # the Database code is looking for this one .. ?
 | 
						|
        self.hero               = None
 | 
						|
        self.maxseats           = None
 | 
						|
        self.entries            = 0
 | 
						|
        self.speed              = "Normal"
 | 
						|
        self.prizepool          = None  # Make it a dict in order to deal (eventually later) with non-money winnings : {'MONEY' : amount, 'OTHER' : Value ??}
 | 
						|
        self.buyInChips         = None
 | 
						|
        self.mixed              = None
 | 
						|
        self.isRebuy            = False
 | 
						|
        self.isKO               = False
 | 
						|
        self.isHU               = False
 | 
						|
        self.isMatrix           = False
 | 
						|
        self.isShootout         = False
 | 
						|
        self.matrixMatchId      = None  # For Matrix tourneys : 1-4 => match tables (traditionnal), 0 => Positional winnings info
 | 
						|
        self.subTourneyBuyin    = None
 | 
						|
        self.subTourneyFee      = None
 | 
						|
        self.rebuyChips         = 0
 | 
						|
        self.addOnChips         = 0
 | 
						|
        self.rebuyAmount		= 0
 | 
						|
        self.addOnAmount		= 0
 | 
						|
        self.totalRebuys        = 0
 | 
						|
        self.totalAddOns        = 0
 | 
						|
        self.koBounty           = 0
 | 
						|
        self.tourneyComment     = None
 | 
						|
        self.players            = []
 | 
						|
 | 
						|
        # Collections indexed by player names
 | 
						|
        self.finishPositions    = {}
 | 
						|
        self.winnings           = {}
 | 
						|
        self.payinAmounts       = {}
 | 
						|
        self.countRebuys        = {}
 | 
						|
        self.countAddOns        = {}
 | 
						|
        self.countKO            = {}
 | 
						|
 | 
						|
        # currency symbol for this summary
 | 
						|
        self.sym = None
 | 
						|
        #self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        #TODO : Update
 | 
						|
        vars = ( ("SITE", self.sitename),
 | 
						|
                 ("START TIME", self.starttime),
 | 
						|
                 ("END TIME", self.endtime),
 | 
						|
                 ("TOURNEY NAME", self.tourneyName),
 | 
						|
                 ("TOURNEY NO", self.tourNo),
 | 
						|
                 ("BUYIN", self.buyin),
 | 
						|
                 ("FEE", self.fee),
 | 
						|
                 ("HERO", self.hero),
 | 
						|
                 ("MAXSEATS", self.maxseats),
 | 
						|
                 ("ENTRIES", self.entries),
 | 
						|
                 ("SPEED", self.speed),
 | 
						|
                 ("PRIZE POOL", self.prizepool),
 | 
						|
                 ("STARTING CHIP COUNT", self.buyInChips),
 | 
						|
                 ("MIXED", self.mixed),
 | 
						|
                 ("REBUY ADDON", self.isRebuy),
 | 
						|
                 ("KO", self.isKO),
 | 
						|
                 ("HU", self.isHU),
 | 
						|
                 ("MATRIX", self.isMatrix),
 | 
						|
                 ("SHOOTOUT", self.isShootout),
 | 
						|
                 ("MATRIX MATCH ID", self.matrixMatchId),
 | 
						|
                 ("SUB TOURNEY BUY IN", self.subTourneyBuyin),
 | 
						|
                 ("SUB TOURNEY FEE", self.subTourneyFee),
 | 
						|
                 ("REBUY CHIPS", self.rebuyChips),
 | 
						|
                 ("ADDON CHIPS", self.addOnChips),
 | 
						|
                 ("REBUY AMOUNT", self.rebuyAmount),
 | 
						|
                 ("ADDON AMOUNT", self.addOnAmount),
 | 
						|
                 ("TOTAL REBUYS", self.totalRebuys),
 | 
						|
                 ("TOTAL ADDONS", self.totalAddOns),
 | 
						|
                 ("KO BOUNTY", self.koBounty),
 | 
						|
                 ("TOURNEY COMMENT", self.tourneyComment)
 | 
						|
        )
 | 
						|
 
 | 
						|
        structs = ( ("GAMETYPE", self.gametype),
 | 
						|
                    ("PLAYERS", self.players),
 | 
						|
                    ("PAYIN AMOUNTS", self.payinAmounts),
 | 
						|
                    ("POSITIONS", self.finishPositions),                    
 | 
						|
                    ("WINNINGS", self.winnings),
 | 
						|
                    ("COUNT REBUYS", self.countRebuys),
 | 
						|
                    ("COUNT ADDONS", self.countAddOns),
 | 
						|
                    ("NB OF KO", self.countKO)
 | 
						|
        )
 | 
						|
        str = ''
 | 
						|
        for (name, var) in vars:
 | 
						|
            str = str + "\n%s = " % name + pprint.pformat(var)
 | 
						|
 | 
						|
        for (name, struct) in structs:
 | 
						|
            str = str + "\n%s =\n" % name + pprint.pformat(struct, 4)
 | 
						|
        return str
 | 
						|
 | 
						|
    def getSummaryText(self):
 | 
						|
        return self.summaryText
 | 
						|
 | 
						|
    def prepInsert(self, db):
 | 
						|
        pass
 | 
						|
 | 
						|
    def insert(self, db):
 | 
						|
        print "TODO: Insert Tourney in DB"
 | 
						|
        # First : check all needed info is filled in the object, especially for the initial select
 | 
						|
 | 
						|
        # Notes on DB Insert
 | 
						|
        # Some identified issues for tourneys already in the DB (which occurs when the HH file is parsed and inserted before the Summary)
 | 
						|
        # Be careful on updates that could make the HH import not match the tourney inserted from a previous summary import !!
 | 
						|
        # BuyIn/Fee can be at 0/0 => match may not be easy
 | 
						|
        # Only one existinf Tourney entry for Matrix Tourneys, but multiple Summary files
 | 
						|
        # Starttime may not match the one in the Summary file : HH = time of the first Hand / could be slighltly different from the one in the summary file
 | 
						|
        # Note: If the TourneyNo could be a unique id .... this would really be a relief to deal with matrix matches ==> Ask on the IRC / Ask Fulltilt ??
 | 
						|
        
 | 
						|
        dbTourneyTypeId = db.tRecogniseTourneyType(self)
 | 
						|
        print "Tourney Type ID = %d" % dbTourneyTypeId
 | 
						|
        dbTourneyId = db.tRecognizeTourney(self, dbTourneyTypeId)
 | 
						|
        print "Tourney ID = %d" % dbTourneyId
 | 
						|
        dbTourneysPlayersIds = db.tStoreTourneyPlayers(self, dbTourneyId)
 | 
						|
        db.tCheckTourneysHandsPlayers(self, dbTourneysPlayersIds, dbTourneyTypeId)
 | 
						|
        
 | 
						|
        # TO DO : Return what has been done (tourney created, updated, nothing)
 | 
						|
        # ?? stored = 1 if tourney is fully created / duplicates = 1, if everything was already here and correct / partial=1 if some things were already here (between tourney, tourneyPlayers and handsplayers)
 | 
						|
        # if so, prototypes may need changes to know what has been done
 | 
						|
        stored = 0
 | 
						|
        duplicates = 0
 | 
						|
        partial = 0
 | 
						|
        errors = 0
 | 
						|
        ttime = 0
 | 
						|
        return (stored, duplicates, partial, errors, ttime)
 | 
						|
 | 
						|
    
 | 
						|
    def old_insert_from_Hand(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
 | 
						|
        sqlids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId)
 | 
						|
 | 
						|
        #Gametypes
 | 
						|
        gtid = db.getGameTypeId(self.siteId, self.gametype)
 | 
						|
 | 
						|
        # HudCache data to come from DerivedStats class
 | 
						|
        # HandsActions - all actions for all players for all streets - self.actions
 | 
						|
        # Hands - Summary information of hand indexed by handId - gameinfo
 | 
						|
        #This should be moved to prepInsert
 | 
						|
        hh = {}
 | 
						|
        hh['siteHandNo'] =  self.handid
 | 
						|
        hh['handStart'] = self.starttime
 | 
						|
        hh['gameTypeId'] = gtid
 | 
						|
        # seats TINYINT NOT NULL,
 | 
						|
        hh['tableName'] = self.tablename
 | 
						|
        hh['maxSeats'] = self.maxseats
 | 
						|
        hh['seats'] = len(sqlids)
 | 
						|
        # Flop turn and river may all be empty - add (likely) too many elements and trim with range
 | 
						|
        boardcards = self.board['FLOP'] + self.board['TURN'] + self.board['RIVER'] + [u'0x', u'0x', u'0x', u'0x', u'0x']
 | 
						|
        cards = [Card.encodeCard(c) for c in boardcards[0:5]]
 | 
						|
        hh['boardcard1'] = cards[0]
 | 
						|
        hh['boardcard2'] = cards[1]
 | 
						|
        hh['boardcard3'] = cards[2]
 | 
						|
        hh['boardcard4'] = cards[3]
 | 
						|
        hh['boardcard5'] = cards[4]
 | 
						|
 | 
						|
             # texture smallint,
 | 
						|
             # playersVpi SMALLINT NOT NULL,         /* num of players vpi */
 | 
						|
                # Needs to be recorded
 | 
						|
             # playersAtStreet1 SMALLINT NOT NULL,   /* num of players seeing flop/street4 */
 | 
						|
                # Needs to be recorded
 | 
						|
             # playersAtStreet2 SMALLINT NOT NULL,
 | 
						|
                # Needs to be recorded
 | 
						|
             # playersAtStreet3 SMALLINT NOT NULL,
 | 
						|
                # Needs to be recorded
 | 
						|
             # playersAtStreet4 SMALLINT NOT NULL,
 | 
						|
                # Needs to be recorded
 | 
						|
             # playersAtShowdown SMALLINT NOT NULL,
 | 
						|
                # Needs to be recorded
 | 
						|
             # street0Raises TINYINT NOT NULL, /* num small bets paid to see flop/street4, including blind */
 | 
						|
                # Needs to be recorded
 | 
						|
             # street1Raises TINYINT NOT NULL, /* num small bets paid to see turn/street5 */
 | 
						|
                # Needs to be recorded
 | 
						|
             # street2Raises TINYINT NOT NULL, /* num big bets paid to see river/street6 */
 | 
						|
                # Needs to be recorded
 | 
						|
             # street3Raises TINYINT NOT NULL, /* num big bets paid to see sd/street7 */
 | 
						|
                # Needs to be recorded
 | 
						|
             # street4Raises TINYINT NOT NULL, /* num big bets paid to see showdown */
 | 
						|
                # Needs to be recorded
 | 
						|
 | 
						|
        #print "DEBUG: self.getStreetTotals = (%s, %s, %s, %s, %s)" %  self.getStreetTotals()
 | 
						|
        #FIXME: Pot size still in decimal, needs to be converted to cents
 | 
						|
        (hh['street1Pot'], hh['street2Pot'], hh['street3Pot'], hh['street4Pot'], hh['showdownPot']) = self.getStreetTotals()
 | 
						|
 | 
						|
             # comment TEXT,
 | 
						|
             # commentTs DATETIME
 | 
						|
        #print hh
 | 
						|
        handid = db.storeHand(hh)
 | 
						|
        # HandsPlayers - ? ... Do we fix winnings?
 | 
						|
        # Tourneys ?
 | 
						|
        # TourneysPlayers
 | 
						|
 | 
						|
        pass
 | 
						|
 | 
						|
    def select(self, tourneyId):
 | 
						|
        """ Function to create Tourney object from database """
 | 
						|
        
 | 
						|
        
 | 
						|
 | 
						|
    def addPlayer(self, rank, name, winnings, payinAmount, nbRebuys, nbAddons, nbKO):
 | 
						|
        """\
 | 
						|
Adds a player to the tourney, and initialises data structures indexed by player.
 | 
						|
rank        (int) indicating the finishing rank (can be -1 if unknown)
 | 
						|
name        (string) player name
 | 
						|
winnings    (decimal) the money the player ended the tourney with (can be 0, or -1 if unknown)
 | 
						|
"""
 | 
						|
        log.debug("addPlayer: rank:%s - name : '%s' - Winnings (%s)" % (rank, name, winnings))
 | 
						|
        self.players.append(name)
 | 
						|
        self.finishPositions.update( { name : Decimal(rank) } )
 | 
						|
        self.winnings.update( { name : Decimal(winnings) } )
 | 
						|
        self.payinAmounts.update( {name : Decimal(payinAmount) } )
 | 
						|
        self.countRebuys.update( {name: Decimal(nbRebuys) } )
 | 
						|
        self.countAddOns.update( {name: Decimal(nbAddons) } )
 | 
						|
        self.countKO.update( {name : Decimal(nbKO) } )
 | 
						|
        
 | 
						|
 | 
						|
    def incrementPlayerWinnings(self, name, additionnalWinnings):
 | 
						|
        log.debug("incrementPlayerWinnings: name : '%s' - Add Winnings (%s)" % (name, additionnalWinnings))
 | 
						|
        oldWins = 0
 | 
						|
        if self.winnings.has_key(name):
 | 
						|
            oldWins = self.winnings[name]
 | 
						|
        else:
 | 
						|
            self.players.append([-1, name, 0])
 | 
						|
            
 | 
						|
        self.winnings[name] = oldWins + Decimal(additionnalWinnings)
 | 
						|
 | 
						|
    def checkPlayerExists(self,player):
 | 
						|
        if player not in [p[1] for p in self.players]:
 | 
						|
            print "checkPlayerExists", player, "fail"
 | 
						|
            raise FpdbParseError
 | 
						|
 | 
						|
 | 
						|
    def getGameTypeAsString(self):
 | 
						|
        """\
 | 
						|
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"  : "Omaha Hi/Lo",
 | 
						|
              "razz"       : "Razz",
 | 
						|
              "studhi"     : "7 Card Stud",
 | 
						|
              "studhilo"   : "7 Card Stud Hi/Lo",
 | 
						|
              "fivedraw"   : "5 Card Draw",
 | 
						|
              "27_1draw"   : "FIXME",
 | 
						|
              "27_3draw"   : "Triple Draw 2-7 Lowball",
 | 
						|
              "badugi"     : "Badugi"
 | 
						|
             }
 | 
						|
        ls = {"nl"  : "No Limit",
 | 
						|
              "pl"  : "Pot Limit",
 | 
						|
              "fl"  : "Limit",
 | 
						|
              "cn"  : "Cap No Limit",
 | 
						|
              "cp"  : "Cap Pot Limit"
 | 
						|
             }
 | 
						|
 | 
						|
        log.debug("gametype: %s" %(self.gametype))
 | 
						|
        retstring = "%s %s" %(gs[self.gametype['category']], ls[self.gametype['limitType']])
 | 
						|
        return retstring
 | 
						|
 | 
						|
 | 
						|
    def writeSummary(self, fh=sys.__stdout__):
 | 
						|
        print >>fh, "Override me"
 | 
						|
 | 
						|
    def printSummary(self):
 | 
						|
        self.writeSummary(sys.stdout)
 | 
						|
 | 
						|
 | 
						|
def assemble(cnxn, tourneyId):
 | 
						|
    # TODO !!
 | 
						|
    c = cnxn.cursor()
 | 
						|
    
 | 
						|
    # We need at least sitename, gametype, handid
 | 
						|
    # for the Hand.__init__
 | 
						|
    c.execute("""
 | 
						|
select
 | 
						|
    s.name,
 | 
						|
    g.category,
 | 
						|
    g.base,
 | 
						|
    g.type,
 | 
						|
    g.limitType,
 | 
						|
    g.hilo,
 | 
						|
    round(g.smallBlind / 100.0,2),
 | 
						|
    round(g.bigBlind / 100.0,2),
 | 
						|
    round(g.smallBet / 100.0,2),
 | 
						|
    round(g.bigBet / 100.0,2),
 | 
						|
    s.currency,
 | 
						|
    h.boardcard1,
 | 
						|
    h.boardcard2,
 | 
						|
    h.boardcard3,
 | 
						|
    h.boardcard4,
 | 
						|
    h.boardcard5
 | 
						|
from
 | 
						|
    hands as h,
 | 
						|
    sites as s,
 | 
						|
    gametypes as g,
 | 
						|
    handsplayers as hp,
 | 
						|
    players as p
 | 
						|
where
 | 
						|
    h.id = %(handid)s
 | 
						|
and g.id = h.gametypeid
 | 
						|
and hp.handid = h.id
 | 
						|
and p.id = hp.playerid
 | 
						|
and s.id = p.siteid
 | 
						|
limit 1""", {'handid':handid})
 | 
						|
    #TODO: siteid should be in hands table - we took the scenic route through players here.
 | 
						|
    res = c.fetchone()
 | 
						|
    gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]}
 | 
						|
    h = HoldemOmahaHand(hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid)
 | 
						|
    cards = map(Card.valueSuitFromCard, res[11:16] )
 | 
						|
    if cards[0]:
 | 
						|
        h.setCommunityCards('FLOP', cards[0:3])
 | 
						|
    if cards[3]:
 | 
						|
        h.setCommunityCards('TURN', [cards[3]])
 | 
						|
    if cards[4]:      
 | 
						|
        h.setCommunityCards('RIVER', [cards[4]])
 | 
						|
    #[Card.valueSuitFromCard(x) for x in cards]
 | 
						|
    
 | 
						|
    # HandInfo : HID, TABLE
 | 
						|
    # BUTTON - why is this treated specially in Hand?
 | 
						|
    # answer: it is written out in hand histories
 | 
						|
    # still, I think we should record all the active seat positions in a seat_order array
 | 
						|
    c.execute("""
 | 
						|
SELECT
 | 
						|
    h.sitehandno as hid,
 | 
						|
    h.tablename as table,
 | 
						|
    h.handstart as starttime
 | 
						|
FROM
 | 
						|
    hands as h
 | 
						|
WHERE h.id = %(handid)s
 | 
						|
""", {'handid':handid})
 | 
						|
    res = c.fetchone()
 | 
						|
    h.handid = res[0]
 | 
						|
    h.tablename = res[1]
 | 
						|
    h.starttime = res[2] # automatically a datetime
 | 
						|
    
 | 
						|
    # PlayerStacks
 | 
						|
    c.execute("""
 | 
						|
SELECT
 | 
						|
    hp.seatno,
 | 
						|
    round(hp.winnings / 100.0,2) as winnings,
 | 
						|
    p.name,
 | 
						|
    round(hp.startcash / 100.0,2) as chips,
 | 
						|
    hp.card1,hp.card2,
 | 
						|
    hp.position
 | 
						|
FROM
 | 
						|
    handsplayers as hp,
 | 
						|
    players as p
 | 
						|
WHERE
 | 
						|
    hp.handid = %(handid)s
 | 
						|
and p.id = hp.playerid
 | 
						|
""", {'handid':handid})
 | 
						|
    for (seat, winnings, name, chips, card1,card2, position) in c.fetchall():
 | 
						|
        h.addPlayer(seat,name,chips)
 | 
						|
        if card1 and card2:
 | 
						|
            h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)), name, dealt=True)
 | 
						|
        if winnings > 0:
 | 
						|
            h.addCollectPot(name, winnings)
 | 
						|
        if position == 'B':
 | 
						|
            h.buttonpos = seat
 | 
						|
    
 | 
						|
 | 
						|
    # actions
 | 
						|
    c.execute("""
 | 
						|
SELECT
 | 
						|
    (ha.street,ha.actionno) as actnum,
 | 
						|
    p.name,
 | 
						|
    ha.street,
 | 
						|
    ha.action,
 | 
						|
    ha.allin,
 | 
						|
    round(ha.amount / 100.0,2)
 | 
						|
FROM
 | 
						|
    handsplayers as hp,
 | 
						|
    handsactions as ha,
 | 
						|
    players as p
 | 
						|
WHERE
 | 
						|
    hp.handid = %(handid)s
 | 
						|
and ha.handsplayerid = hp.id
 | 
						|
and p.id = hp.playerid
 | 
						|
ORDER BY
 | 
						|
    ha.street,ha.actionno
 | 
						|
""", {'handid':handid})
 | 
						|
    res = c.fetchall()
 | 
						|
    for (actnum,player, streetnum, act, allin, amount) in res:
 | 
						|
        act=act.strip()
 | 
						|
        street = h.allStreets[streetnum+1]
 | 
						|
        if act==u'blind':
 | 
						|
            h.addBlind(player, 'big blind', amount)
 | 
						|
            # TODO: The type of blind is not recorded in the DB.
 | 
						|
            # TODO: preflop street name anomalies in Hand
 | 
						|
        elif act==u'fold':
 | 
						|
            h.addFold(street,player)
 | 
						|
        elif act==u'call':
 | 
						|
            h.addCall(street,player,amount)
 | 
						|
        elif act==u'bet':
 | 
						|
            h.addBet(street,player,amount)
 | 
						|
        elif act==u'check':
 | 
						|
            h.addCheck(street,player)
 | 
						|
        elif act==u'unbet':
 | 
						|
            pass
 | 
						|
        else:
 | 
						|
            print act, player, streetnum, allin, amount
 | 
						|
            # TODO : other actions
 | 
						|
 | 
						|
    #hhc.readShowdownActions(self)
 | 
						|
    #hc.readShownCards(self)
 | 
						|
    h.totalPot()
 | 
						|
    h.rake = h.totalpot - h.totalcollected
 | 
						|
    
 | 
						|
 | 
						|
    return h
 | 
						|
 |