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

This commit is contained in:
grindi 2009-08-10 00:39:52 +04:00
commit dfac9dfeb1
12 changed files with 213 additions and 187 deletions

View File

@ -26,6 +26,11 @@ from HandHistoryConverter import *
class Betfair(HandHistoryConverter): class Betfair(HandHistoryConverter):
sitename = 'Betfair'
filetype = "text"
codepage = "cp1252"
siteId = 7 # Needs to match id entry in Sites database
# Static regexes # Static regexes
re_GameInfo = re.compile("^(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAME>(Texas Hold\'em|Omaha Hi|Razz))", re.MULTILINE) re_GameInfo = re.compile("^(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAME>(Texas Hold\'em|Omaha Hi|Razz))", re.MULTILINE)
re_SplitHands = re.compile(r'\n\n+') re_SplitHands = re.compile(r'\n\n+')
@ -34,19 +39,6 @@ class Betfair(HandHistoryConverter):
re_PlayerInfo = re.compile("Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*)\s\(\s(\$(?P<CASH>[.0-9]+)) \)") re_PlayerInfo = re.compile("Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*)\s\(\s(\$(?P<CASH>[.0-9]+)) \)")
re_Board = re.compile(ur"\[ (?P<CARDS>.+) \]") re_Board = re.compile(ur"\[ (?P<CARDS>.+) \]")
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0):
"""\
in_path (default '-' = sys.stdin)
out_path (default '-' = sys.stdout)
follow : whether to tail -f the input"""
HandHistoryConverter.__init__(self, in_path, out_path, sitename="Betfair", follow=follow, index) # Call super class init.
logging.info("Initialising Betfair converter class")
self.filetype = "text"
self.codepage = "cp1252"
self.siteId = 7 # Needs to match id entry in Sites database
if autostart:
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])

View File

@ -26,6 +26,11 @@ from HandHistoryConverter import *
class Everleaf(HandHistoryConverter): class Everleaf(HandHistoryConverter):
sitename = 'Everleaf'
filetype = "text"
codepage = "cp1252"
siteId = 3 # Needs to match id entry in Sites database
# Static regexes # Static regexes
re_SplitHands = re.compile(r"\n\n\n+") re_SplitHands = re.compile(r"\n\n\n+")
re_TailSplitHands = re.compile(r"(\n\n\n+)") re_TailSplitHands = re.compile(r"(\n\n\n+)")
@ -37,24 +42,6 @@ class Everleaf(HandHistoryConverter):
re_Board = re.compile(ur"\[ (?P<CARDS>.+) \]") re_Board = re.compile(ur"\[ (?P<CARDS>.+) \]")
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, debugging=False, index=0):
"""\
in_path (default '-' = sys.stdin)
out_path (default '-' = sys.stdout)
follow : whether to tail -f the input
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..."""
#print "DEBUG: XXXXXXXXXXXXXXX"
HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow, index=index)
logging.info("Initialising Everleaf converter class")
self.filetype = "text"
self.codepage = "cp1252"
self.siteId = 3 # Needs to match id entry in Sites database
self.debugging = debugging
if autostart:
self.start()
# otherwise you need to call start yourself.
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'

View File

@ -1 +1,4 @@
class FpdbParseError(Exception): pass class FpdbParseError(Exception):
def __init__(self,hid=None):
self.hid = hid

View File

