Writes hands to stderr, miscellanous crap to stdout; usuable as cmdline
filter: ./Everleaf 'hhfile' 1>/dev/null 2>outfile Holecards are sets -- should work on Omaha hi hands also. Successfully imported Speed_Kuala_full.txt to fpdb. Added gettext. cards strings are handled a little better (one fewer regex) Testfile can be supplied as first cmd line arg.
This commit is contained in:
parent
fb02d9224b
commit
9c5d0f4598
|
@ -76,11 +76,11 @@ class Everleaf(HandHistoryConverter):
|
||||||
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]+)')
|
||||||
self.rexx.setPostBothRegex('.*\n(?P<PNAME>.*): posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
|
self.rexx.setPostBothRegex('.*\n(?P<PNAME>.*): posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
|
||||||
# mct : what about posting small & big blinds simultaneously?
|
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<CARDS>.*) \]')
|
||||||
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.setShowdownActionRegex('.*\n(?P<PNAME>.*) shows \[ (?P<CARDS>.*) \]')
|
self.rexx.setShowdownActionRegex('.*\n(?P<PNAME>.*) shows \[ (?P<CARDS>.*) \]')
|
||||||
self.rexx.setCollectPotRegex('.*\n(?P<PNAME>.*) wins \$ (?P<POT>[.\d]+) USD(.*\[ (?P<HAND>.*) \])?')
|
self.rexx.setCollectPotRegex('.*\n(?P<PNAME>.*) wins \$ (?P<POT>[.\d]+) USD(.*\[ (?P<CARDS>.*) \])?')
|
||||||
|
self.rexx.sits_out_re = re.compile('(?P<PNAME>.*) sits out')
|
||||||
self.rexx.compileRegexes()
|
self.rexx.compileRegexes()
|
||||||
|
|
||||||
def readSupportedGames(self):
|
def readSupportedGames(self):
|
||||||
|
@ -163,7 +163,11 @@ class Everleaf(HandHistoryConverter):
|
||||||
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')], m.group('PNAME'))
|
# "2c, qh" -> set(["2c","qc"])
|
||||||
|
# Also works with Omaha hands.
|
||||||
|
cards = m.group('CARDS')
|
||||||
|
cards = set(cards.split(', '))
|
||||||
|
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.rexx.action_re.finditer(hand.streets.group(street))
|
||||||
|
@ -186,24 +190,30 @@ 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.rexx.showdown_action_re.finditer(hand.string):
|
||||||
print shows.groups()
|
cards = shows.group('CARDS')
|
||||||
re_card = re.compile('(?P<CARD>[0-9tjqka][schd])') # copied from earlier
|
cards = set(cards.split(', '))
|
||||||
cards = [card.group('CARD') for card in re_card.finditer(shows.group('CARDS'))]
|
#re_card = re.compile('(?P<CARD>[0-9tjqka][schd])') # copied from earlier
|
||||||
print cards
|
#cards = set([card.group('CARD') for card in re_card.finditer(shows.group('CARDS'))])
|
||||||
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.rexx.collect_pot_re.finditer(hand.string):
|
||||||
if m.group('HAND') is not None:
|
if m.group('CARDS') is not None:
|
||||||
re_card = re.compile('(?P<CARD>[0-9tjqka][schd])') # copied from earlier
|
cards = m.group('CARDS')
|
||||||
cards = set([hand.card(card.group('CARD')) for card in re_card.finditer(m.group('HAND'))])
|
cards = set(cards.split(', '))
|
||||||
|
#re_card = re.compile('(?P<CARD>[0-9tjqka][schd])') # copied from earlier
|
||||||
|
#cards = set([hand.card(card.group('CARD')) for card in re_card.finditer(m.group('HAND'))])
|
||||||
hand.addShownCards(cards=None, player=m.group('PNAME'), holeandboard=cards)
|
hand.addShownCards(cards=None, player=m.group('PNAME'), holeandboard=cards)
|
||||||
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
c = Configuration.Config()
|
c = Configuration.Config()
|
||||||
e = Everleaf(c, "regression-test-files/everleaf/Speed_Kuala_full.txt")
|
if sys.argv[0] == '':
|
||||||
|
testfile = "regression-test-files/everleaf/Speed_Kuala_full.txt"
|
||||||
|
else:
|
||||||
|
testfile = sys.argv[1]
|
||||||
|
print "Converting: ", testfile
|
||||||
|
e = Everleaf(c, testfile)
|
||||||
e.processFile()
|
e.processFile()
|
||||||
print str(e)
|
print str(e)
|
||||||
|
|
||||||
|
|
110
pyfpdb/Hand.py
110
pyfpdb/Hand.py
|
@ -106,7 +106,7 @@ chips (string) the chips the player has at the start of the hand (can be None)
|
||||||
If a player has None chips he won't be added."""
|
If a player has None chips he won't be added."""
|
||||||
if chips is not None:
|
if chips is not None:
|
||||||
self.players.append([seat, name, chips])
|
self.players.append([seat, name, chips])
|
||||||
self.holecards[name] = []
|
self.holecards[name] = set()
|
||||||
for street in self.streetList:
|
for street in self.streetList:
|
||||||
self.bets[street][name] = []
|
self.bets[street][name] = []
|
||||||
|
|
||||||
|
@ -125,29 +125,27 @@ If a player has None chips he won't be added."""
|
||||||
def addHoleCards(self, cards, player):
|
def addHoleCards(self, cards, player):
|
||||||
"""\
|
"""\
|
||||||
Assigns observed holecards to a player.
|
Assigns observed holecards to a player.
|
||||||
cards list of card bigrams e.g. ['2h','jc']
|
cards set of card bigrams e.g. set(['2h','Jc'])
|
||||||
player (string) name of player
|
player (string) name of player
|
||||||
hand
|
|
||||||
Note, will automatically uppercase the rank letter.
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.checkPlayerExists(player)
|
self.checkPlayerExists(player)
|
||||||
self.holecards[player] = set([self.card(c) for c in cards])
|
cards = set([self.card(c) for c in cards])
|
||||||
|
self.holecards[player].update(cards)
|
||||||
except FpdbParseError, e:
|
except FpdbParseError, e:
|
||||||
print "Tried to add holecards for unknown player: %s" % (player,)
|
print "Tried to add holecards for unknown player: %s" % (player,)
|
||||||
|
|
||||||
def addShownCards(self, cards, player, holeandboard=None):
|
def addShownCards(self, cards, player, holeandboard=None):
|
||||||
"""\
|
"""\
|
||||||
For when a player shows cards for any reason (for showdown or out of choice).
|
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:
|
if cards is not None:
|
||||||
self.shown.add(player)
|
self.shown.add(player)
|
||||||
self.addHoleCards(cards,player)
|
self.addHoleCards(cards,player)
|
||||||
elif holeandboard is not None:
|
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])
|
board = set([c for s in self.board.values() for c in s])
|
||||||
#print board
|
|
||||||
#print holeandboard
|
|
||||||
#print holeandboard.difference(board)
|
|
||||||
self.addHoleCards(holeandboard.difference(board),player)
|
self.addHoleCards(holeandboard.difference(board),player)
|
||||||
|
|
||||||
|
|
||||||
|
@ -232,14 +230,11 @@ Add a raise on [street] by [player] to [amountTo]
|
||||||
if player not in self.collected:
|
if player not in self.collected:
|
||||||
self.collected[player] = pot
|
self.collected[player] = pot
|
||||||
else:
|
else:
|
||||||
# possibly lines like "p collected $ from pot" appear during the showdown
|
print "[WARNING] %s collected pot more than once; avoidable by reading winnings only from summary lines?"
|
||||||
# but they are usually unique in the summary, so it's best to try to get them from there.
|
|
||||||
print "%s collected pot more than once; avoidable by reading winnings only from summary lines?"
|
|
||||||
|
|
||||||
|
|
||||||
def totalPot(self):
|
def totalPot(self):
|
||||||
"""If all bets and blinds have been added, totals up the total pot size
|
"""If all bets and blinds have been added, totals up the total pot size"""
|
||||||
Known bug: doesn't take into account side pots"""
|
|
||||||
if self.totalpot is None:
|
if self.totalpot is None:
|
||||||
self.totalpot = 0
|
self.totalpot = 0
|
||||||
|
|
||||||
|
@ -288,10 +283,6 @@ Known bug: doesn't take into account side pots"""
|
||||||
for amount in self.collected.values():
|
for amount in self.collected.values():
|
||||||
self.totalcollected += Decimal(amount)
|
self.totalcollected += Decimal(amount)
|
||||||
|
|
||||||
# TODO: Some sites (Everleaf) don't record uncalled bets. Figure out if a bet is uncalled and subtract it from self.totalcollected.
|
|
||||||
# remember that portions of bets may be uncalled, so:
|
|
||||||
# bet followed by no call is an uncalled bet
|
|
||||||
# bet x followed by call y where y < x has x-y uncalled (and second player all in)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -322,81 +313,89 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
||||||
|
|
||||||
return string
|
return string
|
||||||
|
|
||||||
def printHand(self):
|
def writeHand(self, fh=sys.__stdout__):
|
||||||
# PokerStars format.
|
# PokerStars format.
|
||||||
print "\n### Pseudo stars format ###"
|
#print "\n### Pseudo stars format ###"
|
||||||
print "%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" %(self.sitename, self.handid, self.getGameTypeAsString(), self.sb, self.bb, self.starttime))
|
||||||
print "Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)
|
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, self.starttime))
|
||||||
for player in self.players:
|
print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||||
print "Seat %s: %s ($%s)" %(player[0], player[1], player[2])
|
|
||||||
|
players_who_act_preflop = set([x[0] for x in self.actions['PREFLOP']])
|
||||||
|
print players_who_act_preflop
|
||||||
|
print [x[1] for x in self.players]
|
||||||
|
print [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_act_preflop]:
|
||||||
|
#Only print stacks of players who do something preflop
|
||||||
|
print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2]))
|
||||||
|
|
||||||
if(self.posted[0] is None):
|
if(self.posted[0] is None):
|
||||||
print "No small blind posted"
|
#print >>fh, _("No small blind posted") # PS doesn't say this
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
print "%s: posts small blind $%s" %(self.posted[0], self.sb)
|
print >>fh, _("%s: posts small blind $%s" %(self.posted[0], self.sb))
|
||||||
|
|
||||||
#May be more than 1 bb posting
|
#May be more than 1 bb posting
|
||||||
for a in self.posted[1:]:
|
for a in self.posted[1:]:
|
||||||
print "%s: posts big blind $%s" %(self.posted[1], self.bb)
|
print >>fh, _("%s: posts big blind $%s" %(self.posted[1], self.bb))
|
||||||
|
|
||||||
# What about big & small blinds?
|
# TODO: What about big & small blinds?
|
||||||
|
|
||||||
print "*** HOLE CARDS ***"
|
print >>fh, _("*** HOLE CARDS ***")
|
||||||
if self.involved:
|
if self.involved:
|
||||||
print "Dealt to %s [%s]" %(self.hero , " ".join(self.holecards[self.hero]))
|
print >>fh, _("Dealt to %s [%s]" %(self.hero , " ".join(self.holecards[self.hero])))
|
||||||
|
|
||||||
if 'PREFLOP' in self.actions:
|
if 'PREFLOP' in self.actions:
|
||||||
for act in self.actions['PREFLOP']:
|
for act in self.actions['PREFLOP']:
|
||||||
self.printActionLine(act)
|
self.printActionLine(act, fh)
|
||||||
|
|
||||||
if 'FLOP' in self.actions:
|
if 'FLOP' in self.actions:
|
||||||
print "*** FLOP *** [%s]" %( " ".join(self.board['Flop']))
|
print >>fh, _("*** FLOP *** [%s]" %( " ".join(self.board['Flop'])))
|
||||||
for act in self.actions['FLOP']:
|
for act in self.actions['FLOP']:
|
||||||
self.printActionLine(act)
|
self.printActionLine(act, fh)
|
||||||
|
|
||||||
if 'TURN' in self.actions:
|
if 'TURN' in self.actions:
|
||||||
print "*** TURN *** [%s] [%s]" %( " ".join(self.board['Flop']), " ".join(self.board['Turn']))
|
print >>fh, _("*** TURN *** [%s] [%s]" %( " ".join(self.board['Flop']), " ".join(self.board['Turn'])))
|
||||||
for act in self.actions['TURN']:
|
for act in self.actions['TURN']:
|
||||||
self.printActionLine(act)
|
self.printActionLine(act, fh)
|
||||||
|
|
||||||
if 'RIVER' in self.actions:
|
if 'RIVER' in self.actions:
|
||||||
print "*** RIVER *** [%s] [%s]" %(" ".join(self.board['Flop']+self.board['Turn']), " ".join(self.board['River']) )
|
print >>fh, _("*** RIVER *** [%s] [%s]" %(" ".join(self.board['Flop']+self.board['Turn']), " ".join(self.board['River']) ))
|
||||||
for act in self.actions['RIVER']:
|
for act in self.actions['RIVER']:
|
||||||
self.printActionLine(act)
|
self.printActionLine(act, fh)
|
||||||
|
|
||||||
|
|
||||||
#Some sites don't have a showdown section so we have to figure out if there should be one
|
#Some sites don't have a showdown section so we have to figure out if there should be one
|
||||||
# The logic for a showdown is: at the end of river action there are at least two players in the hand
|
# The logic for a showdown is: at the end of river action there are at least two players in the hand
|
||||||
# we probably don't need a showdown section in pseudo stars format for our filtering purposes
|
# we probably don't need a showdown section in pseudo stars format for our filtering purposes
|
||||||
if 'SHOWDOWN' in self.actions:
|
if 'SHOWDOWN' in self.actions:
|
||||||
print "*** SHOW DOWN ***"
|
print >>fh, _("*** SHOW DOWN ***")
|
||||||
print "what do they show"
|
print >>fh, "DEBUG: what do they show"
|
||||||
|
|
||||||
print "*** SUMMARY ***"
|
print >>fh, _("*** SUMMARY ***")
|
||||||
print "Total pot $%s | Rake $%.2f" % (self.totalcollected, self.rake) # TODO: side pots
|
print >>fh, _("Total pot $%s | Rake $%.2f" % (self.totalcollected, self.rake)) # TODO: side pots
|
||||||
|
|
||||||
board = []
|
board = []
|
||||||
for s in self.board.values():
|
for s in self.board.values():
|
||||||
board += s
|
board += s
|
||||||
if board: # sometimes hand ends preflop without a board
|
if board: # sometimes hand ends preflop without a board
|
||||||
print "Board [%s]" % (" ".join(board))
|
print >>fh, _("Board [%s]" % (" ".join(board)))
|
||||||
|
|
||||||
|
|
||||||
for player in self.players:
|
for player in self.players:
|
||||||
seatnum = player[0]
|
seatnum = player[0]
|
||||||
name = player[1]
|
name = player[1]
|
||||||
if name in self.collected and self.holecards[name]:
|
if name in self.collected and self.holecards[name]:
|
||||||
print "Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]), self.collected[name])
|
print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]), self.collected[name]))
|
||||||
elif name in self.collected:
|
elif name in self.collected:
|
||||||
print "Seat %d: %s collected ($%s)" % (seatnum, name, self.collected[name])
|
print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collected[name]))
|
||||||
elif player[1] in self.shown:
|
elif player[1] in self.shown:
|
||||||
print "Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]))
|
print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name])))
|
||||||
elif player[1] in self.folded:
|
elif player[1] in self.folded:
|
||||||
print "Seat %d: %s folded" % (seatnum, name)
|
print >>fh, _("Seat %d: %s folded" % (seatnum, name))
|
||||||
else:
|
else:
|
||||||
print "Seat %d: %s mucked" % (seatnum, name)
|
print >>fh, _("Seat %d: %s mucked" % (seatnum, name))
|
||||||
|
|
||||||
print
|
print >>fh, "\n\n"
|
||||||
# TODO:
|
# TODO:
|
||||||
# logic for side pots
|
# logic for side pots
|
||||||
# logic for which players get to showdown
|
# logic for which players get to showdown
|
||||||
|
@ -413,15 +412,20 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
||||||
#print "Seat %d: %s mucked or folded" % (player[0], player[1])
|
#print "Seat %d: %s mucked or folded" % (player[0], player[1])
|
||||||
|
|
||||||
|
|
||||||
def printActionLine(self, act):
|
def printHand(self):
|
||||||
if act[1] == 'folds' or act[1] == 'checks':
|
self.writeHand(sys.stdout)
|
||||||
print "%s: %s " %(act[0], act[1])
|
|
||||||
|
def printActionLine(self, act, fh):
|
||||||
|
if act[1] == 'folds':
|
||||||
|
print >>fh, _("%s: folds" %(act[0]))
|
||||||
|
elif act[1] == 'checks':
|
||||||
|
print >>fh, _("%s: checks" %(act[0]))
|
||||||
if act[1] == 'calls':
|
if act[1] == 'calls':
|
||||||
print "%s: %s $%s" %(act[0], act[1], act[2])
|
print >>fh, _("%s: calls $%s" %(act[0], act[2]))
|
||||||
if act[1] == 'bets':
|
if act[1] == 'bets':
|
||||||
print "%s: %s $%s" %(act[0], act[1], act[2])
|
print >>fh, _("%s: bets $%s" %(act[0], act[2]))
|
||||||
if act[1] == 'raises':
|
if act[1] == 'raises':
|
||||||
print "%s: %s $%s to $%s" %(act[0], act[1], act[2], act[3])
|
print >>fh, _("%s: raises $%s to $%s" %(act[0], act[2], act[3]))
|
||||||
|
|
||||||
# going to use pokereval to figure out hands at some point.
|
# going to use pokereval to figure out hands at some point.
|
||||||
# these functions are copied from pokergame.py
|
# these functions are copied from pokergame.py
|
||||||
|
|
|
@ -30,6 +30,8 @@ import operator
|
||||||
from xml.dom.minidom import Node
|
from xml.dom.minidom import Node
|
||||||
from pokereval import PokerEval
|
from pokereval import PokerEval
|
||||||
from time import time
|
from time import time
|
||||||
|
import gettext
|
||||||
|
|
||||||
#from pokerengine.pokercards import *
|
#from pokerengine.pokercards import *
|
||||||
# provides letter2name{}, letter2names{}, visible_card(), not_visible_card(), is_visible(), card_value(), class PokerCards
|
# provides letter2name{}, letter2names{}, visible_card(), not_visible_card(), is_visible(), card_value(), class PokerCards
|
||||||
# but it's probably not installed so here are the ones we may want:
|
# but it's probably not installed so here are the ones we may want:
|
||||||
|
@ -65,6 +67,11 @@ letter2names = {
|
||||||
'2': 'Deuces'
|
'2': 'Deuces'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
gettext.install('myapplication')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class HandHistoryConverter:
|
class HandHistoryConverter:
|
||||||
eval = PokerEval()
|
eval = PokerEval()
|
||||||
def __init__(self, config, file, sitename):
|
def __init__(self, config, file, sitename):
|
||||||
|
@ -124,7 +131,7 @@ class HandHistoryConverter:
|
||||||
hand.totalPot()
|
hand.totalPot()
|
||||||
self.getRake(hand)
|
self.getRake(hand)
|
||||||
|
|
||||||
hand.printHand()
|
hand.writeHand(sys.stderr)
|
||||||
#if(hand.involved == True):
|
#if(hand.involved == True):
|
||||||
#self.writeHand("output file", hand)
|
#self.writeHand("output file", hand)
|
||||||
#hand.printHand()
|
#hand.printHand()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user