2011-02-26 20:26:46 +01:00
#!/usr/bin/env python
2009-08-28 02:22:08 +02:00
# -*- coding: utf-8 -*-
2008-12-12 15:29:45 +01:00
2011-03-10 06:16:31 +01:00
#Copyright 2008-2011 Carl Gherardi
2008-12-12 15:29:45 +01:00
#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.
2009-08-11 23:13:07 +02:00
#
2008-12-12 15:29:45 +01:00
#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.
2009-08-11 23:13:07 +02:00
#
2008-12-12 15:29:45 +01:00
#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/>.
2010-07-04 03:05:16 +02:00
#In the "official" distribution you can find the license in agpl-3.0.txt.
2008-12-12 15:29:45 +01:00
2010-09-23 08:10:30 +02:00
import L10n
_ = L10n . get_translation ( )
2009-07-13 06:37:51 +02:00
# TODO: get writehand() encoding correct
2008-12-12 15:29:45 +01:00
import re
import sys
import traceback
import os
import os . path
2011-02-25 20:18:12 +01:00
from decimal_wrapper import Decimal
2008-12-12 15:29:45 +01:00
import operator
2009-06-07 22:57:13 +02:00
import time , datetime
2008-12-16 05:29:11 +01:00
from copy import deepcopy
2009-07-04 00:59:50 +02:00
import pprint
2010-01-31 12:25:24 +01:00
2010-02-01 23:31:00 +01:00
import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging . getLogger ( " parser " )
2010-01-31 12:25:24 +01:00
import Configuration
from Exceptions import *
2009-03-14 12:40:27 +01:00
import DerivedStats
2009-06-07 22:57:13 +02:00
import Card
2009-08-09 16:19:43 +02:00
2009-07-15 17:50:27 +02:00
class Hand ( object ) :
2009-07-13 22:22:23 +02:00
###############################################################3
# Class Variables
2008-12-17 01:30:31 +01:00
UPS = { ' a ' : ' A ' , ' t ' : ' T ' , ' j ' : ' J ' , ' q ' : ' Q ' , ' k ' : ' K ' , ' S ' : ' s ' , ' C ' : ' c ' , ' H ' : ' h ' , ' D ' : ' d ' }
2009-03-13 18:51:10 +01:00
LCS = { ' H ' : ' h ' , ' D ' : ' d ' , ' C ' : ' c ' , ' S ' : ' s ' }
2011-03-21 04:15:19 +01:00
SYMBOL = { ' USD ' : ' $ ' , ' CAD ' : ' $ ' , ' EUR ' : u ' $ ' , ' GBP ' : ' $ ' , ' T$ ' : ' ' , ' play ' : ' ' }
2009-07-22 16:24:29 +02:00
MS = { ' horse ' : ' HORSE ' , ' 8game ' : ' 8-Game ' , ' hose ' : ' HOSE ' , ' ha ' : ' HA ' }
2010-09-28 22:50:33 +02:00
ACTION = { ' ante ' : 1 , ' small blind ' : 2 , ' secondsb ' : 3 , ' big blind ' : 4 , ' both ' : 5 , ' calls ' : 6 , ' raises ' : 7 ,
' bets ' : 8 , ' stands pat ' : 9 , ' folds ' : 10 , ' checks ' : 11 , ' discards ' : 12 , ' bringin ' : 13 , ' completes ' : 14 }
2009-07-13 22:22:23 +02:00
2010-01-31 12:25:24 +01:00
def __init__ ( self , config , sitename , gametype , handText , builtFrom = " HHC " ) :
2010-08-29 00:57:04 +02:00
#log.debug( _("Hand.init(): handText is ") + str(handText) )
2010-01-31 12:25:24 +01:00
self . config = config
2010-09-28 23:17:15 +02:00
self . saveActions = self . config . get_import_parameters ( ) . get ( ' saveActions ' )
2011-03-22 20:16:22 +01:00
self . callHud = self . config . get_import_parameters ( ) . get ( " callFpdbHud " )
2011-01-01 09:35:14 +01:00
self . cacheSessions = self . config . get_import_parameters ( ) . get ( " cacheSessions " )
2010-02-01 23:31:00 +01:00
#log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log)
2008-12-12 15:29:45 +01:00
self . sitename = sitename
2010-08-31 23:44:41 +02:00
self . siteId = self . config . get_site_id ( sitename )
2009-03-14 12:40:27 +01:00
self . stats = DerivedStats . DerivedStats ( self )
2008-12-12 15:29:45 +01:00
self . gametype = gametype
2010-07-05 11:48:26 +02:00
self . startTime = 0
2009-03-04 16:10:08 +01:00
self . handText = handText
2008-12-12 15:29:45 +01:00
self . handid = 0
2009-12-17 08:53:12 +01:00
self . cancelled = False
2009-12-06 16:02:07 +01:00
self . dbid_hands = 0
2009-12-13 06:48:17 +01:00
self . dbid_pids = None
2010-09-28 23:09:24 +02:00
self . dbid_hpid = None
2009-12-13 06:48:17 +01:00
self . dbid_gt = 0
2009-06-19 08:21:35 +02:00
self . tablename = " "
self . hero = " "
2009-07-20 16:01:51 +02:00
self . maxseats = None
2008-12-12 15:29:45 +01:00
self . counted_seats = 0
self . buttonpos = 0
2011-04-04 06:50:01 +02:00
self . runItTimes = 0
2010-09-28 06:04:40 +02:00
2010-07-05 11:48:26 +02:00
#tourney stuff
2009-07-11 19:44:32 +02:00
self . tourNo = None
2010-07-07 04:01:40 +02:00
self . tourneyId = None
self . tourneyTypeId = None
2009-07-11 19:44:32 +02:00
self . buyin = None
2010-07-05 11:48:26 +02:00
self . buyinCurrency = None
2010-07-07 04:01:40 +02:00
self . buyInChips = None
2009-07-31 03:50:08 +02:00
self . fee = None # the Database code is looking for this one .. ?
2009-07-11 19:44:32 +02:00
self . level = None
2009-07-13 22:22:23 +02:00
self . mixed = None
2010-08-11 03:10:08 +02:00
self . speed = " Normal "
self . isRebuy = False
self . isAddOn = False
self . isKO = False
2010-08-02 13:53:50 +02:00
self . koBounty = None
2010-08-11 03:10:08 +02:00
self . isMatrix = False
self . isShootout = False
2010-07-17 02:19:12 +02:00
self . added = None
self . addedCurrency = None
2009-08-26 01:13:34 +02:00
self . tourneyComment = None
2008-12-12 15:29:45 +01:00
self . seating = [ ]
self . players = [ ]
self . posted = [ ]
2011-03-30 05:18:36 +02:00
self . tourneysPlayersIds = { }
2010-09-28 06:04:40 +02:00
2008-12-12 15:29:45 +01:00
# Collections indexed by street names
2009-03-02 00:22:47 +01:00
self . bets = { }
self . lastBet = { }
self . streets = { }
self . actions = { } # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']]
2009-03-03 19:45:02 +01:00
self . board = { } # dict from street names to community cards
2009-06-19 08:21:35 +02:00
self . holecards = { }
2009-07-11 19:44:32 +02:00
self . discards = { }
2011-04-04 21:57:54 +02:00
self . showdownStrings = { }
2009-06-19 08:21:35 +02:00
for street in self . allStreets :
2009-03-02 00:22:47 +01:00
self . streets [ street ] = " " # portions of the handText, filled by markStreets()
2009-07-11 19:44:32 +02:00
self . actions [ street ] = [ ]
for street in self . actionStreets :
2009-03-02 00:22:47 +01:00
self . bets [ street ] = { }
self . lastBet [ street ] = 0
2009-03-03 19:45:02 +01:00
self . board [ street ] = [ ]
2009-07-11 19:44:32 +02:00
for street in self . holeStreets :
2009-06-19 08:21:35 +02:00
self . holecards [ street ] = { } # dict from player names to holecards
2009-07-11 19:44:32 +02:00
self . discards [ street ] = { } # dict from player names to dicts by street ... of tuples ... of discarded holecards
2008-12-12 15:29:45 +01:00
# Collections indexed by player names
2008-12-16 05:29:11 +01:00
self . stacks = { }
2009-03-07 16:43:33 +01:00
self . collected = [ ] #list of ?
2009-03-02 00:22:47 +01:00
self . collectees = { } # dict from player names to amounts collected (?)
2008-12-12 15:29:45 +01:00
# Sets of players
self . folded = set ( )
2009-06-19 08:21:35 +02:00
self . dealt = set ( ) # 'dealt to' line to be printed
self . shown = set ( ) # cards were shown
2009-07-04 00:59:50 +02:00
self . mucked = set ( ) # cards were mucked at showdown
2008-12-12 15:29:45 +01:00
2009-03-02 22:48:30 +01:00
# Things to do with money
self . pot = Pot ( )
2008-12-12 15:29:45 +01:00
self . totalpot = None
2008-12-14 20:25:04 +01:00
self . totalcollected = None
2008-12-12 15:29:45 +01:00
self . rake = None
2009-07-16 18:13:24 +02:00
# currency symbol for this hand
self . sym = self . SYMBOL [ self . gametype [ ' currency ' ] ] # save typing! delete this attr when done
self . pot . setSym ( self . sym )
2010-02-20 18:49:03 +01:00
self . is_duplicate = False # i.e. don't update hudcache if true
2008-12-12 15:29:45 +01:00
2009-06-12 18:29:17 +02:00
def __str__ ( self ) :
2010-08-15 05:59:05 +02:00
vars = ( ( _ ( " BB " ) , self . bb ) ,
( _ ( " SB " ) , self . sb ) ,
( _ ( " BUTTONPOS " ) , self . buttonpos ) ,
( _ ( " HAND NO. " ) , self . handid ) ,
( _ ( " SITE " ) , self . sitename ) ,
( _ ( " TABLE NAME " ) , self . tablename ) ,
( _ ( " HERO " ) , self . hero ) ,
( _ ( " MAXSEATS " ) , self . maxseats ) ,
( _ ( " LEVEL " ) , self . level ) ,
( _ ( " MIXED " ) , self . mixed ) ,
( _ ( " LASTBET " ) , self . lastBet ) ,
( _ ( " ACTION STREETS " ) , self . actionStreets ) ,
( _ ( " STREETS " ) , self . streets ) ,
( _ ( " ALL STREETS " ) , self . allStreets ) ,
( _ ( " COMMUNITY STREETS " ) , self . communityStreets ) ,
( _ ( " HOLE STREETS " ) , self . holeStreets ) ,
( _ ( " COUNTED SEATS " ) , self . counted_seats ) ,
( _ ( " DEALT " ) , self . dealt ) ,
( _ ( " SHOWN " ) , self . shown ) ,
( _ ( " MUCKED " ) , self . mucked ) ,
( _ ( " TOTAL POT " ) , self . totalpot ) ,
( _ ( " TOTAL COLLECTED " ) , self . totalcollected ) ,
( _ ( " RAKE " ) , self . rake ) ,
( _ ( " START TIME " ) , self . startTime ) ,
( _ ( " TOURNAMENT NO " ) , self . tourNo ) ,
( _ ( " TOURNEY ID " ) , self . tourneyId ) ,
( _ ( " TOURNEY TYPE ID " ) , self . tourneyTypeId ) ,
( _ ( " BUYIN " ) , self . buyin ) ,
( _ ( " BUYIN CURRENCY " ) , self . buyinCurrency ) ,
( _ ( " BUYIN CHIPS " ) , self . buyInChips ) ,
( _ ( " FEE " ) , self . fee ) ,
( _ ( " IS REBUY " ) , self . isRebuy ) ,
( _ ( " IS ADDON " ) , self . isAddOn ) ,
( _ ( " IS KO " ) , self . isKO ) ,
( _ ( " KO BOUNTY " ) , self . koBounty ) ,
( _ ( " IS MATRIX " ) , self . isMatrix ) ,
( _ ( " IS SHOOTOUT " ) , self . isShootout ) ,
( _ ( " TOURNEY COMMENT " ) , self . tourneyComment ) ,
2009-07-04 00:59:50 +02:00
)
2009-08-11 23:13:07 +02:00
2010-08-15 05:59:05 +02:00
structs = ( ( _ ( " PLAYERS " ) , self . players ) ,
( _ ( " STACKS " ) , self . stacks ) ,
( _ ( " POSTED " ) , self . posted ) ,
( _ ( " POT " ) , self . pot ) ,
( _ ( " SEATING " ) , self . seating ) ,
( _ ( " GAMETYPE " ) , self . gametype ) ,
( _ ( " ACTION " ) , self . actions ) ,
( _ ( " COLLECTEES " ) , self . collectees ) ,
( _ ( " BETS " ) , self . bets ) ,
( _ ( " BOARD " ) , self . board ) ,
( _ ( " DISCARDS " ) , self . discards ) ,
( _ ( " HOLECARDS " ) , self . holecards ) ,
( _ ( " TOURNEYS PLAYER IDS " ) , self . tourneysPlayersIds ) ,
2009-07-04 00:59:50 +02:00
)
2009-06-12 18:29:17 +02:00
str = ' '
2009-07-04 00:59:50 +02:00
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 )
2009-06-12 18:29:17 +02:00
return str
2008-12-12 15:29:45 +01:00
2009-07-12 22:01:02 +02:00
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
"""
2009-08-09 16:19:43 +02:00
# log.debug("addHoleCards %s %s" % (open + closed, player))
2009-07-12 22:01:02 +02:00
try :
self . checkPlayerExists ( player )
except FpdbParseError , e :
2010-08-15 05:59:05 +02:00
print _ ( " [ERROR] Tried to add holecards for unknown player: %s " ) % ( player , )
2009-07-12 22:01:02 +02:00
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 ]
2011-03-29 08:58:44 +02:00
def prepInsert ( self , db , printtest = False ) :
2010-01-23 08:20:17 +01:00
#####
2009-10-06 12:30:52 +02:00
# Players, Gametypes, TourneyTypes are all shared functions that are needed for additional tables
# These functions are intended for prep insert eventually
#####
2009-12-13 06:48:17 +01:00
self . dbid_pids = db . getSqlPlayerIDs ( [ p [ 1 ] for p in self . players ] , self . siteId )
2011-03-29 08:58:44 +02:00
self . dbid_gt = db . getGameTypeId ( self . siteId , self . gametype , printdata = printtest )
#Gametypes
hilo = " h "
if self . gametype [ ' category ' ] in [ ' studhilo ' , ' omahahilo ' ] :
hilo = " s "
elif self . gametype [ ' category ' ] in [ ' razz ' , ' 27_3draw ' , ' badugi ' , ' 27_1draw ' ] :
hilo = " l "
self . gametyperow = ( self . siteId , self . gametype [ ' currency ' ] , self . gametype [ ' type ' ] , self . gametype [ ' base ' ] ,
self . gametype [ ' category ' ] , self . gametype [ ' limitType ' ] , hilo ,
int ( Decimal ( self . gametype [ ' sb ' ] ) * 100 ) , int ( Decimal ( self . gametype [ ' bb ' ] ) * 100 ) ,
int ( Decimal ( self . gametype [ ' bb ' ] ) * 100 ) , int ( Decimal ( self . gametype [ ' bb ' ] ) * 200 ) )
# Note: the above data is calculated in db.getGameTypeId
# Only being calculated above so we can grab the testdata
self . dbid_gt = db . getGameTypeId ( self . siteId , self . gametype , printdata = printtest )
2011-03-22 20:16:22 +01:00
2010-07-07 00:52:44 +02:00
if self . tourNo != None :
2010-07-14 21:07:19 +02:00
self . tourneyTypeId = db . createTourneyType ( self )
2010-07-08 23:46:54 +02:00
self . tourneyId = db . createOrUpdateTourney ( self , " HHC " )
self . tourneysPlayersIds = db . createOrUpdateTourneysPlayers ( self , " HHC " )
2011-03-22 20:16:22 +01:00
#db.commit() #commit these transactions'
def assembleHand ( self ) :
2009-10-14 14:28:07 +02:00
self . stats . getStats ( self )
2011-03-22 20:16:22 +01:00
self . hands = self . stats . getHands ( )
self . handsplayers = self . stats . getHandsPlayers ( )
2011-01-01 21:40:06 +01:00
2011-03-22 20:16:22 +01:00
def getHandId ( self , db , id ) :
if db . isDuplicate ( self . dbid_gt , self . hands [ ' siteHandNo ' ] ) :
#log.info(_("Hand.insert(): hid #: %s is a duplicate") % hh['siteHandNo'])
self . is_duplicate = True # i.e. don't update hudcache
next = id
raise FpdbHandDuplicate ( self . hands [ ' siteHandNo ' ] )
else :
self . dbid_hands = id
self . hands [ ' id ' ] = self . dbid_hands
next = id + 1
return next
2009-03-14 13:19:20 +01:00
2011-04-03 01:56:52 +02:00
def insertHands ( self , db , hbulk , fileId , doinsert = False , printtest = False ) :
2011-03-22 20:16:22 +01:00
""" Function to insert Hand into database
Should not commit , and do minimal selects . Callers may want to cache commits
db : a connected Database object """
2011-03-30 05:49:13 +02:00
self . hands [ ' gametypeId ' ] = self . dbid_gt
2011-03-22 20:16:22 +01:00
self . hands [ ' seats ' ] = len ( self . dbid_pids )
2011-04-03 01:56:52 +02:00
self . hands [ ' fileId ' ] = fileId
2011-03-23 05:59:44 +01:00
hbulk = db . storeHand ( self . hands , hbulk , doinsert , printtest )
2011-03-22 20:16:22 +01:00
return hbulk
2011-03-23 05:59:44 +01:00
def insertHandsPlayers ( self , db , hpbulk , doinsert = False , printtest = False ) :
2011-03-22 20:16:22 +01:00
""" Function to inserts HandsPlayers into database """
2011-03-23 05:59:44 +01:00
hpbulk = db . storeHandsPlayers ( self . dbid_hands , self . dbid_pids , self . handsplayers , hpbulk , doinsert , printtest )
2011-03-22 20:16:22 +01:00
return hpbulk
2011-03-23 05:59:44 +01:00
def insertHandsActions ( self , db , habulk , doinsert = False , printtest = False ) :
2011-03-22 20:16:22 +01:00
""" Function to inserts HandsActions into database """
handsactions = self . stats . getHandsActions ( )
2011-03-23 05:59:44 +01:00
habulk = db . storeHandsActions ( self . dbid_hands , self . dbid_pids , handsactions , habulk , doinsert , printtest )
2011-03-22 20:16:22 +01:00
return habulk
def updateHudCache ( self , db , hcbulk , doinsert = False ) :
""" Function to update the HudCache """
if self . callHud :
hcbulk = db . storeHudCache ( self . dbid_gt , self . dbid_pids , self . startTime , self . handsplayers , hcbulk , doinsert )
return hcbulk
2010-12-02 07:58:02 +01:00
2011-03-22 20:16:22 +01:00
def updateSessionsCache ( self , db , sc , gsc , tz , doinsert = False ) :
""" Function to update the SessionsCache """
if self . cacheSessions :
self . heros = db . getHeroIds ( self . dbid_pids , self . sitename )
sc = db . prepSessionsCache ( self . dbid_hands , self . dbid_pids , self . startTime , sc , self . heros , doinsert )
gsc = db . storeSessionsCache ( self . dbid_hands , self . dbid_pids , self . startTime , self . gametype
, self . dbid_gt , self . handsplayers , sc , gsc , tz , self . heros , doinsert )
2011-03-29 16:18:00 +02:00
if doinsert and sc [ ' bk ' ] and gsc [ ' bk ' ] :
self . hands [ ' sc ' ] = sc
self . hands [ ' gsc ' ] = gsc
2011-03-22 20:16:22 +01:00
else :
self . hands [ ' sc ' ] = None
self . hands [ ' gsc ' ] = None
return sc , gsc
2009-12-23 16:14:34 +01:00
2010-12-17 12:03:50 +01:00
def select ( self , db , handId ) :
2009-03-14 13:19:20 +01:00
""" Function to create Hand object from database """
2010-12-17 12:03:50 +01:00
c = db . get_cursor ( )
q = """ SELECT
2010-10-09 09:27:58 +02:00
hp . seatno ,
round ( hp . winnings / 100.0 , 2 ) as winnings ,
p . name ,
2010-12-22 05:13:58 +01:00
round ( hp . startCash / 100.0 , 2 ) as chips ,
hp . card1 , hp . card2 , hp . card3 , hp . card4 ,
2010-10-09 09:27:58 +02:00
hp . position
FROM
2010-12-17 12:03:50 +01:00
HandsPlayers as hp ,
Players as p
2010-10-09 09:27:58 +02:00
WHERE
2010-12-17 12:03:50 +01:00
hp . handId = % s
2010-12-22 05:13:58 +01:00
and p . id = hp . playerId
2010-12-22 06:04:20 +01:00
ORDER BY
hp . seatno
2010-12-17 12:03:50 +01:00
"""
q = q . replace ( ' %s ' , db . sql . query [ ' placeholder ' ] )
# PlayerStacks
c . execute ( q , ( handId , ) )
2010-12-22 05:13:58 +01:00
for ( seat , winnings , name , chips , card1 , card2 , card3 , card4 , position ) in c . fetchall ( ) :
2010-12-22 06:04:20 +01:00
#print "DEBUG: addPlayer(%s, %s, %s)" %(seat,name,str(chips))
2010-12-17 12:03:50 +01:00
self . addPlayer ( seat , name , str ( chips ) )
2010-12-22 06:04:20 +01:00
#print "DEBUG: card1: %s" % card1
2010-12-22 06:20:43 +01:00
# map() should work, but is returning integers... FIXME later
#cardlist = map(Card.valueSuitFromCard, [card1, card2, card3, card4])
cardlist = [ Card . valueSuitFromCard ( card1 ) , Card . valueSuitFromCard ( card2 ) , Card . valueSuitFromCard ( card3 ) , Card . valueSuitFromCard ( card4 ) ]
2010-12-22 06:04:20 +01:00
#print "DEUBG: cardlist: '%s'" % cardlist
2010-12-22 06:20:43 +01:00
if cardlist [ 0 ] == ' ' :
pass
elif self . gametype [ ' category ' ] == ' holdem ' :
self . addHoleCards ( ' PREFLOP ' , name , closed = cardlist [ 0 : 2 ] , shown = False , mucked = False , dealt = True )
elif self . gametype [ ' category ' ] == ' omaha ' :
self . addHoleCards ( ' PREFLOP ' , name , closed = cardlist , shown = False , mucked = False , dealt = True )
2010-12-22 05:13:58 +01:00
if winnings > 0 :
self . addCollectPot ( name , str ( winnings ) )
if position == ' B ' :
self . buttonpos = seat
# HandInfo
q = """ SELECT *
FROM Hands
WHERE id = % s
"""
q = q . replace ( ' %s ' , db . sql . query [ ' placeholder ' ] )
c . execute ( q , ( handId , ) )
# NOTE: This relies on row_factory = sqlite3.Row (set in connect() params)
# Need to find MySQL and Postgres equivalents
# MySQL maybe: cursorclass=MySQLdb.cursors.DictCursor
2011-03-01 09:13:58 +01:00
#res = c.fetchone()
# Using row_factory is global, and affects the rest of fpdb. The following 2 line achieves
# a similar result
res = [ dict ( line ) for line in [ zip ( [ column [ 0 ] for column in c . description ] , row ) for row in c . fetchall ( ) ] ]
res = res [ 0 ]
2011-01-25 06:10:50 +01:00
#res['tourneyId'] #res['seats'] #res['rush']
2010-12-22 05:13:58 +01:00
self . tablename = res [ ' tableName ' ]
2010-12-22 06:04:20 +01:00
self . handid = res [ ' siteHandNo ' ]
2011-03-01 09:13:58 +01:00
#print "DBEUG: res['startTime']: %s" % res['startTime']
2010-12-22 06:04:20 +01:00
self . startTime = datetime . datetime . strptime ( res [ ' startTime ' ] , " % Y- % m- %d % H: % M: % S+00:00 " )
2010-12-22 05:13:58 +01:00
self . maxseats = res [ ' maxSeats ' ]
2011-01-25 06:10:50 +01:00
2010-12-22 05:13:58 +01:00
cards = map ( Card . valueSuitFromCard , [ res [ ' boardcard1 ' ] , res [ ' boardcard2 ' ] , res [ ' boardcard3 ' ] , res [ ' boardcard4 ' ] , res [ ' boardcard5 ' ] ] )
2010-12-22 06:04:20 +01:00
#print "DEBUG: res['boardcard1']: %s" % res['boardcard1']
#print "DEBUG: cards: %s" % cards
2010-12-22 05:13:58 +01:00
if cards [ 0 ] :
self . setCommunityCards ( ' FLOP ' , cards [ 0 : 3 ] )
if cards [ 3 ] :
self . setCommunityCards ( ' TURN ' , [ cards [ 3 ] ] )
if cards [ 4 ] :
self . setCommunityCards ( ' RIVER ' , [ cards [ 4 ] ] )
# playersVpi | playersAtStreet1 | playersAtStreet2 | playersAtStreet3 |
# playersAtStreet4 | playersAtShowdown | street0Raises | street1Raises |
# street2Raises | street3Raises | street4Raises | street1Pot | street2Pot |
# street3Pot | street4Pot | showdownPot | comment | commentTs | texture
# Actions
q = """ SELECT
ha . actionNo ,
p . name ,
ha . street ,
ha . actionId ,
ha . allIn ,
round ( ha . amount / 100.0 , 2 ) as bet
FROM
HandsActions as ha ,
HandsPlayers as hp ,
Players as p ,
Hands as h
WHERE
2011-03-01 09:13:58 +01:00
h . id = % s
AND ha . handId = h . id
AND ha . playerId = hp . playerid
AND hp . playerId = p . id
2010-12-22 05:13:58 +01:00
AND h . id = hp . handId
ORDER BY
ha . id ASC
2011-03-01 09:13:58 +01:00
"""
2010-12-22 05:13:58 +01:00
q = q . replace ( ' %s ' , db . sql . query [ ' placeholder ' ] )
c . execute ( q , ( handId , ) )
2011-03-01 09:13:58 +01:00
res = [ dict ( line ) for line in [ zip ( [ column [ 0 ] for column in c . description ] , row ) for row in c . fetchall ( ) ] ]
for row in res :
2010-12-22 05:13:58 +01:00
name = row [ ' name ' ]
street = row [ ' street ' ]
act = row [ ' actionId ' ]
# allin True/False if row['allIn'] == 0
bet = row [ ' bet ' ]
street = self . allStreets [ int ( street ) + 1 ]
2010-12-22 06:04:20 +01:00
#print "DEBUG: name: '%s' street: '%s' act: '%s' bet: '%s'" %(name, street, act, bet)
2010-12-22 05:13:58 +01:00
if act == 2 : # Small Blind
self . addBlind ( name , ' small blind ' , str ( bet ) )
elif act == 4 : # Big Blind
self . addBlind ( name , ' big blind ' , str ( bet ) )
elif act == 6 : # Call
self . addCall ( street , name , str ( bet ) )
elif act == 8 : # Bet
self . addBet ( street , name , str ( bet ) )
elif act == 10 : # Fold
self . addFold ( street , name )
elif act == 11 : # Check
self . addCheck ( street , name )
2011-03-01 09:13:58 +01:00
elif act == 7 : # Raise
self . addRaiseBy ( street , name , str ( bet ) )
2010-12-22 05:13:58 +01:00
else :
print " DEBUG: unknown action: ' %s ' " % act
2009-08-11 23:13:07 +02:00
2010-12-22 06:26:41 +01:00
self . totalPot ( )
self . rake = self . totalpot - self . totalcollected
2010-12-22 06:08:41 +01:00
self . writeHand ( )
2010-12-22 06:04:20 +01:00
2010-10-09 09:27:58 +02:00
#hhc.readShowdownActions(self)
#hc.readShownCards(self)
2009-08-11 23:13:07 +02:00
2009-03-14 13:19:20 +01:00
2008-12-12 15:29:45 +01:00
def addPlayer ( self , seat , name , chips ) :
""" \
Adds a player to the hand , and initialises data structures indexed by player .
seat ( int ) indicating the seat
name ( string ) player name
chips ( string ) the chips the player has at the start of the hand ( can be None )
If a player has None chips he won ' t be added. " " "
2009-08-09 16:19:43 +02:00
log . debug ( " addPlayer: %s %s ( %s ) " % ( seat , name , chips ) )
2008-12-12 15:29:45 +01:00
if chips is not None :
2011-02-24 15:49:50 +01:00
chips = chips . replace ( u ' , ' , u ' ' ) #some sites have commas
2008-12-12 15:29:45 +01:00
self . players . append ( [ seat , name , chips ] )
2008-12-16 05:29:11 +01:00
self . stacks [ name ] = Decimal ( chips )
2008-12-20 17:48:25 +01:00
self . pot . addPlayer ( name )
2009-07-11 19:44:32 +02:00
for street in self . actionStreets :
2008-12-12 15:29:45 +01:00
self . bets [ street ] [ name ] = [ ]
2009-06-19 08:21:35 +02:00
#self.holecards[name] = {} # dict from street names.
2009-07-11 19:44:32 +02:00
#self.discards[name] = {} # dict from street names.
2008-12-12 15:29:45 +01:00
2008-12-14 23:05:51 +01:00
def addStreets ( self , match ) :
# go through m and initialise actions to empty list for each street.
2009-03-04 17:46:01 +01:00
if match :
2009-03-02 00:22:47 +01:00
self . streets . update ( match . groupdict ( ) )
2009-08-09 16:19:43 +02:00
log . debug ( " markStreets: \n " + str ( self . streets ) )
2008-12-14 23:05:51 +01:00
else :
2010-06-04 09:59:47 +02:00
tmp = self . handText [ 0 : 100 ]
2010-08-29 00:57:04 +02:00
log . error ( _ ( " markstreets didn ' t match - Assuming hand %s was cancelled " ) % self . handid )
2009-12-17 08:53:12 +01:00
self . cancelled = True
2011-03-10 05:14:16 +01:00
raise FpdbParseError ( _ ( " markStreets appeared to fail: First 100 chars: ' %s ' " ) % tmp )
2008-12-14 23:05:51 +01:00
2008-12-12 15:29:45 +01:00
def checkPlayerExists ( self , player ) :
if player not in [ p [ 1 ] for p in self . players ] :
2011-03-10 05:14:16 +01:00
print ( _ ( " DEBUG: " ) + _ ( " checkPlayerExists: %s fail on hand number %s " ) % ( player , self . handid ) )
raise FpdbParseError ( _ ( " checkPlayerExists: %s fail on hand number %s " ) % ( player , self . handid ) )
2008-12-12 15:29:45 +01:00
def setCommunityCards ( self , street , cards ) :
2009-08-09 16:19:43 +02:00
log . debug ( " setCommunityCards %s %s " % ( street , cards ) )
2008-12-12 15:29:45 +01:00
self . board [ street ] = [ self . card ( c ) for c in cards ]
2009-07-16 03:22:07 +02:00
# print "DEBUG: self.board: %s" % self.board
2008-12-12 15:29:45 +01:00
def card ( self , c ) :
""" upper case the ranks but not suits, ' atjqk ' => ' ATJQK ' """
for k , v in self . UPS . items ( ) :
c = c . replace ( k , v )
return c
2010-01-28 08:13:49 +01:00
def addAllIn ( self , street , player , amount ) :
""" \
For sites ( currently only Carbon Poker ) which record " all in " as a special action , which can mean either " calls and is all in " or " raises all in " .
"""
self . checkPlayerExists ( player )
2011-02-24 15:49:50 +01:00
amount = amount . replace ( u ' , ' , u ' ' ) #some sites have commas
2010-01-28 08:13:49 +01:00
Ai = Decimal ( amount )
Bp = self . lastBet [ street ]
2011-02-25 06:05:39 +01:00
Bc = sum ( self . bets [ street ] [ player ] )
2010-01-28 08:13:49 +01:00
C = Bp - Bc
if Ai < = C :
self . addCall ( street , player , amount )
elif Bp == 0 :
self . addBet ( street , player , amount )
else :
Rb = Ai - C
self . _addRaise ( street , player , C , Rb , Ai )
2009-02-25 16:45:46 +01:00
def addAnte ( self , player , ante ) :
2009-08-11 23:19:01 +02:00
log . debug ( " %s %s antes %s " % ( ' BLINDSANTES ' , player , ante ) )
2009-02-25 16:45:46 +01:00
if player is not None :
2011-02-24 15:49:50 +01:00
ante = ante . replace ( u ' , ' , u ' ' ) #some sites have commas
2011-02-24 15:51:40 +01:00
ante = Decimal ( ante )
self . bets [ ' BLINDSANTES ' ] [ player ] . append ( ante )
self . stacks [ player ] - = ante
act = ( player , ' ante ' , ante , self . stacks [ player ] == 0 )
2009-08-11 23:19:01 +02:00
self . actions [ ' BLINDSANTES ' ] . append ( act )
2011-02-24 15:51:40 +01:00
# self.pot.addMoney(player, ante)
self . pot . addCommonMoney ( player , ante )
2010-02-18 16:17:08 +01:00
#I think the antes should be common money, don't have enough hand history to check
2010-09-28 06:04:40 +02:00
2008-12-14 23:05:51 +01:00
def addBlind ( self , player , blindtype , amount ) :
2008-12-12 15:29:45 +01:00
# if player is None, it's a missing small blind.
2008-12-20 17:48:25 +01:00
# 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
2009-03-02 00:22:47 +01:00
# - this is a call of 1 sb and a raise to 1 bb
2009-03-14 11:48:34 +01:00
#
2009-08-09 16:19:43 +02:00
log . debug ( " addBlind: %s posts %s , %s " % ( player , blindtype , amount ) )
2008-12-12 15:29:45 +01:00
if player is not None :
2011-02-24 15:49:50 +01:00
amount = amount . replace ( u ' , ' , u ' ' ) #some sites have commas
2011-02-24 15:51:40 +01:00
amount = Decimal ( amount )
self . stacks [ player ] - = amount
act = ( player , blindtype , amount , self . stacks [ player ] == 0 )
2009-03-02 00:22:47 +01:00
self . actions [ ' BLINDSANTES ' ] . append ( act )
2009-08-11 23:19:01 +02:00
if blindtype == ' both ' :
2010-06-21 15:41:45 +02:00
# work with the real amount. limit games are listed as $1, $2, where
2010-02-18 16:17:08 +01:00
# the SB 0.50 and the BB is $1, after the turn the minimum bet amount is $2....
2011-02-24 15:51:40 +01:00
amount = Decimal ( self . bb )
sb = Decimal ( self . sb )
self . bets [ ' BLINDSANTES ' ] [ player ] . append ( sb )
self . pot . addCommonMoney ( player , sb )
2009-08-11 23:19:01 +02:00
2010-02-17 12:57:26 +01:00
if blindtype == ' secondsb ' :
amount = Decimal ( 0 )
2011-02-24 15:51:40 +01:00
sb = Decimal ( self . sb )
self . bets [ ' BLINDSANTES ' ] [ player ] . append ( sb )
self . pot . addCommonMoney ( player , sb )
2010-02-17 12:57:26 +01:00
2011-01-14 07:18:14 +01:00
street = ' BLAH '
if self . gametype [ ' base ' ] == ' hold ' :
street = ' PREFLOP '
elif self . gametype [ ' base ' ] == ' draw ' :
street = ' DEAL '
2011-02-24 15:51:40 +01:00
self . bets [ street ] [ player ] . append ( amount )
self . pot . addMoney ( player , amount )
self . lastBet [ street ] = amount
2009-03-14 13:44:14 +01:00
self . posted = self . posted + [ [ player , blindtype ] ]
2008-12-12 15:29:45 +01:00
2009-02-25 17:23:46 +01:00
2008-12-12 15:29:45 +01:00
def addCall ( self , street , player = None , amount = None ) :
2009-07-19 03:31:39 +02:00
if amount :
2011-02-24 15:49:50 +01:00
amount = amount . replace ( u ' , ' , u ' ' ) #some sites have commas
2010-08-15 05:59:05 +02:00
log . debug ( _ ( " %s %s calls %s " ) % ( street , player , amount ) )
2008-12-12 15:29:45 +01:00
# Potentially calculate the amount of the call if not supplied
# corner cases include if player would be all in
if amount is not None :
2011-02-24 15:51:40 +01:00
amount = Decimal ( amount )
self . bets [ street ] [ player ] . append ( amount )
#self.lastBet[street] = amount
self . stacks [ player ] - = amount
2009-02-22 06:37:38 +01:00
#print "DEBUG %s calls %s, stack %s" % (player, amount, self.stacks[player])
2011-02-24 15:51:40 +01:00
act = ( player , ' calls ' , amount , self . stacks [ player ] == 0 )
2008-12-20 17:48:25 +01:00
self . actions [ street ] . append ( act )
2011-02-24 15:51:40 +01:00
self . pot . addMoney ( player , amount )
2009-08-11 23:13:07 +02:00
2008-12-17 12:54:26 +01:00
def addRaiseBy ( self , street , player , amountBy ) :
2008-12-12 15:29:45 +01:00
""" \
2009-08-11 23:13:07 +02:00
Add a raise by amountBy on [ street ] by [ player ]
2008-12-12 15:29:45 +01:00
"""
2008-12-17 12:54:26 +01:00
#Given only the amount raised by, the amount of the raise can be calculated by
2009-08-11 23:13:07 +02:00
# working out how much this player has already in the pot
2008-12-12 15:29:45 +01:00
# (which is the sum of self.bets[street][player])
2009-08-11 23:13:07 +02:00
# and how much he needs to call to match the previous player
2008-12-12 15:29:45 +01:00
# (which is tracked by self.lastBet)
2009-08-11 23:13:07 +02:00
# let Bp = previous bet
2008-12-17 12:54:26 +01:00
# Bc = amount player has committed so far
# Rb = raise by
# then: C = Bp - Bc (amount to call)
# Rt = Bp + Rb (raise to)
2009-08-11 23:13:07 +02:00
#
2011-02-24 15:49:50 +01:00
amountBy = amountBy . replace ( u ' , ' , u ' ' ) #some sites have commas
2008-12-17 12:54:26 +01:00
self . checkPlayerExists ( player )
Rb = Decimal ( amountBy )
Bp = self . lastBet [ street ]
2011-02-25 06:05:39 +01:00
Bc = sum ( self . bets [ street ] [ player ] )
2008-12-17 12:54:26 +01:00
C = Bp - Bc
Rt = Bp + Rb
2009-08-11 23:13:07 +02:00
2009-03-11 19:40:17 +01:00
self . _addRaise ( street , player , C , Rb , Rt )
#~ self.bets[street][player].append(C + Rb)
#~ self.stacks[player] -= (C + Rb)
#~ self.actions[street] += [(player, 'raises', Rb, Rt, C, self.stacks[player]==0)]
#~ self.lastBet[street] = Rt
2008-12-17 12:54:26 +01:00
def addCallandRaise ( self , street , player , amount ) :
""" \
For sites which by " raises x " mean " calls and raises putting a total of x in the por " . """
self . checkPlayerExists ( player )
2011-02-24 15:49:50 +01:00
amount = amount . replace ( u ' , ' , u ' ' ) #some sites have commas
2008-12-17 12:54:26 +01:00
CRb = Decimal ( amount )
Bp = self . lastBet [ street ]
2011-02-25 06:05:39 +01:00
Bc = sum ( self . bets [ street ] [ player ] )
2008-12-17 12:54:26 +01:00
C = Bp - Bc
Rb = CRb - C
Rt = Bp + Rb
2009-08-11 23:13:07 +02:00
2008-12-17 12:54:26 +01:00
self . _addRaise ( street , player , C , Rb , Rt )
2008-12-20 17:48:25 +01:00
2008-12-17 12:54:26 +01:00
def addRaiseTo ( self , street , player , amountTo ) :
""" \
Add a raise on [ street ] by [ player ] to [ amountTo ]
"""
2009-02-19 18:26:29 +01:00
#CG - No idea if this function has been test/verified
2008-12-12 15:29:45 +01:00
self . checkPlayerExists ( player )
2011-02-24 15:49:50 +01:00
amountTo = amountTo . replace ( u ' , ' , u ' ' ) #some sites have commas
2009-02-19 17:37:48 +01:00
Bp = self . lastBet [ street ]
2011-02-25 06:05:39 +01:00
Bc = sum ( self . bets [ street ] [ player ] )
2008-12-17 12:54:26 +01:00
Rt = Decimal ( amountTo )
C = Bp - Bc
2010-01-23 02:55:13 +01:00
Rb = Rt - C - Bc
2008-12-17 12:54:26 +01:00
self . _addRaise ( street , player , C , Rb , Rt )
2008-12-20 17:48:25 +01:00
2010-09-28 22:50:33 +02:00
def _addRaise ( self , street , player , C , Rb , Rt , action = ' raises ' ) :
2010-08-15 05:59:05 +02:00
log . debug ( _ ( " %s %s raise %s " ) % ( street , player , Rt ) )
2008-12-20 17:48:25 +01:00
self . bets [ street ] [ player ] . append ( C + Rb )
self . stacks [ player ] - = ( C + Rb )
2010-09-28 23:33:15 +02:00
act = ( player , action , Rb , Rt , C , self . stacks [ player ] == 0 )
2008-12-20 17:48:25 +01:00
self . actions [ street ] . append ( act )
self . lastBet [ street ] = Rt # TODO check this is correct
self . pot . addMoney ( player , C + Rb )
2009-08-11 23:13:07 +02:00
2008-12-12 15:29:45 +01:00
def addBet ( self , street , player , amount ) :
2010-08-15 05:59:05 +02:00
log . debug ( _ ( " %s %s bets %s " ) % ( street , player , amount ) )
2011-02-24 15:49:50 +01:00
amount = amount . replace ( u ' , ' , u ' ' ) #some sites have commas
2011-02-24 15:51:40 +01:00
amount = Decimal ( amount )
2008-12-12 15:29:45 +01:00
self . checkPlayerExists ( player )
2011-02-24 15:51:40 +01:00
self . bets [ street ] [ player ] . append ( amount )
self . stacks [ player ] - = amount
2009-02-22 06:37:38 +01:00
#print "DEBUG %s bets %s, stack %s" % (player, amount, self.stacks[player])
2011-02-24 15:51:40 +01:00
act = ( player , ' bets ' , amount , self . stacks [ player ] == 0 )
2008-12-20 17:48:25 +01:00
self . actions [ street ] . append ( act )
2011-02-24 15:51:40 +01:00
self . lastBet [ street ] = amount
self . pot . addMoney ( player , amount )
2009-03-14 11:48:34 +01:00
2011-03-24 07:00:10 +01:00
def addStandsPat ( self , street , player , cards ) :
2009-03-14 11:48:34 +01:00
self . checkPlayerExists ( player )
act = ( player , ' stands pat ' )
self . actions [ street ] . append ( act )
2011-03-24 07:00:10 +01:00
if cards :
cards = cards . split ( ' ' )
self . addHoleCards ( street , player , open = [ ] , closed = cards )
2009-08-11 23:13:07 +02:00
2008-12-12 15:29:45 +01:00
def addFold ( self , street , player ) :
2010-08-15 05:59:05 +02:00
log . debug ( _ ( " %s %s folds " ) % ( street , player ) )
2008-12-12 15:29:45 +01:00
self . checkPlayerExists ( player )
self . folded . add ( player )
2008-12-20 17:48:25 +01:00
self . pot . addFold ( player )
self . actions [ street ] . append ( ( player , ' folds ' ) )
2009-08-11 23:13:07 +02:00
2008-12-12 15:29:45 +01:00
def addCheck ( self , street , player ) :
2009-02-22 06:37:38 +01:00
#print "DEBUG: %s %s checked" % (street, player)
2010-08-15 05:59:05 +02:00
logging . debug ( _ ( " %s %s checks " ) % ( street , player ) )
2008-12-12 15:29:45 +01:00
self . checkPlayerExists ( player )
2008-12-20 17:48:25 +01:00
self . actions [ street ] . append ( ( player , ' checks ' ) )
2008-12-12 15:29:45 +01:00
2009-02-20 09:33:25 +01:00
2008-12-12 15:29:45 +01:00
def addCollectPot ( self , player , pot ) :
2009-08-09 16:19:43 +02:00
log . debug ( " %s collected %s " % ( player , pot ) )
2008-12-12 15:29:45 +01:00
self . checkPlayerExists ( player )
2009-02-21 17:17:06 +01:00
self . collected = self . collected + [ [ player , pot ] ]
if player not in self . collectees :
self . collectees [ player ] = Decimal ( pot )
2008-12-12 15:29:45 +01:00
else :
2009-02-21 17:17:06 +01:00
self . collectees [ player ] + = Decimal ( pot )
2008-12-12 15:29:45 +01:00
2011-04-04 21:57:54 +02:00
def addShownCards ( self , cards , player , holeandboard = None , shown = True , mucked = False , string = None ) :
2009-07-04 20:35:20 +02:00
""" \
For when a player shows cards for any reason ( for showdown or out of choice ) .
Card ranks will be uppercased
"""
2010-08-15 05:59:05 +02:00
log . debug ( _ ( " addShownCards %s hole= %s all= %s " ) % ( player , cards , holeandboard ) )
2009-07-04 20:35:20 +02:00
if cards is not None :
self . addHoleCards ( cards , player , shown , mucked )
2011-04-04 21:57:54 +02:00
if string is not None :
self . showdownStrings [ player ] = string
2009-07-04 20:35:20 +02:00
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 , mucked )
2008-12-12 15:29:45 +01:00
def totalPot ( self ) :
2008-12-16 00:56:19 +01:00
""" If all bets and blinds have been added, totals up the total pot size """
2009-08-11 23:13:07 +02:00
2008-12-20 17:57:12 +01:00
# This gives us the total amount put in the pot
2008-12-12 15:29:45 +01:00
if self . totalpot is None :
2008-12-20 17:48:25 +01:00
self . pot . end ( )
2008-12-20 17:57:12 +01:00
self . totalpot = self . pot . total
# This gives us the amount collected, i.e. after rake
2008-12-14 20:25:04 +01:00
if self . totalcollected is None :
self . totalcollected = 0 ;
2009-02-21 17:17:06 +01:00
#self.collected looks like [[p1,amount][px,amount]]
for entry in self . collected :
2010-09-28 06:04:40 +02:00
self . totalcollected + = Decimal ( entry [ 1 ] )
2008-12-14 20:25:04 +01:00
2008-12-12 15:29:45 +01:00
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]:
2009-07-13 22:22:23 +02:00
gs = { " holdem " : " Hold ' em " ,
2009-02-22 10:07:11 +01:00
" omahahi " : " Omaha " ,
2009-03-14 14:45:09 +01:00
" omahahilo " : " Omaha Hi/Lo " ,
2008-12-12 15:29:45 +01:00
" razz " : " Razz " ,
2009-03-06 02:24:38 +01:00
" studhi " : " 7 Card Stud " ,
2009-06-12 18:29:17 +02:00
" studhilo " : " 7 Card Stud Hi/Lo " ,
2008-12-12 15:29:45 +01:00
" fivedraw " : " 5 Card Draw " ,
" 27_1draw " : " FIXME " ,
" 27_3draw " : " Triple Draw 2-7 Lowball " ,
2009-03-14 11:48:34 +01:00
" badugi " : " Badugi "
2008-12-12 15:29:45 +01:00
}
ls = { " nl " : " No Limit " ,
" pl " : " Pot Limit " ,
" fl " : " Limit " ,
" cn " : " Cap No Limit " ,
" cp " : " Cap Pot Limit "
}
2009-08-09 16:19:43 +02:00
log . debug ( " gametype: %s " % ( self . gametype ) )
2009-03-10 17:17:54 +01:00
retstring = " %s %s " % ( gs [ self . gametype [ ' category ' ] ] , ls [ self . gametype [ ' limitType ' ] ] )
2009-03-04 17:46:01 +01:00
return retstring
2008-12-12 15:29:45 +01:00
2009-03-01 17:52:52 +01:00
2008-12-16 00:56:19 +01:00
def writeHand ( self , fh = sys . __stdout__ ) :
2009-02-27 19:42:53 +01:00
print >> fh , " Override me "
def printHand ( self ) :
self . writeHand ( sys . stdout )
2009-11-29 09:54:15 +01:00
def actionString ( self , act , street = None ) :
2009-02-27 19:42:53 +01:00
if act [ 1 ] == ' folds ' :
2009-06-19 08:21:35 +02:00
return ( " %s : folds " % ( act [ 0 ] ) )
2009-02-27 19:42:53 +01:00
elif act [ 1 ] == ' checks ' :
2009-06-19 08:21:35 +02:00
return ( " %s : checks " % ( act [ 0 ] ) )
2009-03-02 00:22:47 +01:00
elif act [ 1 ] == ' calls ' :
2009-07-16 05:04:16 +02:00
return ( " %s : calls %s %s %s " % ( act [ 0 ] , self . sym , act [ 2 ] , ' and is all-in ' if act [ 3 ] else ' ' ) )
2009-03-02 00:22:47 +01:00
elif act [ 1 ] == ' bets ' :
2009-07-16 05:04:16 +02:00
return ( " %s : bets %s %s %s " % ( act [ 0 ] , self . sym , act [ 2 ] , ' and is all-in ' if act [ 3 ] else ' ' ) )
2009-03-02 00:22:47 +01:00
elif act [ 1 ] == ' raises ' :
2009-07-16 05:04:16 +02:00
return ( " %s : raises %s %s to %s %s %s " % ( act [ 0 ] , self . sym , act [ 2 ] , self . sym , act [ 3 ] , ' and is all-in ' if act [ 5 ] else ' ' ) )
2009-03-11 17:51:58 +01:00
elif act [ 1 ] == ' completea ' :
2009-07-16 05:04:16 +02:00
return ( " %s : completes to %s %s %s " % ( act [ 0 ] , self . sym , act [ 2 ] , ' and is all-in ' if act [ 3 ] else ' ' ) )
2009-03-02 00:22:47 +01:00
elif act [ 1 ] == ' posts ' :
if ( act [ 2 ] == " small blind " ) :
2009-07-16 05:04:16 +02:00
return ( " %s : posts small blind %s %s %s " % ( act [ 0 ] , self . sym , act [ 3 ] , ' and is all-in ' if act [ 4 ] else ' ' ) )
2009-03-02 00:22:47 +01:00
elif ( act [ 2 ] == " big blind " ) :
2009-07-16 05:04:16 +02:00
return ( " %s : posts big blind %s %s %s " % ( act [ 0 ] , self . sym , act [ 3 ] , ' and is all-in ' if act [ 4 ] else ' ' ) )
2009-03-02 00:22:47 +01:00
elif ( act [ 2 ] == " both " ) :
2009-07-16 05:04:16 +02:00
return ( " %s : posts small & big blinds %s %s %s " % ( act [ 0 ] , self . sym , act [ 3 ] , ' and is all-in ' if act [ 4 ] else ' ' ) )
2009-08-11 23:19:01 +02:00
elif ( act [ 2 ] == " ante " ) :
return ( " %s : posts the ante %s %s %s " % ( act [ 0 ] , self . sym , act [ 3 ] , ' and is all-in ' if act [ 4 ] else ' ' ) )
2009-03-11 17:51:58 +01:00
elif act [ 1 ] == ' bringin ' :
2009-07-16 05:04:16 +02:00
return ( " %s : brings in for %s %s %s " % ( act [ 0 ] , self . sym , act [ 2 ] , ' and is all-in ' if act [ 3 ] else ' ' ) )
2009-03-14 11:48:34 +01:00
elif act [ 1 ] == ' discards ' :
2009-11-29 09:54:15 +01:00
return ( " %s : discards %s %s %s " % ( act [ 0 ] , act [ 2 ] , ' card ' if act [ 2 ] == 1 else ' cards ' , " [ " + " " . join ( self . discards [ street ] [ act [ 0 ] ] ) + " ] " if self . hero == act [ 0 ] else ' ' ) )
2009-03-14 11:48:34 +01:00
elif act [ 1 ] == ' stands pat ' :
2009-06-19 08:21:35 +02:00
return ( " %s : stands pat " % ( act [ 0 ] ) )
2009-03-14 11:48:34 +01:00
2009-07-13 22:22:23 +02:00
def getStakesAsString ( self ) :
2009-07-15 01:18:38 +02:00
""" Return a string of the stakes of the current hand. """
return " %s %s / %s %s " % ( self . sym , self . sb , self . sym , self . bb )
2009-07-13 22:22:23 +02:00
2009-08-12 16:21:54 +02:00
def getStreetTotals ( self ) :
pass
2009-07-13 22:22:23 +02:00
def writeGameLine ( self ) :
2009-07-15 01:18:38 +02:00
""" Return the first HH line for the current hand. """
gs = " PokerStars Game # %s : " % self . handid
2009-08-11 23:13:07 +02:00
2009-11-03 20:30:52 +01:00
if self . tourNo is not None and self . mixed is not None : # mixed tournament
2009-07-15 01:18:38 +02:00
gs = gs + " Tournament # %s , %s %s ( %s ) - Level %s ( %s ) - " % ( self . tourNo , self . buyin , self . MS [ self . mixed ] , self . getGameTypeAsString ( ) , self . level , self . getStakesAsString ( ) )
2009-11-03 20:30:52 +01:00
elif self . tourNo is not None : # all other tournaments
2009-08-11 23:13:07 +02:00
gs = gs + " Tournament # %s , %s %s - Level %s ( %s ) - " % ( self . tourNo ,
2009-07-13 22:22:23 +02:00
self . buyin , self . getGameTypeAsString ( ) , self . level , self . getStakesAsString ( ) )
2009-11-03 20:30:52 +01:00
elif self . mixed is not None : # all other mixed games
2009-08-11 23:13:07 +02:00
gs = gs + " %s ( %s , %s ) - " % ( self . MS [ self . mixed ] ,
2009-07-13 22:22:23 +02:00
self . getGameTypeAsString ( ) , self . getStakesAsString ( ) )
2009-07-15 01:18:38 +02:00
else : # non-mixed cash games
gs = gs + " %s ( %s ) - " % ( self . getGameTypeAsString ( ) , self . getStakesAsString ( ) )
2009-08-31 10:19:23 +02:00
try :
2010-07-05 11:48:26 +02:00
timestr = datetime . datetime . strftime ( self . startTime , ' % Y/ % m/ %d % H: % M: % S ET ' )
2009-08-31 10:19:23 +02:00
except TypeError :
2010-08-15 05:59:05 +02:00
print _ ( " *** ERROR - HAND: calling writeGameLine with unexpected STARTTIME value, expecting datetime.date object, received: " ) , self . startTime
print _ ( " *** Make sure your HandHistoryConverter is setting hand.startTime properly! " )
print _ ( " *** Game String: " ) , gs
2009-08-31 10:19:23 +02:00
return gs
else :
return gs + timestr
2009-07-13 22:22:23 +02:00
def writeTableLine ( self ) :
2009-09-12 23:14:55 +02:00
table_string = " Table "
if self . gametype [ ' type ' ] == ' tour ' :
table_string = table_string + " \' %s %s \' %s -max " % ( self . tourNo , self . tablename , self . maxseats )
else :
table_string = table_string + " \' %s \' %s -max " % ( self . tablename , self . maxseats )
2009-07-13 22:22:23 +02:00
if self . gametype [ ' currency ' ] == ' play ' :
table_string = table_string + " (Play Money) "
2009-07-22 14:53:03 +02:00
if self . buttonpos != None and self . buttonpos != 0 :
2009-07-13 22:22:23 +02:00
table_string = table_string + " Seat # %s is the button " % self . buttonpos
return table_string
2009-03-14 11:48:34 +01:00
2009-07-15 17:50:27 +02:00
def writeHand ( self , fh = sys . __stdout__ ) :
# PokerStars format.
2009-08-11 23:13:07 +02:00
print >> fh , self . writeGameLine ( )
print >> fh , self . writeTableLine ( )
2009-07-15 17:50:27 +02:00
2009-02-27 19:42:53 +01:00
class HoldemOmahaHand ( Hand ) :
2010-01-31 12:25:24 +01:00
def __init__ ( self , config , hhc , sitename , gametype , handText , builtFrom = " HHC " , handid = None ) :
self . config = config
2009-03-10 17:17:54 +01:00
if gametype [ ' base ' ] != ' hold ' :
2009-02-27 19:42:53 +01:00
pass # or indeed don't pass and complain instead
2009-08-09 16:19:43 +02:00
log . debug ( " HoldemOmahaHand " )
2009-06-19 08:21:35 +02:00
self . allStreets = [ ' BLINDSANTES ' , ' PREFLOP ' , ' FLOP ' , ' TURN ' , ' RIVER ' ]
self . holeStreets = [ ' PREFLOP ' ]
2009-03-02 00:22:47 +01:00
self . communityStreets = [ ' FLOP ' , ' TURN ' , ' RIVER ' ]
2009-06-19 08:21:35 +02:00
self . actionStreets = [ ' BLINDSANTES ' , ' PREFLOP ' , ' FLOP ' , ' TURN ' , ' RIVER ' ]
2010-01-31 12:25:24 +01:00
Hand . __init__ ( self , self . config , sitename , gametype , handText , builtFrom = " HHC " )
2009-03-06 19:10:04 +01:00
self . sb = gametype [ ' sb ' ]
self . bb = gametype [ ' bb ' ]
2009-08-11 23:13:07 +02:00
2009-03-02 22:48:30 +01:00
#Populate a HoldemOmahaHand
2009-08-11 23:13:07 +02:00
#Generally, we call 'read' methods here, which get the info according to the particular filter (hhc)
2009-03-02 22:48:30 +01:00
# which then invokes a 'addXXX' callback
2009-03-14 15:01:40 +01:00
if builtFrom == " HHC " :
hhc . readHandInfo ( self )
2010-01-23 11:17:14 +01:00
if self . gametype [ ' type ' ] == ' tour ' :
2010-01-28 11:56:17 +01:00
self . tablename = " %s %s " % ( self . tourNo , self . tablename )
2009-03-14 15:01:40 +01:00
hhc . readPlayerStacks ( self )
hhc . compilePlayerRegexs ( self )
hhc . markStreets ( self )
2010-09-28 06:04:40 +02:00
2009-12-17 08:53:12 +01:00
if self . cancelled :
return
2010-09-28 06:04:40 +02:00
2010-09-14 07:53:47 +02:00
hhc . readBlinds ( self )
2010-09-28 06:04:40 +02:00
2009-08-11 23:19:01 +02:00
hhc . readAntes ( self )
2009-03-14 15:01:40 +01:00
hhc . readButton ( self )
hhc . readHeroCards ( self )
hhc . readShowdownActions ( self )
# Read actions in street order
2011-04-04 06:50:01 +02:00
for street , text in self . streets . iteritems ( ) :
2011-04-10 16:33:19 +02:00
if text and ( street is not " PREFLOP " ) : #TODO: the except PREFLOP shouldn't be necessary, but regression-test-files/cash/Everleaf/Flop/NLHE-10max-USD-0.01-0.02-201008.2Way.All-in.pre.txt fails without it
hhc . readCommunityCards ( self , street )
2009-03-14 15:01:40 +01:00
for street in self . actionStreets :
if self . streets [ street ] :
hhc . readAction ( self , street )
2009-08-12 16:21:54 +02:00
self . pot . markTotal ( street )
2009-03-14 15:01:40 +01:00
hhc . readCollectPot ( self )
hhc . readShownCards ( self )
self . totalPot ( ) # finalise it (total the pot)
hhc . getRake ( self )
2009-11-03 20:30:52 +01:00
if self . maxseats is None :
2009-07-20 16:01:51 +02:00
self . maxseats = hhc . guessMaxSeats ( self )
2009-07-22 16:24:29 +02:00
hhc . readOther ( self )
2010-02-20 18:49:03 +01:00
#print "\nHand:\n"+str(self)
2009-03-14 15:01:40 +01:00
elif builtFrom == " DB " :
2010-12-17 12:03:50 +01:00
#if handid is not None:
# self.select(handid) # Will need a handId
#else:
# log.warning(_("HoldemOmahaHand.__init__:Can't assemble hand from db without a handid"))
print " DEBUG: HoldemOmaha hand initialised for select() "
2009-06-07 22:57:13 +02:00
else :
2010-08-15 05:59:05 +02:00
log . warning ( _ ( " HoldemOmahaHand.__init__:Neither HHC nor DB+handid provided " ) )
2009-06-07 22:57:13 +02:00
pass
2009-08-11 23:13:07 +02:00
2009-03-07 16:43:33 +01:00
2011-04-04 21:57:54 +02:00
def addShownCards ( self , cards , player , shown = True , mucked = False , dealt = False , string = None ) :
2009-07-12 22:01:02 +02:00
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 )
2009-06-19 08:21:35 +02:00
else :
2009-09-27 13:21:22 +02:00
if len ( cards ) in ( 2 , 4 ) : # avoid adding board by mistake (Everleaf problem)
self . addHoleCards ( ' PREFLOP ' , player , open = [ ] , closed = cards , shown = shown , mucked = mucked , dealt = dealt )
elif len ( cards ) == 5 : # cards holds a winning hand, not hole cards
# filter( lambda x: x not in b, a ) # calcs a - b where a and b are lists
# so diff is set to the winning hand minus the board cards, if we're lucky that leaves the hole cards
diff = filter ( lambda x : x not in self . board [ ' FLOP ' ] + self . board [ ' TURN ' ] + self . board [ ' RIVER ' ] , cards )
if len ( diff ) == 2 and self . gametype [ ' category ' ] in ( ' holdem ' ) :
self . addHoleCards ( ' PREFLOP ' , player , open = [ ] , closed = diff , shown = shown , mucked = mucked , dealt = dealt )
2011-04-04 21:57:54 +02:00
if string is not None :
self . showdownStrings [ player ] = string
2009-07-12 22:01:02 +02:00
2009-08-12 16:21:54 +02:00
def getStreetTotals ( self ) :
# street1Pot INT, /* pot size at flop/street4 */
# street2Pot INT, /* pot size at turn/street5 */
# street3Pot INT, /* pot size at river/street6 */
# street4Pot INT, /* pot size at sd/street7 */
# showdownPot INT, /* pot size at sd/street7 */
tmp1 = self . pot . getTotalAtStreet ( ' FLOP ' )
tmp2 = self . pot . getTotalAtStreet ( ' TURN ' )
tmp3 = self . pot . getTotalAtStreet ( ' RIVER ' )
tmp4 = 0
tmp5 = 0
return ( tmp1 , tmp2 , tmp3 , tmp4 , tmp5 )
2009-03-02 22:48:30 +01:00
2009-11-30 07:20:48 +01:00
def join_holecards ( self , player , asList = False ) :
""" With asList = True it returns the set cards for a player including down cards if they aren ' t know """
hcs = [ u ' 0x ' , u ' 0x ' , u ' 0x ' , u ' 0x ' ]
for street in self . holeStreets :
if player in self . holecards [ street ] . keys ( ) :
hcs [ 0 ] = self . holecards [ street ] [ player ] [ 1 ] [ 0 ]
hcs [ 1 ] = self . holecards [ street ] [ player ] [ 1 ] [ 1 ]
try :
hcs [ 2 ] = self . holecards [ street ] [ player ] [ 1 ] [ 2 ]
hcs [ 3 ] = self . holecards [ street ] [ player ] [ 1 ] [ 3 ]
except IndexError :
pass
if asList == False :
return " " . join ( hcs )
else :
return hcs
2009-08-28 02:22:08 +02:00
def writeHTMLHand ( self ) :
2009-06-16 01:29:44 +02:00
from nevow import tags as T
from nevow import flat
players_who_act_preflop = ( ( [ x [ 0 ] for x in self . actions [ ' PREFLOP ' ] ] + [ x [ 0 ] for x in self . actions [ ' BLINDSANTES ' ] ] ) )
players_stacks = [ x for x in self . players if x [ 1 ] in players_who_act_preflop ]
action_streets = [ x for x in self . actionStreets if len ( self . actions [ x ] ) > 0 ]
def render_stack ( context , data ) :
pat = context . tag . patternGenerator ( ' list_item ' )
for player in data :
2009-07-16 05:04:16 +02:00
x = " Seat %s : %s ( %s %s in chips) " % ( player [ 0 ] , player [ 1 ] ,
self . sym , player [ 2 ] )
2009-06-16 01:29:44 +02:00
context . tag [ pat ( ) . fillSlots ( ' playerStack ' , x ) ]
return context . tag
def render_street ( context , data ) :
pat = context . tag . patternGenerator ( ' list_item ' )
for street in data :
2009-06-19 08:21:35 +02:00
lines = [ ]
if street in self . holeStreets and self . holecards [ street ] :
lines . append (
T . ol ( class_ = ' dealclosed ' , data = street ,
render = render_deal ) [
T . li ( pattern = ' list_item ' ) [ T . slot ( name = ' deal ' ) ]
]
)
if street in self . communityStreets and self . board [ street ] :
lines . append (
T . ol ( class_ = ' community ' , data = street ,
render = render_deal_community ) [
T . li ( pattern = ' list_item ' ) [ T . slot ( name = ' deal ' ) ]
]
)
if street in self . actionStreets and self . actions [ street ] :
2009-08-11 23:13:07 +02:00
lines . append (
2009-06-19 08:21:35 +02:00
T . ol ( class_ = ' actions ' , data = self . actions [ street ] , render = render_action ) [
T . li ( pattern = ' list_item ' ) [ T . slot ( name = ' action ' ) ]
]
)
if lines :
context . tag [ pat ( ) . fillSlots ( ' street ' , [ T . h3 [ street ] ] + lines ) ]
return context . tag
def render_deal ( context , data ) :
# data is streetname
# we can have open+closed, or just open, or just closed.
if self . holecards [ data ] :
for player in self . holecards [ data ] :
somestuff = ' dealt to %s %s ' % ( player , self . holecards [ data ] [ player ] )
pat = context . tag . patternGenerator ( ' list_item ' )
context . tag [ pat ( ) . fillSlots ( ' deal ' , somestuff ) ]
2009-06-16 01:29:44 +02:00
return context . tag
2009-06-19 08:21:35 +02:00
def render_deal_community ( context , data ) :
# data is streetname
if self . board [ data ] :
somestuff = ' [ ' + ' ' . join ( self . board [ data ] ) + ' ] '
pat = context . tag . patternGenerator ( ' list_item ' )
context . tag [ pat ( ) . fillSlots ( ' deal ' , somestuff ) ]
return context . tag
2009-06-16 01:29:44 +02:00
def render_action ( context , data ) :
pat = context . tag . patternGenerator ( ' list_item ' )
for act in data :
2009-06-19 08:21:35 +02:00
x = self . actionString ( act )
2009-06-16 01:29:44 +02:00
context . tag [ pat ( ) . fillSlots ( ' action ' , x ) ]
return context . tag
2009-08-11 23:13:07 +02:00
s = T . p [
T . h1 [
2009-06-19 08:21:35 +02:00
T . span ( class_ = ' site ' ) [ " %s Game # %s ] " % ( ' PokerStars ' , self . handid ) ] ,
T . span ( class_ = ' type_limit ' ) [ " %s ($ %s /$ %s ) " % ( self . getGameTypeAsString ( ) , self . sb , self . bb ) ] ,
2010-07-05 11:48:26 +02:00
T . span ( class_ = ' date ' ) [ datetime . datetime . strftime ( self . startTime , ' % Y/ % m/ %d - % H: % M: % S ET ' ) ]
2009-06-16 01:29:44 +02:00
] ,
T . h2 [ " Table ' %s ' %d -max Seat # %s is the button " % ( self . tablename ,
self . maxseats , self . buttonpos ) ] ,
T . ol ( class_ = ' stacks ' , data = players_stacks , render = render_stack ) [
T . li ( pattern = ' list_item ' ) [ T . slot ( name = ' playerStack ' ) ]
] ,
2009-06-19 08:21:35 +02:00
T . ol ( class_ = ' streets ' , data = self . allStreets ,
2009-06-16 01:29:44 +02:00
render = render_street ) [
T . li ( pattern = ' list_item ' ) [ T . slot ( name = ' street ' ) ]
]
]
2009-06-19 08:21:35 +02:00
import tidy
options = dict ( input_xml = True ,
output_xhtml = True ,
add_xml_decl = False ,
doctype = ' omit ' ,
indent = ' auto ' ,
tidy_mark = False )
return str ( tidy . parseString ( flat . flatten ( s ) , * * options ) )
2009-06-16 01:29:44 +02:00
2009-08-11 23:13:07 +02:00
2009-02-27 19:42:53 +01:00
def writeHand ( self , fh = sys . __stdout__ ) :
2008-12-12 15:29:45 +01:00
# PokerStars format.
2009-07-15 17:50:27 +02:00
super ( HoldemOmahaHand , self ) . writeHand ( fh )
2009-07-13 22:22:23 +02:00
2009-03-11 15:07:38 +01:00
players_who_act_preflop = set ( ( [ x [ 0 ] for x in self . actions [ ' PREFLOP ' ] ] + [ x [ 0 ] for x in self . actions [ ' BLINDSANTES ' ] ] ) )
2009-08-09 16:19:43 +02:00
log . debug ( self . actions [ ' PREFLOP ' ] )
2008-12-16 00:56:19 +01:00
for player in [ x for x in self . players if x [ 1 ] in players_who_act_preflop ] :
#Only print stacks of players who do something preflop
2010-12-22 06:08:41 +01:00
print >> fh , ( " Seat %s : %s ($ %.2f in chips) " % ( player [ 0 ] , player [ 1 ] , float ( player [ 2 ] ) ) )
2008-12-12 15:29:45 +01:00
2009-03-02 00:22:47 +01:00
if self . actions [ ' BLINDSANTES ' ] :
for act in self . actions [ ' BLINDSANTES ' ] :
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2009-08-11 23:13:07 +02:00
2009-06-07 22:57:13 +02:00
print >> fh , ( " *** HOLE CARDS *** " )
2009-06-19 08:21:35 +02:00
for player in self . dealt :
2009-07-12 22:01:02 +02:00
print >> fh , ( " Dealt to %s [ %s ] " % ( player , " " . join ( self . holecards [ ' PREFLOP ' ] [ player ] [ 1 ] ) ) )
2009-06-19 08:21:35 +02:00
if self . hero == " " :
for player in self . shown . difference ( self . dealt ) :
2009-07-12 22:01:02 +02:00
print >> fh , ( " Dealt to %s [ %s ] " % ( player , " " . join ( self . holecards [ ' PREFLOP ' ] [ player ] [ 1 ] ) ) )
2008-12-12 15:29:45 +01:00
2009-03-02 00:22:47 +01:00
if self . actions [ ' PREFLOP ' ] :
2008-12-12 15:29:45 +01:00
for act in self . actions [ ' PREFLOP ' ] :
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2008-12-12 15:29:45 +01:00
2009-03-03 19:45:02 +01:00
if self . board [ ' FLOP ' ] :
2009-06-07 22:57:13 +02:00
print >> fh , ( " *** FLOP *** [ %s ] " % ( " " . join ( self . board [ ' FLOP ' ] ) ) )
2009-03-03 19:45:02 +01:00
if self . actions [ ' FLOP ' ] :
2008-12-12 15:29:45 +01:00
for act in self . actions [ ' FLOP ' ] :
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2008-12-12 15:29:45 +01:00
2009-03-03 19:45:02 +01:00
if self . board [ ' TURN ' ] :
2009-06-07 22:57:13 +02:00
print >> fh , ( " *** TURN *** [ %s ] [ %s ] " % ( " " . join ( self . board [ ' FLOP ' ] ) , " " . join ( self . board [ ' TURN ' ] ) ) )
2009-03-03 19:45:02 +01:00
if self . actions [ ' TURN ' ] :
2008-12-12 15:29:45 +01:00
for act in self . actions [ ' TURN ' ] :
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2008-12-12 15:29:45 +01:00
2009-03-03 19:45:02 +01:00
if self . board [ ' RIVER ' ] :
2009-06-07 22:57:13 +02:00
print >> fh , ( " *** RIVER *** [ %s ] [ %s ] " % ( " " . join ( self . board [ ' FLOP ' ] + self . board [ ' TURN ' ] ) , " " . join ( self . board [ ' RIVER ' ] ) ) )
2009-03-03 19:45:02 +01:00
if self . actions [ ' RIVER ' ] :
2008-12-12 15:29:45 +01:00
for act in self . actions [ ' RIVER ' ] :
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2008-12-12 15:29:45 +01:00
#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
2009-03-14 16:02:23 +01:00
if self . shown :
2009-06-07 22:57:13 +02:00
print >> fh , ( " *** SHOW DOWN *** " )
2009-03-14 16:02:23 +01:00
for name in self . shown :
2009-03-15 17:51:50 +01:00
# TODO: legacy importer can't handle only one holecard here, make sure there are 2 for holdem, 4 for omaha
# TOOD: If HoldHand subclass supports more than omahahi, omahahilo, holdem, add them here
numOfHoleCardsNeeded = None
if self . gametype [ ' category ' ] in ( ' omahahi ' , ' omahahilo ' ) :
numOfHoleCardsNeeded = 4
elif self . gametype [ ' category ' ] in ( ' holdem ' ) :
numOfHoleCardsNeeded = 2
2009-06-19 08:21:35 +02:00
if len ( self . holecards [ ' PREFLOP ' ] [ name ] ) == numOfHoleCardsNeeded :
2009-07-12 22:01:02 +02:00
print >> fh , ( " %s shows [ %s ] (a hand...) " % ( name , " " . join ( self . holecards [ ' PREFLOP ' ] [ name ] [ 1 ] ) ) )
2009-08-11 23:13:07 +02:00
2009-02-21 12:24:11 +01:00
# Current PS format has the lines:
2009-02-21 13:37:47 +01:00
# Uncalled bet ($111.25) returned to s0rrow
2009-02-21 12:24:11 +01:00
# 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
2009-02-21 13:37:47 +01:00
for name in self . pot . returned :
2009-07-16 05:04:16 +02:00
print >> fh , ( " Uncalled bet ( %s %s ) returned to %s " % ( self . sym , self . pot . returned [ name ] , name ) )
2009-02-21 17:17:06 +01:00
for entry in self . collected :
2009-07-16 05:04:16 +02:00
print >> fh , ( " %s collected %s %s from x pot " % ( entry [ 0 ] , self . sym , entry [ 1 ] ) )
2009-02-21 12:24:11 +01:00
2009-06-07 22:57:13 +02:00
print >> fh , ( " *** SUMMARY *** " )
2009-07-16 05:04:16 +02:00
print >> fh , " %s | Rake %s %.2f " % ( self . pot , self . sym , self . rake )
2008-12-14 23:05:51 +01:00
2008-12-12 15:29:45 +01:00
board = [ ]
2009-07-16 04:30:41 +02:00
for street in [ " FLOP " , " TURN " , " RIVER " ] :
board + = self . board [ street ]
2008-12-12 15:29:45 +01:00
if board : # sometimes hand ends preflop without a board
2009-06-07 22:57:13 +02:00
print >> fh , ( " Board [ %s ] " % ( " " . join ( board ) ) )
2008-12-12 15:29:45 +01:00
2008-12-16 22:49:04 +01:00
for player in [ x for x in self . players if x [ 1 ] in players_who_act_preflop ] :
2008-12-12 15:29:45 +01:00
seatnum = player [ 0 ]
name = player [ 1 ]
2009-02-21 17:17:06 +01:00
if name in self . collectees and name in self . shown :
2009-07-16 05:04:16 +02:00
print >> fh , ( " Seat %d : %s showed [ %s ] and won ( %s %s ) " % ( seatnum , name , " " . join ( self . holecards [ ' PREFLOP ' ] [ name ] [ 1 ] ) , self . sym , self . collectees [ name ] ) )
2009-02-21 17:17:06 +01:00
elif name in self . collectees :
2009-07-16 05:04:16 +02:00
print >> fh , ( " Seat %d : %s collected ( %s %s ) " % ( seatnum , name , self . sym , self . collectees [ name ] ) )
2009-03-13 17:50:46 +01:00
#~ elif name in self.shown:
#~ print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP'])))
2009-02-25 13:34:05 +01:00
elif name in self . folded :
2009-06-07 22:57:13 +02:00
print >> fh , ( " Seat %d : %s folded " % ( seatnum , name ) )
2009-02-25 13:34:05 +01:00
else :
2009-03-13 17:50:46 +01:00
if name in self . shown :
2009-07-12 22:01:02 +02:00
print >> fh , ( " Seat %d : %s showed [ %s ] and lost with... " % ( seatnum , name , " " . join ( self . holecards [ ' PREFLOP ' ] [ name ] [ 1 ] ) ) )
2009-07-04 21:28:20 +02:00
elif name in self . mucked :
2009-07-12 22:01:02 +02:00
print >> fh , ( " Seat %d : %s mucked [ %s ] " % ( seatnum , name , " " . join ( self . holecards [ ' PREFLOP ' ] [ name ] [ 1 ] ) ) )
2009-03-13 17:50:46 +01:00
else :
2009-06-07 22:57:13 +02:00
print >> fh , ( " Seat %d : %s mucked " % ( seatnum , name ) )
2009-02-25 13:34:05 +01:00
print >> fh , " \n \n "
2009-08-11 23:13:07 +02:00
2009-03-06 02:24:38 +01:00
class DrawHand ( Hand ) :
2010-01-31 12:25:24 +01:00
def __init__ ( self , config , hhc , sitename , gametype , handText , builtFrom = " HHC " ) :
self . config = config
2009-03-10 17:17:54 +01:00
if gametype [ ' base ' ] != ' draw ' :
2009-03-06 02:24:38 +01:00
pass # or indeed don't pass and complain instead
2009-03-14 11:48:34 +01:00
self . streetList = [ ' BLINDSANTES ' , ' DEAL ' , ' DRAWONE ' , ' DRAWTWO ' , ' DRAWTHREE ' ]
2009-07-11 19:44:32 +02:00
self . allStreets = [ ' BLINDSANTES ' , ' DEAL ' , ' DRAWONE ' , ' DRAWTWO ' , ' DRAWTHREE ' ]
2009-03-14 11:48:34 +01:00
self . holeStreets = [ ' DEAL ' , ' DRAWONE ' , ' DRAWTWO ' , ' DRAWTHREE ' ]
2009-11-29 08:22:46 +01:00
self . actionStreets = [ ' BLINDSANTES ' , ' DEAL ' , ' DRAWONE ' , ' DRAWTWO ' , ' DRAWTHREE ' ]
2009-07-11 19:44:32 +02:00
self . communityStreets = [ ]
2010-01-31 12:25:24 +01:00
Hand . __init__ ( self , self . config , sitename , gametype , handText )
2009-03-14 11:48:34 +01:00
self . sb = gametype [ ' sb ' ]
self . bb = gametype [ ' bb ' ]
# Populate the draw hand.
2009-03-14 15:01:40 +01:00
if builtFrom == " HHC " :
hhc . readHandInfo ( self )
2010-01-23 11:17:14 +01:00
if self . gametype [ ' type ' ] == ' tour ' :
2010-01-28 11:56:17 +01:00
self . tablename = " %s %s " % ( self . tourNo , self . tablename )
2009-03-14 15:01:40 +01:00
hhc . readPlayerStacks ( self )
hhc . compilePlayerRegexs ( self )
hhc . markStreets ( self )
2011-01-25 06:10:50 +01:00
# markStreets in Draw may match without dealing cards
if self . streets [ ' DEAL ' ] == None :
2011-03-10 04:15:53 +01:00
raise FpdbParseError ( _ ( " DrawHand.__init__: street ' DEAL ' is empty. Hand cancelled? HandID: ' %s ' " ) % self . handid )
2009-03-14 15:01:40 +01:00
hhc . readBlinds ( self )
2009-08-11 23:19:01 +02:00
hhc . readAntes ( self )
2009-03-14 15:01:40 +01:00
hhc . readButton ( self )
2009-07-13 06:37:51 +02:00
hhc . readHeroCards ( self )
2009-03-14 15:01:40 +01:00
hhc . readShowdownActions ( self )
# Read actions in street order
for street in self . streetList :
if self . streets [ street ] :
hhc . readAction ( self , street )
2009-08-12 16:21:54 +02:00
self . pot . markTotal ( street )
2009-03-14 15:01:40 +01:00
hhc . readCollectPot ( self )
hhc . readShownCards ( self )
self . totalPot ( ) # finalise it (total the pot)
hhc . getRake ( self )
2009-11-03 20:30:52 +01:00
if self . maxseats is None :
2009-07-22 14:53:03 +02:00
self . maxseats = hhc . guessMaxSeats ( self )
2009-07-23 01:21:00 +02:00
hhc . readOther ( self )
2009-03-14 15:01:40 +01:00
elif builtFrom == " DB " :
self . select ( " dummy " ) # Will need a handId
2009-03-14 11:48:34 +01:00
2011-04-04 21:57:54 +02:00
def addShownCards ( self , cards , player , shown = True , mucked = False , dealt = False , string = None ) :
2009-07-13 06:37:51 +02:00
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 )
2011-04-04 21:57:54 +02:00
if string is not None :
self . showdownStrings [ player ] = string
2009-03-14 11:48:34 +01:00
2009-07-13 06:37:51 +02:00
2009-03-14 11:48:34 +01:00
def discardDrawHoleCards ( self , cards , player , street ) :
2009-08-09 16:19:43 +02:00
log . debug ( " discardDrawHoleCards ' %s ' ' %s ' ' %s ' " % ( cards , player , street ) )
2009-07-11 19:44:32 +02:00
self . discards [ street ] [ player ] = set ( [ cards ] )
2009-03-14 11:48:34 +01:00
2009-03-14 14:23:30 +01:00
def addDiscard ( self , street , player , num , cards ) :
self . checkPlayerExists ( player )
if cards :
2010-09-28 22:50:33 +02:00
act = ( player , ' discards ' , Decimal ( num ) , cards )
2009-03-14 14:23:30 +01:00
self . discardDrawHoleCards ( cards , player , street )
else :
2010-09-28 22:50:33 +02:00
act = ( player , ' discards ' , Decimal ( num ) )
2009-03-14 14:23:30 +01:00
self . actions [ street ] . append ( act )
2009-11-29 07:40:32 +01:00
def holecardsAsSet ( self , street , player ) :
""" Return holdcards: (oc, nc) as set() """
( nc , oc ) = self . holecards [ street ] [ player ]
nc = set ( nc )
oc = set ( oc )
return ( nc , oc )
2009-08-12 16:21:54 +02:00
def getStreetTotals ( self ) :
# street1Pot INT, /* pot size at flop/street4 */
# street2Pot INT, /* pot size at turn/street5 */
# street3Pot INT, /* pot size at river/street6 */
# street4Pot INT, /* pot size at sd/street7 */
# showdownPot INT, /* pot size at sd/street7 */
return ( 0 , 0 , 0 , 0 , 0 )
2009-11-30 07:20:48 +01:00
def join_holecards ( self , player , asList = False ) :
""" With asList = True it returns the set cards for a player including down cards if they aren ' t know """
# FIXME: This should actually return
2011-03-24 07:00:10 +01:00
holecards = [ u ' 0x ' ] * 20
for i , street in enumerate ( self . holeStreets ) :
if player in self . holecards [ street ] . keys ( ) :
2011-04-01 04:08:20 +02:00
allhole = self . holecards [ street ] [ player ] [ 1 ] + self . holecards [ street ] [ player ] [ 0 ]
2011-03-24 07:00:10 +01:00
for c in range ( len ( allhole ) ) :
idx = c + ( i * 5 )
holecards [ idx ] = allhole [ c ]
2009-11-30 07:20:48 +01:00
if asList == False :
return " " . join ( holecards )
else :
return holecards
2009-03-14 14:23:30 +01:00
2009-03-14 11:48:34 +01:00
def writeHand ( self , fh = sys . __stdout__ ) :
# PokerStars format.
2011-03-10 04:15:53 +01:00
# HH output should not be translated
2009-07-15 17:50:27 +02:00
super ( DrawHand , self ) . writeHand ( fh )
2009-03-14 11:48:34 +01:00
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
2011-03-10 04:15:53 +01:00
print >> fh , ( ( " Seat %s : %s ( %s %s in chips) " ) % ( player [ 0 ] , player [ 1 ] , self . sym , player [ 2 ] ) )
2009-03-14 11:48:34 +01:00
if ' BLINDSANTES ' in self . actions :
for act in self . actions [ ' BLINDSANTES ' ] :
2011-03-10 04:15:53 +01:00
print >> fh , ( " %s : %s %s %s %s " % ( act [ 0 ] , act [ 1 ] , act [ 2 ] , self . sym , act [ 3 ] ) )
2009-03-14 11:48:34 +01:00
if ' DEAL ' in self . actions :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** DEALING HANDS *** " )
2009-03-14 11:48:34 +01:00
for player in [ x [ 1 ] for x in self . players if x [ 1 ] in players_who_act_ondeal ] :
2009-11-29 07:40:32 +01:00
if ' DEAL ' in self . holecards :
if self . holecards [ ' DEAL ' ] . has_key ( player ) :
( nc , oc ) = self . holecards [ ' DEAL ' ] [ player ]
2011-03-10 04:15:53 +01:00
print >> fh , ( " Dealt to %s : [ %s ] " ) % ( player , " " . join ( nc ) )
2009-03-14 11:48:34 +01:00
for act in self . actions [ ' DEAL ' ] :
2009-11-29 09:54:15 +01:00
print >> fh , self . actionString ( act , ' DEAL ' )
2009-03-14 11:48:34 +01:00
if ' DRAWONE ' in self . actions :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** FIRST DRAW *** " )
2009-03-14 11:48:34 +01:00
for act in self . actions [ ' DRAWONE ' ] :
2009-11-29 09:54:15 +01:00
print >> fh , self . actionString ( act , ' DRAWONE ' )
2009-03-14 11:48:34 +01:00
if act [ 0 ] == self . hero and act [ 1 ] == ' discards ' :
2009-11-29 07:40:32 +01:00
( nc , oc ) = self . holecardsAsSet ( ' DRAWONE ' , act [ 0 ] )
2009-07-11 19:44:32 +02:00
dc = self . discards [ ' DRAWONE ' ] [ act [ 0 ] ]
2009-03-14 11:48:34 +01:00
kc = oc - dc
2011-03-10 04:15:53 +01:00
print >> fh , ( ( " Dealt to %s [ %s ] [ %s ] " ) % ( act [ 0 ] , " " . join ( kc ) , " " . join ( nc ) ) )
2009-03-14 11:48:34 +01:00
if ' DRAWTWO ' in self . actions :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** SECOND DRAW *** " )
2009-03-14 11:48:34 +01:00
for act in self . actions [ ' DRAWTWO ' ] :
2009-11-29 09:54:15 +01:00
print >> fh , self . actionString ( act , ' DRAWTWO ' )
2009-03-14 11:48:34 +01:00
if act [ 0 ] == self . hero and act [ 1 ] == ' discards ' :
2009-11-29 07:40:32 +01:00
( nc , oc ) = self . holecardsAsSet ( ' DRAWONE ' , act [ 0 ] )
2009-07-11 19:44:32 +02:00
dc = self . discards [ ' DRAWTWO ' ] [ act [ 0 ] ]
2009-03-14 11:48:34 +01:00
kc = oc - dc
2011-03-10 04:15:53 +01:00
print >> fh , ( ( " Dealt to %s [ %s ] [ %s ] " ) % ( act [ 0 ] , " " . join ( kc ) , " " . join ( nc ) ) )
2009-03-14 11:48:34 +01:00
if ' DRAWTHREE ' in self . actions :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** THIRD DRAW *** " )
2009-03-14 11:48:34 +01:00
for act in self . actions [ ' DRAWTHREE ' ] :
2009-11-29 09:54:15 +01:00
print >> fh , self . actionString ( act , ' DRAWTHREE ' )
2009-03-14 11:48:34 +01:00
if act [ 0 ] == self . hero and act [ 1 ] == ' discards ' :
2009-11-29 07:40:32 +01:00
( nc , oc ) = self . holecardsAsSet ( ' DRAWONE ' , act [ 0 ] )
2009-07-11 19:44:32 +02:00
dc = self . discards [ ' DRAWTHREE ' ] [ act [ 0 ] ]
2009-03-14 11:48:34 +01:00
kc = oc - dc
2011-03-10 04:15:53 +01:00
print >> fh , ( ( " Dealt to %s [ %s ] [ %s ] " ) % ( act [ 0 ] , " " . join ( kc ) , " " . join ( nc ) ) )
2009-03-14 11:48:34 +01:00
if ' SHOWDOWN ' in self . actions :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** SHOW DOWN *** " )
2009-03-14 11:48:34 +01:00
#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 :
2011-03-10 04:15:53 +01:00
print >> fh , ( " Uncalled bet ( %s %s ) returned to %s " % ( self . sym , self . pot . returned [ name ] , name ) )
2009-03-14 11:48:34 +01:00
for entry in self . collected :
2011-03-10 04:15:53 +01:00
print >> fh , ( " %s collected %s %s from x pot " % ( entry [ 0 ] , self . sym , entry [ 1 ] ) )
2009-03-14 11:48:34 +01:00
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** SUMMARY *** " )
2009-07-16 05:04:16 +02:00
print >> fh , " %s | Rake %s %.2f " % ( self . pot , self . sym , self . rake )
2009-03-14 11:48:34 +01:00
print >> fh , " \n \n "
2009-02-27 19:42:53 +01:00
class StudHand ( Hand ) :
2010-01-31 12:25:24 +01:00
def __init__ ( self , config , hhc , sitename , gametype , handText , builtFrom = " HHC " ) :
self . config = config
2009-03-10 17:17:54 +01:00
if gametype [ ' base ' ] != ' stud ' :
2009-02-27 19:42:53 +01:00
pass # or indeed don't pass and complain instead
2009-07-01 19:53:30 +02:00
2009-08-11 23:19:01 +02:00
self . allStreets = [ ' BLINDSANTES ' , ' THIRD ' , ' FOURTH ' , ' FIFTH ' , ' SIXTH ' , ' SEVENTH ' ]
2009-07-01 19:53:30 +02:00
self . communityStreets = [ ]
2009-08-11 23:19:01 +02:00
self . actionStreets = [ ' BLINDSANTES ' , ' THIRD ' , ' FOURTH ' , ' FIFTH ' , ' SIXTH ' , ' SEVENTH ' ]
2009-07-01 19:53:30 +02:00
2009-08-11 23:19:01 +02:00
self . streetList = [ ' BLINDSANTES ' , ' THIRD ' , ' FOURTH ' , ' FIFTH ' , ' SIXTH ' , ' SEVENTH ' ] # a list of the observed street names in order
2009-07-16 03:22:07 +02:00
self . holeStreets = [ ' THIRD ' , ' FOURTH ' , ' FIFTH ' , ' SIXTH ' , ' SEVENTH ' ]
2010-01-31 12:25:24 +01:00
Hand . __init__ ( self , self . config , sitename , gametype , handText )
2009-03-06 19:10:04 +01:00
self . sb = gametype [ ' sb ' ]
self . bb = gametype [ ' bb ' ]
2009-03-02 22:48:30 +01:00
#Populate the StudHand
2009-08-11 23:13:07 +02:00
#Generally, we call a 'read' method here, which gets the info according to the particular filter (hhc)
2009-03-02 22:48:30 +01:00
# which then invokes a 'addXXX' callback
2009-03-14 15:01:40 +01:00
if builtFrom == " HHC " :
hhc . readHandInfo ( self )
2010-01-23 11:17:14 +01:00
if self . gametype [ ' type ' ] == ' tour ' :
2010-01-28 11:56:17 +01:00
self . tablename = " %s %s " % ( self . tourNo , self . tablename )
2009-03-14 15:01:40 +01:00
hhc . readPlayerStacks ( self )
hhc . compilePlayerRegexs ( self )
hhc . markStreets ( self )
hhc . readAntes ( self )
hhc . readBringIn ( self )
2009-07-13 06:37:51 +02:00
hhc . readHeroCards ( self )
2009-03-14 15:01:40 +01:00
# Read actions in street order
2009-07-22 14:53:03 +02:00
for street in self . actionStreets :
2009-08-11 23:19:01 +02:00
if street == ' BLINDSANTES ' : continue # OMG--sometime someone folds in the ante round
2009-03-14 15:01:40 +01:00
if self . streets [ street ] :
2009-08-09 16:19:43 +02:00
log . debug ( street + self . streets [ street ] )
2009-03-14 15:01:40 +01:00
hhc . readAction ( self , street )
2009-08-12 16:21:54 +02:00
self . pot . markTotal ( street )
2009-03-14 15:01:40 +01:00
hhc . readCollectPot ( self )
2009-07-04 20:35:20 +02:00
hhc . readShownCards ( self ) # not done yet
2009-03-14 15:01:40 +01:00
self . totalPot ( ) # finalise it (total the pot)
hhc . getRake ( self )
2009-11-03 20:30:52 +01:00
if self . maxseats is None :
2009-07-22 14:53:03 +02:00
self . maxseats = hhc . guessMaxSeats ( self )
2009-07-23 01:21:00 +02:00
hhc . readOther ( self )
2009-03-14 15:01:40 +01:00
elif builtFrom == " DB " :
self . select ( " dummy " ) # Will need a handId
2009-03-02 00:22:47 +01:00
2011-04-04 21:57:54 +02:00
def addShownCards ( self , cards , player , shown = True , mucked = False , dealt = False , string = None ) :
2009-07-13 06:37:51 +02:00
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 ( ' THIRD ' , player , open = [ cards [ 2 ] ] , closed = cards [ 0 : 2 ] , shown = shown , mucked = mucked )
2009-07-16 03:22:07 +02:00
self . addHoleCards ( ' FOURTH ' , player , open = [ cards [ 3 ] ] , closed = [ cards [ 2 ] ] , shown = shown , mucked = mucked )
self . addHoleCards ( ' FIFTH ' , player , open = [ cards [ 4 ] ] , closed = cards [ 2 : 4 ] , shown = shown , mucked = mucked )
self . addHoleCards ( ' SIXTH ' , player , open = [ cards [ 5 ] ] , closed = cards [ 2 : 5 ] , shown = shown , mucked = mucked )
2010-09-09 07:19:19 +02:00
if len ( cards ) > 6 :
self . addHoleCards ( ' SEVENTH ' , player , open = [ ] , closed = [ cards [ 6 ] ] , shown = shown , mucked = mucked )
2011-04-04 21:57:54 +02:00
if string is not None :
self . showdownStrings [ player ] = string
2009-07-13 06:37:51 +02:00
2009-03-02 22:48:30 +01:00
def addPlayerCards ( self , player , street , open = [ ] , closed = [ ] ) :
""" \
Assigns observed cards to a player .
player ( string ) name of player
street ( string ) the street name ( in streetList )
open list of card bigrams e . g . [ ' 2h ' , ' Jc ' ] , dealt face up
closed likewise , but known only to player
"""
2009-08-09 16:19:43 +02:00
log . debug ( " addPlayerCards %s , o %s x %s " % ( player , open , closed ) )
2009-03-02 22:48:30 +01:00
try :
self . checkPlayerExists ( player )
2009-07-01 19:53:30 +02:00
self . holecards [ street ] [ player ] = ( open , closed )
2009-03-02 22:48:30 +01:00
except FpdbParseError , e :
2010-08-15 05:59:05 +02:00
print _ ( " [ERROR] Tried to add holecards for unknown player: %s " ) % ( player , )
2009-03-02 22:48:30 +01:00
2009-03-11 17:51:58 +01:00
# TODO: def addComplete(self, player, amount):
def addComplete ( self , street , player , amountTo ) :
# assert street=='THIRD'
# This needs to be called instead of addRaiseTo, and it needs to take account of self.lastBet['THIRD'] to determine the raise-by size
""" \
Add a complete on [ street ] by [ player ] to [ amountTo ]
"""
2010-08-15 05:59:05 +02:00
log . debug ( _ ( " %s %s completes %s " ) % ( street , player , amountTo ) )
2011-02-24 15:49:50 +01:00
amountTo = amountTo . replace ( u ' , ' , u ' ' ) #some sites have commas
2009-03-11 17:51:58 +01:00
self . checkPlayerExists ( player )
Bp = self . lastBet [ ' THIRD ' ]
2011-02-25 06:05:39 +01:00
Bc = sum ( self . bets [ street ] [ player ] )
2009-03-11 17:51:58 +01:00
Rt = Decimal ( amountTo )
C = Bp - Bc
Rb = Rt - C
2010-09-28 22:50:33 +02:00
self . _addRaise ( street , player , C , Rb , Rt , ' completes ' )
2009-03-11 17:51:58 +01:00
#~ self.bets[street][player].append(C + Rb)
#~ self.stacks[player] -= (C + Rb)
#~ act = (player, 'raises', Rb, Rt, C, self.stacks[player]==0)
#~ self.actions[street].append(act)
#~ self.lastBet[street] = Rt # TODO check this is correct
#~ self.pot.addMoney(player, C+Rb)
2009-08-11 23:13:07 +02:00
2009-03-02 22:48:30 +01:00
def addBringIn ( self , player , bringin ) :
2009-03-02 00:22:47 +01:00
if player is not None :
2010-08-15 05:59:05 +02:00
log . debug ( _ ( " Bringin: %s , %s " ) % ( player , bringin ) )
2011-02-25 11:07:14 +01:00
bringin = bringin . replace ( u ' , ' , u ' ' ) #some sites have commas
2011-02-24 15:51:40 +01:00
bringin = Decimal ( bringin )
self . bets [ ' THIRD ' ] [ player ] . append ( bringin )
self . stacks [ player ] - = bringin
act = ( player , ' bringin ' , bringin , self . stacks [ player ] == 0 )
2009-03-02 00:22:47 +01:00
self . actions [ ' THIRD ' ] . append ( act )
2011-02-24 15:51:40 +01:00
self . lastBet [ ' THIRD ' ] = bringin
self . pot . addMoney ( player , bringin )
2009-07-04 20:35:20 +02:00
2009-08-12 16:21:54 +02:00
def getStreetTotals ( self ) :
# street1Pot INT, /* pot size at flop/street4 */
# street2Pot INT, /* pot size at turn/street5 */
# street3Pot INT, /* pot size at river/street6 */
# street4Pot INT, /* pot size at sd/street7 */
# showdownPot INT, /* pot size at sd/street7 */
return ( 0 , 0 , 0 , 0 , 0 )
2010-01-28 11:56:17 +01:00
2009-03-02 22:48:30 +01:00
def writeHand ( self , fh = sys . __stdout__ ) :
2009-02-25 13:34:05 +01:00
# PokerStars format.
2011-03-10 04:15:53 +01:00
# HH output should not be translated
2009-07-15 17:50:27 +02:00
super ( StudHand , self ) . writeHand ( fh )
2009-08-11 23:13:07 +02:00
2009-08-11 23:19:01 +02:00
players_who_post_antes = set ( [ x [ 0 ] for x in self . actions [ ' BLINDSANTES ' ] ] )
2009-02-25 13:34:05 +01:00
for player in [ x for x in self . players if x [ 1 ] in players_who_post_antes ] :
#Only print stacks of players who do something preflop
2011-03-10 04:15:53 +01:00
print >> fh , ( " Seat %s : %s ( %s %s in chips) " % ( player [ 0 ] , player [ 1 ] , self . sym , player [ 2 ] ) )
2009-02-25 13:34:05 +01:00
2009-08-11 23:19:01 +02:00
if ' BLINDSANTES ' in self . actions :
for act in self . actions [ ' BLINDSANTES ' ] :
2011-03-10 04:15:53 +01:00
print >> fh , ( " %s : posts the ante %s %s " % ( act [ 0 ] , self . sym , act [ 3 ] ) )
2009-02-25 16:45:46 +01:00
2009-02-25 13:34:05 +01:00
if ' THIRD ' in self . actions :
2009-03-11 17:51:58 +01:00
dealt = 0
2011-03-10 04:15:53 +01:00
#~ print >>fh, ("*** 3RD STREET ***")
2009-03-02 22:48:30 +01:00
for player in [ x [ 1 ] for x in self . players if x [ 1 ] in players_who_post_antes ] :
2009-07-01 19:53:30 +02:00
if self . holecards [ ' THIRD ' ] . has_key ( player ) :
( open , closed ) = self . holecards [ ' THIRD ' ] [ player ]
2009-03-11 17:51:58 +01:00
dealt + = 1
if dealt == 1 :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** 3RD STREET *** " )
# print >>fh, ("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "] " if closed else " ", "[" + " ".join(open) + "]" if open else "")
2009-07-16 03:22:07 +02:00
print >> fh , self . writeHoleCards ( ' THIRD ' , player )
2009-02-25 13:34:05 +01:00
for act in self . actions [ ' THIRD ' ] :
2009-02-25 17:23:46 +01:00
#FIXME: Need some logic here for bringin vs completes
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2009-02-25 13:34:05 +01:00
if ' FOURTH ' in self . actions :
2009-03-11 17:51:58 +01:00
dealt = 0
2011-03-10 04:15:53 +01:00
#~ print >>fh, ("*** 4TH STREET ***")
2009-03-11 17:51:58 +01:00
for player in [ x [ 1 ] for x in self . players if x [ 1 ] in players_who_post_antes ] :
2009-07-01 19:53:30 +02:00
if player in self . holecards [ ' FOURTH ' ] :
2009-03-11 17:51:58 +01:00
dealt + = 1
if dealt == 1 :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** 4TH STREET *** " )
2009-07-16 03:22:07 +02:00
print >> fh , self . writeHoleCards ( ' FOURTH ' , player )
2009-02-25 13:34:05 +01:00
for act in self . actions [ ' FOURTH ' ] :
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2009-02-25 13:34:05 +01:00
if ' FIFTH ' in self . actions :
2009-03-11 17:51:58 +01:00
dealt = 0
2011-03-10 04:15:53 +01:00
#~ print >>fh, ("*** 5TH STREET ***")
2009-03-11 17:51:58 +01:00
for player in [ x [ 1 ] for x in self . players if x [ 1 ] in players_who_post_antes ] :
2009-07-01 19:53:30 +02:00
if self . holecards [ ' FIFTH ' ] . has_key ( player ) :
2009-03-11 17:51:58 +01:00
dealt + = 1
if dealt == 1 :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** 5TH STREET *** " )
2009-07-16 03:22:07 +02:00
print >> fh , self . writeHoleCards ( ' FIFTH ' , player )
2009-02-25 13:34:05 +01:00
for act in self . actions [ ' FIFTH ' ] :
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2009-02-25 13:34:05 +01:00
if ' SIXTH ' in self . actions :
2009-03-11 17:51:58 +01:00
dealt = 0
2011-03-10 04:15:53 +01:00
#~ print >>fh, ("*** 6TH STREET ***")
2009-03-11 17:51:58 +01:00
for player in [ x [ 1 ] for x in self . players if x [ 1 ] in players_who_post_antes ] :
2009-07-01 19:53:30 +02:00
if self . holecards [ ' SIXTH ' ] . has_key ( player ) :
2009-03-11 17:51:58 +01:00
dealt + = 1
if dealt == 1 :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** 6TH STREET *** " )
2009-07-16 03:22:07 +02:00
print >> fh , self . writeHoleCards ( ' SIXTH ' , player )
2009-02-25 13:34:05 +01:00
for act in self . actions [ ' SIXTH ' ] :
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2009-02-25 13:34:05 +01:00
if ' SEVENTH ' in self . actions :
2009-03-11 17:51:58 +01:00
# OK. It's possible that they're all in at an earlier street, but only closed cards are dealt.
# Then we have no 'dealt to' lines, no action lines, but still 7th street should appear.
# The only way I can see to know whether to print this line is by knowing the state of the hand
# i.e. are all but one players folded; is there an allin showdown; and all that.
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** RIVER *** " )
2009-03-11 17:51:58 +01:00
for player in [ x [ 1 ] for x in self . players if x [ 1 ] in players_who_post_antes ] :
2009-07-01 19:53:30 +02:00
if self . holecards [ ' SEVENTH ' ] . has_key ( player ) :
2009-07-16 03:22:07 +02:00
if self . writeHoleCards ( ' SEVENTH ' , player ) :
print >> fh , self . writeHoleCards ( ' SEVENTH ' , player )
2009-02-25 13:34:05 +01:00
for act in self . actions [ ' SEVENTH ' ] :
2009-06-19 08:21:35 +02:00
print >> fh , self . actionString ( act )
2009-02-25 13:34:05 +01:00
#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 :
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** SHOW DOWN *** " )
2009-03-04 15:29:13 +01:00
# TODO: print showdown lines.
2009-02-25 13:34:05 +01:00
# 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 :
2011-03-10 04:15:53 +01:00
print >> fh , ( " Uncalled bet ( %s %s ) returned to %s " % ( self . sym , self . pot . returned [ name ] , name ) )
2009-02-25 13:34:05 +01:00
for entry in self . collected :
2011-03-10 04:15:53 +01:00
print >> fh , ( " %s collected %s %s from x pot " % ( entry [ 0 ] , self . sym , entry [ 1 ] ) )
2009-02-25 13:34:05 +01:00
2011-03-10 04:15:53 +01:00
print >> fh , ( " *** SUMMARY *** " )
2009-07-16 05:04:16 +02:00
print >> fh , " %s | Rake %s %.2f " % ( self . pot , self . sym , self . rake )
2009-07-16 05:40:07 +02:00
# TODO: side pots
2009-02-25 13:34:05 +01:00
board = [ ]
for s in self . board . values ( ) :
board + = s
if board : # sometimes hand ends preflop without a board
2011-03-10 04:15:53 +01:00
print >> fh , ( " Board [ %s ] " % ( " " . join ( board ) ) )
2009-02-25 13:34:05 +01:00
for player in [ x for x in self . players if x [ 1 ] in players_who_post_antes ] :
seatnum = player [ 0 ]
name = player [ 1 ]
if name in self . collectees and name in self . shown :
2011-03-10 04:15:53 +01:00
print >> fh , ( " Seat %d : %s showed [ %s ] and won ( %s %s ) " % ( seatnum , name , self . join_holecards ( name ) , self . sym , self . collectees [ name ] ) )
2009-02-25 13:34:05 +01:00
elif name in self . collectees :
2011-03-10 04:15:53 +01:00
print >> fh , ( " Seat %d : %s collected ( %s %s ) " % ( seatnum , name , self . sym , self . collectees [ name ] ) )
2008-12-16 22:08:10 +01:00
elif name in self . shown :
2011-03-10 04:15:53 +01:00
print >> fh , ( " Seat %d : %s showed [ %s ] " % ( seatnum , name , self . join_holecards ( name ) ) )
2009-07-04 21:19:46 +02:00
elif name in self . mucked :
2011-03-10 04:15:53 +01:00
print >> fh , ( " Seat %d : %s mucked [ %s ] " % ( seatnum , name , self . join_holecards ( name ) ) )
2008-12-16 22:08:10 +01:00
elif name in self . folded :
2011-03-10 04:15:53 +01:00
print >> fh , ( " Seat %d : %s folded " % ( seatnum , name ) )
2008-12-12 15:29:45 +01:00
else :
2011-03-10 04:15:53 +01:00
print >> fh , ( " Seat %d : %s mucked " % ( seatnum , name ) )
2008-12-12 15:29:45 +01:00
2008-12-16 00:56:19 +01:00
print >> fh , " \n \n "
2008-12-12 15:29:45 +01:00
2009-07-16 03:22:07 +02:00
def writeHoleCards ( self , street , player ) :
hc = " Dealt to %s [ " % player
if street == ' THIRD ' :
if player == self . hero :
return hc + " " . join ( self . holecards [ street ] [ player ] [ 1 ] ) + " " + " " . join ( self . holecards [ street ] [ player ] [ 0 ] ) + ' ] '
else :
return hc + " " . join ( self . holecards [ street ] [ player ] [ 0 ] ) + ' ] '
2009-08-11 23:13:07 +02:00
if street == ' SEVENTH ' and player != self . hero : return # only write 7th st line for hero, LDO
2009-07-16 03:46:45 +02:00
return hc + " " . join ( self . holecards [ street ] [ player ] [ 1 ] ) + " ] [ " + " " . join ( self . holecards [ street ] [ player ] [ 0 ] ) + " ] "
2009-07-16 03:22:07 +02:00
2009-11-30 07:20:48 +01:00
def join_holecards ( self , player , asList = False ) :
""" Function returns a string for the stud writeHand method by default
With asList = True it returns the set cards for a player including down cards if they aren ' t know " " "
2009-07-04 21:19:46 +02:00
holecards = [ ]
for street in self . holeStreets :
if self . holecards [ street ] . has_key ( player ) :
2009-07-16 04:11:23 +02:00
if street == ' THIRD ' :
holecards = holecards + self . holecards [ street ] [ player ] [ 1 ] + self . holecards [ street ] [ player ] [ 0 ]
elif street == ' SEVENTH ' :
if player == self . hero :
holecards = holecards + self . holecards [ street ] [ player ] [ 0 ]
else :
holecards = holecards + self . holecards [ street ] [ player ] [ 1 ]
else :
holecards = holecards + self . holecards [ street ] [ player ] [ 0 ]
2009-11-30 07:20:48 +01:00
if asList == False :
return " " . join ( holecards )
else :
if player == self . hero or len ( holecards ) == 7 :
return holecards
elif len ( holecards ) < = 4 :
#Non hero folded before showdown, add first two downcards
holecards = [ u ' 0x ' , u ' 0x ' ] + holecards
else :
2010-08-15 05:59:05 +02:00
log . warning ( _ ( " join_holecards: # of holecards should be either < 4, 4 or 7 - 5 and 6 should be impossible for anyone who is not a hero " ) )
log . warning ( _ ( " join_holcards: holecards( %s ): %s " ) % ( player , holecards ) )
2010-12-10 18:26:56 +01:00
if holecards == [ u ' 0x ' , u ' 0x ' ] :
log . warning ( _ ( " join_holecards: Player ' %s ' appears not to have been dealt a card " ) )
# If a player is listed but not dealt a card in a cash game this can occur
# Noticed in FTP Razz hand. Return 3 empty cards in this case
holecards = [ u ' 0x ' , u ' 0x ' , u ' 0x ' ]
2009-11-30 07:20:48 +01:00
return holecards
2008-12-19 04:01:45 +01:00
class Pot ( object ) :
2008-12-20 17:48:25 +01:00
def __init__ ( self ) :
2009-08-12 16:21:54 +02:00
self . contenders = set ( )
self . committed = { }
self . streettotals = { }
2010-02-18 16:17:08 +01:00
self . common = { }
2009-08-12 16:21:54 +02:00
self . total = None
self . returned = { }
self . sym = u ' $ ' # this is the default currency symbol
2009-07-16 18:13:24 +02:00
def setSym ( self , sym ) :
self . sym = sym
2009-08-11 23:13:07 +02:00
2008-12-20 17:48:25 +01:00
def addPlayer ( self , player ) :
self . committed [ player ] = Decimal ( 0 )
2010-02-18 16:17:08 +01:00
self . common [ player ] = Decimal ( 0 )
2009-08-11 23:13:07 +02:00
2008-12-19 04:01:45 +01:00
def addFold ( self , player ) :
2008-12-20 17:48:25 +01:00
# addFold must be called when a player folds
self . contenders . discard ( player )
2009-08-11 23:13:07 +02:00
2010-02-18 16:17:08 +01:00
def addCommonMoney ( self , player , amount ) :
self . common [ player ] + = amount
2009-08-11 23:19:01 +02:00
2008-12-19 04:01:45 +01:00
def addMoney ( self , player , amount ) :
2008-12-20 17:48:25 +01:00
# addMoney must be called for any actions that put money in the pot, in the order they occur
self . contenders . add ( player )
2008-12-19 04:01:45 +01:00
self . committed [ player ] + = amount
2008-12-20 17:48:25 +01:00
2009-08-12 16:21:54 +02:00
def markTotal ( self , street ) :
2010-02-18 16:17:08 +01:00
self . streettotals [ street ] = sum ( self . committed . values ( ) ) + sum ( self . common . values ( ) )
2009-08-12 16:21:54 +02:00
def getTotalAtStreet ( self , street ) :
if street in self . streettotals :
return self . streettotals [ street ]
return 0
2008-12-20 17:48:25 +01:00
def end ( self ) :
2010-02-18 16:17:08 +01:00
self . total = sum ( self . committed . values ( ) ) + sum ( self . common . values ( ) )
2009-08-11 23:13:07 +02:00
2008-12-20 17:48:25 +01:00
# Return any uncalled bet.
2008-12-19 04:01:45 +01:00
committed = sorted ( [ ( v , k ) for ( k , v ) in self . committed . items ( ) ] )
2010-02-18 22:12:01 +01:00
#print "DEBUG: committed: %s" % committed
2010-09-28 06:04:40 +02:00
#ERROR below. lastbet is correct in most cases, but wrong when
2010-02-15 17:42:13 +01:00
# additional money is committed to the pot in cash games
# due to an additional sb being posted. (Speculate that
# posting sb+bb is also potentially wrong)
2008-12-19 04:01:45 +01:00
lastbet = committed [ - 1 ] [ 0 ] - committed [ - 2 ] [ 0 ]
if lastbet > 0 : # uncalled
returnto = committed [ - 1 ] [ 1 ]
2009-02-21 13:37:47 +01:00
#print "DEBUG: returning %f to %s" % (lastbet, returnto)
2008-12-19 04:01:45 +01:00
self . total - = lastbet
self . committed [ returnto ] - = lastbet
2009-02-21 13:37:47 +01:00
self . returned [ returnto ] = lastbet
2009-02-20 09:22:58 +01:00
2008-12-20 17:48:25 +01:00
# Work out side pots
2008-12-19 04:01:45 +01:00
commitsall = sorted ( [ ( v , k ) for ( k , v ) in self . committed . items ( ) if v > 0 ] )
2009-02-20 09:22:58 +01:00
2008-12-20 17:48:25 +01:00
self . pots = [ ]
2010-09-02 08:02:19 +02:00
try :
while len ( commitsall ) > 0 :
commitslive = [ ( v , k ) for ( v , k ) in commitsall if k in self . contenders ]
v1 = commitslive [ 0 ] [ 0 ]
self . pots + = [ sum ( [ min ( v , v1 ) for ( v , k ) in commitsall ] ) ]
commitsall = [ ( ( v - v1 ) , k ) for ( v , k ) in commitsall if v - v1 > 0 ]
except IndexError , e :
2011-03-10 04:15:53 +01:00
log . error ( _ ( " Pot.end(): Major failure while calculating pot: ' %s ' " ) % e )
raise FpdbParseError ( _ ( " Pot.end(): Major failure while calculating pot: ' %s ' " ) % e )
2008-12-19 04:01:45 +01:00
# TODO: I think rake gets taken out of the pots.
# so it goes:
# total pot x. main pot y, side pot z. | rake r
# and y+z+r = x
# for example:
# Total pot $124.30 Main pot $98.90. Side pot $23.40. | Rake $2
2009-08-11 23:13:07 +02:00
2008-12-20 17:48:25 +01:00
def __str__ ( self ) :
2009-07-27 20:25:24 +02:00
if self . sym is None :
self . sym = " C "
2008-12-20 17:48:25 +01:00
if self . total is None :
2011-03-10 05:14:16 +01:00
print ( _ ( " DEBUG: " ) + _ ( " call Pot.end() before printing pot total " ) )
2008-12-20 17:48:25 +01:00
# NB if I'm sure end() is idempotent, call it here.
2011-03-10 05:14:16 +01:00
raise FpdbParseError ( _ ( " Error in printing Hand object " ) )
2009-08-11 23:13:07 +02:00
2009-07-27 20:25:24 +02:00
ret = " Total pot %s %.2f " % ( self . sym , self . total )
if len ( self . pots ) < 2 :
return ret ;
ret + = " Main pot %s %.2f " % ( self . sym , self . pots [ 0 ] )
2009-08-11 23:13:07 +02:00
2009-07-27 20:25:24 +02:00
return ret + ' ' . join ( [ ( " Side pot %s %.2f . " % ( self . sym , self . pots [ x ] ) ) for x in xrange ( 1 , len ( self . pots ) ) ] )