@ -27,6 +27,11 @@ from HandHistoryConverter import *
class Fulltilt(HandHistoryConverter): class Fulltilt(HandHistoryConverter):
sitename = "Fulltilt"
filetype = "text"
codepage = "cp1252"
siteId = 1 # Needs to match id entry in Sites database
# Static regexes # Static regexes
re_GameInfo = re.compile('''(?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)? re_GameInfo = re.compile('''(?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)?
.+ .+
@ -39,7 +44,7 @@ class Fulltilt(HandHistoryConverter):
''', re.VERBOSE) ''', re.VERBOSE)
re_SplitHands = re.compile(r"\n\n+") re_SplitHands = re.compile(r"\n\n+")
re_TailSplitHands = re.compile(r"(\n\n+)") re_TailSplitHands = re.compile(r"(\n\n+)")
re_HandInfo = re.compile('''.*\#(?P<HID>[0-9]+):\s re_HandInfo = re.compile(r'''.*\#(?P<HID>[0-9]+):\s
(?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)? (?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)?
Table\s Table\s
(?P<PLAY>Play\sChip\s|PC)? (?P<PLAY>Play\sChip\s|PC)?
@ -47,8 +52,9 @@ class Fulltilt(HandHistoryConverter):
(\((?P<TABLEATTRIBUTES>.+)\)\s)?-\s (\((?P<TABLEATTRIBUTES>.+)\)\s)?-\s
\$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\s(Ante\s\$?(?P<ANTE>[.0-9]+)\s)?-\s \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\s(Ante\s\$?(?P<ANTE>[.0-9]+)\s)?-\s
(?P<GAMETYPE>[a-zA-Z\/\'\s]+)\s-\s (?P<GAMETYPE>[a-zA-Z\/\'\s]+)\s-\s
(?P<DATETIME>.*) (?P<DATETIME>.*?)\n
''', re.VERBOSE) (?:.*?\n(?P<CANCELLED>Hand\s\#(?P=HID)\shas\sbeen\scanceled))?
''', re.VERBOSE|re.DOTALL)
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE) 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]+)\)$', re.MULTILINE) re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[,.0-9]+)\)$', re.MULTILINE)
re_Board = re.compile(r"\[(?P<CARDS>.+)\]") re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
@ -60,20 +66,6 @@ class Fulltilt(HandHistoryConverter):
mixes = { 'HORSE': 'horse', '7-Game': '7game', 'HOSE': 'hose', 'HA': 'ha'} mixes = { 'HORSE': 'horse', '7-Game': '7game', 'HOSE': 'hose', 'HA': 'ha'}
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0):
"""\
in_path (default '-' = sys.stdin)
out_path (default '-' = sys.stdout)
follow : whether to tail -f the input"""
HandHistoryConverter.__init__(self, in_path, out_path, sitename="Fulltilt", follow=follow, index=index)
logging.info("Initialising Fulltilt converter class")
self.filetype = "text"
self.codepage = "cp1252"
self.siteId = 1 # Needs to match id entry in Sites database
if autostart:
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'
@ -162,7 +154,7 @@ follow : whether to tail -f the input"""
return re.split(self.re_SplitHands, self.obs) return re.split(self.re_SplitHands, self.obs)
def readHandInfo(self, hand): def readHandInfo(self, hand):
m = self.re_HandInfo.search(hand.handText,re.DOTALL) m = self.re_HandInfo.search(hand.handText)
if(m == None): if(m == None):
logging.info("Didn't match re_HandInfo") logging.info("Didn't match re_HandInfo")
logging.info(hand.handText) logging.info(hand.handText)
@ -170,6 +162,10 @@ follow : whether to tail -f the input"""
hand.handid = m.group('HID') hand.handid = m.group('HID')
hand.tablename = m.group('TABLE') hand.tablename = m.group('TABLE')
hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d") hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d")
if m.group("CANCELLED"):
raise FpdbParseError(hid=m.group('HID'))
if m.group('TABLEATTRIBUTES'): if m.group('TABLEATTRIBUTES'):
m2 = self.re_Max.search(m.group('TABLEATTRIBUTES')) m2 = self.re_Max.search(m.group('TABLEATTRIBUTES'))
if m2: hand.maxseats = int(m2.group('MAX')) if m2: hand.maxseats = int(m2.group('MAX'))
@ -369,7 +365,4 @@ if __name__ == "__main__":
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
LOG_FILENAME = './logging.out'
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)

View File

@ -32,6 +32,8 @@ import pprint
import DerivedStats import DerivedStats
import Card import Card
log = logging.getLogger("parser")
class Hand(object): class Hand(object):
###############################################################3 ###############################################################3
@ -162,7 +164,7 @@ shown whether they were revealed at showdown
mucked whether they were mucked at showdown mucked whether they were mucked at showdown
dealt whether they were seen in a 'dealt to' line dealt whether they were seen in a 'dealt to' line
""" """
# logging.debug("addHoleCards %s %s" % (open + closed, player)) # log.debug("addHoleCards %s %s" % (open + closed, player))
try: try:
self.checkPlayerExists(player) self.checkPlayerExists(player)
except FpdbParseError, e: except FpdbParseError, e:
@ -284,7 +286,7 @@ seat (int) indicating the seat
name (string) player name name (string) player name
chips (string) the chips the player has at the start of the hand (can be None) 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."""
logging.debug("addPlayer: %s %s (%s)" % (seat, name, chips)) log.debug("addPlayer: %s %s (%s)" % (seat, name, chips))
if chips is not None: if chips is not None:
chips = re.sub(u',', u'', chips) #some sites have commas chips = re.sub(u',', u'', chips) #some sites have commas
self.players.append([seat, name, chips]) self.players.append([seat, name, chips])
@ -300,9 +302,9 @@ If a player has None chips he won't be added."""
# go through m and initialise actions to empty list for each street. # go through m and initialise actions to empty list for each street.
if match: if match:
self.streets.update(match.groupdict()) self.streets.update(match.groupdict())
logging.debug("markStreets:\n"+ str(self.streets)) log.debug("markStreets:\n"+ str(self.streets))
else: else:
logging.error("markstreets didn't match") log.error("markstreets didn't match")
def checkPlayerExists(self,player): def checkPlayerExists(self,player):
if player not in [p[1] for p in self.players]: if player not in [p[1] for p in self.players]:
@ -312,7 +314,7 @@ If a player has None chips he won't be added."""
def setCommunityCards(self, street, cards): def setCommunityCards(self, street, cards):
logging.debug("setCommunityCards %s %s" %(street, cards)) log.debug("setCommunityCards %s %s" %(street, cards))
self.board[street] = [self.card(c) for c in cards] self.board[street] = [self.card(c) for c in cards]
# print "DEBUG: self.board: %s" % self.board # print "DEBUG: self.board: %s" % self.board
@ -323,7 +325,7 @@ If a player has None chips he won't be added."""
return c return c
def addAnte(self, player, ante): def addAnte(self, player, ante):
logging.debug("%s %s antes %s" % ('ANTES', player, ante)) log.debug("%s %s antes %s" % ('ANTES', player, ante))
if player is not None: if player is not None:
ante = re.sub(u',', u'', ante) #some sites have commas ante = re.sub(u',', u'', ante) #some sites have commas
self.bets['ANTES'][player].append(Decimal(ante)) self.bets['ANTES'][player].append(Decimal(ante))
@ -342,7 +344,7 @@ If a player has None chips he won't be added."""
# - 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)) log.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount))
if player is not None: if player is not None:
amount = re.sub(u',', u'', amount) #some sites have commas amount = re.sub(u',', u'', amount) #some sites have commas
self.bets['PREFLOP'][player].append(Decimal(amount)) self.bets['PREFLOP'][player].append(Decimal(amount))
@ -364,7 +366,7 @@ If a player has None chips he won't be added."""
def addCall(self, street, player=None, amount=None): def addCall(self, street, player=None, amount=None):
if amount: if amount:
amount = re.sub(u',', u'', amount) #some sites have commas amount = re.sub(u',', u'', amount) #some sites have commas
logging.debug("%s %s calls %s" %(street, player, amount)) log.debug("%s %s calls %s" %(street, player, amount))
# Potentially calculate the amount of the call if not supplied # Potentially calculate the amount of the call if not supplied
# corner cases include if player would be all in # corner cases include if player would be all in
if amount is not None: if amount is not None:
@ -434,7 +436,7 @@ Add a raise on [street] by [player] to [amountTo]
self._addRaise(street, player, C, Rb, Rt) self._addRaise(street, player, C, Rb, Rt)
def _addRaise(self, street, player, C, Rb, Rt): def _addRaise(self, street, player, C, Rb, Rt):
logging.debug("%s %s raise %s" %(street, player, Rt)) log.debug("%s %s raise %s" %(street, player, Rt))
self.bets[street][player].append(C + Rb) self.bets[street][player].append(C + Rb)
self.stacks[player] -= (C + Rb) self.stacks[player] -= (C + Rb)
act = (player, 'raises', Rb, Rt, C, self.stacks[player]==0) act = (player, 'raises', Rb, Rt, C, self.stacks[player]==0)
@ -445,7 +447,7 @@ Add a raise on [street] by [player] to [amountTo]
def addBet(self, street, player, amount): def addBet(self, street, player, amount):
logging.debug("%s %s bets %s" %(street, player, amount)) log.debug("%s %s bets %s" %(street, player, amount))
amount = re.sub(u',', u'', amount) #some sites have commas amount = re.sub(u',', u'', amount) #some sites have commas
self.checkPlayerExists(player) self.checkPlayerExists(player)
self.bets[street][player].append(Decimal(amount)) self.bets[street][player].append(Decimal(amount))
@ -464,7 +466,7 @@ Add a raise on [street] by [player] to [amountTo]
def addFold(self, street, player): def addFold(self, street, player):
logging.debug("%s %s folds" % (street, player)) log.debug("%s %s folds" % (street, player))
self.checkPlayerExists(player) self.checkPlayerExists(player)
self.folded.add(player) self.folded.add(player)
self.pot.addFold(player) self.pot.addFold(player)
@ -479,7 +481,7 @@ Add a raise on [street] by [player] to [amountTo]
def addCollectPot(self,player, pot): def addCollectPot(self,player, pot):
logging.debug("%s collected %s" % (player, pot)) log.debug("%s collected %s" % (player, pot))
self.checkPlayerExists(player) self.checkPlayerExists(player)
self.collected = self.collected + [[player, pot]] self.collected = self.collected + [[player, pot]]
if player not in self.collectees: if player not in self.collectees:
@ -493,7 +495,7 @@ Add a raise on [street] by [player] to [amountTo]
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 Card ranks will be uppercased
""" """
logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) log.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
if cards is not None: if cards is not None:
self.addHoleCards(cards,player,shown, mucked) self.addHoleCards(cards,player,shown, mucked)
elif holeandboard is not None: elif holeandboard is not None:
@ -543,7 +545,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
"cp" : "Cap Pot Limit" "cp" : "Cap Pot Limit"
} }
logging.debug("gametype: %s" %(self.gametype)) log.debug("gametype: %s" %(self.gametype))
retstring = "%s %s" %(gs[self.gametype['category']], ls[self.gametype['limitType']]) retstring = "%s %s" %(gs[self.gametype['category']], ls[self.gametype['limitType']])
return retstring return retstring
@ -622,7 +624,7 @@ class HoldemOmahaHand(Hand):
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None): def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None):
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") log.debug("HoldemOmahaHand")
self.allStreets = ['BLINDSANTES', 'PREFLOP','FLOP','TURN','RIVER'] self.allStreets = ['BLINDSANTES', 'PREFLOP','FLOP','TURN','RIVER']
self.holeStreets = ['PREFLOP'] self.holeStreets = ['PREFLOP']
self.communityStreets = ['FLOP', 'TURN', 'RIVER'] self.communityStreets = ['FLOP', 'TURN', 'RIVER']
@ -661,9 +663,9 @@ class HoldemOmahaHand(Hand):
if handid is not None: if handid is not None:
self.select(handid) # Will need a handId self.select(handid) # Will need a handId
else: else:
logging.warning("HoldemOmahaHand.__init__:Can't assemble hand from db without a handid") log.warning("HoldemOmahaHand.__init__:Can't assemble hand from db without a handid")
else: else:
logging.warning("HoldemOmahaHand.__init__:Neither HHC nor DB+handid provided") log.warning("HoldemOmahaHand.__init__:Neither HHC nor DB+handid provided")
pass pass
@ -775,7 +777,7 @@ class HoldemOmahaHand(Hand):
super(HoldemOmahaHand, self).writeHand(fh) super(HoldemOmahaHand, self).writeHand(fh)
players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']]))
logging.debug(self.actions['PREFLOP']) log.debug(self.actions['PREFLOP'])
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_act_preflop]:
#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]))
@ -918,7 +920,7 @@ class DrawHand(Hand):
# - 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)) log.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount))
if player is not None: if player is not None:
self.bets['DEAL'][player].append(Decimal(amount)) self.bets['DEAL'][player].append(Decimal(amount))
self.stacks[player] -= Decimal(amount) self.stacks[player] -= Decimal(amount)
@ -945,7 +947,7 @@ class DrawHand(Hand):
def discardDrawHoleCards(self, cards, player, street): def discardDrawHoleCards(self, cards, player, street):
logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street)) log.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street))
self.discards[street][player] = set([cards]) self.discards[street][player] = set([cards])
@ -1063,8 +1065,7 @@ class StudHand(Hand):
for street in self.actionStreets: for street in self.actionStreets:
if street == 'ANTES': continue # OMG--sometime someone folds in the ante round if street == 'ANTES': continue # OMG--sometime someone folds in the ante round
if self.streets[street]: if self.streets[street]:
logging.debug(street) log.debug(street + self.streets[street])
logging.debug(self.streets[street])
hhc.readAction(self, street) hhc.readAction(self, street)
hhc.readCollectPot(self) hhc.readCollectPot(self)
hhc.readShownCards(self) # not done yet hhc.readShownCards(self) # not done yet
@ -1096,7 +1097,7 @@ street (string) the street name (in streetList)
open list of card bigrams e.g. ['2h','Jc'], dealt face up open list of card bigrams e.g. ['2h','Jc'], dealt face up
closed likewise, but known only to player closed likewise, but known only to player
""" """
logging.debug("addPlayerCards %s, o%s x%s" % (player, open, closed)) log.debug("addPlayerCards %s, o%s x%s" % (player, open, closed))
try: try:
self.checkPlayerExists(player) self.checkPlayerExists(player)
self.holecards[street][player] = (open, closed) self.holecards[street][player] = (open, closed)
@ -1110,7 +1111,7 @@ closed likewise, but known only to player
"""\ """\
Add a complete on [street] by [player] to [amountTo] Add a complete on [street] by [player] to [amountTo]
""" """
logging.debug("%s %s completes %s" % (street, player, amountTo)) log.debug("%s %s completes %s" % (street, player, amountTo))
amountTo = re.sub(u',', u'', amountTo) #some sites have commas amountTo = re.sub(u',', u'', amountTo) #some sites have commas
self.checkPlayerExists(player) self.checkPlayerExists(player)
Bp = self.lastBet['THIRD'] Bp = self.lastBet['THIRD']
@ -1128,7 +1129,7 @@ Add a complete on [street] by [player] to [amountTo]
def addBringIn(self, player, bringin): def addBringIn(self, player, bringin):
if player is not None: if player is not None:
logging.debug("Bringin: %s, %s" % (player , bringin)) log.debug("Bringin: %s, %s" % (player , bringin))
self.bets['THIRD'][player].append(Decimal(bringin)) self.bets['THIRD'][player].append(Decimal(bringin))
self.stacks[player] -= Decimal(bringin) self.stacks[player] -= Decimal(bringin)
act = (player, 'bringin', bringin, self.stacks[player]==0) act = (player, 'bringin', bringin, self.stacks[player]==0)

