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

This commit is contained in:
Worros 2008-12-10 09:50:42 +09:00
commit 390519c549
2 changed files with 144 additions and 106 deletions

View File

@ -70,15 +70,16 @@ class Everleaf(HandHistoryConverter):
self.sitename = "Everleaf"
self.setFileType("text")
self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)')
self.rexx.setSplitHandRegex('\n\n\n\n')
self.rexx.setSplitHandRegex('\n\n+')
self.rexx.setHandInfoRegex('.*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+)\nTable (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
self.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \( \$ (?P<CASH>[.0-9]+) USD \)')
self.rexx.setPlayerInfoRegex('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)')
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]+)')
# mct : what about posting small & big blinds simultaneously?
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<HOLE1>\S\S), (?P<HOLE2>\S\S) \]')
self.rexx.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.setCollectPotRegex('.*\n(?P<PNAME>.*) wins \$ (?P<POT>[.\d]+) USD.*')
self.rexx.compileRegexes()
def readSupportedGames(self):
@ -117,16 +118,38 @@ class Everleaf(HandHistoryConverter):
def readPlayerStacks(self, hand):
m = self.rexx.player_info_re.finditer(hand.string)
players = []
print "\nReading stacks - players seen:"
for a in m:
print a.group('PNAME')
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
def markStreets(self, hand):
# PREFLOP = ** Dealing down cards **
m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.string,re.DOTALL)
# for street in m.groupdict():
# print "DEBUG: Street: %s\tspan: %s" %(street, str(m.span(street)))
# This re fails if, say, river is missing; then we don't get the ** that starts the river.
#m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.string,re.DOTALL)
m = re.search(r"\*\* Dealing down cards \*\*(?P<PREFLOP>.+(?=\*\* Dealing Flop \*\*)|.+)"
r"(\*\* Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \](?P<FLOP>.+(?=\*\* Dealing Turn \*\*)|.+))?"
r"(\*\* Dealing Turn \*\* \[ (?P<TURN1>\S\S) \](?P<TURN>.+(?=\*\* Dealing River \*\*)|.+))?"
r"(\*\* Dealing River \*\* \[ (?P<RIVER1>\S\S) \](?P<RIVER>.+))?", hand.string,re.DOTALL)
# that wasn't easy.
#m1 = re.search(r'(\*\* Dealing down cards \*\*)?(?P<PREFLOP>.*?\n\*\*)',hand.string,re.DOTALL)
#m2 = re.search(r'(\*\* Dealing Flop \*\*)?(?P<FLOP>.*\n\*\*)',hand.string,re.DOTALL)
#print hand.string
#print "m groups:\n",m.groupdict()
#print "m1 groups:\n",m1.groupdict()
#print "m2 groups:\n",m2.groupdict()
#(\*\* Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \](?P<FLOP>.*?)?)?
#(\*\* Dealing Turn \*\* \[ (?P<TURN1>\S\S) \](?P<TURN>.*?))?
#(\*\* Dealing River \*\* \[ (?P<RIVER1>\S\S) \](?P<RIVER>.*?))?', hand.string,re.DOTALL)
#for street in m.groupdict():
#print "DEBUG: Street: %s\tspan: %s" %(street, str(m.span(street)))
hand.streets = m
#sys.exit()
def readCommunityCards(self, hand):
# currently regex in wrong place pls fix my brain's fried
@ -184,13 +207,19 @@ class Everleaf(HandHistoryConverter):
print cards
hand.addHoleCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand):
m = self.rexx.collect_pot_re.search(hand.string)
if m is not None:
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
else:
print "WARNING: Unusual, no one collected; can happen if it's folded to big blind with a dead small blind."
def getRake(self, hand):
hand.rake = hand.totalpot * Decimal('0.05') # probably not quite right
if __name__ == "__main__":
c = Configuration.Config()
e = Everleaf(c, "Speed_Kuala.txt")
e = Everleaf(c, "Speed_Kuala_full.txt")
e.processFile()
print str(e)

View File

@ -28,6 +28,41 @@ import operator
from xml.dom.minidom import Node
from pokereval import PokerEval
#from pokerengine.pokercards import *
# 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:
letter2name = {
'A': 'Ace',
'K': 'King',
'Q': 'Queen',
'J': 'Jack',
'T': 'Ten',
'9': 'Nine',
'8': 'Eight',
'7': 'Seven',
'6': 'Six',
'5': 'Five',
'4': 'Four',
'3': 'Trey',
'2': 'Deuce'
}
letter2names = {
'A': 'Aces',
'K': 'Kings',
'Q': 'Queens',
'J': 'Jacks',
'T': 'Tens',
'9': 'Nines',
'8': 'Eights',
'7': 'Sevens',
'6': 'Sixes',
'5': 'Fives',
'4': 'Fours',
'3': 'Treys',
'2': 'Deuces'
}
class HandHistoryConverter:
eval = PokerEval()
def __init__(self, config, file, sitename):
@ -67,6 +102,7 @@ class HandHistoryConverter:
self.gametype = self.determineGameType()
self.hands = self.splitFileIntoHands()
for hand in self.hands:
print "\nInput:\n"+hand.string
self.readHandInfo(hand)
self.readPlayerStacks(hand)
self.markStreets(hand)
@ -76,17 +112,21 @@ class HandHistoryConverter:
self.readShowdownActions(hand)
# Read action (Note: no guarantee this is in hand order.
for street in hand.streets.groupdict():
self.readAction(hand, street)
if hand.streets.group(street) is not None:
self.readAction(hand, street)
self.readCollectPot(hand)
# finalise it (total the pot)
hand.totalPot()
self.getRake(hand)
if(hand.involved == True):
hand.printHand()
#if(hand.involved == True):
#self.writeHand("output file", hand)
hand.printHand()
else:
pass #Don't write out observed hands
#hand.printHand()
#else:
#pass #Don't write out observed hands
#####
# These functions are parse actions that may be overridden by the inheriting class
@ -124,6 +164,7 @@ class HandHistoryConverter:
def readBlinds(self, hand): abstract
def readHeroCards(self, hand): abstract
def readAction(self, hand, street): abstract
def readCollectPot(self, hand): abstract
# Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated
# so that an inheriting class can calculate it for the specific site if need be.
@ -156,6 +197,7 @@ class HandHistoryConverter:
def splitFileIntoHands(self):
hands = []
self.obs.strip()
list = self.rexx.split_hand_re.split(self.obs)
list.pop() #Last entry is empty
for l in list:
@ -177,66 +219,6 @@ class HandHistoryConverter:
except:
traceback.print_exc(file=sys.stderr)
def writeHand(self, file, hand):
"""Write out parsed data"""
print "DEBUG: *************************"
print "DEBUG: Start of print hand"
print "DEBUG: *************************"
print "%s Game #%s: %s ($%s/$%s) - %s" %(hand.sitename, hand.handid, "XXXXhand.gametype", hand.sb, hand.bb, hand.starttime)
print "Table '%s' %d-max Seat #%s is the button" %(hand.tablename, hand.maxseats, hand.buttonpos)
for player in hand.players:
print "Seat %s: %s ($%s)" %(player[0], player[1], player[2])
if(hand.posted[0] == "FpdbNBP"):
print "No small blind posted"
else:
print "%s: posts small blind $%s" %(hand.posted[0], hand.sb)
#May be more than 1 bb posting
print "%s: posts big blind $%s" %(hand.posted[1], hand.bb)
if(len(hand.posted) > 2):
# Need to loop on all remaining big blinds - lazy
print "XXXXXXXXX FIXME XXXXXXXX"
print "*** HOLE CARDS ***"
print "Dealt to %s [%s %s]" %(hand.hero , hand.holecards[0], hand.holecards[1])
for act in hand.actions['PREFLOP']:
self.printActionLine(act, 0)
if 'PREFLOP' in hand.actions:
for act in hand.actions['PREFLOP']:
print "PF action"
if 'FLOP' in hand.actions:
print "*** FLOP *** [%s %s %s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"))
for act in hand.actions['FLOP']:
self.printActionLine(act, 0)
if 'TURN' in hand.actions:
print "*** TURN *** [%s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"))
for act in hand.actions['TURN']:
self.printActionLine(act, 0)
if 'RIVER' in hand.actions:
print "*** RIVER *** [%s %s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"), hand.streets.group("RIVER1"))
for act in hand.actions['RIVER']:
self.printActionLine(act, 0)
print "*** SUMMARY ***"
print "XXXXXXXXXXXX Need sumary info XXXXXXXXXXX"
def printActionLine(self, act, pot):
if act[1] == 'folds' or act[1] == 'checks':
print "%s: %s " %(act[0], act[1])
if act[1] == 'calls':
print "%s: %s $%s" %(act[0], act[1], act[2])
if act[1] == 'raises':
print "%s: %s $%s to XXXpottotalXXX" %(act[0], act[1], act[2])
#takes a poker float (including , for thousand seperator and converts it to an int
def float2int (self, string):
@ -282,6 +264,7 @@ class Hand:
self.hero = "Hiro"
self.holecards = {} # dict from player names to lists of hole cards
self.board = {} # dict from street names to community cards
self.collected = {} # dict from player names to amounts collected
self.action = []
self.totalpot = None
@ -296,8 +279,7 @@ class Hand:
def addPlayer(self, seat, name, chips):
"""seat, an int indicating the seat
name, the player name
chips, the chips the player has at the start of the hand"""
#self.players.append(name)
chips, the chips the player has at the start of the hand (can be None)"""
self.players.append([seat, name, chips])
self.holecards[name] = []
#self.startChips[name] = chips
@ -370,10 +352,19 @@ class Hand:
self.actions[street] += [[player, 'raises', amountBy, amountTo]]
def addBet(self, street, player=None, amount=0):
self.bets[street][name].append(Decimal(amount))
self.bets[street][player].append(Decimal(amount))
self.orderedBets[street].append(Decimal(amount))
self.actions[street] += [[player, 'bets', amount]]
def addCollectPot(self,player, pot):
if player not in self.collected:
self.collected[player] = pot
else:
# possibly lines like "p collected $ from pot" appear during the showdown
# but they are usually unique in the summary.
print "%s collected pot more than once; avoidable by reading winnings only from summary lines?"
def totalPot(self):
"""If all bets and blinds have been added, totals up the total pot size
Known bug: doesn't take into account side pots"""
@ -391,7 +382,7 @@ Known bug: doesn't take into account side pots"""
def printHand(self):
# PokerStars format.
print "### DEBUG ###"
print "### Pseudo stars format ###"
print "%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, "XXXXhand.gametype", self.sb, self.bb, self.starttime)
print "Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)
for player in self.players:
@ -409,7 +400,8 @@ Known bug: doesn't take into account side pots"""
# What about big & small blinds?
print "*** HOLE CARDS ***"
print "Dealt to %s [%s %s]" %(self.hero , self.holecards[self.hero][0], self.holecards[self.hero][1])
if self.involved:
print "Dealt to %s [%s %s]" %(self.hero , self.holecards[self.hero][0], self.holecards[self.hero][1])
if 'PREFLOP' in self.actions:
for act in self.actions['PREFLOP']:
@ -438,21 +430,39 @@ Known bug: doesn't take into account side pots"""
print "what do they show"
print "*** SUMMARY ***"
print "Total pot $%s | Rake $%s)" % (self.totalpot, self.rake)
print "Board [%s %s %s %s %s]" % (self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1"))
print "Total pot $%s | Rake $%.2f)" % (self.totalpot, self.rake) # TODO side pots
board = []
for s in self.board.values():
board += s
if board: # sometimes hand ends preflop without a board
print "Board [%s]" % (board)
#print self.board
for player in self.players:
if self.holecards[player[1]]: # empty list default is false
hole = self.holecards[player[1]]
#print self.board.values()
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)
if player[1] in self.collected and self.holecards[player[1]]:
print "Seat %d: %s showed [%s %s] and won ($%s)" % (player[0], player[1], self.holecards[player[1]][0], self.holecards[player[1]][1], self.collected[player[1]])
elif player[1] in self.collected:
print "Seat %d: %s collected ($%s)" % (player[0], player[1], self.collected[player[1]])
elif self.holecards[player[1]]:
print "Seat %d: %s showed [%s %s]" % (player[0], player[1], self.holecards[player[1]][0], self.holecards[player[1]][1])
else:
print "Seat %d: %s mucked or folded" % (player[0], player[1])
print "Seat %d: %s folded (or mucked..)" % (player[0], player[1])
print
# 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 printActionLine(self, act):
@ -463,10 +473,8 @@ Known bug: doesn't take into account side pots"""
if act[1] == 'raises':
print "%s: %s $%s to $%s" %(act[0], act[1], act[2], act[3])
# going to use pokereval to figure out hands
# going to use pokereval to figure out hands at some point.
# these functions are copied from pokergame.py
# im thinking perhaps its best to use all the functionality of pokergame instead
# of reinventing the wheel
def bestHand(self, side, cards):
#if self.variant == "omaha" or self.variant == "omaha8":
#hand = self.serial2player[serial].hand.tolist(True)
@ -477,38 +485,39 @@ Known bug: doesn't take into account side pots"""
print cards
return HandHistoryConverter.eval.best('hi', cards, [])
# from pokergame.py
def bestHandValue(self, side, serial):
(value, cards) = self.bestHand(side, serial)
return value
# from pokergame.py
# got rid of the _ for internationalisation
def readableHandValueLong(self, side, value, cards):
cards = self.eval.card2string(cards)
if value == "NoPair":
if side == "low":
if cards[0][0] == '5':
return _("The wheel")
return ("The wheel")
else:
return join(map(lambda card: card[0], cards), ", ")
else:
return _("High card %(card)s") % { 'card' : _(letter2name[cards[0][0]]) }
return ("High card %(card)s") % { 'card' : (letter2name[cards[0][0]]) }
elif value == "OnePair":
return _("A pair of %(card)s") % { 'card' : _(letter2names[cards[0][0]]) } + _(", %(card)s kicker") % { 'card' : _(letter2name[cards[2][0]]) }
return ("A pair of %(card)s") % { 'card' : (letter2names[cards[0][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[2][0]]) }
elif value == "TwoPair":
return _("Two pairs %(card1)s and %(card2)s") % { 'card1' : _(letter2names[cards[0][0]]), 'card2' : _(letter2names[cards[2][0]]) } + _(", %(card)s kicker") % { 'card' : _(letter2name[cards[4][0]]) }
return ("Two pairs %(card1)s and %(card2)s") % { 'card1' : (letter2names[cards[0][0]]), 'card2' : _(letter2names[cards[2][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[4][0]]) }
elif value == "Trips":
return _("Three of a kind %(card)s") % { 'card' : _(letter2names[cards[0][0]]) } + _(", %(card)s kicker") % { 'card' : _(letter2name[cards[3][0]]) }
return ("Three of a kind %(card)s") % { 'card' : (letter2names[cards[0][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[3][0]]) }
elif value == "Straight":
return _("Straight %(card1)s to %(card2)s") % { 'card1' : _(letter2name[cards[0][0]]), 'card2' : _(letter2name[cards[4][0]]) }
return ("Straight %(card1)s to %(card2)s") % { 'card1' : (letter2name[cards[0][0]]), 'card2' : (letter2name[cards[4][0]]) }
elif value == "Flush":
return _("Flush %(card)s high") % { 'card' : _(letter2name[cards[0][0]]) }
return ("Flush %(card)s high") % { 'card' : (letter2name[cards[0][0]]) }
elif value == "FlHouse":
return _("%(card1)ss full of %(card2)ss") % { 'card1' : _(letter2name[cards[0][0]]), 'card2' : _(letter2name[cards[3][0]]) }
return ("%(card1)ss full of %(card2)ss") % { 'card1' : (letter2name[cards[0][0]]), 'card2' : (letter2name[cards[3][0]]) }
elif value == "Quads":
return _("Four of a kind %(card)s") % { 'card' : _(letter2names[cards[0][0]]) } + _(", %(card)s kicker") % { 'card' : _(letter2name[cards[4][0]]) }
return _("Four of a kind %(card)s") % { 'card' : (letter2names[cards[0][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[4][0]]) }
elif value == "StFlush":
if letter2name[cards[0][0]] == 'Ace':
return _("Royal flush")
return ("Royal flush")
else:
return _("Straight flush %(card)s high") % { 'card' : _(letter2name[cards[0][0]]) }
return ("Straight flush %(card)s high") % { 'card' : (letter2name[cards[0][0]]) }
return value