Explicit matching of player names

About the only place where we are guaranteed to get all the players'
names correctly is in the seating plan in the hand header. We extract
the names and build a regex that matches only the names. We only do this
if the current regex is out of date, to avoid recompiling them too
often.
I also did away with self.rexx because it seemed unnecessary and was
difficult to work with.
This commit is contained in:
Matt Turnbull 2009-02-20 16:29:52 +00:00
parent 81c92f9599
commit 483e177346
4 changed files with 61 additions and 52 deletions

View File

@ -70,20 +70,24 @@ class Everleaf(HandHistoryConverter):
HandHistoryConverter.__init__(self, config, file, sitename="Everleaf") # Call super class init. HandHistoryConverter.__init__(self, config, file, sitename="Everleaf") # Call super class init.
self.sitename = "Everleaf" self.sitename = "Everleaf"
self.setFileType("text", "cp1252") self.setFileType("text", "cp1252")
self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)')
self.rexx.setSplitHandRegex('\n\n+') self.re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)")
self.rexx.setHandInfoRegex('.*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)') self.re_SplitHands = re.compile(r"\n\n+")
self.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)') self.re_HandInfo = re.compile(r".*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)")
self.rexx.setPostSbRegex('.*\n(?P<PNAME>.*): posts small blind \[\$? (?P<SB>[.0-9]+)') self.re_PlayerInfo = re.compile(r"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)", re.MULTILINE)
self.rexx.setPostBbRegex('.*\n(?P<PNAME>.*): posts big blind \[\$? (?P<BB>[.0-9]+)') self.re_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
self.rexx.setPostBothRegex('.*\n(?P<PNAME>.*): posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<CARDS>.*) \]') def compile_player_regexs(self):
self.rexx.setActionStepRegex('.*\n(?P<PNAME>[^: ]*)(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[\$ (?P<BET>[.\d]+) (USD|EUR)\])?') player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")"
self.rexx.setShowdownActionRegex('.*\n(?P<PNAME>.*) shows \[ (?P<CARDS>.*) \]') print "DEBUG player_re: " + player_re
self.rexx.setCollectPotRegex('.*\n(?P<PNAME>.*) wins \$ (?P<POT>[.\d]+) (USD|EUR)(.*?\[ (?P<CARDS>.*?) \])?') self.re_PostSB = re.compile(r"^%s: posts small blind \[\$? (?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
#self.rexx.setCollectPotRegex('.*\n(?P<PNAME>.*) wins \$ (?P<POT>[.\d]+) USD(.*\[ (?P<CARDS>) \S\S, \S\S, \S\S, \S\S, \S\S \])?') self.re_PostBB = re.compile(r"^%s: posts big blind \[\$? (?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
self.rexx.sits_out_re = re.compile('(?P<PNAME>.*) sits out') self.re_PostBoth = re.compile(r"^%s: posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
self.rexx.compileRegexes() self.re_HeroCards = re.compile(r"^Dealt to %s \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
self.re_Action = re.compile(r"^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[\$ (?P<BET>[.\d]+) (USD|EUR)\])?" % player_re, re.MULTILINE)
self.re_ShowdownAction = re.compile(r"^%s shows \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
self.re_CollectPot = re.compile(r"^%s wins \$ (?P<POT>[.\d]+) (USD|EUR)(.*?\[ (?P<CARDS>.*?) \])?" % player_re, re.MULTILINE)
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE)
def readSupportedGames(self): def readSupportedGames(self):
return [["ring", "hold", "nl"]] return [["ring", "hold", "nl"]]
@ -91,15 +95,13 @@ class Everleaf(HandHistoryConverter):
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.re_GameInfo.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.re_HandInfo.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.
@ -118,11 +120,12 @@ class Everleaf(HandHistoryConverter):
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.re_PlayerInfo.finditer(hand.string)
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. # This re fails if, say, river is missing; then we don't get the ** that starts the river.
@ -137,25 +140,26 @@ class Everleaf(HandHistoryConverter):
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
self.rexx.board_re = re.compile(r"\[ (?P<CARDS>.+) \]") print "DEBUG " + street + ":"
print hand.streets.group(street) print hand.streets.group(street) + "\n"
if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP) if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
m = self.rexx.board_re.search(hand.streets.group(street)) m = self.re_Board.search(hand.streets.group(street))
hand.setCommunityCards(street, m.group('CARDS').split(', ')) hand.setCommunityCards(street, m.group('CARDS').split(', '))
def readBlinds(self, hand): def readBlinds(self, hand):
try: try:
m = self.rexx.small_blind_re.search(hand.string) m = self.re_PostSB.search(hand.string)
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 Exception, e: # no small blind
print e
hand.addBlind(None, None, None) hand.addBlind(None, None, None)
for a in self.rexx.big_blind_re.finditer(hand.string): for a in self.re_PostBB.finditer(hand.string):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.rexx.both_blinds_re.finditer(hand.string): for a in self.re_PostBoth.finditer(hand.string):
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB')) hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
def readHeroCards(self, hand): def readHeroCards(self, hand):
m = self.rexx.hero_cards_re.search(hand.string) m = self.re_HeroCards.search(hand.string)
if(m == None): if(m == None):
#Not involved in hand #Not involved in hand
hand.involved = False hand.involved = False
@ -168,7 +172,7 @@ class Everleaf(HandHistoryConverter):
hand.addHoleCards(cards, m.group('PNAME')) hand.addHoleCards(cards, m.group('PNAME'))
def readAction(self, hand, street): def readAction(self, hand, street):
m = self.rexx.action_re.finditer(hand.streets.group(street)) m = self.re_Action.finditer(hand.streets.group(street))
for action in m: for action in m:
if action.group('ATYPE') == ' raises': if action.group('ATYPE') == ' raises':
hand.addCallandRaise( street, action.group('PNAME'), action.group('BET') ) hand.addCallandRaise( street, action.group('PNAME'), action.group('BET') )
@ -185,17 +189,17 @@ class Everleaf(HandHistoryConverter):
def readShowdownActions(self, hand): def readShowdownActions(self, hand):
for shows in self.rexx.showdown_action_re.finditer(hand.string): for shows in self.re_ShowdownAction.finditer(hand.string):
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.rexx.collect_pot_re.finditer(hand.string): for m in self.re_CollectPot.finditer(hand.string):
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.rexx.collect_pot_re.finditer(hand.string): for m in self.re_CollectPot.finditer(hand.string):
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(', '))

View File

@ -145,7 +145,7 @@ class GuiAutoImport (threading.Thread):
# Add directories to importer object. # Add directories to importer object.
for site in self.input_settings: for site in self.input_settings:
self.importer.addImportDirectory(self.input_settings[site][0], True, site, self.input_settings[site][1]) self.importer.addImportDirectory(self.input_settings[site][0], monitor=True, site, self.input_settings[site][1])
print "Adding import directories - Site: " + site + " dir: "+ str(self.input_settings[site][0]) print "Adding import directories - Site: " + site + " dir: "+ str(self.input_settings[site][0])
self.do_import() self.do_import()

View File

@ -89,7 +89,9 @@ class HandHistoryConverter:
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, os.path.basename(file)) self.ofile = os.path.join(self.hhdir, os.path.basename(file))
print self.ofile
self.rexx = FpdbRegex.FpdbRegex() self.rexx = FpdbRegex.FpdbRegex()
self.players = set()
def __str__(self): def __str__(self):
tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) tmp = "HandHistoryConverter: '%s'\n" % (self.sitename)
@ -116,10 +118,21 @@ class HandHistoryConverter:
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:
print "\nInput:\n"+hand.string print "\nInput:\n"+hand.string+"\n"
self.readHandInfo(hand) self.readHandInfo(hand)
self.readPlayerStacks(hand) self.readPlayerStacks(hand)
print "DEBUG stacks:", hand.stacks print "DEBUG stacks:", hand.stacks
# at this point we know the player names, they are in hand.players
playersThisHand = set([player[1] for player in hand.players])
if playersThisHand <= self.players: # x <= y means 'x is subset of y'
# we're ok; the regex should already cover them all.
pass
else:
# we need to recompile the player regexs.
self.players = playersThisHand
self.compile_player_regexs()
self.markStreets(hand) self.markStreets(hand)
self.readBlinds(hand) self.readBlinds(hand)
self.readHeroCards(hand) # want to generalise to draw games self.readHeroCards(hand) # want to generalise to draw games
@ -178,7 +191,11 @@ class HandHistoryConverter:
# 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
# Given
#
def compile_player_regexs(self): 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
# so groups are called by street names 'PREFLOP', 'FLOP', 'STREET2' etc # so groups are called by street names 'PREFLOP', 'FLOP', 'STREET2' etc
# blinds are done seperately # blinds are done seperately
@ -228,7 +245,7 @@ class HandHistoryConverter:
def splitFileIntoHands(self): def splitFileIntoHands(self):
hands = [] hands = []
self.obs.strip() self.obs.strip()
list = self.rexx.split_hand_re.split(self.obs) list = self.re_SplitHands.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 + "'"
@ -250,22 +267,6 @@ class HandHistoryConverter:
traceback.print_exc(file=sys.stderr) traceback.print_exc(file=sys.stderr)
#takes a poker float (including , for thousand seperator and converts it to an int
def float2int (self, string):
pos=string.find(",")
if (pos!=-1): #remove , the thousand seperator
string=string[0:pos]+string[pos+1:]
pos=string.find(".")
if (pos!=-1): #remove decimal point
string=string[0:pos]+string[pos+1:]
result = int(string)
if pos==-1: #no decimal point - was in full dollars - need to multiply with 100
result*=100
return result
#end def float2int
def getStatus(self): def getStatus(self):
#TODO: Return a status of true if file processed ok #TODO: Return a status of true if file processed ok
return True return True

View File

@ -218,6 +218,10 @@ class Importer:
conv.processFile() conv.processFile()
if(conv.getStatus()): if(conv.getStatus()):
(stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(conv.getProcessedFile(), site) (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(conv.getProcessedFile(), site)
else:
# conversion didn't work
# TODO: appropriate response?
return (0, 0, 0, 1, 0)
#This will barf if conv.getStatus != True #This will barf if conv.getStatus != True
return (stored, duplicates, partial, errors, ttime) return (stored, duplicates, partial, errors, ttime)