View File

@ -20,7 +20,6 @@ import Hand
import re import re
import sys import sys
import traceback import traceback
import logging
from optparse import OptionParser from optparse import OptionParser
import os import os
import os.path import os.path
@ -31,19 +30,37 @@ import operator
from xml.dom.minidom import Node from xml.dom.minidom import Node
import time import time
import datetime import datetime
from Exceptions import FpdbParseError
import gettext import gettext
gettext.install('fpdb') gettext.install('fpdb')
import logging, logging.config
logging.config.fileConfig("logging.conf")
log = logging.getLogger("parser")
class HandHistoryConverter(): class HandHistoryConverter():
READ_CHUNK_SIZE = 10000 # bytes to read at a time from file (in tail mode) READ_CHUNK_SIZE = 10000 # bytes to read at a time from file in tail mode
def __init__(self, in_path = '-', out_path = '-', sitename = None, follow=False, index=0):
logging.info("HandHistory init") # filetype can be "text" or "xml"
# so far always "text"
# subclass HHC_xml for xml parsing
filetype = "text"
# codepage indicates the encoding of the text file.
# cp1252 is a safe default
# "utf_8" is more likely if there are funny characters
codepage = "cp1252"
def __init__(self, in_path = '-', out_path = '-', follow=False, index=0, autostart=True):
"""\
in_path (default '-' = sys.stdin)
out_path (default '-' = sys.stdout)
follow : whether to tail -f the input"""
log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) )
# default filetype and codepage. Subclasses should set these properly.
self.filetype = "text"
self.codepage = "utf8"
self.index = 0 self.index = 0
self.in_path = in_path self.in_path = in_path
@ -60,54 +77,72 @@ class HandHistoryConverter():
# TODO: out_path should be sanity checked. # TODO: out_path should be sanity checked.
out_dir = os.path.dirname(self.out_path) out_dir = os.path.dirname(self.out_path)
if not os.path.isdir(out_dir): if not os.path.isdir(out_dir):
logging.info("Creatin directory '%s'" % out_dir) log.info("Creating directory '%s'" % out_dir)
os.makedirs(out_dir) os.makedirs(out_dir)
self.out_fh = open(self.out_path, 'w') try:
self.out_fh = open(self.out_path, 'w')
log.debug("out_path %s opened as %s" % (self.out_path, self.out_fh))
except:
log.error("out_path %s couldn't be opened" % (self.out_path))
self.sitename = sitename
self.follow = follow self.follow = follow
self.compiledPlayers = set() self.compiledPlayers = set()
self.maxseats = 10 self.maxseats = 10
if autostart:
self.start()
def __str__(self): def __str__(self):
return """ return """
HandHistoryConverter: '%(sitename)s' HandHistoryConverter: '%(sitename)s'
filetype: '%(filetype)s' filetype '%(filetype)s'
in_path: '%(in_path)s' in_path '%(in_path)s'
out_path: '%(out_path)s' out_path '%(out_path)s'
""" % { 'sitename':self.sitename, 'filetype':self.filetype, 'in_path':self.in_path, 'out_path':self.out_path } follow '%(follow)s'
""" % locals()
def start(self): def start(self):
"""process a hand at a time from the input specified by in_path. """Process a hand at a time from the input specified by in_path.
If in follow mode, wait for more data to turn up. If in follow mode, wait for more data to turn up.
Otherwise, finish at eof. Otherwise, finish at EOF.
""" """
starttime = time.time() starttime = time.time()
if not self.sanityCheck(): if not self.sanityCheck():
print "Cowardly refusing to continue after failed sanity check" log.warning("Failed sanity check")
return return
if self.follow: try:
numHands = 0 numHands = 0
for handText in self.tailHands(): numErrors = 0
numHands+=1 if self.follow:
self.processHand(handText) log.info("Tailing '%s'" % self.in_path)
else: for handText in self.tailHands():
handsList = self.allHandsAsList() try:
logging.info("Parsing %d hands" % len(handsList)) self.processHand(handText)
nBadHangs = 0 numHands+=1
for handText in handsList: except FpdbParseError, e:
try: numErrors+=1
self.processedHands.append(self.processHand(handText)) log.warning("Failed to convert hand %s" % e.hid)
except Exception, e: # TODO: it's better to replace it with s-t like HhcEception log.debug(handText)
nBadHangs += 1 else:
logging.error("Caught exception while parsing hand: %s" % str(e)) handsList = self.allHandsAsList()
numHands = len(handsList) - nBadHangs log.info("Parsing %d hands" % len(handsList))
endtime = time.time() for handText in handsList:
print "read %d hands in %.3f seconds" % (numHands, endtime - starttime) try:
if self.out_fh != sys.stdout: self.processedHands.append(self.processHand(handText))
self.out_fh.close() except FpdbParseError, e:
numErrors+=1
log.warning("Failed to convert hand %s" % e.hid)
log.debug(handText)
numHands = len(handsList)
endtime = time.time()
log.info("Read %d hands (%d failed) in %.3f seconds" % (numHands, numErrors, endtime - starttime))
except IOError, ioe:
log.exception("Error converting '%s'" % self.in_path)
finally:
if self.out_fh != sys.stdout:
self.out_fh.close()
def tailHands(self): def tailHands(self):
@ -134,7 +169,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
time.sleep(interval) time.sleep(interval)
fd.seek(where) fd.seek(where)
else: else:
logging.debug("%s changed inode numbers from %d to %d" % (self.in_path, fd_results[1], st_results[1])) log.debug("%s changed inode numbers from %d to %d" % (self.in_path, fd_results[1], st_results[1]))
fd = codecs.open(self.in_path, 'r', self.codepage) fd = codecs.open(self.in_path, 'r', self.codepage)
fd.seek(where) fd.seek(where)
else: else:
@ -179,13 +214,13 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
self.obs = self.obs.strip() self.obs = self.obs.strip()
self.obs = self.obs.replace('\r\n', '\n') self.obs = self.obs.replace('\r\n', '\n')
if self.obs == "" or self.obs == None: if self.obs == "" or self.obs == None:
logging.info("Read no hands.") log.info("Read no hands.")
return return
return re.split(self.re_SplitHands, self.obs) return re.split(self.re_SplitHands, self.obs)
def processHand(self, handText): def processHand(self, handText):
gametype = self.determineGameType(handText) gametype = self.determineGameType(handText)
logging.debug("gametype %s" % gametype) log.debug("gametype %s" % gametype)
hand = None hand = None
if gametype is None: if gametype is None:
l = None l = None
@ -200,14 +235,14 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
l = [type] + [base] + [limit] l = [type] + [base] + [limit]
if l in self.readSupportedGames(): if l in self.readSupportedGames():
if gametype['base'] == 'hold': if gametype['base'] == 'hold':
logging.debug("hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handtext)") log.debug("hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handtext)")
hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handText) hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handText)
elif gametype['base'] == 'stud': elif gametype['base'] == 'stud':
hand = Hand.StudHand(self, self.sitename, gametype, handText) hand = Hand.StudHand(self, self.sitename, gametype, handText)
elif gametype['base'] == 'draw': elif gametype['base'] == 'draw':
hand = Hand.DrawHand(self, self.sitename, gametype, handText) hand = Hand.DrawHand(self, self.sitename, gametype, handText)
else: else:
logging.info("Unsupported game type: %s" % gametype) log.info("Unsupported game type: %s" % gametype)
if hand: if hand:
# uncomment these to calculate some stats # uncomment these to calculate some stats
@ -216,7 +251,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
hand.writeHand(self.out_fh) hand.writeHand(self.out_fh)
return hand return hand
else: else:
logging.info("Unsupported game type: %s" % gametype) log.info("Unsupported game type: %s" % gametype)
# TODO: pity we don't know the HID at this stage. Log the entire hand? # TODO: pity we don't know the HID at this stage. Log the entire hand?
# From the log we can deduce that it is the hand after the one before :) # From the log we can deduce that it is the hand after the one before :)
@ -342,26 +377,23 @@ or None if we fail to get the info """
return hands return hands
def readFile(self): def readFile(self):
"""open in_path according to self.codepage""" """Open in_path according to self.codepage. Exceptions caught further up"""
if(self.filetype == "text"): if(self.filetype == "text"):
if self.in_path == '-': if self.in_path == '-':
# read from stdin # read from stdin
logging.debug("Reading stdin with %s" % self.codepage) # is this necessary? or possible? or what? log.debug("Reading stdin with %s" % self.codepage) # is this necessary? or possible? or what?
in_fh = codecs.getreader('cp1252')(sys.stdin) in_fh = codecs.getreader('cp1252')(sys.stdin)
else: else:
logging.debug("Opening %s with %s" % (self.in_path, self.codepage))
in_fh = codecs.open(self.in_path, 'r', self.codepage) in_fh = codecs.open(self.in_path, 'r', self.codepage)
in_fh.seek(self.index) in_fh.seek(self.index)
self.obs = in_fh.read() log.debug("Opened in_path: '%s' with %s" % (self.in_path, self.codepage))
self.index = in_fh.tell() self.obs = in_fh.read()
in_fh.close() self.index = in_fh.tell()
in_fh.close()
elif(self.filetype == "xml"): elif(self.filetype == "xml"):
try: doc = xml.dom.minidom.parse(filename)
doc = xml.dom.minidom.parse(filename) self.doc = doc
self.doc = doc
except:
traceback.print_exc(file=sys.stderr)
def guessMaxSeats(self, hand): def guessMaxSeats(self, hand):
"""Return a guess at max_seats when not specified in HH.""" """Return a guess at max_seats when not specified in HH."""

39
pyfpdb/PartyPokerToFpdb.py Normal file → Executable file
View File

@ -43,6 +43,12 @@ class PartyPoker(HandHistoryConverter):
############################################################ ############################################################
# Class Variables # Class Variables
sitename = "PartyPoker"
codepage = "cp1252"
siteId = 9 # TODO: automate; it's a class variable so shouldn't hit DB too often
filetype = "text" # "text" or "xml". I propose we subclass HHC to HHC_Text and HHC_XML.
sym = {'USD': "\$", } sym = {'USD': "\$", }
# Static regexes # Static regexes
@ -97,20 +103,6 @@ class PartyPoker(HandHistoryConverter):
re_NoSmallBlind = re.compile('^There is no Small Blind in this hand as the Big Blind of the previous hand left the table') re_NoSmallBlind = re.compile('^There is no Small Blind in this hand as the Big Blind of the previous hand left the table')
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0):
"""\
in_path (default '-' = sys.stdin)
out_path (default '-' = sys.stdout)
follow : whether to tail -f the input"""
HandHistoryConverter.__init__(self, in_path, out_path, sitename="PartyPoker", follow=follow, index=index)
logging.info("Initialising PartyPoker converter class")
self.filetype = "text"
self.codepage = "cp1252" # FIXME: wtf?
self.siteId = 9 # Needs to match id entry in Sites database
self._gameType = None # cached reg-parse result
if autostart:
self.start()
def allHandsAsList(self): def allHandsAsList(self):
list = HandHistoryConverter.allHandsAsList(self) list = HandHistoryConverter.allHandsAsList(self)
if list is None: if list is None:
@ -135,9 +127,9 @@ follow : whether to tail -f the input"""
'CUR': hand.gametype['currency'] if hand.gametype['currency']!='T$' else ''} 'CUR': hand.gametype['currency'] if hand.gametype['currency']!='T$' else ''}
for key in ('CUR_SYM', 'CUR'): for key in ('CUR_SYM', 'CUR'):
subst[key] = re.escape(subst[key]) subst[key] = re.escape(subst[key])
logging.debug("player_re: " + subst['PLYR']) log.debug("player_re: " + subst['PLYR'])
logging.debug("CUR_SYM: " + subst['CUR_SYM']) log.debug("CUR_SYM: " + subst['CUR_SYM'])
logging.debug("CUR: " + subst['CUR']) log.debug("CUR: " + subst['CUR'])
self.re_PostSB = re.compile( self.re_PostSB = re.compile(
r"^%(PLYR)s posts small blind \[%(CUR_SYM)s(?P<SB>[.0-9]+) ?%(CUR)s\]\." % subst, r"^%(PLYR)s posts small blind \[%(CUR_SYM)s(?P<SB>[.0-9]+) ?%(CUR)s\]\." % subst,
re.MULTILINE) re.MULTILINE)
@ -193,7 +185,7 @@ follow : whether to tail -f the input"""
gametype dict is: gametype dict is:
{'limitType': xxx, 'base': xxx, 'category': xxx}""" {'limitType': xxx, 'base': xxx, 'category': xxx}"""
logging.debug(self.ParsingException().wrapHh( handText )) log.debug(self.ParsingException().wrapHh( handText ))
info = {} info = {}
m = self._getGameType(handText) m = self._getGameType(handText)
@ -266,7 +258,7 @@ follow : whether to tail -f the input"""
#hand.maxseats = ??? #hand.maxseats = ???
hand.mixed = None hand.mixed = None
logging.debug("readHandInfo: %s" % info) log.debug("readHandInfo: %s" % info)
for key in info: for key in info:
if key == 'DATETIME': if key == 'DATETIME':
#Saturday, July 25, 07:53:52 EDT 2009 #Saturday, July 25, 07:53:52 EDT 2009
@ -308,10 +300,10 @@ follow : whether to tail -f the input"""
if m: if m:
hand.buttonpos = int(m.group('BUTTON')) hand.buttonpos = int(m.group('BUTTON'))
else: else:
logging.info('readButton: not found') log.info('readButton: not found')
def readPlayerStacks(self, hand): def readPlayerStacks(self, hand):
logging.debug("readPlayerStacks") log.debug("readPlayerStacks")
m = self.re_PlayerInfo.finditer(hand.handText) m = self.re_PlayerInfo.finditer(hand.handText)
players = [] players = []
for a in m: for a in m:
@ -338,7 +330,7 @@ follow : whether to tail -f the input"""
hand.setCommunityCards(street, renderCards(m.group('CARDS'))) hand.setCommunityCards(street, renderCards(m.group('CARDS')))
def readAntes(self, hand): def readAntes(self, hand):
logging.debug("reading antes") log.debug("reading antes")
m = self.re_Antes.finditer(hand.handText) m = self.re_Antes.finditer(hand.handText)
for player in m: for player in m:
hand.addAnte(player.group('PNAME'), player.group('ANTE')) hand.addAnte(player.group('PNAME'), player.group('ANTE'))
@ -469,7 +461,4 @@ if __name__ == "__main__":
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
#LOG_FILENAME = './logging.out'
logging.basicConfig(level=options.verbosity)
e = PartyPoker(in_path = options.ipath, out_path = options.opath, follow = options.follow) e = PartyPoker(in_path = options.ipath, out_path = options.opath, follow = options.follow)

View File

@ -19,6 +19,7 @@
######################################################################## ########################################################################
# TODO: straighten out discards for draw games # TODO: straighten out discards for draw games
import sys import sys
from HandHistoryConverter import * from HandHistoryConverter import *
@ -26,8 +27,12 @@ from HandHistoryConverter import *
class PokerStars(HandHistoryConverter): class PokerStars(HandHistoryConverter):
############################################################ # Class Variables
# Class Variables
sitename = "PokerStars"
filetype = "text"
codepage = "cp1252"
siteId = 2 # Needs to match id entry in Sites database
mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games
sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\x80", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "\x80", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE
@ -77,20 +82,6 @@ class PokerStars(HandHistoryConverter):
# self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)') # self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0):
"""\
in_path (default '-' = sys.stdin)
out_path (default '-' = sys.stdout)
follow : whether to tail -f the input"""
HandHistoryConverter.__init__(self, in_path, out_path, sitename="PokerStars", follow=follow, index=index)
logging.info("Initialising PokerStars converter class")
self.filetype = "text"
self.codepage = "cp1252"
self.siteId = 2 # Needs to match id entry in Sites database
if autostart:
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'
@ -388,7 +379,4 @@ if __name__ == "__main__":
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
LOG_FILENAME = './logging.out'
logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity)
e = PokerStars(in_path = options.ipath, out_path = options.opath, follow = options.follow) e = PokerStars(in_path = options.ipath, out_path = options.opath, follow = options.follow)

View File

@ -26,6 +26,11 @@ from HandHistoryConverter import *
class Win2day(HandHistoryConverter): class Win2day(HandHistoryConverter):
sitename = "Win2day"
filetype = "text"
codepage = "cp1252"
siteID = 4
# Static regexes # Static regexes
#<HISTORY ID="102271403" SESSION="session31237702.xml" TABLE="Innsbruck 3" GAME="GAME_THM" GAMETYPE="GAMETYPE_REAL" GAMEKIND="GAMEKIND_CASH" TABLECURRENCY="EUR" LIMIT="NL" STAKES="0.25/0.50" DATE="1246909773" WIN="0.00" LOSS="0.50"> #<HISTORY ID="102271403" SESSION="session31237702.xml" TABLE="Innsbruck 3" GAME="GAME_THM" GAMETYPE="GAMETYPE_REAL" GAMEKIND="GAMEKIND_CASH" TABLECURRENCY="EUR" LIMIT="NL" STAKES="0.25/0.50" DATE="1246909773" WIN="0.00" LOSS="0.50">
@ -39,15 +44,6 @@ class Win2day(HandHistoryConverter):
re_Card = re.compile('^<CARD LINK="(?P<CARD>[0-9]+)"></CARD>', re.MULTILINE) re_Card = re.compile('^<CARD LINK="(?P<CARD>[0-9]+)"></CARD>', re.MULTILINE)
re_BoardLast = re.compile('^<CARD LINK="(?P<CARD>[0-9]+)"></CARD></ACTION>', re.MULTILINE) re_BoardLast = re.compile('^<CARD LINK="(?P<CARD>[0-9]+)"></CARD></ACTION>', re.MULTILINE)
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0):
HandHistoryConverter.__init__(self, in_path, out_path, sitename="Win2day", follow=follow, index=index)
logging.info("Initialising Win2day converter class")
self.filetype = "text"
self.codepage = "cp1252"
self.sideID = 4
if autostart:
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])
@ -65,7 +61,7 @@ class Win2day(HandHistoryConverter):
self.re_PostBoth = re.compile(r'^<ACTION TYPE="HAND_BLINDS" PLAYER="%s" KIND="HAND_AB" VALUE="(?P<SBBB>[.0-9]+)"></ACTION>' % player_re, re.MULTILINE) self.re_PostBoth = re.compile(r'^<ACTION TYPE="HAND_BLINDS" PLAYER="%s" KIND="HAND_AB" VALUE="(?P<SBBB>[.0-9]+)"></ACTION>' % player_re, re.MULTILINE)
#r'<ACTION TYPE="HAND_DEAL" PLAYER="%s">\n<CARD LINK="(?P<CARD1>[0-9]+)"></CARD>\n<CARD LINK="(?P<CARD2>[0-9]+)"></CARD></ACTION>' #r'<ACTION TYPE="HAND_DEAL" PLAYER="%s">\n<CARD LINK="(?P<CARD1>[0-9]+)"></CARD>\n<CARD LINK="(?P<CARD2>[0-9]+)"></CARD></ACTION>'
self.re_HeroCards = re.compile(r'<ACTION TYPE="HAND_DEAL" PLAYER="%s">\n(?P<CARDS><CARD LINK="[0-9]+"></CARD>\n<CARD LINK="[0-9]"></CARD>)</ACTION>' % player_re, re.MULTILINE) self.re_HeroCards = re.compile(r'<ACTION TYPE="HAND_DEAL" PLAYER="%s">\n(?P<CARDS><CARD LINK="[0-9]+"></CARD>\n<CARD LINK="[0-9]+"></CARD>)</ACTION>' % player_re, re.MULTILINE)
#'^<ACTION TYPE="(?P<ATYPE>[_A-Z]+)" PLAYER="%s"( VALUE="(?P<BET>[.0-9]+)")?></ACTION>' #'^<ACTION TYPE="(?P<ATYPE>[_A-Z]+)" PLAYER="%s"( VALUE="(?P<BET>[.0-9]+)")?></ACTION>'
self.re_Action = re.compile(r'^<ACTION TYPE="(?P<ATYPE>[_A-Z]+)" PLAYER="%s"( VALUE="(?P<BET>[.0-9]+)")?></ACTION>' % player_re, re.MULTILINE) self.re_Action = re.compile(r'^<ACTION TYPE="(?P<ATYPE>[_A-Z]+)" PLAYER="%s"( VALUE="(?P<BET>[.0-9]+)")?></ACTION>' % player_re, re.MULTILINE)

40
pyfpdb/logging.conf Normal file
View File

@ -0,0 +1,40 @@
[loggers]
keys=root,parser
[handlers]
keys=consoleHandler,fileHandler
[formatters]
keys=fileFormatter,stderrFormatter
[logger_root]
level=INFO
handlers=consoleHandler,fileHandler
[logger_parser]
level=INFO
# set to NOTSET or DEBUG to see everything the parser does
handlers=consoleHandler,fileHandler
qualname=parser
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=INFO
formatter=stderrFormatter
args=(sys.stderr,)
[handler_fileHandler]
class=FileHandler
level=INFO
formatter=fileFormatter
args=('logging.out', 'a')
[formatter_fileFormatter]
format=%(asctime)s - %(name)-12s %(levelname)-8s %(message)s
datefmt=
[formatter_stderrFormatter]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt=

View File

@ -4,7 +4,12 @@ import py
# regression-test-files/fulltilt/nlhe/NLHE-6max-1.txt # regression-test-files/fulltilt/nlhe/NLHE-6max-1.txt
# Sorrowful: start: $8.85 end: $14.70 total: $5.85 # Sorrowful: start: $8.85 end: $14.70 total: $5.85
# 'Canceled' hand
# regression-test-files/fulltilt/lh/Marlin.txt
def checkGameInfo(hhc, header, info): def checkGameInfo(hhc, header, info):
assert hhc.determineGameType(header) == info assert hhc.determineGameType(header) == info

View File

@ -14,7 +14,7 @@ text = ""
hhc = PokerStarsToFpdb.PokerStars(autostart=False) hhc = PokerStarsToFpdb.PokerStars(autostart=False)
h = HoldemOmahaHand(None, "ASite", gametype, text, builtFrom = "Test") h = HoldemOmahaHand(None, "PokerStars", gametype, text, builtFrom = "Test")
h.addPlayer("1", "s0rrow", "100000") h.addPlayer("1", "s0rrow", "100000")
hhc.compilePlayerRegexs(h) hhc.compilePlayerRegexs(h)