message
This commit is contained in:
parent
426b5c2db5
commit
ca6f6e513b
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: iso-8859-15 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2008, Carl Gherardi
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
@ -27,16 +27,16 @@ class Everleaf(HandHistoryConverter):
|
|||
|
||||
# Static regexes
|
||||
re_SplitHands = re.compile(r"\n\n+")
|
||||
re_GameInfo = re.compile(r"^(Blinds )?\$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) ((?P<LTYPE>NL|PL) )?(?P<GAME>(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE)
|
||||
re_HandInfo = re.compile(r".*#(?P<HID>[0-9]+)\n.*\n(Blinds )?\$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)")
|
||||
re_GameInfo = re.compile(u"^(Blinds )?(?P<currency>\$| €|)(?P<sb>[.0-9]+)/(?:\$| €)?(?P<bb>[.0-9]+) (?P<limit>NL|PL|) (?P<game>(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE)
|
||||
re_HandInfo = re.compile(u".*#(?P<HID>[0-9]+)\n.*\n(Blinds )?(?:\$| €|)(?P<SB>[.0-9]+)/(?:\$| €|)(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)")
|
||||
# re_GameInfo = re.compile(r".*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<LTYPE>(NL|PL)) (?P<GAME>(Hold\'em|Omaha|7 Card Stud))")
|
||||
#re_HandInfo = re.compile(r".*#(?P<HID>[0-9]+)\n.*\nBlinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>[- a-zA-Z]+)", re.MULTILINE)
|
||||
re_Button = re.compile(r"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
|
||||
re_PlayerInfo = re.compile(r"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+(\$ (?P<CASH>[.0-9]+) USD|new player|All-in) \)", re.MULTILINE)
|
||||
re_PlayerInfo = re.compile(u"^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\s+((?:\$| €|) (?P<CASH>[.0-9]+) (USD|EUR|)|new player|All-in) \)", re.MULTILINE)
|
||||
re_Board = re.compile(r"\[ (?P<CARDS>.+) \]")
|
||||
|
||||
|
||||
def __init__(self, in_path = '-', out_path = '-', follow = False):
|
||||
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True):
|
||||
"""\
|
||||
in_path (default '-' = sys.stdin)
|
||||
out_path (default '-' = sys.stdout)
|
||||
|
@ -45,23 +45,24 @@ follow : whether to tail -f the input"""
|
|||
logging.info("Initialising Everleaf converter class")
|
||||
self.filetype = "text"
|
||||
self.codepage = "cp1252"
|
||||
self.start()
|
||||
# TODO: It's not clear that init should start the thread.
|
||||
if autostart:
|
||||
self.start()
|
||||
|
||||
def compilePlayerRegexs(self, players):
|
||||
def compilePlayerRegexs(self, hand):
|
||||
players = set([player[1] for player in hand.players])
|
||||
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
|
||||
# we need to recompile the player regexs.
|
||||
self.compiledPlayers = players
|
||||
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
|
||||
logging.debug("player_re: "+ player_re)
|
||||
self.re_PostSB = re.compile(r"^%s: posts small blind \[\$? (?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_PostBB = re.compile(r"^%s: posts big blind \[\$? (?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_PostBoth = re.compile(r"^%s: posts both blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_HeroCards = re.compile(r"^Dealt to %s \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
|
||||
self.re_Action = re.compile(r"^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[\$ (?P<BET>[.\d]+) (USD|EUR)\])?" % player_re, re.MULTILINE)
|
||||
self.re_ShowdownAction = re.compile(r"^%s shows \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
|
||||
self.re_CollectPot = re.compile(r"^%s wins \$ (?P<POT>[.\d]+) (USD|EUR)(.*?\[ (?P<CARDS>.*?) \])?" % player_re, re.MULTILINE)
|
||||
self.re_SitsOut = re.compile(r"^%s sits out" % player_re, re.MULTILINE)
|
||||
self.re_PostSB = re.compile(u"^%s: posts small blind \[(?:\$| €|) (?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_PostBB = re.compile(u"^%s: posts big blind \[(?:\$| €|) (?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_PostBoth = re.compile(u"^%s: posts both blinds \[(?:\$| €|) (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_HeroCards = re.compile(u"^Dealt to %s \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
|
||||
self.re_Action = re.compile(u"^%s(?P<ATYPE>: bets| checks| raises| calls| folds)(\s\[(?:\$| €|) (?P<BET>[.\d]+) (USD|EUR|)\])?" % player_re, re.MULTILINE)
|
||||
self.re_ShowdownAction = re.compile(u"^%s shows \[ (?P<CARDS>.*) \]" % player_re, re.MULTILINE)
|
||||
self.re_CollectPot = re.compile(u"^%s wins (?:\$| €|) (?P<POT>[.\d]+) (USD|EUR|chips)(.*?\[ (?P<CARDS>.*?) \])?" % player_re, re.MULTILINE)
|
||||
self.re_SitsOut = re.compile(u"^%s sits out" % player_re, re.MULTILINE)
|
||||
|
||||
def readSupportedGames(self):
|
||||
return [["ring", "hold", "nl"],
|
||||
|
@ -71,6 +72,33 @@ follow : whether to tail -f the input"""
|
|||
]
|
||||
|
||||
def determineGameType(self, handText):
|
||||
info = {}
|
||||
|
||||
m = self.re_GameInfo.search(handText)
|
||||
if not m:
|
||||
return None
|
||||
|
||||
info.update(m.groupdict())
|
||||
|
||||
limits = { 'NL':'nl', 'PL':'pl', '':'fl' }
|
||||
games = { 'Hold\'em':'hold', 'Omaha':'omahahi', 'Razz':'razz','7 Card Stud':'studhi' }
|
||||
currencies = { u' €':'EUR', '$':'USD', '':'T$' }
|
||||
for key in info:
|
||||
if key == 'limit':
|
||||
info[key] = limits[info[key]]
|
||||
if key == 'game':
|
||||
info[key] = games[info[key]]
|
||||
if key == 'sb':
|
||||
pass
|
||||
if key == 'bb':
|
||||
pass
|
||||
if key == 'currency':
|
||||
info[key] = currencies[info[key]]
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def determineGameType2(self, handText):
|
||||
# Cheating with this regex, only support nlhe at the moment
|
||||
# Blinds $0.50/$1 PL Omaha - 2008/12/07 - 21:59:48
|
||||
# Blinds $0.05/$0.10 NL Hold'em - 2009/02/21 - 11:21:57
|
||||
|
@ -84,7 +112,8 @@ follow : whether to tail -f the input"""
|
|||
|
||||
structure = "" # nl, pl, cn, cp, fl
|
||||
game = ""
|
||||
|
||||
currency = "USD" # USD, EUR
|
||||
|
||||
m = self.re_GameInfo.search(handText)
|
||||
if m == None:
|
||||
logging.debug("Gametype didn't match")
|
||||
|
@ -103,7 +132,7 @@ follow : whether to tail -f the input"""
|
|||
elif m.group('GAME') == "7 Card Stud":
|
||||
game = "studhi" # Everleaf currently only does Hi stud
|
||||
|
||||
gametype = ["ring", game, structure, m.group('SB'), m.group('BB')]
|
||||
gametype = ["ring", game, structure, m.group('SB'), m.group('BB'), currency]
|
||||
|
||||
return gametype
|
||||
|
||||
|
@ -111,7 +140,7 @@ follow : whether to tail -f the input"""
|
|||
m = self.re_HandInfo.search(hand.handText)
|
||||
if(m == None):
|
||||
logging.info("Didn't match re_HandInfo")
|
||||
logging.info(hand.handtext)
|
||||
logging.info(hand.handText)
|
||||
return None
|
||||
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
|
||||
hand.handid = m.group('HID')
|
||||
|
|
|
@ -31,7 +31,7 @@ class FullTilt(HandHistoryConverter):
|
|||
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
|
||||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
|
||||
def __init__(self, in_path = '-', out_path = '-', follow = False):
|
||||
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True):
|
||||
"""\
|
||||
in_path (default '-' = sys.stdin)
|
||||
out_path (default '-' = sys.stdout)
|
||||
|
@ -40,7 +40,9 @@ follow : whether to tail -f the input"""
|
|||
logging.info("Initialising FullTilt converter class")
|
||||
self.filetype = "text"
|
||||
self.codepage = "cp1252"
|
||||
self.start()
|
||||
if autostart:
|
||||
self.start()
|
||||
|
||||
|
||||
def compilePlayerRegexs(self, players):
|
||||
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
|
||||
|
|
|
@ -314,7 +314,7 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
|||
}
|
||||
|
||||
logging.debug("gametype: %s" %(self.gametype))
|
||||
retstring = "%s %s" %(gs[self.gametype[1]], ls[self.gametype[2]])
|
||||
retstring = "%s %s" %(gs[self.gametype['game']], ls[self.gametype['limit']])
|
||||
|
||||
return retstring
|
||||
|
||||
|
@ -363,22 +363,22 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
|||
|
||||
class HoldemOmahaHand(Hand):
|
||||
def __init__(self, hhc, sitename, gametype, handText):
|
||||
if gametype[1] not in ["hold","omaha"]:
|
||||
if gametype['game'] not in ["hold","omaha"]:
|
||||
pass # or indeed don't pass and complain instead
|
||||
logging.debug("HoldemOmahaHand")
|
||||
self.streetList = ['BLINDSANTES', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order
|
||||
self.communityStreets = ['FLOP', 'TURN', 'RIVER']
|
||||
self.actionStreets = ['PREFLOP','FLOP','TURN','RIVER']
|
||||
Hand.__init__(self, sitename, gametype, handText)
|
||||
self.sb = gametype[3]
|
||||
self.bb = gametype[4]
|
||||
self.sb = gametype['sb']
|
||||
self.bb = gametype['bb']
|
||||
|
||||
#Populate a HoldemOmahaHand
|
||||
#Generally, we call 'read' methods here, which get the info according to the particular filter (hhc)
|
||||
# which then invokes a 'addXXX' callback
|
||||
hhc.readHandInfo(self)
|
||||
hhc.readPlayerStacks(self)
|
||||
hhc.compilePlayerRegexs(players = set([player[1] for player in self.players]))
|
||||
hhc.compilePlayerRegexs(self)
|
||||
hhc.markStreets(self)
|
||||
hhc.readBlinds(self)
|
||||
hhc.readButton(self)
|
||||
|
@ -441,7 +441,7 @@ Card ranks will be uppercased
|
|||
|
||||
|
||||
#May be more than 1 bb posting
|
||||
if self.gametype[2] == "fl":
|
||||
if self.gametype['limit'] == "fl":
|
||||
(smallbet, bigbet) = self.lookupLimitBetSize()
|
||||
else:
|
||||
smallbet = self.sb
|
||||
|
@ -533,7 +533,7 @@ Card ranks will be uppercased
|
|||
|
||||
class DrawHand(Hand):
|
||||
def __init__(self, hhc, sitename, gametype, handText):
|
||||
if gametype[1] not in ["badugi","5-card-draw"]:
|
||||
if gametype['game'] not in ["badugi","5-card-draw"]:
|
||||
pass # or indeed don't pass and complain instead
|
||||
|
||||
def discardHoleCards(self, cards, player):
|
||||
|
@ -548,19 +548,19 @@ class DrawHand(Hand):
|
|||
|
||||
class StudHand(Hand):
|
||||
def __init__(self, hhc, sitename, gametype, handText):
|
||||
if gametype[1] not in ["razz","stud","stud8"]:
|
||||
if gametype['game'] not in ["razz","stud","stud8"]:
|
||||
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.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH']
|
||||
Hand.__init__(self, sitename, gametype, handText)
|
||||
self.sb = gametype[3]
|
||||
self.bb = gametype[4]
|
||||
self.sb = gametype['sb']
|
||||
self.bb = gametype['bb']
|
||||
#Populate the StudHand
|
||||
#Generally, we call a 'read' method here, which gets the info according to the particular filter (hhc)
|
||||
# which then invokes a 'addXXX' callback
|
||||
hhc.readHandInfo(self)
|
||||
hhc.readPlayerStacks(self)
|
||||
hhc.compilePlayerRegexs(players = set([player[1] for player in self.players]))
|
||||
hhc.compilePlayerRegexs(self)
|
||||
hhc.markStreets(self)
|
||||
hhc.readAntes(self)
|
||||
hhc.readBringIn(self)
|
||||
|
|
|
@ -88,7 +88,7 @@ class HandHistoryConverter(threading.Thread):
|
|||
# write to stdout
|
||||
self.out_fh = sys.stdout
|
||||
else:
|
||||
self.out_fh = open(self.out_path, 'a')
|
||||
self.out_fh = open(self.out_path, 'a') #TODO: append may be overly conservative.
|
||||
self.sitename = sitename
|
||||
self.follow = follow
|
||||
self.compiledPlayers = set()
|
||||
|
@ -117,6 +117,8 @@ class HandHistoryConverter(threading.Thread):
|
|||
logging.info("Parsing %d hands" % len(handsList))
|
||||
for handtext in handsList:
|
||||
self.processHand(handtext)
|
||||
if self.out_fh != sys.stdout:
|
||||
self.ouf_fh.close()
|
||||
|
||||
def tailHands(self):
|
||||
"""pseudo-code"""
|
||||
|
@ -141,19 +143,20 @@ class HandHistoryConverter(threading.Thread):
|
|||
|
||||
def processHand(self, handtext):
|
||||
gametype = self.determineGameType(handtext)
|
||||
logging.debug("gametype %s" % gametype)
|
||||
if gametype is None:
|
||||
return
|
||||
|
||||
hand = None
|
||||
if gametype[1] in ("hold", "omaha"):
|
||||
if gametype['game'] in ("hold", "omaha"):
|
||||
hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handtext)
|
||||
elif gametype[1] in ("razz","stud","stud8"):
|
||||
elif gametype['game'] in ("razz","stud","stud8"):
|
||||
hand = Hand.StudHand(self, self.sitename, gametype, handtext)
|
||||
|
||||
if hand:
|
||||
hand.writeHand(self.out_fh)
|
||||
else:
|
||||
logging.info("Unrecognised game type: %s" % gametype[1])
|
||||
logging.info("Unsupported game type: %s" % gametype)
|
||||
# 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 :)
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ class PokerStars(HandHistoryConverter):
|
|||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
# 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):
|
||||
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True):
|
||||
"""\
|
||||
in_path (default '-' = sys.stdin)
|
||||
out_path (default '-' = sys.stdout)
|
||||
|
@ -84,7 +84,8 @@ follow : whether to tail -f the input"""
|
|||
logging.info("Initialising PokerStars converter class")
|
||||
self.filetype = "text"
|
||||
self.codepage = "cp1252"
|
||||
self.start()
|
||||
if autostart:
|
||||
self.start()
|
||||
|
||||
|
||||
def compilePlayerRegexs(self, players):
|
||||
|
|
|
@ -231,7 +231,7 @@ class Importer:
|
|||
|
||||
# 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,
|
||||
# someone can just create their own python module for it
|
||||
if filter == "EverleafToFpdb":
|
||||
if filter in ("EverleafToFpdb","Everleaf"):
|
||||
print "converting ", file
|
||||
hhbase = self.config.get_import_parameters().get("hhArchiveBase")
|
||||
hhbase = os.path.expanduser(hhbase)
|
||||
|
|
36
pyfpdb/test_Everleaf.py
Normal file
36
pyfpdb/test_Everleaf.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import EverleafToFpdb
|
||||
import py
|
||||
class TestEverleaf:
|
||||
def testGameInfo1(self):
|
||||
e = EverleafToFpdb.Everleaf(autostart=False)
|
||||
g = """Everleaf Gaming Game #3732225
|
||||
***** Hand history for game #3732225 *****
|
||||
Blinds €0.50/ €1 NL Hold'em - 2009/01/11 - 16:09:40
|
||||
Table Casino Lyon Vert 58
|
||||
Seat 3 is the button
|
||||
Total number of players: 6"""
|
||||
assert e.determineGameType(g) == {'sb':'0.50', 'bb':'1','game':"hold", 'currency':'EUR', 'limit':'nl'}
|
||||
|
||||
|
||||
def testGameInfo2(self):
|
||||
e = EverleafToFpdb.Everleaf(autostart=False)
|
||||
g = """Everleaf Gaming Game #55198191
|
||||
***** Hand history for game #55198191 *****
|
||||
Blinds $0.50/$1 NL Hold'em - 2008/09/01 - 10:02:11
|
||||
Table Speed Kuala
|
||||
Seat 8 is the button
|
||||
Total number of players: 10"""
|
||||
assert e.determineGameType(g) == {'sb':'0.50', 'bb':'1','game':"hold", 'currency':'USD', 'limit':'nl'}
|
||||
|
||||
def testGameInfo3(self):
|
||||
# Note: It looks difficult to distinguish T$ from play money.
|
||||
e = EverleafToFpdb.Everleaf(autostart=False)
|
||||
g = """Everleaf Gaming Game #75065769
|
||||
***** Hand history for game #75065769 *****
|
||||
Blinds 10/20 NL Hold'em - 2009/02/25 - 17:30:32
|
||||
Table 2
|
||||
Seat 1 is the button
|
||||
Total number of players: 10"""
|
||||
assert e.determineGameType(g) == {'sb':'10', 'bb':'20','game':"hold", 'currency':'T$', 'limit':'nl'}
|
||||
|
Loading…
Reference in New Issue
Block a user