whitespace

This commit is contained in:
Matt Turnbull 2008-12-06 14:15:41 +00:00
parent 95f43dfd74
commit 72addde510
2 changed files with 411 additions and 411 deletions

View File

@ -64,39 +64,39 @@ from HandHistoryConverter import *
# smaragdar wins $ 102 USD from main pot with a pair of aces [ ad, ah, qs, 8h, 6c ] # smaragdar wins $ 102 USD from main pot with a pair of aces [ ad, ah, qs, 8h, 6c ]
class Everleaf(HandHistoryConverter): class Everleaf(HandHistoryConverter):
def __init__(self, config, file): def __init__(self, config, file):
print "Initialising Everleaf converter class" print "Initialising Everleaf converter class"
HandHistoryConverter.__init__(self, config, file, "Everleaf") # Call super class init. HandHistoryConverter.__init__(self, config, file, "Everleaf") # Call super class init.
self.sitename = "Everleaf" self.sitename = "Everleaf"
self.setFileType("text") self.setFileType("text")
self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)') self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)')
self.rexx.setSplitHandRegex('\n\n\n\n') self.rexx.setSplitHandRegex('\n\n\n\n')
self.rexx.setHandInfoRegex('.*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+)\nTable (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)') self.rexx.setHandInfoRegex('.*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+)\nTable (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
self.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \( \$ (?P<CASH>[.0-9]+) USD \)') self.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \( \$ (?P<CASH>[.0-9]+) USD \)')
self.rexx.setPostSbRegex('.*\n(?P<PNAME>.*): posts small blind \[\$? (?P<SB>[.0-9]+)') self.rexx.setPostSbRegex('.*\n(?P<PNAME>.*): posts small blind \[\$? (?P<SB>[.0-9]+)')
self.rexx.setPostBbRegex('.*\n(?P<PNAME>.*): posts big blind \[\$? (?P<BB>[.0-9]+)') self.rexx.setPostBbRegex('.*\n(?P<PNAME>.*): posts big blind \[\$? (?P<BB>[.0-9]+)')
# mct : what about posting small & big blinds simultaneously? # mct : what about posting small & big blinds simultaneously?
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<HOLE1>\S\S), (?P<HOLE2>\S\S) \]') self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<HOLE1>\S\S), (?P<HOLE2>\S\S) \]')
self.rexx.setActionStepRegex('.*\n(?P<PNAME>.*) (?P<ATYPE>bets|checks|raises|calls|folds)(\s\[\$ (?P<BET>[.\d]+) USD\])?') self.rexx.setActionStepRegex('.*\n(?P<PNAME>.*) (?P<ATYPE>bets|checks|raises|calls|folds)(\s\[\$ (?P<BET>[.\d]+) USD\])?')
self.rexx.compileRegexes() self.rexx.compileRegexes()
def readSupportedGames(self): def readSupportedGames(self):
pass pass
def determineGameType(self): def determineGameType(self):
# Cheating with this regex, only support nlhe at the moment # Cheating with this regex, only support nlhe at the moment
gametype = ["ring", "hold", "nl"] gametype = ["ring", "hold", "nl"]
m = self.rexx.game_info_re.search(self.obs) m = self.rexx.game_info_re.search(self.obs)
gametype = gametype + [m.group('SB')] gametype = gametype + [m.group('SB')]
gametype = gametype + [m.group('BB')] gametype = gametype + [m.group('BB')]
return gametype return gametype
def readHandInfo(self, hand): def readHandInfo(self, hand):
m = self.rexx.hand_info_re.search(hand.string) m = self.rexx.hand_info_re.search(hand.string)
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')
# These work, but the info is already in the Hand class - should be used for tourneys though. # These work, but the info is already in the Hand class - should be used for tourneys though.
# m.group('SB') # m.group('SB')
# m.group('BB') # m.group('BB')
@ -109,68 +109,68 @@ class Everleaf(HandHistoryConverter):
# 2008/11/10 3:58:52 ET # 2008/11/10 3:58:52 ET
#TODO: Do conversion from GMT to ET #TODO: Do conversion from GMT to ET
#TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this) #TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this)
hand.starttime = "%d/%02d/%02d %d:%02d:%02d ET" %(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), hand.starttime = "%d/%02d/%02d %d:%02d:%02d ET" %(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')),
int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC'))) int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
hand.buttonpos = int(m.group('BUTTON')) hand.buttonpos = int(m.group('BUTTON'))
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
m = self.rexx.player_info_re.finditer(hand.string) m = self.rexx.player_info_re.finditer(hand.string)
players = [] players = []
for a in m: for a in m:
hand.addPlayer(a.group('SEAT'), a.group('PNAME'), a.group('CASH')) hand.addPlayer(a.group('SEAT'), a.group('PNAME'), a.group('CASH'))
def markStreets(self, hand): def markStreets(self, hand):
# PREFLOP = ** Dealing down cards ** # PREFLOP = ** Dealing down cards **
m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.string,re.DOTALL) m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.string,re.DOTALL)
# for street in m.groupdict(): # for street in m.groupdict():
# print "DEBUG: Street: %s\tspan: %s" %(street, str(m.span(street))) # print "DEBUG: Street: %s\tspan: %s" %(street, str(m.span(street)))
hand.streets = m hand.streets = m
def readBlinds(self, hand): def readBlinds(self, hand):
try: try:
m = self.rexx.small_blind_re.search(hand.string) m = self.rexx.small_blind_re.search(hand.string)
hand.addBlind(m.group('PNAME'), m.group('SB')) hand.addBlind(m.group('PNAME'), m.group('SB'))
#hand.posted = [m.group('PNAME')] #hand.posted = [m.group('PNAME')]
except: except:
hand.addBlind(None, 0) hand.addBlind(None, 0)
#hand.posted = ["FpdbNBP"] #hand.posted = ["FpdbNBP"]
m = self.rexx.big_blind_re.finditer(hand.string) m = self.rexx.big_blind_re.finditer(hand.string)
for a in m: for a in m:
hand.addBlind(a.group('PNAME'), a.group('BB')) hand.addBlind(a.group('PNAME'), a.group('BB'))
#hand.posted = hand.posted + [a.group('PNAME')] #hand.posted = hand.posted + [a.group('PNAME')]
def readHeroCards(self, hand): def readHeroCards(self, hand):
m = self.rexx.hero_cards_re.search(hand.string) m = self.rexx.hero_cards_re.search(hand.string)
if(m == None): if(m == None):
#Not involved in hand #Not involved in hand
hand.involved = False hand.involved = False
else: else:
hand.hero = m.group('PNAME') hand.hero = m.group('PNAME')
hand.addHoleCards(m.group('HOLE1'), m.group('HOLE2')) hand.addHoleCards(m.group('HOLE1'), m.group('HOLE2'))
def readAction(self, hand, street): def readAction(self, hand, street):
m = self.rexx.action_re.finditer(hand.streets.group(street)) m = self.rexx.action_re.finditer(hand.streets.group(street))
hand.actions[street] = [] hand.actions[street] = []
for action in m: for action in m:
if action.group('ATYPE') == 'raises': if action.group('ATYPE') == 'raises':
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') ) hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
elif action.group('ATYPE') == 'calls': elif action.group('ATYPE') == 'calls':
hand.addCall( street, action.group('PNAME'), action.group('BET') ) hand.addCall( street, action.group('PNAME'), action.group('BET') )
elif action.group('ATYPE') == 'bets': elif action.group('ATYPE') == 'bets':
hand.addBet( street, action.group('PNAME'), action.group('BET') ) hand.addBet( street, action.group('PNAME'), action.group('BET') )
else: else:
print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),) print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)
hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE')]] hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE')]]
def getRake(self, hand): def getRake(self, hand):
hand.rake = hand.totalpot * Decimal('0.05') # probably not quite right hand.rake = hand.totalpot * Decimal('0.05') # probably not quite right
if __name__ == "__main__": if __name__ == "__main__":
c = Configuration.Config() c = Configuration.Config()
e = Everleaf(c, "Speed_Kuala.txt") e = Everleaf(c, "Speed_Kuala.txt")
e.processFile() e.processFile()
print str(e) print str(e)

