Merge branch 'master' of git://git.assembla.com/fpdboz.git

This commit is contained in:
eblade 2009-02-27 13:37:08 -05:00
commit 701079fe35
7 changed files with 305 additions and 64 deletions

View File

@ -25,24 +25,29 @@ from time import strftime
# Class for converting Everleaf HH format.
class Everleaf(HandHistoryConverter):
# Static regexes
re_SplitHands = re.compile(r"\n\n+")
re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<LTYPE>(NL|PL)) (?P<GAME>(Hold\'em|Omaha|7 Card Stud))")
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]+)")
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_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
def __init__(self, config, file):
print "Initialising Everleaf converter class"
HandHistoryConverter.__init__(self, config, file, sitename="Everleaf") # Call super class init.
self.sitename = "Everleaf"
self.setFileType("text", "cp1252")
self.re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<LTYPE>(NL|PL)) (?P<GAME>(Hold\'em|Omaha|7 Card Stud))")
self.re_SplitHands = re.compile(r"\n\n+")
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.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.re_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
try:
self.ofile = os.path.join(self.hhdir, file.split(os.path.sep)[-2]+"-"+os.path.basename(file))
except:
self.ofile = os.path.join(self.hhdir, "x"+strftime("%d-%m-%y")+os.path.basename(file))
def compile_player_regexs(self):
def compilePlayerRegexs(self):
player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")"
#print "DEBUG player_re: " + player_re
self.re_PostSB = re.compile(r"^%s: posts small blind \[\$? (?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
@ -116,7 +121,6 @@ class Everleaf(HandHistoryConverter):
#TODO: Do conversion from GMT to ET
#TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this)
hand.starttime = time.strptime(m.group('DATETIME'), "%Y/%m/%d - %H:%M:%S")
hand.buttonpos = int(m.group('BUTTON'))
def readPlayerStacks(self, hand):
m = self.re_PlayerInfo.finditer(hand.string)
@ -160,6 +164,9 @@ class Everleaf(HandHistoryConverter):
for a in self.re_PostBoth.finditer(hand.string):
hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB'))
def readButton(self, hand):
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON'))
def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.string)
if(m == None):

View File

@ -23,36 +23,41 @@ from HandHistoryConverter import *
# FullTilt HH Format converter
class FullTilt(HandHistoryConverter):
# Static regexes
re_GameInfo = re.compile('- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<LTYPE>(No|Pot)? )?Limit (?P<GAME>(Hold\'em|Omaha|Razz))')
re_SplitHands = re.compile(r"\n\n+")
re_HandInfo = re.compile('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[- a-zA-Z]+) (\((?P<TABLEATTRIBUTES>.+)\) )?- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<GAMETYPE>[a-zA-Z\' ]+) - (?P<DATETIME>.*)')
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE)
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
def __init__(self, config, file):
print "Initialising FullTilt converter class"
HandHistoryConverter.__init__(self, config, file, sitename="FullTilt") # Call super class init.
self.sitename = "FullTilt"
self.setFileType("text", "cp1252")
self.re_GameInfo = re.compile('- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<LTYPE>(No|Pot)) Limit (?P<GAME>(Hold\'em|Omaha))')
self.re_SplitHands = re.compile(r"\n\n+")
self.re_HandInfo = re.compile('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[- a-zA-Z]+) (\((?P<TABLEATTRIBUTES>.+)\) )?- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>[a-zA-Z\' ]+) - (?P<DATETIME>.*)')
self.re_Button = re.compile('The button is in seat #(?P<BUTTON>\d+)')
self.re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
self.re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
def compile_player_regexs(self):
def compilePlayerRegexs(self):
player_re = "(?P<PNAME>" + "|".join(map(re.escape, self.players)) + ")"
#print "DEBUG player_re: " + player_re
self.re_PostSB = re.compile('.*\n(?P<PNAME>.*) posts the small blind of \$?(?P<SB>[.0-9]+)')
self.re_PostBB = re.compile('.*\n(?P<PNAME>.*) posts (the big blind of )?\$?(?P<BB>[.0-9]+)')
self.re_PostBoth = re.compile('.*\n(?P<PNAME>.*) posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
self.re_HeroCards = re.compile('.*\nDealt\sto\s(?P<PNAME>.*)\s\[(?P<CARDS>.*)\]')
self.re_Action = re.compile('.*\n(?P<PNAME>.*)(?P<ATYPE> bets| checks| raises to| calls| folds)(\s\$(?P<BET>[.\d]+))?')
self.re_ShowdownAction = re.compile('.*\n(?P<PNAME>.*) shows \[(?P<CARDS>.*)\]')
self.re_CollectPot = re.compile(r"Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*?) (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*)")
self.re_SitsOut = re.compile('(?P<PNAME>.*) sits out')
self.re_ShownCards = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(.*\) showed \[(?P<CARDS>.*)\].*')
print "DEBUG player_re: " + player_re
self.re_PostSB = re.compile(r"^%s posts the small blind of \$?(?P<SB>[.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_Antes = re.compile(r"^%s antes \$?(?P<ANTE>[.0-9]+)" % player_re, re.MULTILINE)
self.re_BringIn = re.compile(r"^%s brings in for \$?(?P<BRINGIN>[.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_HeroCards = re.compile(r"^Dealt to %s \[(?P<CARDS>[AKQJT0-9hcsd ]+)\]( \[(?P<NEWCARD>[AKQJT0-9hcsd ]+)\])?" % 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_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):
return [["ring", "hold", "nl"],
["ring", "hold", "pl"],
["ring", "razz", "fl"],
["ring", "omaha", "pl"]
]
@ -66,15 +71,21 @@ class FullTilt(HandHistoryConverter):
m = self.re_GameInfo.search(self.obs)
if m.group('LTYPE') == "No":
if m.group('LTYPE') == "No ":
structure = "nl"
elif m.group('LTYPE') == "Pot":
elif m.group('LTYPE') == "Pot ":
structure = "pl"
elif m.group('LTYPE') == None:
structure = "fl"
if m.group('GAME') == "Hold\'em":
game = "hold"
if m.group('GAME') == "Omaha":
elif m.group('GAME') == "Omaha":
game = "omahahi"
elif m.group('GAME') == "Razz":
game = "razz"
print m.groups()
gametype = ["ring", game, structure, m.group('SB'), m.group('BB')]
@ -85,7 +96,6 @@ class FullTilt(HandHistoryConverter):
#print m.groups()
hand.handid = m.group('HID')
hand.tablename = m.group('TABLE')
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON'))
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.
# m.group('SB')
@ -112,11 +122,18 @@ class FullTilt(HandHistoryConverter):
# 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":
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
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"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.string,re.DOTALL)
elif self.gametype[1] == "razz":
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)"
r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?"
r"(\*\*\* 4TH STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5TH STREET \*\*\*)|.+))?"
r"(\*\*\* 5TH STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6TH STREET \*\*\*)|.+))?"
r"(\*\*\* 6TH STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* 7TH STREET \*\*\*)|.+))?"
r"(\*\*\* 7TH STREET \*\*\*(?P<SEVENTH>.+))?", hand.string,re.DOTALL)
hand.addStreets(m)
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
@ -137,6 +154,23 @@ class FullTilt(HandHistoryConverter):
for a in self.re_PostBoth.finditer(hand.string):
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
def readAntes(self, hand):
print "DEBUG: reading antes"
m = self.re_Antes.finditer(hand.string)
for player in m:
print "DEBUG: hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
def readBringIn(self, hand):
print "DEBUG: reading bring in"
# 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'))
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
def readButton(self, hand):
hand.buttonpos = int(self.re_Button.search(hand.string).group('BUTTON'))
def readHeroCards(self, hand):
m = self.re_HeroCards.search(hand.string)
if(m == None):
@ -150,6 +184,20 @@ class FullTilt(HandHistoryConverter):
cards = set(cards.split(' '))
hand.addHoleCards(cards, m.group('PNAME'))
def readPlayerCards(self, hand, street):
#Used for stud hands - borrows the HeroCards regex for now.
m = self.re_HeroCards.finditer(hand.streets.group(street))
print "DEBUG: razz/stud readPlayerCards"
print hand.streets.group(street)
for player in m:
print player.groups()
cards = player.group('CARDS')
if player.group('NEWCARD') != None:
print cards
cards = cards + " " + player.group('NEWCARD')
cards = set(cards.split(' '))
hand.addPlayerCards(cards, player.group('PNAME'))
def readAction(self, hand, street):
m = self.re_Action.finditer(hand.streets.group(street))
for action in m:
@ -188,7 +236,7 @@ class FullTilt(HandHistoryConverter):
if __name__ == "__main__":
c = Configuration.Config()
if len(sys.argv) == 1:
testfile = "regression-test-files/fulltilt/FT20081209 CR - tay - $0.05-$0.10 - No Limit Hold'em.txt"
testfile = "regression-test-files/fulltilt/razz/FT20090223 Danville - $0.50-$1 Ante $0.10 - Limit Razz.txt"
else:
testfile = sys.argv[1]
print "Converting: ", testfile

View File

@ -106,7 +106,8 @@ class GuiAutoImport (threading.Thread):
"""Callback for timer to do an import iteration."""
if self.doAutoImportBool:
self.importer.runUpdated()
print "GuiAutoImport.import_dir done"
sys.stdout.write(".")
sys.stdout.flush()
return True
else:
return False

View File

@ -35,17 +35,6 @@ import Configuration
class GuiBulkImport():
def import_dir(self):
"""imports a directory, non-recursive. todo: move this to fpdb_import so CLI can use it"""
self.path = self.inputFile
self.importer.addImportDirectory(self.path)
self.importer.setCallHud(False)
starttime = time()
(stored, dups, partial, errs, ttime) = self.importer.runImport()
print 'GuiBulkImport.import_dir done: Stored: %d Duplicates: %d Partial: %d Errors: %d in %s seconds - %d/sec'\
% (stored, dups, partial, errs, ttime, stored / ttime)
def load_clicked(self, widget, data=None):
# get the dir to import from the chooser
self.inputFile = self.chooser.get_filename()
@ -63,18 +52,22 @@ class GuiBulkImport():
self.importer.setDropIndexes(cb_model[cb_index][0])
else:
self.importer.setDropIndexes("auto")
hhc=self.cbfilter.get_model()[self.cbfilter.get_active()][0]
self.lab_info.set_text("Importing")
if os.path.isdir(self.inputFile):
self.import_dir()
else:
self.importer.addImportFile(self.inputFile)
self.importer.addBulkImportImportFileOrDir(self.inputFile,filter=hhc)
self.importer.setCallHud(False)
self.importer.runImport()
starttime = time()
(stored, dups, partial, errs, ttime) = self.importer.runImport()
print 'GuiBulkImport.import_dir done: Stored: %d Duplicates: %d Partial: %d Errors: %d in %s seconds - %d/sec'\
% (stored, dups, partial, errs, ttime, stored / ttime)
self.importer.clearFileList()
self.lab_info.set_text("Import finished")
def get_vbox(self):
return self.vbox
def __init__(self, db, settings, config):
self.db = db # this is an instance of fpdb_db
self.settings = settings
@ -159,6 +152,20 @@ class GuiBulkImport():
self.table.attach(self.cb, 4, 5, 1, 2, xpadding = 10, ypadding = 0, yoptions=gtk.SHRINK)
self.cb.show()
# label - filter
self.lab_filter = gtk.Label("Site filter:")
self.table.attach(self.lab_filter, 2, 3, 2, 3, xpadding = 0, ypadding = 0, yoptions=gtk.SHRINK)
self.lab_filter.show()
self.lab_filter.set_justify(gtk.JUSTIFY_RIGHT)
# ComboBox - filter
self.cbfilter = gtk.combo_box_new_text()
self.cbfilter.append_text("passthrough")
self.cbfilter.append_text("Everleaf")
self.cbfilter.set_active(0)
self.table.attach(self.cbfilter, 3, 4, 2, 3, xpadding = 10, ypadding = 0, yoptions=gtk.SHRINK)
self.cbfilter.show()
# label - info
self.lab_info = gtk.Label()
self.table.attach(self.lab_info, 0, 4, 2, 3, xpadding = 0, ypadding = 0, yoptions=gtk.SHRINK)

View File

@ -39,7 +39,10 @@ class Hand:
self.gametype = gametype
self.string = string
if gametype[1] == "hold" or self.gametype[1] == "omaha":
self.streetList = ['PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order
elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8":
self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
self.handid = 0
self.sb = gametype[3]
@ -143,6 +146,22 @@ player (string) name of player
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 set of card bigrams e.g. set(['2h','Jc'])
player (string) name of player
Should probably be merged with addHoleCards
"""
print "DEBUG: addPlayerCards", 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).
@ -182,6 +201,14 @@ Card ranks will be uppercased
c = c.replace(k,v)
return c
def addAnte(self, player, ante):
if player is not None:
self.bets['ANTES'][player].append(Decimal(ante))
self.stacks[player] -= Decimal(ante)
act = (player, 'posts', "ante", ante, self.stacks[player]==0)
self.actions['ANTES'].append(act)
self.pot.addMoney(player, Decimal(ante))
def addBlind(self, player, blindtype, amount):
# if player is None, it's a missing small blind.
# TODO:
@ -210,6 +237,14 @@ Card ranks will be uppercased
self.posted = self.posted + [[player,blindtype]]
#print "DEBUG: self.posted: %s" %(self.posted)
def addBringIn(self, player, ante):
if player is not None:
self.bets['THIRD'][player].append(Decimal(ante))
self.stacks[player] -= Decimal(ante)
act = (player, 'bringin', "bringin", ante, self.stacks[player]==0)
self.actions['THIRD'].append(act)
self.pot.addMoney(player, Decimal(ante))
def addCall(self, street, player=None, amount=None):
# Potentially calculate the amount of the call if not supplied
@ -362,11 +397,19 @@ Map the tuple self.gametype onto the pokerstars string describing it
"cp" : "Cap Pot Limit"
}
print "DEBUG: self.gametype: %s" %(self.gametype)
string = "%s %s" %(gs[self.gametype[1]], ls[self.gametype[2]])
return string
def writeHand(self, fh=sys.__stdout__):
if self.gametype[1] == "hold" or self.gametype[1] == "omaha":
self.writeHoldemHand(fh)
else:
self.writeStudHand(fh)
def writeHoldemHand(self, fh=sys.__stdout__):
# PokerStars format.
#print "\n### Pseudo stars format ###"
#print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, self.getGameTypeAsString(), self.sb, self.bb, self.starttime))
@ -413,6 +456,110 @@ Map the tuple self.gametype onto the pokerstars string describing it
self.printActionLine(act, fh)
#Some sites don't have a showdown section so we have to figure out if there should be one
# The logic for a showdown is: at the end of river action there are at least two players in the hand
# we probably don't need a showdown section in pseudo stars format for our filtering purposes
if 'SHOWDOWN' in self.actions:
print >>fh, _("*** SHOW DOWN ***")
#TODO: Complete SHOWDOWN
# Current PS format has the lines:
# Uncalled bet ($111.25) returned to s0rrow
# s0rrow collected $5.15 from side pot
# stervels: shows [Ks Qs] (two pair, Kings and Queens)
# stervels collected $45.35 from main pot
# Immediately before the summary.
# The current importer uses those lines for importing winning rather than the summary
for name in self.pot.returned:
print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name))
for entry in self.collected:
print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1]))
print >>fh, _("*** SUMMARY ***")
print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake)
board = []
for s in self.board.values():
board += s
if board: # sometimes hand ends preflop without a board
print >>fh, _("Board [%s]" % (" ".join(board)))
for player in [x for x in self.players if x[1] in players_who_act_preflop]:
seatnum = player[0]
name = player[1]
if name in self.collectees and name in self.shown:
print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]), self.collectees[name]))
elif name in self.collectees:
print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
elif name in self.shown:
print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name])))
elif name in self.folded:
print >>fh, _("Seat %d: %s folded" % (seatnum, name))
else:
print >>fh, _("Seat %d: %s mucked" % (seatnum, name))
print >>fh, "\n\n"
# TODO:
# logic for side pots
# logic for which players get to showdown
# I'm just not sure we need to do this so heavily.. and if we do, it's probably better to use pokerlib
#if self.holecards[player[1]]: # empty list default is false
#hole = self.holecards[player[1]]
##board = []
##for s in self.board.values():
##board += s
##playerhand = self.bestHand('hi', board+hole)
##print "Seat %d: %s showed %s and won/lost with %s" % (player[0], player[1], hole, playerhand)
#print "Seat %d: %s showed %s" % (player[0], player[1], hole)
#else:
#print "Seat %d: %s mucked or folded" % (player[0], player[1])
def writeStudHand(self, fh=sys.__stdout__):
# PokerStars format.
#print "\n### Pseudo stars format ###"
#print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, self.getGameTypeAsString(), self.sb, self.bb, 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))
players_who_post_antes = set([x[0] for x in self.actions['ANTES']])
for player in [x for x in self.players if x[1] in players_who_post_antes]:
#Only print stacks of players who do something preflop
print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2]))
if 'ANTES' in self.actions:
for act in self.actions['ANTES']:
print >>fh, _("%s: posts the ante $%s" %(act[0], act[3]))
if 'THIRD' in self.actions:
print >>fh, _("*** 3RD STREET ***")
for player in [x for x in self.players if x[1] in players_who_post_antes]:
print >>fh, _("Dealt to ")
for act in self.actions['THIRD']:
#FIXME: Need some logic here for bringin vs completes
self.printActionLine(act, fh)
if 'FOURTH' in self.actions:
print >>fh, _("*** 4TH STREET ***")
for act in self.actions['FOURTH']:
self.printActionLine(act, fh)
if 'FIFTH' in self.actions:
print >>fh, _("*** 5TH STREET ***")
for act in self.actions['FIFTH']:
self.printActionLine(act, fh)
if 'SIXTH' in self.actions:
print >>fh, _("*** 6TH STREET ***")
for act in self.actions['SIXTH']:
self.printActionLine(act, fh)
if 'SEVENTH' in self.actions:
print >>fh, _("*** 7TH STREET ***")
for act in self.actions['SEVENTH']:
self.printActionLine(act, fh)
#Some sites don't have a showdown section so we have to figure out if there should be one
# The logic for a showdown is: at the end of river action there are at least two players in the hand
# we probably don't need a showdown section in pseudo stars format for our filtering purposes
@ -442,7 +589,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
if board: # sometimes hand ends preflop without a board
print >>fh, _("Board [%s]" % (" ".join(board)))
for player in [x for x in self.players if x[1] in players_who_act_preflop]:
for player in [x for x in self.players if x[1] in players_who_post_antes]:
seatnum = player[0]
name = player[1]
if name in self.collectees and name in self.shown:

View File

@ -91,6 +91,7 @@ class HandHistoryConverter:
self.ofile = os.path.join(self.hhdir, os.path.basename(file))
self.rexx = FpdbRegex.FpdbRegex()
self.players = set()
self.maxseats = 10
def __str__(self):
tmp = "HandHistoryConverter: '%s'\n" % (self.sitename)
@ -136,18 +137,29 @@ class HandHistoryConverter:
else:
# we need to recompile the player regexs.
self.players = playersThisHand
self.compile_player_regexs()
self.compilePlayerRegexs()
self.markStreets(hand)
# Different calls if stud or holdem like
if self.gametype[1] == "hold" or self.gametype[1] == "omaha":
self.readBlinds(hand)
self.readButton(hand)
self.readHeroCards(hand) # want to generalise to draw games
elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8":
self.readAntes(hand)
self.readBringIn(hand)
self.readShowdownActions(hand)
# Read actions in street order
for street in hand.streetList: # go through them in order
print "DEBUG: ", street
if hand.streets.group(street) is not None:
if self.gametype[1] == "hold" or self.gametype[1] == "omaha":
self.readCommunityCards(hand, street) # read community cards
elif self.gametype[1] == "razz" or self.gametype[1] == "stud" or self.gametype[1] == "stud8":
self.readPlayerCards(hand, street)
self.readAction(hand, street)
@ -197,9 +209,8 @@ class HandHistoryConverter:
# [['seat#', 'player1name', 'stacksize'] ['seat#', 'player2name', 'stacksize'] [...]]
def readPlayerStacks(self, hand): abstract
# Given
#
def compile_player_regexs(self): abstract
def compilePlayerRegexs(self): abstract
"""Compile dynamic regexes -- these explicitly match known player names and must be updated if a new player joins"""
# 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
@ -210,7 +221,11 @@ class HandHistoryConverter:
# ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb,
# addtional players are assumed to post a bb oop
def readBlinds(self, hand): abstract
def readAntes(self, hand): abstract
def readBringIn(self, hand): abstract
def readButton(self, hand): abstract
def readHeroCards(self, hand): abstract
def readPlayerCards(self, hand, street): abstract
def readAction(self, hand, street): abstract
def readCollectPot(self, hand): abstract
def readShownCards(self, hand): abstract

View File

@ -114,11 +114,27 @@ class Importer:
#TODO: test it is a valid file -> put that in config!!
self.filelist[filename] = [site] + [filter]
# Called from GuiBulkImport to add a file or directory.
def addBulkImportImportFileOrDir(self, inputPath,filter = "passthrough"):
"""Add a file or directory for bulk import"""
# Bulk import never monitors
# if directory, add all files in it. Otherwise add single file.
# TODO: only add sane files?
if os.path.isdir(inputPath):
for subdir in os.walk(inputPath):
for file in subdir[2]:
self.addImportFile(os.path.join(inputPath, subdir[0], file), site="default", filter=filter)
else:
self.addImportFile(inputPath, site="default", filter=filter)
#Add a directory of files to filelist
#Only one import directory per site supported.
#dirlist is a hash of lists:
#dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] }
def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"):
#This should really be using os.walk
#http://docs.python.org/library/os.html
if os.path.isdir(dir):
if monitor == True:
self.monitor = True
@ -370,7 +386,7 @@ class Importer:
sys.exit(0)
startpos=endpos
ttime = time() - starttime
print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", ttime
print "\rTotal stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", ttime
if stored==0:
if duplicates>0: