Merge branch 'master' of git://git.assembla.com/fpdboz
This commit is contained in:
commit
5348737819
91
pyfpdb/DerivedStats.py
Normal file
91
pyfpdb/DerivedStats.py
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
#Copyright 2008 Carl Gherardi
|
||||||
|
#This program is free software: you can redistribute it and/or modify
|
||||||
|
#it under the terms of the GNU Affero General Public License as published by
|
||||||
|
#the Free Software Foundation, version 3 of the License.
|
||||||
|
#
|
||||||
|
#This program is distributed in the hope that it will be useful,
|
||||||
|
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
#GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
#You should have received a copy of the GNU Affero General Public License
|
||||||
|
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#In the "official" distribution you can find the license in
|
||||||
|
#agpl-3.0.txt in the docs folder of the package.
|
||||||
|
|
||||||
|
class DerivedStats():
|
||||||
|
def __init__(self, hand):
|
||||||
|
self.hand = hand
|
||||||
|
|
||||||
|
self.activeSeats = 0
|
||||||
|
self.position = 0
|
||||||
|
self.tourneyTypeId = 0
|
||||||
|
|
||||||
|
self.HDs = 0
|
||||||
|
self.street0VPI = 0
|
||||||
|
self.street0Aggr = 0
|
||||||
|
self.street0_3B4BChance = 0
|
||||||
|
self.street0_3B4BDone = 0
|
||||||
|
|
||||||
|
self.street1Seen = 0
|
||||||
|
self.street2Seen = 0
|
||||||
|
self.street3Seen = 0
|
||||||
|
self.street4Seen = 0
|
||||||
|
self.sawShowdown = 0
|
||||||
|
|
||||||
|
self.street1Aggr = 0
|
||||||
|
self.street2Aggr = 0
|
||||||
|
self.street3Aggr = 0
|
||||||
|
self.street4Aggr = 0
|
||||||
|
|
||||||
|
self.otherRaisedStreet1 = 0
|
||||||
|
self.otherRaisedStreet2 = 0
|
||||||
|
self.otherRaisedStreet3 = 0
|
||||||
|
self.otherRaisedStreet4 = 0
|
||||||
|
self.foldToOtherRaisedStreet1 = 0
|
||||||
|
self.foldToOtherRaisedStreet2 = 0
|
||||||
|
self.foldToOtherRaisedStreet3 = 0
|
||||||
|
self.foldToOtherRaisedStreet4 = 0
|
||||||
|
self.wonWhenSeenStreet1 = 0
|
||||||
|
self.wonAtSD = 0
|
||||||
|
|
||||||
|
self.stealAttemptChance = 0
|
||||||
|
self.stealAttempted = 0
|
||||||
|
self.foldBbToStealChance = 0
|
||||||
|
self.foldedBbToSteal = 0
|
||||||
|
self.foldSbToStealChance = 0
|
||||||
|
self.foldedSbToSteal = 0
|
||||||
|
|
||||||
|
self.street1CBChance = 0
|
||||||
|
self.street1CBDone = 0
|
||||||
|
self.street2CBChance = 0
|
||||||
|
self.street2CBDone = 0
|
||||||
|
self.street3CBChance = 0
|
||||||
|
self.street3CBDone = 0
|
||||||
|
self.street4CBChance = 0
|
||||||
|
self.street4CBDone = 0
|
||||||
|
|
||||||
|
self.foldToStreet1CBChance = 0
|
||||||
|
self.foldToStreet1CBDone = 0
|
||||||
|
self.foldToStreet2CBChance = 0
|
||||||
|
self.foldToStreet2CBDone = 0
|
||||||
|
self.foldToStreet3CBChance = 0
|
||||||
|
self.foldToStreet3CBDone = 0
|
||||||
|
self.foldToStreet4CBChance = 0
|
||||||
|
self.foldToStreet4CBDone = 0
|
||||||
|
|
||||||
|
self.totalProfit = 0
|
||||||
|
|
||||||
|
self.street1CheckCallRaiseChance = 0
|
||||||
|
self.street1CheckCallRaiseDone = 0
|
||||||
|
self.street2CheckCallRaiseChance = 0
|
||||||
|
self.street2CheckCallRaiseDone = 0
|
||||||
|
self.street3CheckCallRaiseChance = 0
|
||||||
|
self.street3CheckCallRaiseDone = 0
|
||||||
|
self.street4CheckCallRaiseChance = 0
|
||||||
|
self.street4CheckCallRaiseDone = 0
|
||||||
|
|
||||||
|
def getStats():
|
||||||
|
pass
|
|
@ -43,6 +43,7 @@ out_path (default '-' = sys.stdout)
|
||||||
follow : whether to tail -f the input
|
follow : whether to tail -f the input
|
||||||
autostart: whether to run the thread (or you can call start() yourself)
|
autostart: whether to run the thread (or you can call start() yourself)
|
||||||
debugging: if False, pass on partially supported game types. If true, have a go and error..."""
|
debugging: if False, pass on partially supported game types. If true, have a go and error..."""
|
||||||
|
print "DEBUG: XXXXXXXXXXXXXXX"
|
||||||
HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow)
|
HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow)
|
||||||
logging.info("Initialising Everleaf converter class")
|
logging.info("Initialising Everleaf converter class")
|
||||||
self.filetype = "text"
|
self.filetype = "text"
|
||||||
|
@ -130,12 +131,10 @@ or None if we fail to get the info """
|
||||||
info['bb'] = mg['BB']
|
info['bb'] = mg['BB']
|
||||||
if 'CURRENCY' in mg:
|
if 'CURRENCY' in mg:
|
||||||
info['currency'] = currencies[mg['CURRENCY']]
|
info['currency'] = currencies[mg['CURRENCY']]
|
||||||
|
if info['currency'] == 'T$':
|
||||||
|
info['type'] = 'tour'
|
||||||
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
|
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
|
||||||
|
|
||||||
if not self.debugging and info['base']=='stud':
|
|
||||||
logging.warning("Not processing Everleaf Stud hand")
|
|
||||||
#return None
|
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ import sys
|
||||||
import logging
|
import logging
|
||||||
from HandHistoryConverter import *
|
from HandHistoryConverter import *
|
||||||
|
|
||||||
# FullTilt HH Format converter
|
# Fulltilt HH Format converter
|
||||||
|
|
||||||
class FullTilt(HandHistoryConverter):
|
class Fulltilt(HandHistoryConverter):
|
||||||
|
|
||||||
# Static regexes
|
# Static regexes
|
||||||
re_GameInfo = re.compile('- (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<LIMIT>(No Limit|Pot Limit|Limit))? (?P<GAME>(Hold\'em|Omaha Hi|Razz))')
|
re_GameInfo = re.compile('- (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<LIMIT>(No Limit|Pot Limit|Limit))? (?P<GAME>(Hold\'em|Omaha Hi|Razz))')
|
||||||
|
@ -39,8 +39,8 @@ class FullTilt(HandHistoryConverter):
|
||||||
in_path (default '-' = sys.stdin)
|
in_path (default '-' = sys.stdin)
|
||||||
out_path (default '-' = sys.stdout)
|
out_path (default '-' = sys.stdout)
|
||||||
follow : whether to tail -f the input"""
|
follow : whether to tail -f the input"""
|
||||||
HandHistoryConverter.__init__(self, in_path, out_path, sitename="FullTilt", follow=follow)
|
HandHistoryConverter.__init__(self, in_path, out_path, sitename="Fulltilt", follow=follow)
|
||||||
logging.info("Initialising FullTilt converter class")
|
logging.info("Initialising Fulltilt converter class")
|
||||||
self.filetype = "text"
|
self.filetype = "text"
|
||||||
self.codepage = "cp1252"
|
self.codepage = "cp1252"
|
||||||
if autostart:
|
if autostart:
|
||||||
|
@ -70,6 +70,7 @@ follow : whether to tail -f the input"""
|
||||||
def readSupportedGames(self):
|
def readSupportedGames(self):
|
||||||
return [["ring", "hold", "nl"],
|
return [["ring", "hold", "nl"],
|
||||||
["ring", "hold", "pl"],
|
["ring", "hold", "pl"],
|
||||||
|
["ring", "hold", "fl"],
|
||||||
["ring", "stud", "fl"],
|
["ring", "stud", "fl"],
|
||||||
["ring", "omaha", "pl"]
|
["ring", "omaha", "pl"]
|
||||||
]
|
]
|
||||||
|
@ -313,4 +314,4 @@ if __name__ == "__main__":
|
||||||
LOG_FILENAME = './logging.out'
|
LOG_FILENAME = './logging.out'
|
||||||
logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity)
|
logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity)
|
||||||
|
|
||||||
e = FullTilt(in_path = options.ipath, out_path = options.opath, follow = options.follow)
|
e = Fulltilt(in_path = options.ipath, out_path = options.opath, follow = options.follow)
|
||||||
|
|
379
pyfpdb/Hand.py
379
pyfpdb/Hand.py
|
@ -27,10 +27,14 @@ import time
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from Exceptions import *
|
from Exceptions import *
|
||||||
|
|
||||||
|
import DerivedStats
|
||||||
|
|
||||||
class Hand:
|
class Hand:
|
||||||
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'}
|
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'}
|
||||||
def __init__(self, sitename, gametype, handText):
|
LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'}
|
||||||
|
def __init__(self, sitename, gametype, handText, builtFrom = "HHC"):
|
||||||
self.sitename = sitename
|
self.sitename = sitename
|
||||||
|
self.stats = DerivedStats.DerivedStats(self)
|
||||||
self.gametype = gametype
|
self.gametype = gametype
|
||||||
self.handText = handText
|
self.handText = handText
|
||||||
self.handid = 0
|
self.handid = 0
|
||||||
|
@ -57,9 +61,9 @@ class Hand:
|
||||||
self.actions[street] = []
|
self.actions[street] = []
|
||||||
self.board[street] = []
|
self.board[street] = []
|
||||||
|
|
||||||
|
|
||||||
# Collections indexed by player names
|
# Collections indexed by player names
|
||||||
self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards
|
self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards
|
||||||
|
self.discards = {} # dict from player names to dicts by street ... of tuples ... of discarded 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 (?)
|
||||||
|
@ -76,6 +80,27 @@ class Hand:
|
||||||
self.rake = None
|
self.rake = None
|
||||||
|
|
||||||
|
|
||||||
|
def insert(self, db):
|
||||||
|
""" Function to insert Hand into database
|
||||||
|
Should not commit, and do minimal selects. Callers may want to cache commits
|
||||||
|
db: a connected fpdb_db object"""
|
||||||
|
# TODO:
|
||||||
|
# Players - base playerid and siteid tuple
|
||||||
|
# HudCache data to come from DerivedStats class
|
||||||
|
# HandsActions - all actions for all players for all streets - self.actions
|
||||||
|
# BoardCards - ?
|
||||||
|
# Hands - Summary information of hand indexed by handId - gameinfo
|
||||||
|
# HandsPlayers - ? ... Do we fix winnings?
|
||||||
|
# Tourneys ?
|
||||||
|
# TourneysPlayers
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
def select(self, handId):
|
||||||
|
""" Function to create Hand object from database """
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
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.
|
||||||
|
@ -88,10 +113,12 @@ If a player has None chips he won't be added."""
|
||||||
self.players.append([seat, name, chips])
|
self.players.append([seat, name, chips])
|
||||||
self.stacks[name] = Decimal(chips)
|
self.stacks[name] = Decimal(chips)
|
||||||
self.holecards[name] = []
|
self.holecards[name] = []
|
||||||
|
self.discards[name] = []
|
||||||
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] = {} # dict from street names.
|
self.holecards[name] = {} # dict from street names.
|
||||||
|
self.discards[name] = {} # dict from street names.
|
||||||
|
|
||||||
|
|
||||||
def addStreets(self, match):
|
def addStreets(self, match):
|
||||||
|
@ -136,8 +163,8 @@ If a player has None chips he won't be added."""
|
||||||
# - this is a bet of 1 sb, as yet uncalled.
|
# - this is a bet of 1 sb, as yet uncalled.
|
||||||
# Player in the big blind posts
|
# Player in the big blind posts
|
||||||
# - this is a call of 1 sb and a raise to 1 bb
|
# - this is a call of 1 sb and a raise to 1 bb
|
||||||
#
|
#
|
||||||
|
|
||||||
logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount))
|
logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount))
|
||||||
if player is not None:
|
if player is not None:
|
||||||
self.bets['PREFLOP'][player].append(Decimal(amount))
|
self.bets['PREFLOP'][player].append(Decimal(amount))
|
||||||
|
@ -147,7 +174,7 @@ If a player has None chips he won't be added."""
|
||||||
self.actions['BLINDSANTES'].append(act)
|
self.actions['BLINDSANTES'].append(act)
|
||||||
self.pot.addMoney(player, Decimal(amount))
|
self.pot.addMoney(player, Decimal(amount))
|
||||||
if blindtype == 'big blind':
|
if blindtype == 'big blind':
|
||||||
self.lastBet['PREFLOP'] = Decimal(amount)
|
self.lastBet['PREFLOP'] = Decimal(amount)
|
||||||
elif blindtype == 'both':
|
elif blindtype == 'both':
|
||||||
# extra small blind is 'dead'
|
# extra small blind is 'dead'
|
||||||
self.lastBet['PREFLOP'] = Decimal(self.bb)
|
self.lastBet['PREFLOP'] = Decimal(self.bb)
|
||||||
|
@ -244,6 +271,12 @@ Add a raise on [street] by [player] to [amountTo]
|
||||||
self.actions[street].append(act)
|
self.actions[street].append(act)
|
||||||
self.lastBet[street] = Decimal(amount)
|
self.lastBet[street] = Decimal(amount)
|
||||||
self.pot.addMoney(player, Decimal(amount))
|
self.pot.addMoney(player, Decimal(amount))
|
||||||
|
|
||||||
|
|
||||||
|
def addStandsPat(self, street, player):
|
||||||
|
self.checkPlayerExists(player)
|
||||||
|
act = (player, 'stands pat')
|
||||||
|
self.actions[street].append(act)
|
||||||
|
|
||||||
|
|
||||||
def addFold(self, street, player):
|
def addFold(self, street, player):
|
||||||
|
@ -302,7 +335,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
||||||
"fivedraw" : "5 Card Draw",
|
"fivedraw" : "5 Card Draw",
|
||||||
"27_1draw" : "FIXME",
|
"27_1draw" : "FIXME",
|
||||||
"27_3draw" : "Triple Draw 2-7 Lowball",
|
"27_3draw" : "Triple Draw 2-7 Lowball",
|
||||||
"badugi" : "FIXME"
|
"badugi" : "Badugi"
|
||||||
}
|
}
|
||||||
ls = {"nl" : "No Limit",
|
ls = {"nl" : "No Limit",
|
||||||
"pl" : "Pot Limit",
|
"pl" : "Pot Limit",
|
||||||
|
@ -316,32 +349,6 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
||||||
|
|
||||||
return retstring
|
return retstring
|
||||||
|
|
||||||
def lookupLimitBetSize(self):
|
|
||||||
#Lookup table for limit games
|
|
||||||
betlist = {
|
|
||||||
"Everleaf" : { "0.10" : ("0.02", "0.05"),
|
|
||||||
"0.20" : ("0.05", "0.10"),
|
|
||||||
"0.50" : ("0.10", "0.25"),
|
|
||||||
"1" : ("0.25", "0.50"),
|
|
||||||
"2" : ("0.50", "1.00"),
|
|
||||||
"4" : ("1.00", "2.00"),
|
|
||||||
"6" : ("1.00", "3.00")
|
|
||||||
},
|
|
||||||
"FullTilt" : { "0.10" : ("0.02", "0.05"),
|
|
||||||
"0.20" : ("0.05", "0.10"),
|
|
||||||
"1" : ("0.25", "0.50"),
|
|
||||||
"2" : ("0.50", "1"),
|
|
||||||
"4" : ("1", "2")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try:
|
|
||||||
ret = betlist[self.sitename][self.bb]
|
|
||||||
except:
|
|
||||||
logging.warning("Don't know the small blind/big blind size for %s, big bet size %s." % (self.sitename, self.bb))
|
|
||||||
ret = (Decimal(self.sb)/2,Decimal(self.bb)/2)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def writeHand(self, fh=sys.__stdout__):
|
def writeHand(self, fh=sys.__stdout__):
|
||||||
print >>fh, "Override me"
|
print >>fh, "Override me"
|
||||||
|
@ -371,42 +378,51 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
||||||
print >>fh, _("%s: posts small & big blinds $%s" %(act[0], act[3]))
|
print >>fh, _("%s: posts small & big blinds $%s" %(act[0], act[3]))
|
||||||
elif act[1] == 'bringin':
|
elif act[1] == 'bringin':
|
||||||
print >>fh, _("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
|
print >>fh, _("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else ''))
|
||||||
|
elif act[1] == 'discards':
|
||||||
|
print >>fh, _("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else ''))
|
||||||
|
elif act[1] == 'stands pat':
|
||||||
|
print >>fh, _("%s: stands pat" %(act[0]))
|
||||||
|
|
||||||
|
|
||||||
class HoldemOmahaHand(Hand):
|
class HoldemOmahaHand(Hand):
|
||||||
def __init__(self, hhc, sitename, gametype, handText):
|
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"):
|
||||||
if gametype['base'] != 'hold':
|
if gametype['base'] != 'hold':
|
||||||
pass # or indeed don't pass and complain instead
|
pass # or indeed don't pass and complain instead
|
||||||
logging.debug("HoldemOmahaHand")
|
logging.debug("HoldemOmahaHand")
|
||||||
self.streetList = ['BLINDSANTES', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order
|
self.streetList = ['BLINDSANTES', 'DEAL', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order
|
||||||
self.communityStreets = ['FLOP', 'TURN', 'RIVER']
|
self.communityStreets = ['FLOP', 'TURN', 'RIVER']
|
||||||
self.actionStreets = ['PREFLOP','FLOP','TURN','RIVER']
|
self.actionStreets = ['PREFLOP','FLOP','TURN','RIVER']
|
||||||
Hand.__init__(self, sitename, gametype, handText)
|
Hand.__init__(self, sitename, gametype, handText, builtFrom = "HHC")
|
||||||
self.sb = gametype['sb']
|
self.sb = gametype['sb']
|
||||||
self.bb = gametype['bb']
|
self.bb = gametype['bb']
|
||||||
|
|
||||||
#Populate a HoldemOmahaHand
|
#Populate a HoldemOmahaHand
|
||||||
#Generally, we call 'read' methods here, which get the info according to the particular filter (hhc)
|
#Generally, we call 'read' methods here, which get the info according to the particular filter (hhc)
|
||||||
# which then invokes a 'addXXX' callback
|
# which then invokes a 'addXXX' callback
|
||||||
hhc.readHandInfo(self)
|
if builtFrom == "HHC":
|
||||||
hhc.readPlayerStacks(self)
|
hhc.readHandInfo(self)
|
||||||
hhc.compilePlayerRegexs(self)
|
hhc.readPlayerStacks(self)
|
||||||
hhc.markStreets(self)
|
hhc.compilePlayerRegexs(self)
|
||||||
hhc.readBlinds(self)
|
hhc.markStreets(self)
|
||||||
hhc.readButton(self)
|
hhc.readBlinds(self)
|
||||||
hhc.readHeroCards(self)
|
hhc.readButton(self)
|
||||||
hhc.readShowdownActions(self)
|
hhc.readHeroCards(self)
|
||||||
# Read actions in street order
|
hhc.readShowdownActions(self)
|
||||||
for street in self.communityStreets:
|
# Read actions in street order
|
||||||
if self.streets[street]:
|
for street in self.communityStreets:
|
||||||
hhc.readCommunityCards(self, street)
|
if self.streets[street]:
|
||||||
for street in self.actionStreets:
|
hhc.readCommunityCards(self, street)
|
||||||
if self.streets[street]:
|
for street in self.actionStreets:
|
||||||
hhc.readAction(self, street)
|
if self.streets[street]:
|
||||||
hhc.readCollectPot(self)
|
hhc.readAction(self, street)
|
||||||
hhc.readShownCards(self)
|
hhc.readCollectPot(self)
|
||||||
self.totalPot() # finalise it (total the pot)
|
hhc.readShownCards(self)
|
||||||
hhc.getRake(self)
|
self.totalPot() # finalise it (total the pot)
|
||||||
|
hhc.getRake(self)
|
||||||
|
elif builtFrom == "DB":
|
||||||
|
self.select("dummy") # Will need a handId
|
||||||
|
|
||||||
def addHoleCards(self, cards, player):
|
def addHoleCards(self, cards, player, shown=False):
|
||||||
"""\
|
"""\
|
||||||
Assigns observed holecards to a player.
|
Assigns observed holecards to a player.
|
||||||
cards list of card bigrams e.g. ['2h','Jc']
|
cards list of card bigrams e.g. ['2h','Jc']
|
||||||
|
@ -416,6 +432,8 @@ player (string) name of player
|
||||||
try:
|
try:
|
||||||
self.checkPlayerExists(player)
|
self.checkPlayerExists(player)
|
||||||
cardset = set(self.card(c) for c in cards)
|
cardset = set(self.card(c) for c in cards)
|
||||||
|
if shown and len(cardset) > 0:
|
||||||
|
self.shown.add(player)
|
||||||
if 'PREFLOP' in self.holecards[player]:
|
if 'PREFLOP' in self.holecards[player]:
|
||||||
self.holecards[player]['PREFLOP'].update(cardset)
|
self.holecards[player]['PREFLOP'].update(cardset)
|
||||||
else:
|
else:
|
||||||
|
@ -435,7 +453,7 @@ Card ranks will be uppercased
|
||||||
elif holeandboard is not None:
|
elif holeandboard is not None:
|
||||||
holeandboard = set([self.card(c) for c in holeandboard])
|
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])
|
||||||
self.addHoleCards(holeandboard.difference(board),player)
|
self.addHoleCards(holeandboard.difference(board),player,shown=True)
|
||||||
|
|
||||||
|
|
||||||
def writeHand(self, fh=sys.__stdout__):
|
def writeHand(self, fh=sys.__stdout__):
|
||||||
|
@ -449,23 +467,6 @@ Card ranks will be uppercased
|
||||||
#Only print stacks of players who do something preflop
|
#Only print stacks of players who do something preflop
|
||||||
print >>fh, _("Seat %s: %s ($%s in chips) " %(player[0], player[1], player[2]))
|
print >>fh, _("Seat %s: %s ($%s in chips) " %(player[0], player[1], player[2]))
|
||||||
|
|
||||||
|
|
||||||
#May be more than 1 bb posting
|
|
||||||
if self.gametype['limitType'] == "fl":
|
|
||||||
(smallbet, bigbet) = self.lookupLimitBetSize()
|
|
||||||
else:
|
|
||||||
smallbet = self.sb
|
|
||||||
bigbet = self.bb
|
|
||||||
|
|
||||||
# for a in self.posted:
|
|
||||||
# if(a[1] == "small blind"):
|
|
||||||
# print >>fh, _("%s: posts small blind $%s" %(a[0], smallbet))
|
|
||||||
# if(a[1] == "big blind"):
|
|
||||||
# print >>fh, _("%s: posts big blind $%s" %(a[0], bigbet))
|
|
||||||
# if(a[1] == "both"):
|
|
||||||
# print >>fh, _("%s: posts small & big blinds $%.2f" %(a[0], (Decimal(smallbet) + Decimal(bigbet))))
|
|
||||||
# I think these can just be actions in 'blindsantes' round
|
|
||||||
|
|
||||||
if self.actions['BLINDSANTES']:
|
if self.actions['BLINDSANTES']:
|
||||||
for act in self.actions['BLINDSANTES']:
|
for act in self.actions['BLINDSANTES']:
|
||||||
self.printActionLine(act, fh)
|
self.printActionLine(act, fh)
|
||||||
|
@ -532,32 +533,201 @@ Card ranks will be uppercased
|
||||||
print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']), self.collectees[name]))
|
print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']), self.collectees[name]))
|
||||||
elif name in self.collectees:
|
elif name in self.collectees:
|
||||||
print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
|
print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
|
||||||
elif name in self.shown:
|
#~ elif name in self.shown:
|
||||||
print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP'])))
|
#~ print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP'])))
|
||||||
elif name in self.folded:
|
elif name in self.folded:
|
||||||
print >>fh, _("Seat %d: %s folded" % (seatnum, name))
|
print >>fh, _("Seat %d: %s folded" % (seatnum, name))
|
||||||
else:
|
else:
|
||||||
print >>fh, _("Seat %d: %s mucked" % (seatnum, name))
|
if name in self.shown:
|
||||||
|
print >>fh, _("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards[name]['PREFLOP'])))
|
||||||
|
else:
|
||||||
|
print >>fh, _("Seat %d: %s mucked" % (seatnum, name))
|
||||||
|
|
||||||
print >>fh, "\n\n"
|
print >>fh, "\n\n"
|
||||||
|
|
||||||
class DrawHand(Hand):
|
class DrawHand(Hand):
|
||||||
def __init__(self, hhc, sitename, gametype, handText):
|
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"):
|
||||||
if gametype['base'] != 'draw':
|
if gametype['base'] != 'draw':
|
||||||
pass # or indeed don't pass and complain instead
|
pass # or indeed don't pass and complain instead
|
||||||
|
self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
|
||||||
def discardHoleCards(self, cards, player):
|
self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
|
||||||
|
self.actionStreets = ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
|
||||||
|
Hand.__init__(self, sitename, gametype, handText)
|
||||||
|
self.sb = gametype['sb']
|
||||||
|
self.bb = gametype['bb']
|
||||||
|
# Populate the draw hand.
|
||||||
|
if builtFrom == "HHC":
|
||||||
|
hhc.readHandInfo(self)
|
||||||
|
hhc.readPlayerStacks(self)
|
||||||
|
hhc.compilePlayerRegexs(self)
|
||||||
|
hhc.markStreets(self)
|
||||||
|
hhc.readBlinds(self)
|
||||||
|
hhc.readButton(self)
|
||||||
|
hhc.readShowdownActions(self)
|
||||||
|
# Read actions in street order
|
||||||
|
for street in self.streetList:
|
||||||
|
if self.streets[street]:
|
||||||
|
# hhc.readCommunityCards(self, street)
|
||||||
|
hhc.readDrawCards(self, street)
|
||||||
|
hhc.readAction(self, street)
|
||||||
|
hhc.readCollectPot(self)
|
||||||
|
hhc.readShownCards(self)
|
||||||
|
self.totalPot() # finalise it (total the pot)
|
||||||
|
hhc.getRake(self)
|
||||||
|
elif builtFrom == "DB":
|
||||||
|
self.select("dummy") # Will need a handId
|
||||||
|
|
||||||
|
# Draw games (at least Badugi has blinds - override default Holdem addBlind
|
||||||
|
def addBlind(self, player, blindtype, amount):
|
||||||
|
# if player is None, it's a missing small blind.
|
||||||
|
# The situation we need to cover are:
|
||||||
|
# Player in small blind posts
|
||||||
|
# - this is a bet of 1 sb, as yet uncalled.
|
||||||
|
# Player in the big blind posts
|
||||||
|
# - this is a call of 1 sb and a raise to 1 bb
|
||||||
|
#
|
||||||
|
|
||||||
|
logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount))
|
||||||
|
if player is not None:
|
||||||
|
self.bets['DEAL'][player].append(Decimal(amount))
|
||||||
|
self.stacks[player] -= Decimal(amount)
|
||||||
|
#print "DEBUG %s posts, stack %s" % (player, self.stacks[player])
|
||||||
|
act = (player, 'posts', blindtype, amount, self.stacks[player]==0)
|
||||||
|
self.actions['BLINDSANTES'].append(act)
|
||||||
|
self.pot.addMoney(player, Decimal(amount))
|
||||||
|
if blindtype == 'big blind':
|
||||||
|
self.lastBet['DEAL'] = Decimal(amount)
|
||||||
|
elif blindtype == 'both':
|
||||||
|
# extra small blind is 'dead'
|
||||||
|
self.lastBet['DEAL'] = Decimal(self.bb)
|
||||||
|
self.posted = self.posted + [[player,blindtype]]
|
||||||
|
#print "DEBUG: self.posted: %s" %(self.posted)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False):
|
||||||
|
"""\
|
||||||
|
Assigns observed holecards to a player.
|
||||||
|
cards list of card bigrams e.g. ['2h','Jc']
|
||||||
|
player (string) name of player
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
self.checkPlayerExists(player)
|
self.checkPlayerExists(player)
|
||||||
for card in cards:
|
# if shown and len(cardset) > 0:
|
||||||
self.holecards[player].remove(card)
|
# self.shown.add(player)
|
||||||
|
self.holecards[player][street] = (newcards,oldcards)
|
||||||
except FpdbParseError, e:
|
except FpdbParseError, e:
|
||||||
pass
|
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||||
except ValueError:
|
|
||||||
print "[ERROR] discardHoleCard tried to discard a card %s didn't have" % (player,)
|
|
||||||
|
def discardDrawHoleCards(self, cards, player, street):
|
||||||
|
logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street))
|
||||||
|
self.discards[player][street] = set([cards])
|
||||||
|
|
||||||
|
|
||||||
|
def addDiscard(self, street, player, num, cards):
|
||||||
|
self.checkPlayerExists(player)
|
||||||
|
if cards:
|
||||||
|
act = (player, 'discards', num, cards)
|
||||||
|
self.discardDrawHoleCards(cards, player, street)
|
||||||
|
else:
|
||||||
|
act = (player, 'discards', num)
|
||||||
|
self.actions[street].append(act)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
|
||||||
|
# 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,shown=True)
|
||||||
|
|
||||||
|
|
||||||
|
def writeHand(self, fh=sys.__stdout__):
|
||||||
|
# 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, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||||
|
|
||||||
|
players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']]))
|
||||||
|
|
||||||
|
for player in [x for x in self.players if x[1] in players_who_act_ondeal]:
|
||||||
|
#Only print stacks of players who do something on deal
|
||||||
|
print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2]))
|
||||||
|
|
||||||
|
if 'BLINDSANTES' in self.actions:
|
||||||
|
for act in self.actions['BLINDSANTES']:
|
||||||
|
print >>fh, _("%s: %s %s $%s" %(act[0], act[1], act[2], act[3]))
|
||||||
|
|
||||||
|
if 'DEAL' in self.actions:
|
||||||
|
print >>fh, _("*** DEALING HANDS ***")
|
||||||
|
for player in [x[1] for x in self.players if x[1] in players_who_act_ondeal]:
|
||||||
|
if 'DEAL' in self.holecards[player]:
|
||||||
|
(nc,oc) = self.holecards[player]['DEAL']
|
||||||
|
print >>fh, _("Dealt to %s: [%s]") % (player, " ".join(nc))
|
||||||
|
for act in self.actions['DEAL']:
|
||||||
|
self.printActionLine(act, fh)
|
||||||
|
|
||||||
|
if 'DRAWONE' in self.actions:
|
||||||
|
print >>fh, _("*** FIRST DRAW ***")
|
||||||
|
for act in self.actions['DRAWONE']:
|
||||||
|
self.printActionLine(act, fh)
|
||||||
|
if act[0] == self.hero and act[1] == 'discards':
|
||||||
|
(nc,oc) = self.holecards[act[0]]['DRAWONE']
|
||||||
|
dc = self.discards[act[0]]['DRAWONE']
|
||||||
|
kc = oc - dc
|
||||||
|
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
|
||||||
|
|
||||||
|
if 'DRAWTWO' in self.actions:
|
||||||
|
print >>fh, _("*** SECOND DRAW ***")
|
||||||
|
for act in self.actions['DRAWTWO']:
|
||||||
|
self.printActionLine(act, fh)
|
||||||
|
if act[0] == self.hero and act[1] == 'discards':
|
||||||
|
(nc,oc) = self.holecards[act[0]]['DRAWTWO']
|
||||||
|
dc = self.discards[act[0]]['DRAWTWO']
|
||||||
|
kc = oc - dc
|
||||||
|
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
|
||||||
|
|
||||||
|
if 'DRAWTHREE' in self.actions:
|
||||||
|
print >>fh, _("*** THIRD DRAW ***")
|
||||||
|
for act in self.actions['DRAWTHREE']:
|
||||||
|
self.printActionLine(act, fh)
|
||||||
|
if act[0] == self.hero and act[1] == 'discards':
|
||||||
|
(nc,oc) = self.holecards[act[0]]['DRAWTHREE']
|
||||||
|
dc = self.discards[act[0]]['DRAWTHREE']
|
||||||
|
kc = oc - dc
|
||||||
|
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
|
||||||
|
|
||||||
|
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)
|
||||||
|
print >>fh, "\n\n"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class StudHand(Hand):
|
class StudHand(Hand):
|
||||||
def __init__(self, hhc, sitename, gametype, handText):
|
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"):
|
||||||
if gametype['base'] != 'stud':
|
if gametype['base'] != 'stud':
|
||||||
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
|
||||||
|
@ -568,24 +738,27 @@ class StudHand(Hand):
|
||||||
#Populate the StudHand
|
#Populate the StudHand
|
||||||
#Generally, we call a 'read' method here, which gets the info according to the particular filter (hhc)
|
#Generally, we call a 'read' method here, which gets the info according to the particular filter (hhc)
|
||||||
# which then invokes a 'addXXX' callback
|
# which then invokes a 'addXXX' callback
|
||||||
hhc.readHandInfo(self)
|
if builtFrom == "HHC":
|
||||||
hhc.readPlayerStacks(self)
|
hhc.readHandInfo(self)
|
||||||
hhc.compilePlayerRegexs(self)
|
hhc.readPlayerStacks(self)
|
||||||
hhc.markStreets(self)
|
hhc.compilePlayerRegexs(self)
|
||||||
hhc.readAntes(self)
|
hhc.markStreets(self)
|
||||||
hhc.readBringIn(self)
|
hhc.readAntes(self)
|
||||||
# hhc.readShowdownActions(self) # not done yet
|
hhc.readBringIn(self)
|
||||||
# Read actions in street order
|
#hhc.readShowdownActions(self) # not done yet
|
||||||
for street in self.streetList:
|
# Read actions in street order
|
||||||
if self.streets[street]:
|
for street in self.streetList:
|
||||||
logging.debug(street)
|
if self.streets[street]:
|
||||||
logging.debug(self.streets[street])
|
logging.debug(street)
|
||||||
hhc.readStudPlayerCards(self, street)
|
logging.debug(self.streets[street])
|
||||||
hhc.readAction(self, street)
|
hhc.readStudPlayerCards(self, street)
|
||||||
hhc.readCollectPot(self)
|
hhc.readAction(self, street)
|
||||||
# hhc.readShownCards(self) # not done yet
|
hhc.readCollectPot(self)
|
||||||
self.totalPot() # finalise it (total the pot)
|
#hhc.readShownCards(self) # not done yet
|
||||||
hhc.getRake(self)
|
self.totalPot() # finalise it (total the pot)
|
||||||
|
hhc.getRake(self)
|
||||||
|
elif builtFrom == "DB":
|
||||||
|
self.select("dummy") # Will need a handId
|
||||||
|
|
||||||
def addPlayerCards(self, player, street, open=[], closed=[]):
|
def addPlayerCards(self, player, street, open=[], closed=[]):
|
||||||
"""\
|
"""\
|
||||||
|
|
|
@ -43,11 +43,12 @@ import Configuration
|
||||||
import Stats
|
import Stats
|
||||||
import Mucked
|
import Mucked
|
||||||
import Database
|
import Database
|
||||||
import HUD_main
|
import HUD_main
|
||||||
|
|
||||||
def importName(module_name, name):
|
def importName(module_name, name):
|
||||||
"""Import a named object 'name' from module 'module_name'."""
|
"""Import a named object 'name' from module 'module_name'."""
|
||||||
# Recipe 16.3 in the Python Cookbook, 2nd ed. Thanks!!!!
|
# Recipe 16.3 in the Python Cookbook, 2nd ed. Thanks!!!!
|
||||||
|
|
||||||
try:
|
try:
|
||||||
module = __import__(module_name, globals(), locals(), [name])
|
module = __import__(module_name, globals(), locals(), [name])
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -23,53 +23,10 @@ from HandHistoryConverter import *
|
||||||
|
|
||||||
# PokerStars HH Format
|
# PokerStars HH Format
|
||||||
|
|
||||||
#PokerStars Game #20461877044: Hold'em No Limit ($1/$2) - 2008/09/16 18:58:01 ET
|
|
||||||
#Table 'Gianfar IV' 6-max Seat #1 is the button
|
|
||||||
#Seat 1: ZeKGB ($224 in chips)
|
|
||||||
#Seat 2: quimboavida ($107.75 in chips)
|
|
||||||
#Seat 3: tropical100 ($190 in chips)
|
|
||||||
#Seat 4: jackhama33 ($54.95 in chips)
|
|
||||||
#Seat 5: Olubanu ($196 in chips)
|
|
||||||
#Seat 6: LSgambler ($205.35 in chips)
|
|
||||||
#quimboavida: posts small blind $1
|
|
||||||
#tropical100: posts big blind $2
|
|
||||||
#*** HOLE CARDS ***
|
|
||||||
#jackhama33: folds
|
|
||||||
#Olubanu: folds
|
|
||||||
#LSgambler: folds
|
|
||||||
#ZeKGB: folds
|
|
||||||
#quimboavida: calls $1
|
|
||||||
#tropical100: raises $5 to $7
|
|
||||||
#quimboavida: calls $5
|
|
||||||
#*** FLOP *** [3d Qs Kd]
|
|
||||||
#quimboavida: bets $10
|
|
||||||
#tropical100: calls $10
|
|
||||||
#*** TURN *** [3d Qs Kd] [Ah]
|
|
||||||
#quimboavida: checks
|
|
||||||
#tropical100: checks
|
|
||||||
#*** RIVER *** [3d Qs Kd Ah] [7c]
|
|
||||||
#quimboavida: bets $30
|
|
||||||
#tropical100: folds
|
|
||||||
#quimboavida collected $32.35 from pot
|
|
||||||
#*** SUMMARY ***
|
|
||||||
#Total pot $34 | Rake $1.65
|
|
||||||
#Board [3d Qs Kd Ah 7c]
|
|
||||||
#Seat 1: ZeKGB (button) folded before Flop (didn't bet)
|
|
||||||
#Seat 2: quimboavida (small blind) collected ($32.35)
|
|
||||||
#Seat 3: tropical100 (big blind) folded on the River
|
|
||||||
#Seat 4: jackhama33 folded before Flop (didn't bet)
|
|
||||||
#Seat 5: Olubanu folded before Flop (didn't bet)
|
|
||||||
#Seat 6: LSgambler folded before Flop (didn't bet)
|
|
||||||
|
|
||||||
|
|
||||||
#PokerStars Game #25381215423: HORSE (Razz Limit, $0.10/$0.20) - 2009/02/26 15:20:19 ET
|
|
||||||
#Table 'Natalie V' 8-max
|
|
||||||
|
|
||||||
|
|
||||||
class PokerStars(HandHistoryConverter):
|
class PokerStars(HandHistoryConverter):
|
||||||
|
|
||||||
# Static regexes
|
# Static regexes
|
||||||
re_GameInfo = re.compile('PokerStars Game #(?P<HID>[0-9]+):\s+(HORSE)? \(?(?P<GAME>Hold\'em|Razz|7 Card Stud|Omaha Hi/Lo) (?P<LIMIT>No Limit|Limit|Pot Limit),? \(?(?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\) - (?P<DATETIME>.*$)', re.MULTILINE)
|
re_GameInfo = re.compile("PokerStars Game #(?P<HID>[0-9]+):\s+(HORSE)? \(?(?P<GAME>Hold\'em|Razz|7 Card Stud|Omaha Hi/Lo|Badugi) (?P<LIMIT>No Limit|Limit|Pot Limit),? \(?(?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\) - (?P<DATETIME>.*$)", re.MULTILINE)
|
||||||
re_SplitHands = re.compile('\n\n+')
|
re_SplitHands = re.compile('\n\n+')
|
||||||
re_HandInfo = re.compile("^Table \'(?P<TABLE>[- a-zA-Z]+)\'(?P<TABLEATTRIBUTES>.+?$)?", re.MULTILINE)
|
re_HandInfo = re.compile("^Table \'(?P<TABLE>[- a-zA-Z]+)\'(?P<TABLEATTRIBUTES>.+?$)?", re.MULTILINE)
|
||||||
re_Button = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE)
|
re_Button = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE)
|
||||||
|
@ -89,7 +46,7 @@ follow : whether to tail -f the input"""
|
||||||
if autostart:
|
if autostart:
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
|
|
||||||
def compilePlayerRegexs(self, hand):
|
def compilePlayerRegexs(self, hand):
|
||||||
players = set([player[1] for player in hand.players])
|
players = set([player[1] for player in hand.players])
|
||||||
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
|
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
|
||||||
|
@ -103,7 +60,7 @@ follow : whether to tail -f the input"""
|
||||||
self.re_BringIn = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE)
|
self.re_BringIn = re.compile(r"^%s: brings[- ]in( low|) 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_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<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE)
|
self.re_HeroCards = re.compile(r"^Dealt to %s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE)
|
||||||
self.re_Action = re.compile(r"^%s:(?P<ATYPE> bets| checks| raises| calls| folds)( \$(?P<BET>[.\d]+))?( to \$(?P<BETTO>[.\d]+))?" % player_re, re.MULTILINE)
|
self.re_Action = re.compile(r"^%s:(?P<ATYPE> bets| checks| raises| calls| folds| discards| stands pat)( \$(?P<BET>[.\d]+))?( to \$(?P<BETTO>[.\d]+))?( (?P<NODISCARDED>\d) cards?( \[(?P<DISCARDED>.+?)\])?)?" % player_re, re.MULTILINE)
|
||||||
self.re_ShowdownAction = re.compile(r"^%s: shows \[(?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_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("^%s sits out" % player_re, re.MULTILINE)
|
self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE)
|
||||||
|
@ -111,7 +68,13 @@ follow : whether to tail -f the input"""
|
||||||
|
|
||||||
|
|
||||||
def readSupportedGames(self):
|
def readSupportedGames(self):
|
||||||
return []
|
return [["ring", "hold", "nl"],
|
||||||
|
["ring", "hold", "pl"],
|
||||||
|
["ring", "hold", "fl"],
|
||||||
|
["ring", "stud", "fl"],
|
||||||
|
["ring", "draw", "fl"],
|
||||||
|
["ring", "omaha", "pl"]
|
||||||
|
]
|
||||||
|
|
||||||
def determineGameType(self, handText):
|
def determineGameType(self, handText):
|
||||||
info = {'type':'ring'}
|
info = {'type':'ring'}
|
||||||
|
@ -129,7 +92,8 @@ follow : whether to tail -f the input"""
|
||||||
'Omaha Hi' : ('hold','omahahi'),
|
'Omaha Hi' : ('hold','omahahi'),
|
||||||
'Omaha Hi/Lo' : ('hold','omahahilo'),
|
'Omaha Hi/Lo' : ('hold','omahahilo'),
|
||||||
'Razz' : ('stud','razz'),
|
'Razz' : ('stud','razz'),
|
||||||
'7 Card Stud' : ('stud','studhi')
|
'7 Card Stud' : ('stud','studhi'),
|
||||||
|
'Badugi' : ('draw','badugi')
|
||||||
}
|
}
|
||||||
currencies = { u'€':'EUR', '$':'USD', '':'T$' }
|
currencies = { u'€':'EUR', '$':'USD', '':'T$' }
|
||||||
if 'LIMIT' in mg:
|
if 'LIMIT' in mg:
|
||||||
|
@ -199,6 +163,12 @@ follow : whether to tail -f the input"""
|
||||||
r"(\*\*\* 5th STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6th STREET \*\*\*)|.+))?"
|
r"(\*\*\* 5th STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6th STREET \*\*\*)|.+))?"
|
||||||
r"(\*\*\* 6th STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* RIVER \*\*\*)|.+))?"
|
r"(\*\*\* 6th STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* RIVER \*\*\*)|.+))?"
|
||||||
r"(\*\*\* RIVER \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
|
r"(\*\*\* RIVER \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
|
||||||
|
elif hand.gametype['base'] in ("draw"):
|
||||||
|
m = re.search(r"(?P<PREDEAL>.+(?=\*\*\* DEALING HANDS \*\*\*)|.+)"
|
||||||
|
r"(\*\*\* DEALING HANDS \*\*\*(?P<DEAL>.+(?=\*\*\* FIRST DRAW \*\*\*)|.+))?"
|
||||||
|
r"(\*\*\* FIRST DRAW \*\*\*(?P<DRAWONE>.+(?=\*\*\* SECOND DRAW \*\*\*)|.+))?"
|
||||||
|
r"(\*\*\* SECOND DRAW \*\*\*(?P<DRAWTWO>.+(?=\*\*\* THIRD DRAW \*\*\*)|.+))?"
|
||||||
|
r"(\*\*\* THIRD DRAW \*\*\*(?P<DRAWTHREE>.+))?", 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
|
||||||
|
@ -244,6 +214,27 @@ follow : whether to tail -f the input"""
|
||||||
cards = set(cards.split(' '))
|
cards = set(cards.split(' '))
|
||||||
hand.addHoleCards(cards, m.group('PNAME'))
|
hand.addHoleCards(cards, m.group('PNAME'))
|
||||||
|
|
||||||
|
def readDrawCards(self, hand, street):
|
||||||
|
logging.debug("readDrawCards")
|
||||||
|
m = self.re_HeroCards.finditer(hand.streets[street])
|
||||||
|
if m == None:
|
||||||
|
hand.involved = False
|
||||||
|
else:
|
||||||
|
for player in m:
|
||||||
|
hand.hero = player.group('PNAME') # Only really need to do this once
|
||||||
|
newcards = player.group('NEWCARDS')
|
||||||
|
oldcards = player.group('OLDCARDS')
|
||||||
|
if newcards == None:
|
||||||
|
newcards = set()
|
||||||
|
else:
|
||||||
|
newcards = set(newcards.split(' '))
|
||||||
|
if oldcards == None:
|
||||||
|
oldcards = set()
|
||||||
|
else:
|
||||||
|
oldcards = set(oldcards.split(' '))
|
||||||
|
hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street)
|
||||||
|
|
||||||
|
|
||||||
def readStudPlayerCards(self, hand, street):
|
def readStudPlayerCards(self, hand, street):
|
||||||
# See comments of reference implementation in FullTiltToFpdb.py
|
# See comments of reference implementation in FullTiltToFpdb.py
|
||||||
logging.debug("readStudPlayerCards")
|
logging.debug("readStudPlayerCards")
|
||||||
|
@ -292,8 +283,12 @@ follow : whether to tail -f the input"""
|
||||||
hand.addFold( street, action.group('PNAME'))
|
hand.addFold( street, action.group('PNAME'))
|
||||||
elif action.group('ATYPE') == ' checks':
|
elif action.group('ATYPE') == ' checks':
|
||||||
hand.addCheck( street, action.group('PNAME'))
|
hand.addCheck( street, action.group('PNAME'))
|
||||||
|
elif action.group('ATYPE') == ' discards':
|
||||||
|
hand.addDiscard(street, action.group('PNAME'), action.group('NODISCARDED'), action.group('DISCARDED'))
|
||||||
|
elif action.group('ATYPE') == ' stands pat':
|
||||||
|
hand.addStandsPat( street, action.group('PNAME'))
|
||||||
else:
|
else:
|
||||||
print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)
|
print "DEBUG: unimplemented readAction: '%s' '%s'" %(action.group('PNAME'),action.group('ATYPE'),)
|
||||||
|
|
||||||
|
|
||||||
def readShowdownActions(self, hand):
|
def readShowdownActions(self, hand):
|
||||||
|
|
|
@ -33,8 +33,6 @@ import fpdb_simple
|
||||||
import fpdb_db
|
import fpdb_db
|
||||||
import fpdb_parse_logic
|
import fpdb_parse_logic
|
||||||
import Configuration
|
import Configuration
|
||||||
import EverleafToFpdb
|
|
||||||
import FulltiltToFpdb
|
|
||||||
|
|
||||||
# database interface modules
|
# database interface modules
|
||||||
try:
|
try:
|
||||||
|
@ -228,7 +226,6 @@ class Importer:
|
||||||
conv = None
|
conv = None
|
||||||
# Load filter, process file, pass returned filename to import_fpdb_file
|
# Load filter, process file, pass returned filename to import_fpdb_file
|
||||||
|
|
||||||
# TODO: Shouldn't we be able to use some sort of lambda or something to just call a Python object by whatever name we specify? then we don't have to hardcode them,
|
|
||||||
print "converting %s" % file
|
print "converting %s" % file
|
||||||
hhbase = self.config.get_import_parameters().get("hhArchiveBase")
|
hhbase = self.config.get_import_parameters().get("hhArchiveBase")
|
||||||
hhbase = os.path.expanduser(hhbase)
|
hhbase = os.path.expanduser(hhbase)
|
||||||
|
@ -238,21 +235,22 @@ class Importer:
|
||||||
except:
|
except:
|
||||||
out_path = os.path.join(hhdir, "x"+strftime("%d-%m-%y")+os.path.basename(file))
|
out_path = os.path.join(hhdir, "x"+strftime("%d-%m-%y")+os.path.basename(file))
|
||||||
|
|
||||||
# someone can just create their own python module for it
|
filter_name = filter.replace("ToFpdb", "")
|
||||||
if filter in ("EverleafToFpdb","Everleaf"):
|
|
||||||
conv = EverleafToFpdb.Everleaf(in_path = file, out_path = out_path)
|
mod = __import__(filter)
|
||||||
elif filter == "FulltiltToFpdb":
|
obj = getattr(mod, filter_name, None)
|
||||||
conv = FulltiltToFpdb.FullTilt(in_path = file, out_path = out_path)
|
if callable(obj):
|
||||||
|
conv = obj(in_path = file, out_path = out_path)
|
||||||
|
if(conv.getStatus()):
|
||||||
|
(stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(out_path, site)
|
||||||
|
else:
|
||||||
|
# conversion didn't work
|
||||||
|
# TODO: appropriate response?
|
||||||
|
return (0, 0, 0, 1, 0)
|
||||||
else:
|
else:
|
||||||
print "Unknown filter ", filter
|
print "Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(conv.getStatus()):
|
|
||||||
(stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(out_path, 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)
|
||||||
|
|
|
@ -31,7 +31,7 @@ Blinds 10/20 NL Hold'em - 2009/02/25 - 17:30:32
|
||||||
Table 2
|
Table 2
|
||||||
Seat 1 is the button
|
Seat 1 is the button
|
||||||
Total number of players: 10""",
|
Total number of players: 10""",
|
||||||
{'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'10', 'bb':'20', 'currency':'T$'}),
|
{'type':'tour', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'10', 'bb':'20', 'currency':'T$'}),
|
||||||
|
|
||||||
("""Everleaf Gaming Game #65087798
|
("""Everleaf Gaming Game #65087798
|
||||||
***** Hand history for game #65087798 *****
|
***** Hand history for game #65087798 *****
|
||||||
|
@ -43,7 +43,7 @@ Table Plymouth""",
|
||||||
***** Hand history for game #65295370 *****
|
***** Hand history for game #65295370 *****
|
||||||
Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48
|
Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48
|
||||||
Table Guanajuato""",
|
Table Guanajuato""",
|
||||||
{'type':'ring', 'base':'hold', 'category':'omahahi', 'limitType':'pl', 'sb':'0.50', 'bb':'1','currency':'USD'})
|
{'type':'ring', 'base':'hold', 'category':'omahahi', 'limitType':'pl', 'sb':'0.50', 'bb':'1','currency':'USD'}),
|
||||||
|
|
||||||
)
|
)
|
||||||
for (header, info) in pairs:
|
for (header, info) in pairs:
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
import FulltiltToFpdb
|
import FulltiltToFpdb
|
||||||
import py
|
import py
|
||||||
|
|
||||||
|
# regression-test-files/fulltilt/nlhe/NLHE-6max-1.txt
|
||||||
|
# Sorrowful: start: $8.85 end: $14.70 total: $5.85
|
||||||
|
|
||||||
def checkGameInfo(hhc, header, info):
|
def checkGameInfo(hhc, header, info):
|
||||||
assert hhc.determineGameType(header) == info
|
assert hhc.determineGameType(header) == info
|
||||||
|
|
||||||
def testGameInfo():
|
def testGameInfo():
|
||||||
hhc = FulltiltToFpdb.FullTilt(autostart=False)
|
hhc = FulltiltToFpdb.Fulltilt(autostart=False)
|
||||||
pairs = (
|
pairs = (
|
||||||
("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",
|
||||||
{'type':'ring', 'base':'hold', 'category':'omahahi', 'limitType':'pl', 'sb':'0.01', 'bb':'0.02', 'currency':'USD'}),
|
{'type':'ring', 'base':'hold', 'category':'omahahi', 'limitType':'pl', 'sb':'0.01', 'bb':'0.02', 'currency':'USD'}),
|
||||||
|
|
|
@ -1,7 +1,21 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import PokerStarsToFpdb
|
import PokerStarsToFpdb
|
||||||
|
from Hand import *
|
||||||
import py
|
import py
|
||||||
|
|
||||||
|
#regression-test-files/stars/badugi/ring-fl-badugi.txt
|
||||||
|
# s0rrow: start $30.00 end: $22.65 total: ($7.35)
|
||||||
|
|
||||||
|
gametype = {'type':'ring', 'base':'draw', 'category':'badugi', 'limitType':'fl', 'sb':'0.25', 'bb':'0.50','currency':'USD'}
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
hhc = PokerStarsToFpdb.PokerStars(autostart=False)
|
||||||
|
|
||||||
|
h = HoldemOmahaHand(None, "ASite", gametype, text, builtFrom = "Test")
|
||||||
|
h.addPlayer("1", "s0rrow", "100000")
|
||||||
|
|
||||||
|
hhc.compilePlayerRegexs(h)
|
||||||
|
|
||||||
|
|
||||||
def checkGameInfo(hhc, header, info):
|
def checkGameInfo(hhc, header, info):
|
||||||
assert hhc.determineGameType(header) == info
|
assert hhc.determineGameType(header) == info
|
||||||
|
@ -13,7 +27,10 @@ def testGameInfo():
|
||||||
{'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'1', 'bb':'2', 'currency':'USD'}),
|
{'type':'ring', 'base':"hold", 'category':'holdem', 'limitType':'nl', 'sb':'1', 'bb':'2', 'currency':'USD'}),
|
||||||
|
|
||||||
(u"PokerStars Game #5999635897: HORSE (Omaha Hi/Lo Limit, $2/$4) - 2006/08/21 - 13:59:19 (ET)",
|
(u"PokerStars Game #5999635897: HORSE (Omaha Hi/Lo Limit, $2/$4) - 2006/08/21 - 13:59:19 (ET)",
|
||||||
{'type':'ring', 'base':'hold', 'category':'omahahilo', 'limitType':'fl', 'sb':'2', 'bb':'4','currency':'USD'})
|
{'type':'ring', 'base':'hold', 'category':'omahahilo', 'limitType':'fl', 'sb':'2', 'bb':'4','currency':'USD'}),
|
||||||
|
|
||||||
|
(u"PokerStars Game #25923772706: Badugi Limit ($0.25/$0.50) - 2009/03/13 16:40:58 ET",
|
||||||
|
{'type':'ring', 'base':'draw', 'category':'badugi', 'limitType':'fl', 'sb':'0.25', 'bb':'0.50','currency':'USD'})
|
||||||
)
|
)
|
||||||
for (header, info) in pairs:
|
for (header, info) in pairs:
|
||||||
yield checkGameInfo, hhc, header, info
|
yield checkGameInfo, hhc, header, info
|
||||||
|
|
Loading…
Reference in New Issue
Block a user