More futzing
- made it so that Hand.__init__ calls the hhc readX methods in the right order for that kind of Hand (Stud or Holdem/Omaha) - hhc.readX methods then callback Hand.addX methods Why? WHY! I hear you ask. Actually I can see there's very little gain, sorry about that; but it sort of makes sense. Now you just make the right kind of Hand, give it the text and the right kind of HHC filter, and it makes itself. - apart from that, biggest actual thing done is probably in adding player cards for stud hands -- revamped and made it really clear (I think) whats happening (see FullTilt.readStudPlayerCards) When I run FullTiltToFpdf.py it goes through all the hands. - Still have some print statements, have been changing them to logging.debug or logging.info as I come across them. You may find "tail -f logging.out" useful Actually I'm not at all convinced about the use of logging except that you can redirect it to stderr quite easily and then set the threshold for what gets logged quite easily, so that might be a plus. - Oh and the subclassing of Hand is getting clearer.
This commit is contained in:
parent
5c26bb028d
commit
36befa43a8
|
@ -32,7 +32,6 @@ class Everleaf(HandHistoryConverter):
|
||||||
re_Button = re.compile(r"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
|
re_Button = re.compile(r"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
|
||||||
re_PlayerInfo = re.compile(r"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)", re.MULTILINE)
|
re_PlayerInfo = re.compile(r"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)", re.MULTILINE)
|
||||||
re_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
|
re_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
|
||||||
splitstring = "\n\n\n"
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, in_path = '-', out_path = '-', follow = False):
|
def __init__(self, in_path = '-', out_path = '-', follow = False):
|
||||||
|
@ -67,7 +66,7 @@ follow : whether to tail -f the input"""
|
||||||
["ring", "omaha", "pl"]
|
["ring", "omaha", "pl"]
|
||||||
]
|
]
|
||||||
|
|
||||||
def determineGameType(self, handtext):
|
def determineGameType(self, handText):
|
||||||
# Cheating with this regex, only support nlhe at the moment
|
# Cheating with this regex, only support nlhe at the moment
|
||||||
# Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48
|
# Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48
|
||||||
# Blinds $0.05/$0.10 NL Hold'em - 2009/02/21 - 11:21:57
|
# Blinds $0.05/$0.10 NL Hold'em - 2009/02/21 - 11:21:57
|
||||||
|
@ -82,7 +81,7 @@ follow : whether to tail -f the input"""
|
||||||
structure = "" # nl, pl, cn, cp, fl
|
structure = "" # nl, pl, cn, cp, fl
|
||||||
game = ""
|
game = ""
|
||||||
|
|
||||||
m = self.re_GameInfo.search(handtext)
|
m = self.re_GameInfo.search(handText)
|
||||||
if m == None:
|
if m == None:
|
||||||
logging.debug("Gametype didn't match")
|
logging.debug("Gametype didn't match")
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import Configuration
|
|
||||||
from HandHistoryConverter import *
|
from HandHistoryConverter import *
|
||||||
|
|
||||||
# FullTilt HH Format converter
|
# FullTilt HH Format converter
|
||||||
|
@ -32,26 +31,34 @@ class FullTilt(HandHistoryConverter):
|
||||||
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
|
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
|
||||||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||||
|
|
||||||
def __init__(self, config, file):
|
def __init__(self, in_path = '-', out_path = '-', follow = False):
|
||||||
print "Initialising FullTilt converter class"
|
"""\
|
||||||
HandHistoryConverter.__init__(self, config, file, sitename="FullTilt") # Call super class init.
|
in_path (default '-' = sys.stdin)
|
||||||
self.sitename = "FullTilt"
|
out_path (default '-' = sys.stdout)
|
||||||
self.setFileType("text", "cp1252")
|
follow : whether to tail -f the input"""
|
||||||
|
HandHistoryConverter.__init__(self, in_path, out_path, sitename="FullTilt", follow=follow)
|
||||||
|
logging.info("Initialising FullTilt converter class")
|
||||||
|
self.filetype = "text"
|
||||||
|
self.codepage = "cp1252"
|
||||||
|
self.start()
|
||||||
|
|
||||||
def compilePlayerRegexs(self):
|
def compilePlayerRegexs(self, players):
|
||||||
player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")"
|
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
|
||||||
print "DEBUG player_re: " + player_re
|
# we need to recompile the player regexs.
|
||||||
self.re_PostSB = re.compile(r"^%s posts the small blind of \$?(?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
|
self.compiledPlayers = players
|
||||||
self.re_PostBB = re.compile(r"^%s posts (the big blind of )?\$?(?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
|
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
|
||||||
self.re_Antes = re.compile(r"^%s antes \$?(?P<ANTE>[.0-9]+)" % player_re, re.MULTILINE)
|
logging.debug("player_re: " + player_re)
|
||||||
self.re_BringIn = re.compile(r"^%s brings in for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE)
|
self.re_PostSB = re.compile(r"^%s posts the small blind of \$?(?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||||
self.re_PostBoth = re.compile(r"^%s posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
|
self.re_PostBB = re.compile(r"^%s posts (the big blind of )?\$?(?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||||
self.re_HeroCards = re.compile(r"^Dealt to %s \[(?P<CARDS>[AKQJT0-9hcsd ]+)\]( \[(?P<NEWCARD>[AKQJT0-9hcsd ]+)\])?" % player_re, re.MULTILINE)
|
self.re_Antes = re.compile(r"^%s antes \$?(?P<ANTE>[.0-9]+)" % player_re, re.MULTILINE)
|
||||||
self.re_Action = re.compile(r"^%s(?P<ATYPE> bets| checks| raises to| calls| folds)(\s\$(?P<BET>[.\d]+))?" % player_re, re.MULTILINE)
|
self.re_BringIn = re.compile(r"^%s brings in for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE)
|
||||||
self.re_ShowdownAction = re.compile(r"^%s shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
|
self.re_PostBoth = re.compile(r"^%s posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||||
self.re_CollectPot = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*)" % player_re, re.MULTILINE)
|
self.re_HeroCards = re.compile(r"^Dealt to %s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE)
|
||||||
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE)
|
self.re_Action = re.compile(r"^%s(?P<ATYPE> bets| checks| raises to| calls| folds)(\s\$(?P<BET>[.\d]+))?" % player_re, re.MULTILINE)
|
||||||
self.re_ShownCards = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s \(.*\) showed \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
|
self.re_ShowdownAction = re.compile(r"^%s shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
|
||||||
|
self.re_CollectPot = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*)" % player_re, re.MULTILINE)
|
||||||
|
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE)
|
||||||
|
self.re_ShownCards = re.compile(r"^Seat (?P<SEAT>[0-9]+): %s \(.*\) showed \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
|
||||||
|
|
||||||
|
|
||||||
def readSupportedGames(self):
|
def readSupportedGames(self):
|
||||||
|
@ -61,16 +68,17 @@ class FullTilt(HandHistoryConverter):
|
||||||
["ring", "omaha", "pl"]
|
["ring", "omaha", "pl"]
|
||||||
]
|
]
|
||||||
|
|
||||||
def determineGameType(self):
|
def determineGameType(self, handText):
|
||||||
# Cheating with this regex, only support nlhe at the moment
|
# Cheating with this regex, only support nlhe at the moment
|
||||||
# Full Tilt Poker Game #10777181585: Table Deerfly (deep 6) - $0.01/$0.02 - Pot Limit Omaha Hi - 2:24:44 ET - 2009/02/22
|
# Full Tilt Poker Game #10777181585: Table Deerfly (deep 6) - $0.01/$0.02 - Pot Limit Omaha Hi - 2:24:44 ET - 2009/02/22
|
||||||
# Full Tilt Poker Game #10773265574: Table Butte (6 max) - $0.01/$0.02 - Pot Limit Hold'em - 21:33:46 ET - 2009/02/21
|
# Full Tilt Poker Game #10773265574: Table Butte (6 max) - $0.01/$0.02 - Pot Limit Hold'em - 21:33:46 ET - 2009/02/21
|
||||||
# Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09
|
# Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09
|
||||||
|
# Full Tilt Poker Game #10809877615: Table Danville - $0.50/$1 Ante $0.10 - Limit Razz - 21:47:27 ET - 2009/02/23
|
||||||
structure = "" # nl, pl, cn, cp, fl
|
structure = "" # nl, pl, cn, cp, fl
|
||||||
game = ""
|
game = ""
|
||||||
|
|
||||||
|
|
||||||
m = self.re_GameInfo.search(self.obs)
|
m = self.re_GameInfo.search(handText)
|
||||||
if m.group('LTYPE') == "No ":
|
if m.group('LTYPE') == "No ":
|
||||||
structure = "nl"
|
structure = "nl"
|
||||||
elif m.group('LTYPE') == "Pot ":
|
elif m.group('LTYPE') == "Pot ":
|
||||||
|
@ -85,22 +93,22 @@ class FullTilt(HandHistoryConverter):
|
||||||
elif m.group('GAME') == "Razz":
|
elif m.group('GAME') == "Razz":
|
||||||
game = "razz"
|
game = "razz"
|
||||||
|
|
||||||
print m.groups()
|
logging.debug("HandInfo: %s", m.groupdict())
|
||||||
|
|
||||||
gametype = ["ring", game, structure, m.group('SB'), m.group('BB')]
|
gametype = ["ring", game, structure, m.group('SB'), m.group('BB')]
|
||||||
|
|
||||||
return gametype
|
return gametype
|
||||||
|
|
||||||
def readHandInfo(self, hand):
|
def readHandInfo(self, hand):
|
||||||
m = self.re_HandInfo.search(hand.string,re.DOTALL)
|
m = self.re_HandInfo.search(hand.handText,re.DOTALL)
|
||||||
#print m.groups()
|
#print m.groups()
|
||||||
hand.handid = m.group('HID')
|
hand.handid = m.group('HID')
|
||||||
hand.tablename = m.group('TABLE')
|
hand.tablename = m.group('TABLE')
|
||||||
hand.starttime = time.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
|
hand.starttime = time.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
|
||||||
# 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')
|
||||||
# m.group('GAMETYPE')
|
# m.group('GAMETYPE')
|
||||||
|
|
||||||
# Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET]
|
# Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET]
|
||||||
# or : 2008/11/07 12:38:49 ET
|
# or : 2008/11/07 12:38:49 ET
|
||||||
|
@ -113,27 +121,26 @@ class FullTilt(HandHistoryConverter):
|
||||||
#FIXME: hand.buttonpos = int(m.group('BUTTON'))
|
#FIXME: hand.buttonpos = int(m.group('BUTTON'))
|
||||||
|
|
||||||
def readPlayerStacks(self, hand):
|
def readPlayerStacks(self, hand):
|
||||||
m = self.re_PlayerInfo.finditer(hand.string)
|
m = self.re_PlayerInfo.finditer(hand.handText)
|
||||||
players = []
|
players = []
|
||||||
for a in m:
|
for a in m:
|
||||||
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
|
hand.addPlayer(int(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 **
|
||||||
# This re fails if, say, river is missing; then we don't get the ** that starts the river.
|
|
||||||
|
|
||||||
if self.gametype[1] == "hold" or self.gametype[1] == "omaha":
|
if hand.gametype[1] in ("hold", "omaha"):
|
||||||
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
|
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
|
||||||
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
|
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
|
||||||
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
|
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
|
||||||
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.string,re.DOTALL)
|
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL)
|
||||||
elif self.gametype[1] == "razz":
|
elif hand.gametype[1] == "razz":
|
||||||
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)"
|
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)"
|
||||||
r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?"
|
r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?"
|
||||||
r"(\*\*\* 4TH STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5TH STREET \*\*\*)|.+))?"
|
r"(\*\*\* 4TH STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5TH STREET \*\*\*)|.+))?"
|
||||||
r"(\*\*\* 5TH STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6TH STREET \*\*\*)|.+))?"
|
r"(\*\*\* 5TH STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6TH STREET \*\*\*)|.+))?"
|
||||||
r"(\*\*\* 6TH STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* 7TH STREET \*\*\*)|.+))?"
|
r"(\*\*\* 6TH STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* 7TH STREET \*\*\*)|.+))?"
|
||||||
r"(\*\*\* 7TH STREET \*\*\*(?P<SEVENTH>.+))?", hand.string,re.DOTALL)
|
r"(\*\*\* 7TH STREET \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
|
||||||
hand.addStreets(m)
|
hand.addStreets(m)
|
||||||
|
|
||||||
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
|
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
|
||||||
|
@ -145,34 +152,32 @@ class FullTilt(HandHistoryConverter):
|
||||||
|
|
||||||
def readBlinds(self, hand):
|
def readBlinds(self, hand):
|
||||||
try:
|
try:
|
||||||
m = self.re_PostSB.search(hand.string)
|
m = self.re_PostSB.search(hand.handText)
|
||||||
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
|
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
|
||||||
except: # no small blind
|
except: # no small blind
|
||||||
hand.addBlind(None, None, None)
|
hand.addBlind(None, None, None)
|
||||||
for a in self.re_PostBB.finditer(hand.string):
|
for a in self.re_PostBB.finditer(hand.handText):
|
||||||
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
|
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
|
||||||
for a in self.re_PostBoth.finditer(hand.string):
|
for a in self.re_PostBoth.finditer(hand.handText):
|
||||||
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
|
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
|
||||||
|
|
||||||
def readAntes(self, hand):
|
def readAntes(self, hand):
|
||||||
print "DEBUG: reading antes"
|
logging.debug("reading antes")
|
||||||
m = self.re_Antes.finditer(hand.string)
|
m = self.re_Antes.finditer(hand.handText)
|
||||||
for player in m:
|
for player in m:
|
||||||
print "DEBUG: hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))
|
logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
|
||||||
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
|
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
|
||||||
|
|
||||||
def readBringIn(self, hand):
|
def readBringIn(self, hand):
|
||||||
print "DEBUG: reading bring in"
|
m = self.re_BringIn.search(hand.handText,re.DOTALL)
|
||||||
# print hand.string
|
|
||||||
m = self.re_BringIn.search(hand.string,re.DOTALL)
|
|
||||||
print "DEBUG: Player bringing in: %s for %s" %(m.group('PNAME'), m.group('BRINGIN'))
|
print "DEBUG: Player bringing in: %s for %s" %(m.group('PNAME'), m.group('BRINGIN'))
|
||||||
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
|
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
|
||||||
|
|
||||||
def readButton(self, hand):
|
def readButton(self, hand):
|
||||||
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON'))
|
hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON'))
|
||||||
|
|
||||||
def readHeroCards(self, hand):
|
def readHeroCards(self, hand):
|
||||||
m = self.re_HeroCards.search(hand.string)
|
m = self.re_HeroCards.search(hand.handText)
|
||||||
if(m == None):
|
if(m == None):
|
||||||
#Not involved in hand
|
#Not involved in hand
|
||||||
hand.involved = False
|
hand.involved = False
|
||||||
|
@ -181,25 +186,67 @@ class FullTilt(HandHistoryConverter):
|
||||||
# "2c, qh" -> set(["2c","qc"])
|
# "2c, qh" -> set(["2c","qc"])
|
||||||
# Also works with Omaha hands.
|
# Also works with Omaha hands.
|
||||||
cards = m.group('CARDS')
|
cards = m.group('CARDS')
|
||||||
cards = set(cards.split(' '))
|
cards = [c.strip() for c in cards.split(' ')]
|
||||||
hand.addHoleCards(cards, m.group('PNAME'))
|
hand.addHoleCards(cards, m.group('PNAME'))
|
||||||
|
|
||||||
def readPlayerCards(self, hand, street):
|
def readStudPlayerCards(self, hand, street):
|
||||||
#Used for stud hands - borrows the HeroCards regex for now.
|
# This could be the most tricky one to get right.
|
||||||
m = self.re_HeroCards.finditer(hand.streets.group(street))
|
# It looks for cards dealt in 'street',
|
||||||
print "DEBUG: razz/stud readPlayerCards"
|
# which may or may not be in the section of the hand designated 'street' by markStreets earlier.
|
||||||
print hand.streets.group(street)
|
# Here's an example at FTP of what 'THIRD' and 'FOURTH' look like to hero PokerAscetic
|
||||||
|
#
|
||||||
|
#"*** 3RD STREET ***
|
||||||
|
#Dealt to BFK23 [Th]
|
||||||
|
#Dealt to cutiepr1nnymaid [8c]
|
||||||
|
#Dealt to PokerAscetic [7c 8s] [3h]
|
||||||
|
#..."
|
||||||
|
#
|
||||||
|
#"*** 4TH STREET ***
|
||||||
|
#Dealt to cutiepr1nnymaid [8c] [2s]
|
||||||
|
#Dealt to PokerAscetic [7c 8s 3h] [5s]
|
||||||
|
#..."
|
||||||
|
#Note that hero's first two holecards are only reported at 3rd street as 'old' cards.
|
||||||
|
logging.debug("readStudPlayerCards")
|
||||||
|
m = self.re_HeroCards.finditer(hand.streets[street])
|
||||||
for player in m:
|
for player in m:
|
||||||
print player.groups()
|
logging.debug(player.groupdict())
|
||||||
cards = player.group('CARDS')
|
(pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS'))
|
||||||
if player.group('NEWCARD') != None:
|
if oldcards:
|
||||||
print cards
|
oldcards = [c.strip() for c in oldcards.split(' ')]
|
||||||
cards = cards + " " + player.group('NEWCARD')
|
if newcards:
|
||||||
cards = set(cards.split(' '))
|
newcards = [c.strip() for c in newcards.split(' ')]
|
||||||
hand.addPlayerCards(cards, player.group('PNAME'))
|
# options here:
|
||||||
|
# (1) we trust the hand will know what to do -- probably check that the old cards match what it already knows, and add the newcards to this street.
|
||||||
|
# (2) we're the experts at this particular history format and we know how we're going to be called (once for each street in Hand.streetList)
|
||||||
|
# so call addPlayerCards with the appropriate information.
|
||||||
|
# I favour (2) here but I'm afraid it is rather stud7-specific.
|
||||||
|
# in the following, the final list of cards will be in 'newcards' whilst if the first list exists (most of the time it does) it will be in 'oldcards'
|
||||||
|
if street=='ANTES':
|
||||||
|
return
|
||||||
|
elif street=='THIRD':
|
||||||
|
# we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS'
|
||||||
|
# hero: [xx][o]
|
||||||
|
# others: [o]
|
||||||
|
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards)
|
||||||
|
elif street in ('FOURTH', 'FIFTH', 'SIXTH'):
|
||||||
|
# 4th:
|
||||||
|
# hero: [xxo] [o]
|
||||||
|
# others: [o] [o]
|
||||||
|
# 5th:
|
||||||
|
# hero: [xxoo] [o]
|
||||||
|
# others: [oo] [o]
|
||||||
|
# 6th:
|
||||||
|
# hero: [xxooo] [o]
|
||||||
|
# others: [ooo] [o]
|
||||||
|
hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards)
|
||||||
|
# we may additionally want to check the earlier streets tally with what we have but lets trust it for now.
|
||||||
|
elif street=='SEVENTH' and newcards:
|
||||||
|
# hero: [xxoooo] [x]
|
||||||
|
# others: not reported.
|
||||||
|
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards)
|
||||||
|
|
||||||
def readAction(self, hand, street):
|
def readAction(self, hand, street):
|
||||||
m = self.re_Action.finditer(hand.streets.group(street))
|
m = self.re_Action.finditer(hand.streets[street])
|
||||||
for action in m:
|
for action in m:
|
||||||
if action.group('ATYPE') == ' raises to':
|
if action.group('ATYPE') == ' raises to':
|
||||||
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
|
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
|
||||||
|
@ -216,17 +263,17 @@ class FullTilt(HandHistoryConverter):
|
||||||
|
|
||||||
|
|
||||||
def readShowdownActions(self, hand):
|
def readShowdownActions(self, hand):
|
||||||
for shows in self.re_ShowdownAction.finditer(hand.string):
|
for shows in self.re_ShowdownAction.finditer(hand.handText):
|
||||||
cards = shows.group('CARDS')
|
cards = shows.group('CARDS')
|
||||||
cards = set(cards.split(' '))
|
cards = set(cards.split(' '))
|
||||||
hand.addShownCards(cards, shows.group('PNAME'))
|
hand.addShownCards(cards, shows.group('PNAME'))
|
||||||
|
|
||||||
def readCollectPot(self,hand):
|
def readCollectPot(self,hand):
|
||||||
for m in self.re_CollectPot.finditer(hand.string):
|
for m in self.re_CollectPot.finditer(hand.handText):
|
||||||
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
||||||
|
|
||||||
def readShownCards(self,hand):
|
def readShownCards(self,hand):
|
||||||
for m in self.re_ShownCards.finditer(hand.string):
|
for m in self.re_ShownCards.finditer(hand.handText):
|
||||||
if m.group('CARDS') is not None:
|
if m.group('CARDS') is not None:
|
||||||
cards = m.group('CARDS')
|
cards = m.group('CARDS')
|
||||||
cards = set(cards.split(' '))
|
cards = set(cards.split(' '))
|
||||||
|
@ -234,12 +281,20 @@ class FullTilt(HandHistoryConverter):
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
c = Configuration.Config()
|
parser = OptionParser()
|
||||||
if len(sys.argv) == 1:
|
parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/fulltilt/razz/FT20090223 Danville - $0.50-$1 Ante $0.10 - Limit Razz.txt")
|
||||||
testfile = "regression-test-files/fulltilt/razz/FT20090223 Danville - $0.50-$1 Ante $0.10 - Limit Razz.txt"
|
parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-")
|
||||||
else:
|
parser.add_option("-f", "--follow", dest="follow", help="follow (tail -f) the input", action="store_true", default=False)
|
||||||
testfile = sys.argv[1]
|
parser.add_option("-q", "--quiet",
|
||||||
print "Converting: ", testfile
|
action="store_const", const=logging.CRITICAL, dest="verbosity", default=logging.INFO)
|
||||||
e = FullTilt(c, testfile)
|
parser.add_option("-v", "--verbose",
|
||||||
e.processFile()
|
action="store_const", const=logging.INFO, dest="verbosity")
|
||||||
print str(e)
|
parser.add_option("--vv",
|
||||||
|
action="store_const", const=logging.DEBUG, dest="verbosity")
|
||||||
|
|
||||||
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
LOG_FILENAME = './logging.out'
|
||||||
|
logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity)
|
||||||
|
|
||||||
|
e = FullTilt(in_path = options.ipath, out_path = options.opath, follow = options.follow)
|
||||||
|
|
142
pyfpdb/Hand.py
142
pyfpdb/Hand.py
|
@ -43,7 +43,7 @@ class Hand:
|
||||||
self.players = []
|
self.players = []
|
||||||
self.posted = []
|
self.posted = []
|
||||||
self.involved = True
|
self.involved = True
|
||||||
self.pot = Pot()
|
|
||||||
|
|
||||||
# Collections indexed by street names
|
# Collections indexed by street names
|
||||||
self.bets = {}
|
self.bets = {}
|
||||||
|
@ -55,11 +55,10 @@ class Hand:
|
||||||
self.bets[street] = {}
|
self.bets[street] = {}
|
||||||
self.lastBet[street] = 0
|
self.lastBet[street] = 0
|
||||||
self.actions[street] = []
|
self.actions[street] = []
|
||||||
|
|
||||||
self.board = {} # dict from street names to community cards
|
self.board = {} # dict from street names to community cards
|
||||||
|
|
||||||
# Collections indexed by player names
|
# Collections indexed by player names
|
||||||
self.holecards = {} # dict from player names to lists of hole cards
|
self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards
|
||||||
self.stacks = {}
|
self.stacks = {}
|
||||||
self.collected = [] #list of ?
|
self.collected = [] #list of ?
|
||||||
self.collectees = {} # dict from player names to amounts collected (?)
|
self.collectees = {} # dict from player names to amounts collected (?)
|
||||||
|
@ -68,14 +67,14 @@ class Hand:
|
||||||
self.shown = set()
|
self.shown = set()
|
||||||
self.folded = set()
|
self.folded = set()
|
||||||
|
|
||||||
self.action = []
|
# self.action = []
|
||||||
|
# Things to do with money
|
||||||
|
self.pot = Pot()
|
||||||
self.totalpot = None
|
self.totalpot = None
|
||||||
self.totalcollected = None
|
self.totalcollected = None
|
||||||
|
|
||||||
self.rake = None
|
self.rake = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def addPlayer(self, seat, name, chips):
|
def addPlayer(self, seat, name, chips):
|
||||||
"""\
|
"""\
|
||||||
Adds a player to the hand, and initialises data structures indexed by player.
|
Adds a player to the hand, and initialises data structures indexed by player.
|
||||||
|
@ -90,6 +89,7 @@ If a player has None chips he won't be added."""
|
||||||
self.pot.addPlayer(name)
|
self.pot.addPlayer(name)
|
||||||
for street in self.streetList:
|
for street in self.streetList:
|
||||||
self.bets[street][name] = []
|
self.bets[street][name] = []
|
||||||
|
self.holecards[name] = {}
|
||||||
|
|
||||||
|
|
||||||
def addStreets(self, match):
|
def addStreets(self, match):
|
||||||
|
@ -100,49 +100,8 @@ If a player has None chips he won't be added."""
|
||||||
else:
|
else:
|
||||||
logging.error("markstreets didn't match")
|
logging.error("markstreets didn't match")
|
||||||
|
|
||||||
def addHoleCards(self, cards, player):
|
|
||||||
"""\
|
|
||||||
Assigns observed holecards to a player.
|
|
||||||
cards list of card bigrams e.g. ['2h','Jc']
|
|
||||||
player (string) name of player
|
|
||||||
"""
|
|
||||||
#print "DEBUG: addHoleCards", cards,player
|
|
||||||
try:
|
|
||||||
self.checkPlayerExists(player)
|
|
||||||
cards = set([self.card(c) for c in cards])
|
|
||||||
self.holecards[player].extend(cards)
|
|
||||||
except FpdbParseError, e:
|
|
||||||
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
|
||||||
|
|
||||||
def addPlayerCards(self, cards, player):
|
|
||||||
"""\
|
|
||||||
Assigns observed cards to a player.
|
|
||||||
cards list of card bigrams e.g. ['2h','Jc']
|
|
||||||
player (string) name of player
|
|
||||||
|
|
||||||
Should probably be merged with addHoleCards
|
|
||||||
"""
|
|
||||||
logging.debug("addPlayerCards %s, %s" % ( cards,player))
|
|
||||||
try:
|
|
||||||
self.checkPlayerExists(player)
|
|
||||||
cards = set([self.card(c) for c in cards])
|
|
||||||
self.holecards[player].update(cards)
|
|
||||||
except FpdbParseError, e:
|
|
||||||
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
|
||||||
|
|
||||||
def addShownCards(self, cards, player, holeandboard=None):
|
|
||||||
"""\
|
|
||||||
For when a player shows cards for any reason (for showdown or out of choice).
|
|
||||||
Card ranks will be uppercased
|
|
||||||
"""
|
|
||||||
|
|
||||||
if cards is not None:
|
|
||||||
self.shown.add(player)
|
|
||||||
self.addHoleCards(cards,player)
|
|
||||||
elif holeandboard is not None:
|
|
||||||
holeandboard = set([self.card(c) for c in holeandboard])
|
|
||||||
board = set([c for s in self.board.values() for c in s])
|
|
||||||
self.addHoleCards(holeandboard.difference(board),player)
|
|
||||||
|
|
||||||
|
|
||||||
def checkPlayerExists(self,player):
|
def checkPlayerExists(self,player):
|
||||||
|
@ -362,8 +321,8 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
||||||
|
|
||||||
return retstring
|
return retstring
|
||||||
|
|
||||||
def writeHand(self, fh=sys.__stdout__):
|
#def writeHand(self, fh=sys.__stdout__):
|
||||||
print >>fh, "Override me"
|
# print >>fh, "Override me"
|
||||||
|
|
||||||
def printHand(self):
|
def printHand(self):
|
||||||
self.writeHand(sys.stdout)
|
self.writeHand(sys.stdout)
|
||||||
|
@ -398,6 +357,9 @@ class HoldemOmahaHand(Hand):
|
||||||
self.sb = gametype[3]
|
self.sb = gametype[3]
|
||||||
self.bb = gametype[4]
|
self.bb = gametype[4]
|
||||||
|
|
||||||
|
#Populate a HoldemOmahaHand
|
||||||
|
#Generally, we call 'read' methods here, which get the info according to the particular filter (hhc)
|
||||||
|
# which then invokes a 'addXXX' callback
|
||||||
hhc.readHandInfo(self)
|
hhc.readHandInfo(self)
|
||||||
hhc.readPlayerStacks(self)
|
hhc.readPlayerStacks(self)
|
||||||
hhc.compilePlayerRegexs(players = set([player[1] for player in self.players]))
|
hhc.compilePlayerRegexs(players = set([player[1] for player in self.players]))
|
||||||
|
@ -418,6 +380,33 @@ class HoldemOmahaHand(Hand):
|
||||||
self.totalPot() # finalise it (total the pot)
|
self.totalPot() # finalise it (total the pot)
|
||||||
hhc.getRake(self)
|
hhc.getRake(self)
|
||||||
|
|
||||||
|
def addHoleCards(self, cards, player):
|
||||||
|
"""\
|
||||||
|
Assigns observed holecards to a player.
|
||||||
|
cards list of card bigrams e.g. ['2h','Jc']
|
||||||
|
player (string) name of player
|
||||||
|
"""
|
||||||
|
#print "DEBUG: addHoleCards", cards,player
|
||||||
|
try:
|
||||||
|
self.checkPlayerExists(player)
|
||||||
|
self.holecards[player] = set(self.card(c) for c in cards)
|
||||||
|
except FpdbParseError, e:
|
||||||
|
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||||
|
|
||||||
|
def addShownCards(self, cards, player, holeandboard=None):
|
||||||
|
"""\
|
||||||
|
For when a player shows cards for any reason (for showdown or out of choice).
|
||||||
|
Card ranks will be uppercased
|
||||||
|
"""
|
||||||
|
if cards is not None:
|
||||||
|
self.shown.add(player)
|
||||||
|
self.addHoleCards(cards,player)
|
||||||
|
elif holeandboard is not None:
|
||||||
|
holeandboard = set([self.card(c) for c in holeandboard])
|
||||||
|
board = set([c for s in self.board.values() for c in s])
|
||||||
|
self.addHoleCards(holeandboard.difference(board),player)
|
||||||
|
|
||||||
|
|
||||||
def writeHand(self, fh=sys.__stdout__):
|
def writeHand(self, fh=sys.__stdout__):
|
||||||
# PokerStars format.
|
# PokerStars format.
|
||||||
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime)))
|
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime)))
|
||||||
|
@ -508,36 +497,59 @@ class StudHand(Hand):
|
||||||
if gametype[1] not in ["razz","stud","stud8"]:
|
if gametype[1] not in ["razz","stud","stud8"]:
|
||||||
pass # or indeed don't pass and complain instead
|
pass # or indeed don't pass and complain instead
|
||||||
self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
|
self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
|
||||||
|
self.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH']
|
||||||
Hand.__init__(self, sitename, gametype, handText)
|
Hand.__init__(self, sitename, gametype, handText)
|
||||||
|
self.sb = gametype[3]
|
||||||
|
self.bb = gametype[4]
|
||||||
|
#Populate the StudHand
|
||||||
|
#Generally, we call a 'read' method here, which gets the info according to the particular filter (hhc)
|
||||||
|
# which then invokes a 'addXXX' callback
|
||||||
hhc.readHandInfo(self)
|
hhc.readHandInfo(self)
|
||||||
hhc.readPlayerStacks(self)
|
hhc.readPlayerStacks(self)
|
||||||
hhc.compilePlayerRegexs(players = set([player[1] for player in self.players]))
|
hhc.compilePlayerRegexs(players = set([player[1] for player in self.players]))
|
||||||
hhc.markStreets(self)
|
hhc.markStreets(self)
|
||||||
hhc.readAntes(self)
|
hhc.readAntes(self)
|
||||||
hhc.readBringIn(self)
|
hhc.readBringIn(self)
|
||||||
hhc.readShowdownActions(self)
|
# hhc.readShowdownActions(self) # not done yet
|
||||||
# Read actions in street order
|
# Read actions in street order
|
||||||
for street in self.streetList:
|
for street in self.streetList:
|
||||||
if self.streets[street]:
|
if self.streets[street]:
|
||||||
logging.debug(street)
|
logging.debug(street)
|
||||||
logging.debug(hand.streets[street])
|
logging.debug(self.streets[street])
|
||||||
hhc.readPlayerCards(self, street)
|
hhc.readStudPlayerCards(self, street)
|
||||||
hhc.readAction(self, street)
|
hhc.readAction(self, street)
|
||||||
hhc.readCollectPot(self)
|
hhc.readCollectPot(self)
|
||||||
hhc.readShownCards(self)
|
# hhc.readShownCards(self) # not done yet
|
||||||
self.totalPot() # finalise it (total the pot)
|
self.totalPot() # finalise it (total the pot)
|
||||||
hhc.getRake(self)
|
hhc.getRake(self)
|
||||||
|
|
||||||
def addBringIn(self, player, ante):
|
def addPlayerCards(self, player, street, open=[], closed=[]):
|
||||||
if player is not None:
|
"""\
|
||||||
self.bets['THIRD'][player].append(Decimal(ante))
|
Assigns observed cards to a player.
|
||||||
self.stacks[player] -= Decimal(ante)
|
player (string) name of player
|
||||||
act = (player, 'bringin', "bringin", ante, self.stacks[player]==0)
|
street (string) the street name (in streetList)
|
||||||
self.actions['THIRD'].append(act)
|
open list of card bigrams e.g. ['2h','Jc'], dealt face up
|
||||||
self.pot.addMoney(player, Decimal(ante))
|
closed likewise, but known only to player
|
||||||
|
"""
|
||||||
|
logging.debug("addPlayerCards %s, o%s x%s" % (player, open, closed))
|
||||||
|
try:
|
||||||
|
self.checkPlayerExists(player)
|
||||||
|
self.holecards[player][street] = (open, closed)
|
||||||
|
# cards = set([self.card(c) for c in cards])
|
||||||
|
# self.holecards[player].update(cards)
|
||||||
|
except FpdbParseError, e:
|
||||||
|
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||||
|
|
||||||
def writeStudHand(self, fh=sys.__stdout__):
|
def addBringIn(self, player, bringin):
|
||||||
|
if player is not None:
|
||||||
|
logging.debug("Bringin: %s, %s" % (player , bringin))
|
||||||
|
self.bets['THIRD'][player].append(Decimal(bringin))
|
||||||
|
self.stacks[player] -= Decimal(bringin)
|
||||||
|
act = (player, 'bringin', "bringin", bringin, self.stacks[player]==0)
|
||||||
|
self.actions['THIRD'].append(act)
|
||||||
|
self.pot.addMoney(player, Decimal(bringin))
|
||||||
|
|
||||||
|
def writeHand(self, fh=sys.__stdout__):
|
||||||
# PokerStars format.
|
# PokerStars format.
|
||||||
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime)))
|
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime)))
|
||||||
print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||||
|
@ -554,8 +566,10 @@ class StudHand(Hand):
|
||||||
|
|
||||||
if 'THIRD' in self.actions:
|
if 'THIRD' in self.actions:
|
||||||
print >>fh, _("*** 3RD STREET ***")
|
print >>fh, _("*** 3RD STREET ***")
|
||||||
for player in [x for x in self.players if x[1] in players_who_post_antes]:
|
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
|
||||||
print >>fh, _("Dealt to ")
|
print player, self.holecards[player]
|
||||||
|
(closed, open) = self.holecards[player]['THIRD']
|
||||||
|
print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "]" if closed else " ", " [" + " ".join(open) + "]" if open else " ")
|
||||||
for act in self.actions['THIRD']:
|
for act in self.actions['THIRD']:
|
||||||
#FIXME: Need some logic here for bringin vs completes
|
#FIXME: Need some logic here for bringin vs completes
|
||||||
self.printActionLine(act, fh)
|
self.printActionLine(act, fh)
|
||||||
|
|
|
@ -136,7 +136,7 @@ class HandHistoryConverter(threading.Thread):
|
||||||
if self.obs == "" or self.obs == None:
|
if self.obs == "" or self.obs == None:
|
||||||
logging.info("Read no hands.")
|
logging.info("Read no hands.")
|
||||||
return
|
return
|
||||||
return self.obs.split(self.splitstring)
|
return re.split(self.re_SplitHands, self.obs)
|
||||||
|
|
||||||
def processHand(self, handtext):
|
def processHand(self, handtext):
|
||||||
gametype = self.determineGameType(handtext)
|
gametype = self.determineGameType(handtext)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user