View File

@ -28,400 +28,400 @@ import operator
from xml.dom.minidom import Node from xml.dom.minidom import Node
class HandHistoryConverter: class HandHistoryConverter:
def __init__(self, config, file, sitename): def __init__(self, config, file, sitename):
print "HandHistory init called" print "HandHistory init called"
self.c = config self.c = config
self.sitename = sitename self.sitename = sitename
self.obs = "" # One big string self.obs = "" # One big string
self.filetype = "text" self.filetype = "text"
self.doc = None # For XML based HH files self.doc = None # For XML based HH files
self.file = file self.file = file
self.hhbase = self.c.get_import_parameters().get("hhArchiveBase") self.hhbase = self.c.get_import_parameters().get("hhArchiveBase")
self.hhbase = os.path.expanduser(self.hhbase) self.hhbase = os.path.expanduser(self.hhbase)
self.hhdir = os.path.join(self.hhbase,sitename) self.hhdir = os.path.join(self.hhbase,sitename)
self.gametype = [] self.gametype = []
# self.ofile = os.path.join(self.hhdir,file) # self.ofile = os.path.join(self.hhdir,file)
self.rexx = FpdbRegex.FpdbRegex() self.rexx = FpdbRegex.FpdbRegex()
def __str__(self): def __str__(self):
tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) tmp = "HandHistoryConverter: '%s'\n" % (self.sitename)
tmp = tmp + "\thhbase: '%s'\n" % (self.hhbase) tmp = tmp + "\thhbase: '%s'\n" % (self.hhbase)
tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir) tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir)
tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype) tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype)
tmp = tmp + "\tinfile: '%s'\n" % (self.file) tmp = tmp + "\tinfile: '%s'\n" % (self.file)
# tmp = tmp + "\toutfile: '%s'\n" % (self.ofile) # tmp = tmp + "\toutfile: '%s'\n" % (self.ofile)
# tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0]) # tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0])
# tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1]) # tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1])
# tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2]) # tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2])
# tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4]) # tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4])
return tmp return tmp
def processFile(self): def processFile(self):
if not self.sanityCheck(): if not self.sanityCheck():
print "Cowardly refusing to continue after failed sanity check" print "Cowardly refusing to continue after failed sanity check"
return return
self.readFile(self.file) self.readFile(self.file)
self.gametype = self.determineGameType() self.gametype = self.determineGameType()
self.hands = self.splitFileIntoHands() self.hands = self.splitFileIntoHands()
for hand in self.hands: for hand in self.hands:
self.readHandInfo(hand) self.readHandInfo(hand)
self.readPlayerStacks(hand) self.readPlayerStacks(hand)
self.markStreets(hand) self.markStreets(hand)
self.readBlinds(hand) self.readBlinds(hand)
self.readHeroCards(hand) self.readHeroCards(hand)
# Read action (Note: no guarantee this is in hand order. # Read action (Note: no guarantee this is in hand order.
for street in hand.streets.groupdict(): for street in hand.streets.groupdict():
self.readAction(hand, street) self.readAction(hand, street)
# finalise it (total the pot) # finalise it (total the pot)
hand.totalPot() hand.totalPot()
self.getRake(hand) self.getRake(hand)
if(hand.involved == True): if(hand.involved == True):
#self.writeHand("output file", hand) #self.writeHand("output file", hand)
hand.printHand() hand.printHand()
else: else:
pass #Don't write out observed hands pass #Don't write out observed hands
##### #####
# These functions are parse actions that may be overridden by the inheriting class # These functions are parse actions that may be overridden by the inheriting class
# #
def readSupportedGames(self): abstract def readSupportedGames(self): abstract
# should return a list # should return a list
# type base limit # type base limit
# [ ring, hold, nl , sb, bb ] # [ ring, hold, nl , sb, bb ]
# Valid types specified in docs/tabledesign.html in Gametypes # Valid types specified in docs/tabledesign.html in Gametypes
def determineGameType(self): abstract def determineGameType(self): abstract
# Read any of: # Read any of:
# HID HandID # HID HandID
# TABLE Table name # TABLE Table name
# SB small blind # SB small blind
# BB big blind # BB big blind
# GAMETYPE gametype # GAMETYPE gametype
# YEAR MON DAY HR MIN SEC datetime # YEAR MON DAY HR MIN SEC datetime
# BUTTON button seat number # BUTTON button seat number
def readHandInfo(self, hand): abstract def readHandInfo(self, hand): abstract
# Needs to return a list of lists in the format # Needs to return a list of lists in the format
# [['seat#', 'player1name', 'stacksize'] ['seat#', 'player2name', 'stacksize'] [...]] # [['seat#', 'player1name', 'stacksize'] ['seat#', 'player2name', 'stacksize'] [...]]
def readPlayerStacks(self, hand): abstract def readPlayerStacks(self, hand): abstract
# Needs to return a MatchObject with group names identifying the streets into the Hand object # Needs to return a MatchObject with group names identifying the streets into the Hand object
# that is, pulls the chunks of preflop, flop, turn and river text into hand.streets MatchObject. # that is, pulls the chunks of preflop, flop, turn and river text into hand.streets MatchObject.
def markStreets(self, hand): abstract def markStreets(self, hand): abstract
#Needs to return a list in the format #Needs to return a list in the format
# ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb, # ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb,
# addtional players are assumed to post a bb oop # addtional players are assumed to post a bb oop
def readBlinds(self, hand): abstract def readBlinds(self, hand): abstract
def readHeroCards(self, hand): abstract def readHeroCards(self, hand): abstract
def readAction(self, hand, street): abstract def readAction(self, hand, street): abstract
# Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated # Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated
# so that an inheriting class can calculate it for the specific site if need be. # so that an inheriting class can calculate it for the specific site if need be.
def getRake(self, hand): abstract def getRake(self, hand): abstract
def sanityCheck(self): def sanityCheck(self):
sane = True sane = True
base_w = False base_w = False
#Check if hhbase exists and is writable #Check if hhbase exists and is writable
#Note: Will not try to create the base HH directory #Note: Will not try to create the base HH directory
if not (os.access(self.hhbase, os.W_OK) and os.path.isdir(self.hhbase)): if not (os.access(self.hhbase, os.W_OK) and os.path.isdir(self.hhbase)):
print "HH Sanity Check: Directory hhbase '" + self.hhbase + "' doesn't exist or is not writable" print "HH Sanity Check: Directory hhbase '" + self.hhbase + "' doesn't exist or is not writable"
else: else:
#Check if hhdir exists and is writable #Check if hhdir exists and is writable
if not os.path.isdir(self.hhdir): if not os.path.isdir(self.hhdir):
# In first pass, dir may not exist. Attempt to create dir # In first pass, dir may not exist. Attempt to create dir
print "Creating directory: '%s'" % (self.hhdir) print "Creating directory: '%s'" % (self.hhdir)
os.mkdir(self.hhdir) os.mkdir(self.hhdir)
sane = True sane = True
elif os.access(self.hhdir, os.W_OK): elif os.access(self.hhdir, os.W_OK):
sane = True sane = True
else: else:
print "HH Sanity Check: Directory hhdir '" + self.hhdir + "' or its parent directory are not writable" print "HH Sanity Check: Directory hhdir '" + self.hhdir + "' or its parent directory are not writable"
return sane return sane
# Functions not necessary to implement in sub class # Functions not necessary to implement in sub class
def setFileType(self, filetype = "text"): def setFileType(self, filetype = "text"):
self.filetype = filetype self.filetype = filetype
def splitFileIntoHands(self): def splitFileIntoHands(self):
hands = [] hands = []
list = self.rexx.split_hand_re.split(self.obs) list = self.rexx.split_hand_re.split(self.obs)
list.pop() #Last entry is empty list.pop() #Last entry is empty
for l in list: for l in list:
# print "'" + l + "'" # print "'" + l + "'"
hands = hands + [Hand(self.sitename, self.gametype, l)] hands = hands + [Hand(self.sitename, self.gametype, l)]
return hands return hands
def readFile(self, filename): def readFile(self, filename):
"""Read file""" """Read file"""
print "Reading file: '%s'" %(filename) print "Reading file: '%s'" %(filename)
if(self.filetype == "text"): if(self.filetype == "text"):
infile=open(filename, "rU") infile=open(filename, "rU")
self.obs = infile.read() self.obs = infile.read()
infile.close() infile.close()
elif(self.filetype == "xml"): elif(self.filetype == "xml"):
try: try:
doc = xml.dom.minidom.parse(filename) doc = xml.dom.minidom.parse(filename)
self.doc = doc self.doc = doc
except: except:
traceback.print_exc(file=sys.stderr) traceback.print_exc(file=sys.stderr)
def writeHand(self, file, hand): def writeHand(self, file, hand):
"""Write out parsed data""" """Write out parsed data"""
print "DEBUG: *************************" print "DEBUG: *************************"
print "DEBUG: Start of print hand" print "DEBUG: Start of print hand"
print "DEBUG: *************************" print "DEBUG: *************************"
print "%s Game #%s: %s ($%s/$%s) - %s" %(hand.sitename, hand.handid, "XXXXhand.gametype", hand.sb, hand.bb, hand.starttime) print "%s Game #%s: %s ($%s/$%s) - %s" %(hand.sitename, hand.handid, "XXXXhand.gametype", hand.sb, hand.bb, hand.starttime)
print "Table '%s' %d-max Seat #%s is the button" %(hand.tablename, hand.maxseats, hand.buttonpos) print "Table '%s' %d-max Seat #%s is the button" %(hand.tablename, hand.maxseats, hand.buttonpos)
for player in hand.players: for player in hand.players:
print "Seat %s: %s ($%s)" %(player[0], player[1], player[2]) print "Seat %s: %s ($%s)" %(player[0], player[1], player[2])
if(hand.posted[0] == "FpdbNBP"): if(hand.posted[0] == "FpdbNBP"):
print "No small blind posted" print "No small blind posted"
else: else:
print "%s: posts small blind $%s" %(hand.posted[0], hand.sb) print "%s: posts small blind $%s" %(hand.posted[0], hand.sb)
#May be more than 1 bb posting #May be more than 1 bb posting
print "%s: posts big blind $%s" %(hand.posted[1], hand.bb) print "%s: posts big blind $%s" %(hand.posted[1], hand.bb)
if(len(hand.posted) > 2): if(len(hand.posted) > 2):
# Need to loop on all remaining big blinds - lazy # Need to loop on all remaining big blinds - lazy
print "XXXXXXXXX FIXME XXXXXXXX" print "XXXXXXXXX FIXME XXXXXXXX"
print "*** HOLE CARDS ***" print "*** HOLE CARDS ***"
print "Dealt to %s [%s %s]" %(hand.hero , hand.holecards[0], hand.holecards[1]) print "Dealt to %s [%s %s]" %(hand.hero , hand.holecards[0], hand.holecards[1])
# #
## ACTION STUFF ## ACTION STUFF
# This is no limit only at the moment # This is no limit only at the moment
for act in hand.actions['PREFLOP']: for act in hand.actions['PREFLOP']:
self.printActionLine(act, 0) self.printActionLine(act, 0)
if 'PREFLOP' in hand.actions: if 'PREFLOP' in hand.actions:
for act in hand.actions['PREFLOP']: for act in hand.actions['PREFLOP']:
print "PF action" print "PF action"
if 'FLOP' in hand.actions: if 'FLOP' in hand.actions:
print "*** FLOP *** [%s %s %s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3")) print "*** FLOP *** [%s %s %s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"))
for act in hand.actions['FLOP']: for act in hand.actions['FLOP']:
self.printActionLine(act, 0) self.printActionLine(act, 0)
if 'TURN' in hand.actions: if 'TURN' in hand.actions:
print "*** TURN *** [%s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1")) print "*** TURN *** [%s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"))
for act in hand.actions['TURN']: for act in hand.actions['TURN']:
self.printActionLine(act, 0) self.printActionLine(act, 0)
if 'RIVER' in hand.actions: if 'RIVER' in hand.actions:
print "*** RIVER *** [%s %s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"), hand.streets.group("RIVER1")) print "*** RIVER *** [%s %s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"), hand.streets.group("RIVER1"))
for act in hand.actions['RIVER']: for act in hand.actions['RIVER']:
self.printActionLine(act, 0) self.printActionLine(act, 0)
print "*** SUMMARY ***" print "*** SUMMARY ***"
print "XXXXXXXXXXXX Need sumary info XXXXXXXXXXX" print "XXXXXXXXXXXX Need sumary info XXXXXXXXXXX"
# print "Total pot $%s | Rake $%s)" %(hand.totalpot $" + hand.rake) # print "Total pot $%s | Rake $%s)" %(hand.totalpot $" + hand.rake)
# print "Board [" + boardcards + "]" # print "Board [" + boardcards + "]"
# #
# SUMMARY STUFF # SUMMARY STUFF
def printActionLine(self, act, pot): def printActionLine(self, act, pot):
if act[1] == 'folds' or act[1] == 'checks': if act[1] == 'folds' or act[1] == 'checks':
print "%s: %s " %(act[0], act[1]) print "%s: %s " %(act[0], act[1])
if act[1] == 'calls': if act[1] == 'calls':
print "%s: %s $%s" %(act[0], act[1], act[2]) print "%s: %s $%s" %(act[0], act[1], act[2])
if act[1] == 'raises': if act[1] == 'raises':
print "%s: %s $%s to XXXpottotalXXX" %(act[0], act[1], act[2]) print "%s: %s $%s to XXXpottotalXXX" %(act[0], act[1], act[2])
#takes a poker float (including , for thousand seperator and converts it to an int #takes a poker float (including , for thousand seperator and converts it to an int
def float2int (self, string): def float2int (self, string):
pos=string.find(",") pos=string.find(",")
if (pos!=-1): #remove , the thousand seperator if (pos!=-1): #remove , the thousand seperator
string=string[0:pos]+string[pos+1:] string=string[0:pos]+string[pos+1:]
pos=string.find(".") pos=string.find(".")
if (pos!=-1): #remove decimal point if (pos!=-1): #remove decimal point
string=string[0:pos]+string[pos+1:] string=string[0:pos]+string[pos+1:]
result = int(string) result = int(string)
if pos==-1: #no decimal point - was in full dollars - need to multiply with 100 if pos==-1: #no decimal point - was in full dollars - need to multiply with 100
result*=100 result*=100
return result return result
#end def float2int #end def float2int
class Hand: class Hand:
# def __init__(self, sitename, gametype, sb, bb, string): # def __init__(self, sitename, gametype, sb, bb, string):
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K'} UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K'}
STREETS = ['BLINDS','PREFLOP','FLOP','TURN','RIVER'] STREETS = ['BLINDS','PREFLOP','FLOP','TURN','RIVER']
def __init__(self, sitename, gametype, string): def __init__(self, sitename, gametype, string):
self.sitename = sitename self.sitename = sitename
self.gametype = gametype self.gametype = gametype
self.string = string self.string = string
self.streets = None # A MatchObject using a groupnames to identify streets. self.streets = None # A MatchObject using a groupnames to identify streets.
self.actions = {} self.actions = {}
self.handid = 0 self.handid = 0
self.sb = gametype[3] self.sb = gametype[3]
self.bb = gametype[4] self.bb = gametype[4]
self.tablename = "Slartibartfast" self.tablename = "Slartibartfast"
self.maxseats = 10 self.maxseats = 10
self.counted_seats = 0 self.counted_seats = 0
self.buttonpos = 0 self.buttonpos = 0
self.seating = [] self.seating = []
self.players = [] self.players = []
self.posted = [] self.posted = []
self.involved = True self.involved = True
self.hero = "Hiro" self.hero = "Hiro"
self.holecards = "Xx Xx" self.holecards = "Xx Xx"
self.action = [] self.action = []
self.totalpot = None self.totalpot = None
self.rake = None self.rake = None
self.bets = {} self.bets = {}
self.lastBet = {} self.lastBet = {}
for street in self.STREETS: for street in self.STREETS:
self.bets[street] = {} self.bets[street] = {}
self.lastBet[street] = 0 self.lastBet[street] = 0
def addPlayer(self, seat, name, chips): def addPlayer(self, seat, name, chips):
"""seat, an int indicating the seat """seat, an int indicating the seat
name, the player name name, the player name
chips, the chips the player has at the start of the hand""" chips, the chips the player has at the start of the hand"""
#self.players.append(name) #self.players.append(name)
self.players.append([seat, name, chips]) self.players.append([seat, name, chips])
#self.startChips[name] = chips #self.startChips[name] = chips
#self.endChips[name] = chips #self.endChips[name] = chips
#self.winners[name] = 0 #self.winners[name] = 0
for street in self.STREETS: for street in self.STREETS:
self.bets[street][name] = [] self.bets[street][name] = []
def addHoleCards(self,h1,h2,seat=None): # generalise to add hole cards for a specific seat or player def addHoleCards(self,h1,h2,seat=None): # generalise to add hole cards for a specific seat or player
self.holecards = [self.card(h1), self.card(h2)] self.holecards = [self.card(h1), self.card(h2)]
def card(self,c): def card(self,c):
"""upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" """upper case the ranks but not suits, 'atjqk' => 'ATJQK'"""
# don't know how to make this 'static' # don't know how to make this 'static'
for k,v in self.UPS.items(): for k,v in self.UPS.items():
c = c.replace(k,v) c = c.replace(k,v)
return c return c
def addBlind(self, player, amount): def addBlind(self, player, amount):
# if player is None, it's a missing small blind. # if player is None, it's a missing small blind.
if player is not None: if player is not None:
self.bets['PREFLOP'][player].append(Decimal(amount)) self.bets['PREFLOP'][player].append(Decimal(amount))
self.lastBet['PREFLOP'] = Decimal(amount) self.lastBet['PREFLOP'] = Decimal(amount)
self.posted += [player] self.posted += [player]
def addCall(self, street, player=None, amount=None): def addCall(self, street, player=None, amount=None):
# Potentially calculate the amount of the call if not supplied # Potentially calculate the amount of the call if not supplied
# corner cases include if player would be all in # corner cases include if player would be all in
if amount is not None: if amount is not None:
self.bets[street][player].append(Decimal(amount)) self.bets[street][player].append(Decimal(amount))
#self.lastBet[street] = Decimal(amount) #self.lastBet[street] = Decimal(amount)
self.actions[street] += [[player, 'calls', amount]] self.actions[street] += [[player, 'calls', amount]]
def addRaiseTo(self, street, player, amountTo): def addRaiseTo(self, street, player, amountTo):
# Given only the amount raised to, the amount of the raise can be calculated by # Given only the amount raised to, the amount of the raise can be calculated by
# working out how much this player has already in the pot # working out how much this player has already in the pot
# (which is the sum of self.bets[street][player]) # (which is the sum of self.bets[street][player])
# and how much he needs to call to match the previous player # and how much he needs to call to match the previous player
# (which is tracked by self.lastBet) # (which is tracked by self.lastBet)
committedThisStreet = reduce(operator.add, self.bets[street][player], 0) committedThisStreet = reduce(operator.add, self.bets[street][player], 0)
amountToCall = self.lastBet[street] - committedThisStreet amountToCall = self.lastBet[street] - committedThisStreet
self.lastBet[street] = Decimal(amountTo) self.lastBet[street] = Decimal(amountTo)
amountBy = Decimal(amountTo) - amountToCall amountBy = Decimal(amountTo) - amountToCall
self.bets[street][player].append(amountBy+amountToCall) self.bets[street][player].append(amountBy+amountToCall)
self.actions[street] += [[player, 'raises', amountBy, amountTo]] self.actions[street] += [[player, 'raises', amountBy, amountTo]]
def addBet(self, street, player=None, amount=0): def addBet(self, street, player=None, amount=0):
self.bets[street][name].append(Decimal(amount)) self.bets[street][name].append(Decimal(amount))
self.orderedBets[street].append(Decimal(amount)) self.orderedBets[street].append(Decimal(amount))
self.actions[street] += [[player, 'bets', amount]] self.actions[street] += [[player, 'bets', amount]]
def totalPot(self): def totalPot(self):
if self.totalpot is None: if self.totalpot is None:
self.totalpot = 0 self.totalpot = 0
# player names: # player names:
# print [x[1] for x in self.players] # print [x[1] for x in self.players]
for player in [x[1] for x in self.players]: for player in [x[1] for x in self.players]:
for street in self.STREETS: for street in self.STREETS:
print street, self.bets[street][player] print street, self.bets[street][player]
self.totalpot += reduce(operator.add, self.bets[street][player], 0) self.totalpot += reduce(operator.add, self.bets[street][player], 0)
def printHand(self): def printHand(self):
# PokerStars format. # PokerStars format.
print "### DEBUG ###" print "### DEBUG ###"
print "%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, "XXXXhand.gametype", self.sb, self.bb, self.starttime) print "%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, "XXXXhand.gametype", self.sb, self.bb, self.starttime)
print "Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos) print "Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)
for player in self.players: for player in self.players:
print "Seat %s: %s ($%s)" %(player[0], player[1], player[2]) print "Seat %s: %s ($%s)" %(player[0], player[1], player[2])
if(self.posted[0] is None): if(self.posted[0] is None):
print "No small blind posted" print "No small blind posted"
else: else:
print "%s: posts small blind $%s" %(self.posted[0], self.sb) print "%s: posts small blind $%s" %(self.posted[0], self.sb)
#May be more than 1 bb posting #May be more than 1 bb posting
for a in self.posted[1:]: for a in self.posted[1:]:
print "%s: posts big blind $%s" %(self.posted[1], self.bb) print "%s: posts big blind $%s" %(self.posted[1], self.bb)
# What about big & small blinds? # What about big & small blinds?
print "*** HOLE CARDS ***" print "*** HOLE CARDS ***"
print "Dealt to %s [%s %s]" %(self.hero , self.holecards[0], self.holecards[1]) print "Dealt to %s [%s %s]" %(self.hero , self.holecards[0], self.holecards[1])
if 'PREFLOP' in self.actions: if 'PREFLOP' in self.actions:
for act in self.actions['PREFLOP']: for act in self.actions['PREFLOP']:
self.printActionLine(act) self.printActionLine(act)
if 'FLOP' in self.actions: if 'FLOP' in self.actions:
print "*** FLOP *** [%s %s %s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3")) print "*** FLOP *** [%s %s %s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"))
for act in self.actions['FLOP']: for act in self.actions['FLOP']:
self.printActionLine(act) self.printActionLine(act)
if 'TURN' in self.actions: if 'TURN' in self.actions:
print "*** TURN *** [%s %s %s] [%s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1")) print "*** TURN *** [%s %s %s] [%s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"))
for act in self.actions['TURN']: for act in self.actions['TURN']:
self.printActionLine(act) self.printActionLine(act)
if 'RIVER' in self.actions: if 'RIVER' in self.actions:
print "*** RIVER *** [%s %s %s %s] [%s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1")) print "*** RIVER *** [%s %s %s %s] [%s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1"))
for act in self.actions['RIVER']: for act in self.actions['RIVER']:
self.printActionLine(act) self.printActionLine(act)
#Some sites don't have a showdown section so we have to figure out if there should be one #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 # The logic for a showdown is: at the end of river action there are at least two players in the hand
if 'SHOWDOWN' in self.actions: if 'SHOWDOWN' in self.actions:
print "*** SHOW DOWN ***" print "*** SHOW DOWN ***"
print "what do they show" print "what do they show"
print "*** SUMMARY ***" print "*** SUMMARY ***"
print "Total pot $%s | Rake $%s)" % (self.totalpot, self.rake) print "Total pot $%s | Rake $%s)" % (self.totalpot, self.rake)
print "Board [%s %s %s %s %s]" % (self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1")) print "Board [%s %s %s %s %s]" % (self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1"))
def printActionLine(self, act): def printActionLine(self, act):
if act[1] == 'folds' or act[1] == 'checks': if act[1] == 'folds' or act[1] == 'checks':
print "%s: %s " %(act[0], act[1]) print "%s: %s " %(act[0], act[1])
if act[1] == 'calls': if act[1] == 'calls':
print "%s: %s $%s" %(act[0], act[1], act[2]) print "%s: %s $%s" %(act[0], act[1], act[2])
if act[1] == 'raises': if act[1] == 'raises':
print "%s: %s $%s to $%s" %(act[0], act[1], act[2], act[3]) print "%s: %s $%s to $%s" %(act[0], act[1], act[2], act[3])