Merge branch 'exp' of git://git.assembla.com/mctfpdb

This commit is contained in:
Worros 2008-12-07 14:04:00 +09:00
commit b1a9109190
2 changed files with 416 additions and 393 deletions

View File

@ -58,42 +58,45 @@ from HandHistoryConverter import *
# smaragdar calls [$ 34.50 USD] # smaragdar calls [$ 34.50 USD]
# ** Dealing Turn ** [ 2d ] # ** Dealing Turn ** [ 2d ]
# ** Dealing River ** [ 6c ] # ** Dealing River ** [ 6c ]
# dogge shows [ 9h, 9c ]a pair of nines
# spicybum shows [ 5d, 6d ]a straight, eight high
# harrydebeng does not show cards
# 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')
@ -106,70 +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'))
#players = players + [[a.group('SEAT'), a.group('PNAME'), a.group('CASH')]]
#hand.players = players
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') )
# mct: do we need to keep bet distinct from raise? else:
# hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE'), action.group('BET')]] print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)
else: hand.actions[street] += [[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')]]
#print "DEBUG: readAction: %s " %(hand.actions)
def getRake(self, hand):
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,378 +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)
if(hand.involved == True): # finalise it (total the pot)
#self.writeHand("output file", hand) hand.totalPot()
hand.printHand() self.getRake(hand)
else:
pass #Don't write out observed hands if(hand.involved == True):
#self.writeHand("output file", hand)
hand.printHand()
else:
pass #Don't write out observed hands
# Functions to be implemented in the inheriting class #####
def readSupportedGames(self): abstract # These functions are parse actions that may be overridden by the inheriting class
#
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
#TODO: Comment # Read any of:
def readHandInfo(self, hand): abstract # HID HandID
# TABLE Table name
# SB small blind
# BB big blind
# GAMETYPE gametype
# YEAR MON DAY HR MIN SEC datetime
# BUTTON button seat number
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
def markStreets(self, hand): abstract # that is, pulls the chunks of preflop, flop, turn and river text into hand.streets MatchObject.
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
# so that an inheriting class can calculate it for the specific site if need be.
def getRake(self, hand): abstract
def sanityCheck(self):
sane = True
base_w = False
#Check if hhbase exists and is writable
#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)):
print "HH Sanity Check: Directory hhbase '" + self.hhbase + "' doesn't exist or is not writable"
else:
#Check if hhdir exists and is writable
if not os.path.isdir(self.hhdir):
# In first pass, dir may not exist. Attempt to create dir
print "Creating directory: '%s'" % (self.hhdir)
os.mkdir(self.hhdir)
sane = True
elif os.access(self.hhdir, os.W_OK):
sane = True
else:
print "HH Sanity Check: Directory hhdir '" + self.hhdir + "' or its parent directory are not writable"
def sanityCheck(self): return sane
sane = True
base_w = False
#Check if hhbase exists and is writable
#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)):
print "HH Sanity Check: Directory hhbase '" + self.hhbase + "' doesn't exist or is not writable"
else:
#Check if hhdir exists and is writable
if not os.path.isdir(self.hhdir):
# In first pass, dir may not exist. Attempt to create dir
print "Creating directory: '%s'" % (self.hhdir)
os.mkdir(self.hhdir)
sane = True
elif os.access(self.hhdir, os.W_OK):
sane = True
else:
print "HH Sanity Check: Directory hhdir '" + self.hhdir + "' or its parent directory are not writable"
return sane # Functions not necessary to implement in sub class
def setFileType(self, filetype = "text"):
self.filetype = filetype
# Functions not necessary to implement in sub class def splitFileIntoHands(self):
def setFileType(self, filetype = "text"): hands = []
self.filetype = filetype list = self.rexx.split_hand_re.split(self.obs)
list.pop() #Last entry is empty
def splitFileIntoHands(self): for l in list:
hands = []
list = self.rexx.split_hand_re.split(self.obs)
list.pop() #Last entry is empty
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.rake = 0 self.rake = None
self.bets = {} self.bets = {}
self.lastBet = {} self.lastBet = {}
self.orderedBets = {} 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] = [0]
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):
#self.bets['BLINDS'][player].append(Decimal(amount)) # if player is None, it's a missing small blind.
self.lastBet['PREFLOP'] = Decimal(amount) if player is not None:
self.posted += [player] self.bets['PREFLOP'][player].append(Decimal(amount))
self.lastBet['PREFLOP'] = Decimal(amount)
self.posted += [player]
def addCall(self, street, player=None, amount=0): def addCall(self, street, player=None, amount=None):
self.bets[street][player].append(Decimal(amount)) # Potentially calculate the amount of the call if not supplied
#self.lastBet[street] = Decimal(amount) # corner cases include if player would be all in
self.actions[street] += [[player, 'calls', amount]] if amount is not None:
self.bets[street][player].append(Decimal(amount))
def addRaiseTo(self, street, player, amountTo): #self.lastBet[street] = Decimal(amount)
# amount is the amount raised to, not the amount raised.by self.actions[street] += [[player, 'calls', amount]]
committedThisStreet = reduce(operator.add, self.bets[street][player], 0)
amountToCall = self.lastBet[street] - committedThisStreet def addRaiseTo(self, street, player, amountTo):
self.lastBet[street] = Decimal(amountTo) # Given only the amount raised to, the amount of the raise can be calculated by
amountBy = Decimal(amountTo) - amountToCall # working out how much this player has already in the pot
self.bets[street][player].append(amountBy) # (which is the sum of self.bets[street][player])
self.actions[street] += [[player, 'raises', amountBy, amountTo]] # and how much he needs to call to match the previous player
# (which is tracked by self.lastBet)
#def addRaiseTo(self, street, player=None, amountTo=None): committedThisStreet = reduce(operator.add, self.bets[street][player], 0)
#self.amounts[street] += Decimal(amountTo) amountToCall = self.lastBet[street] - committedThisStreet
self.lastBet[street] = Decimal(amountTo)
amountBy = Decimal(amountTo) - amountToCall
def addBet(self, street, player=None, amount=0): self.bets[street][player].append(amountBy+amountToCall)
self.bets[street][name].append(Decimal(amount)) self.actions[street] += [[player, 'raises', amountBy, amountTo]]
self.orderedBets[street].append(Decimal(amount))
self.actions[street] += [[player, 'bets', amount]] def addBet(self, street, player=None, amount=0):
self.bets[street][name].append(Decimal(amount))
self.orderedBets[street].append(Decimal(amount))
self.actions[street] += [[player, 'bets', amount]]
def printHand(self):
# PokerStars format. def totalPot(self):
print "### DEBUG ###"
print "%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, "XXXXhand.gametype", self.sb, self.bb, self.starttime) if self.totalpot is None:
print "Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos) self.totalpot = 0
for player in self.players:
print "Seat %s: %s ($%s)" %(player[0], player[1], player[2]) # player names:
# print [x[1] for x in self.players]
for player in [x[1] for x in self.players]:
for street in self.STREETS:
print street, self.bets[street][player]
self.totalpot += reduce(operator.add, self.bets[street][player], 0)
if(self.posted[0] is None):
print "No small blind posted"
else:
print "%s: posts small blind $%s" %(self.posted[0], self.sb)
#May be more than 1 bb posting def printHand(self):
for a in self.posted[1:]: # PokerStars format.
print "%s: posts big blind $%s" %(self.posted[1], self.bb) print "### DEBUG ###"
print "%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, "XXXXhand.gametype", self.sb, self.bb, self.starttime)
# What about big & small blinds? print "Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)
for player in self.players:
print "Seat %s: %s ($%s)" %(player[0], player[1], player[2])
print "*** HOLE CARDS ***" if(self.posted[0] is None):
print "Dealt to %s [%s %s]" %(self.hero , self.holecards[0], self.holecards[1]) print "No small blind posted"
else:
print "%s: posts small blind $%s" %(self.posted[0], self.sb)
if 'PREFLOP' in self.actions: #May be more than 1 bb posting
for act in self.actions['PREFLOP']: for a in self.posted[1:]:
self.printActionLine(act) print "%s: posts big blind $%s" %(self.posted[1], self.bb)
# What about big & small blinds?
if 'FLOP' in self.actions: print "*** HOLE CARDS ***"
print "*** FLOP *** [%s %s %s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3")) print "Dealt to %s [%s %s]" %(self.hero , self.holecards[0], self.holecards[1])
for act in self.actions['FLOP']:
self.printActionLine(act)
if 'TURN' in self.actions: if 'PREFLOP' 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")) for act in self.actions['PREFLOP']:
for act in self.actions['TURN']: self.printActionLine(act)
self.printActionLine(act)
if 'RIVER' in self.actions: if 'FLOP' 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 "*** FLOP *** [%s %s %s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"))
for act in self.actions['RIVER']: for act in self.actions['FLOP']:
self.printActionLine(act) self.printActionLine(act)
print "*** SUMMARY ***" if 'TURN' in self.actions:
print "XXXXXXXXXXXX Need sumary info XXXXXXXXXXX" print "*** TURN *** [%s %s %s] [%s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"))
# print "Total pot $%s | Rake $%s)" %(hand.totalpot $" + hand.rake) for act in self.actions['TURN']:
# print "Board [" + boardcards + "]" self.printActionLine(act)
#
# SUMMARY STUFF
if 'RIVER' in self.actions:
#print self.sitename 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 self.gametype for act in self.actions['RIVER']:
#print self.string self.printActionLine(act)
#print self.handid
#print self.sb
#print self.bb #Some sites don't have a showdown section so we have to figure out if there should be one
#print self.tablename # The logic for a showdown is: at the end of river action there are at least two players in the hand
#print self.maxseats if 'SHOWDOWN' in self.actions:
#print self.counted_seats print "*** SHOW DOWN ***"
#print self.buttonpos print "what do they show"
#print self.seating
#print self.players print "*** SUMMARY ***"
#print self.posted print "Total pot $%s | Rake $%s)" % (self.totalpot, self.rake)
#print self.action 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 self.involved
#print self.hero
def printActionLine(self, act):
if act[1] == 'folds' or act[1] == 'checks': def printActionLine(self, act):
print "%s: %s " %(act[0], act[1]) if act[1] == 'folds' or act[1] == 'checks':
if act[1] == 'calls': print "%s: %s " %(act[0], act[1])
print "%s: %s $%s" %(act[0], act[1], act[2]) if act[1] == 'calls':
if act[1] == 'raises': print "%s: %s $%s" %(act[0], act[1], act[2])
print "%s: %s $%s to $%s" %(act[0], act[1], act[2], act[3]) if act[1] == 'raises':
print "%s: %s $%s to $%s" %(act[0], act[1], act[2], act[3])