Merge branch 'carl'
This commit is contained in:
commit
ee7fc47dc1
|
@ -44,8 +44,9 @@ class Betfair(HandHistoryConverter):
|
||||||
siteId = 7 # Needs to match id entry in Sites database
|
siteId = 7 # Needs to match id entry in Sites database
|
||||||
|
|
||||||
# Static regexes
|
# Static regexes
|
||||||
|
#re_SplitHands = re.compile(r'\n\n+') # Betfair 1.0 version
|
||||||
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'End of hand .{2}-\d{7,9}-\d+ \*\*\*\*\*\n')
|
||||||
re_HandInfo = re.compile("\*\*\*\*\* Betfair Poker Hand History for Game (?P<HID>[0-9]+) \*\*\*\*\*\n(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>(Texas Hold\'em|Omaha Hi|Razz)) - (?P<DATETIME>[a-zA-Z]+, [a-zA-Z]+ \d+, \d\d:\d\d:\d\d GMT \d\d\d\d)\nTable (?P<TABLE>[ a-zA-Z0-9]+) \d-max \(Real Money\)\nSeat (?P<BUTTON>[0-9]+)", re.MULTILINE)
|
re_HandInfo = re.compile("\*\*\*\*\* Betfair Poker Hand History for Game (?P<HID>[0-9]+) \*\*\*\*\*\n(?P<LIMIT>NL|PL|) (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (?P<GAMETYPE>(Texas Hold\'em|Omaha Hi|Razz)) - (?P<DATETIME>[a-zA-Z]+, [a-zA-Z]+ \d+, \d\d:\d\d:\d\d GMT \d\d\d\d)\nTable (?P<TABLE>[ a-zA-Z0-9]+) \d-max \(Real Money\)\nSeat (?P<BUTTON>[0-9]+)", re.MULTILINE)
|
||||||
re_Button = re.compile(ur"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
|
re_Button = re.compile(ur"^Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
|
||||||
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]+)) \)")
|
||||||
|
|
|
@ -326,33 +326,104 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
|
||||||
or None if we fail to get the info """
|
or None if we fail to get the info """
|
||||||
#TODO: which parts are optional/required?
|
#TODO: which parts are optional/required?
|
||||||
|
|
||||||
# Read any of:
|
|
||||||
# HID HandID
|
|
||||||
# TABLE Table name
|
|
||||||
# SB small blind
|
|
||||||
# BB big blind
|
|
||||||
# GAMETYPE gametype
|
|
||||||
# YEAR MON DAY HR MIN SEC datetime
|
|
||||||
# BUTTON button seat number
|
|
||||||
def readHandInfo(self, hand): abstract
|
def readHandInfo(self, hand): abstract
|
||||||
|
"""Read and set information about the hand being dealt, and set the correct
|
||||||
|
variables in the Hand object 'hand
|
||||||
|
|
||||||
|
* hand.startTime - a datetime object
|
||||||
|
* hand.handid - The site identified for the hand - a string.
|
||||||
|
* hand.tablename
|
||||||
|
* hand.buttonpos
|
||||||
|
* hand.maxseats
|
||||||
|
* hand.mixed
|
||||||
|
|
||||||
|
Tournament fields:
|
||||||
|
|
||||||
|
* hand.tourNo - The site identified tournament id as appropriate - a string.
|
||||||
|
* hand.buyin
|
||||||
|
* hand.fee
|
||||||
|
* hand.buyinCurrency
|
||||||
|
* hand.koBounty
|
||||||
|
* hand.isKO
|
||||||
|
* hand.level
|
||||||
|
"""
|
||||||
|
#TODO: which parts are optional/required?
|
||||||
|
|
||||||
# Needs to return a list of lists in the format
|
|
||||||
# [['seat#', 'player1name', 'stacksize'] ['seat#', 'player2name', 'stacksize'] [...]]
|
|
||||||
def readPlayerStacks(self, hand): abstract
|
def readPlayerStacks(self, hand): abstract
|
||||||
|
"""This function is for identifying players at the table, and to pass the
|
||||||
|
information on to 'hand' via Hand.addPlayer(seat, name, chips)
|
||||||
|
|
||||||
|
At the time of writing the reference function in the PS converter is:
|
||||||
|
log.debug("readPlayerStacks")
|
||||||
|
m = self.re_PlayerInfo.finditer(hand.handText)
|
||||||
|
for a in m:
|
||||||
|
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
|
||||||
|
|
||||||
|
Which is pretty simple because the hand history format is consistent. Other hh formats aren't so nice.
|
||||||
|
|
||||||
|
This is the appropriate place to identify players that are sitting out and ignore them
|
||||||
|
|
||||||
|
*** NOTE: You may find this is a more appropriate place to set hand.maxseats ***
|
||||||
|
"""
|
||||||
|
|
||||||
def compilePlayerRegexs(self): abstract
|
def compilePlayerRegexs(self): abstract
|
||||||
"""Compile dynamic regexes -- these explicitly match known player names and must be updated if a new player joins"""
|
"""Compile dynamic regexes -- compile player dependent regexes.
|
||||||
|
|
||||||
|
Depending on the ambiguity of lines you may need to match, and the complexity of
|
||||||
|
player names - we found that we needed to recompile some regexes for player actions so that they actually contained the player names.
|
||||||
|
|
||||||
|
eg.
|
||||||
|
We need to match the ante line:
|
||||||
|
<Player> antes $1.00
|
||||||
|
|
||||||
|
But <Player> is actually named
|
||||||
|
|
||||||
|
YesI antes $4000 - A perfectly legal playername
|
||||||
|
|
||||||
|
Giving:
|
||||||
|
|
||||||
|
YesI antes $4000 antes $1.00
|
||||||
|
|
||||||
|
Which without care in your regexes most people would match 'YesI' and not 'YesI antes $4000'
|
||||||
|
"""
|
||||||
|
|
||||||
# Needs to return a MatchObject with group names identifying the streets into the Hand object
|
# Needs to return a MatchObject with group names identifying the streets into the Hand object
|
||||||
# so groups are called by street names 'PREFLOP', 'FLOP', 'STREET2' etc
|
# so groups are called by street names 'PREFLOP', 'FLOP', 'STREET2' etc
|
||||||
# blinds are done seperately
|
# blinds are done seperately
|
||||||
def markStreets(self, hand): abstract
|
def markStreets(self, hand): abstract
|
||||||
|
"""For dividing the handText into sections.
|
||||||
|
|
||||||
|
The function requires you to pass a MatchObject with groups specifically labeled with
|
||||||
|
the 'correct' street names.
|
||||||
|
|
||||||
|
The Hand object will use the various matches for assigning actions to the correct streets.
|
||||||
|
|
||||||
|
Flop Based Games:
|
||||||
|
PREFLOP, FLOP, TURN, RIVER
|
||||||
|
|
||||||
|
Draw Based Games:
|
||||||
|
PREDEAL, DEAL, DRAWONE, DRAWTWO, DRAWTHREE
|
||||||
|
|
||||||
|
Stud Based Games:
|
||||||
|
ANTES, THIRD, FOURTH, FIFTH, SIXTH, SEVENTH
|
||||||
|
|
||||||
|
The Stars HHC has a good reference implementation
|
||||||
|
"""
|
||||||
|
|
||||||
#Needs to return a list in the format
|
#Needs to return a list in the format
|
||||||
# ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb,
|
# ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb,
|
||||||
# addtional players are assumed to post a bb oop
|
# addtional players are assumed to post a bb oop
|
||||||
def readBlinds(self, hand): abstract
|
def readBlinds(self, hand): abstract
|
||||||
|
"""Function for reading the various blinds from the hand history.
|
||||||
|
|
||||||
|
Pass any small blind to hand.addBlind(<name>, "small blind", <value>)
|
||||||
|
- unless it is a single dead small blind then use:
|
||||||
|
hand.addBlind(<name>, 'secondsb', <value>)
|
||||||
|
Pass any big blind to hand.addBlind(<name>, "big blind", <value>)
|
||||||
|
Pass any play posting both big and small blinds to hand.addBlind(<name>, 'both', <vale>)
|
||||||
|
"""
|
||||||
def readAntes(self, hand): abstract
|
def readAntes(self, hand): abstract
|
||||||
|
"""Function for reading the antes from the hand history and passing the hand.addAnte"""
|
||||||
def readBringIn(self, hand): abstract
|
def readBringIn(self, hand): abstract
|
||||||
def readButton(self, hand): abstract
|
def readButton(self, hand): abstract
|
||||||
def readHeroCards(self, hand): abstract
|
def readHeroCards(self, hand): abstract
|
||||||
|
@ -409,18 +480,6 @@ or None if we fail to get the info """
|
||||||
self.filetype = filetype
|
self.filetype = filetype
|
||||||
self.codepage = codepage
|
self.codepage = codepage
|
||||||
|
|
||||||
#This function doesn't appear to be used
|
|
||||||
def splitFileIntoHands(self):
|
|
||||||
hands = []
|
|
||||||
self.obs = self.obs.strip()
|
|
||||||
list = self.re_SplitHands.split(self.obs)
|
|
||||||
list.pop() #Last entry is empty
|
|
||||||
for l in list:
|
|
||||||
# print "'" + l + "'"
|
|
||||||
hands = hands + [Hand.Hand(self.config, self.sitename, self.gametype, l)]
|
|
||||||
# TODO: This looks like it could be replaced with a list comp.. ?
|
|
||||||
return hands
|
|
||||||
|
|
||||||
def __listof(self, x):
|
def __listof(self, x):
|
||||||
if isinstance(x, list) or isinstance(x, tuple):
|
if isinstance(x, list) or isinstance(x, tuple):
|
||||||
return x
|
return x
|
||||||
|
|
|
@ -43,45 +43,101 @@ class OnGame(HandHistoryConverter):
|
||||||
codepage = ("utf8", "cp1252")
|
codepage = ("utf8", "cp1252")
|
||||||
siteId = 5 # Needs to match id entry in Sites database
|
siteId = 5 # Needs to match id entry in Sites database
|
||||||
|
|
||||||
|
substitutions = {
|
||||||
|
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
|
||||||
|
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
|
||||||
|
}
|
||||||
|
|
||||||
|
limits = { 'NO_LIMIT':'nl', 'LIMIT':'fl'}
|
||||||
|
|
||||||
|
games = { # base, category
|
||||||
|
"TEXAS_HOLDEM" : ('hold','holdem'),
|
||||||
|
# 'Omaha' : ('hold','omahahi'),
|
||||||
|
# 'Omaha Hi/Lo' : ('hold','omahahilo'),
|
||||||
|
# 'Razz' : ('stud','razz'),
|
||||||
|
# 'RAZZ' : ('stud','razz'),
|
||||||
|
# '7 Card Stud' : ('stud','studhi'),
|
||||||
|
# '7 Card Stud Hi/Lo' : ('stud','studhilo'),
|
||||||
|
# 'Badugi' : ('draw','badugi'),
|
||||||
|
# 'Triple Draw 2-7 Lowball' : ('draw','27_3draw'),
|
||||||
|
# '5 Card Draw' : ('draw','fivedraw')
|
||||||
|
}
|
||||||
|
|
||||||
#self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)')
|
#self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)')
|
||||||
# Static regexes
|
# Static regexes
|
||||||
re_SplitHands = re.compile('\n\n\n+')
|
re_SplitHands = re.compile(r'End of hand .{2}-\d{7,9}-\d+ \*\*\*\*\*\n')
|
||||||
|
|
||||||
#Texas Hold'em $.5-$1 NL (real money), hand #P4-76915775-797
|
# ***** History for hand R5-75443872-57 *****
|
||||||
#Table Kuopio, 20 Sep 2008 11:59 PM
|
# Start hand: Wed Aug 18 19:29:10 GMT+0100 2010
|
||||||
re_HandInfo = re.compile(r"Texas Hold'em \$?(?P<SB>[.0-9]+)-\$?(?P<BB>[.0-9]+) NL \(real money\), hand #(?P<HID>[-A-Z\d]+)\nTable\ (?P<TABLE>[\' \w]+), (?P<DATETIME>\d\d \w+ \d\d\d\d \d\d:\d\d (AM|PM))")
|
# Table: someplace [75443872] (LIMIT TEXAS_HOLDEM 0.50/1, Real money)
|
||||||
# SB BB HID TABLE DAY MON YEAR HR12 MIN AMPM
|
re_HandInfo = re.compile(u"""
|
||||||
|
\*\*\*\*\*\sHistory\sfor\shand\s(?P<HID>[-A-Z\d]+).*
|
||||||
|
Start\shand:\s(?P<DATETIME>.*)
|
||||||
|
Table:\s(?P<TABLE>[\'\w]+)\s\[\d+\]\s\(
|
||||||
|
(
|
||||||
|
(?P<LIMIT>No\sLimit|Limit|LIMIT|Pot\sLimit)\s
|
||||||
|
(?P<GAME>TEXAS_HOLDEM|RAZZ)\s
|
||||||
|
(?P<SB>[.0-9]+)/
|
||||||
|
(?P<BB>[.0-9]+)
|
||||||
|
)?
|
||||||
|
""" % substitutions, re.MULTILINE|re.DOTALL|re.VERBOSE)
|
||||||
|
|
||||||
|
# Wed Aug 18 19:45:30 GMT+0100 2010
|
||||||
|
re_DateTime = re.compile("""
|
||||||
|
[a-zA-Z]{3}\s
|
||||||
|
(?P<M>[a-zA-Z]{3})\s
|
||||||
|
(?P<D>[0-9]{2})\s
|
||||||
|
(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)\sGMT
|
||||||
|
(?P<OFFSET>[-+]\d+)\s
|
||||||
|
(?P<Y>[0-9]{4})
|
||||||
|
""", re.MULTILINE|re.VERBOSE)
|
||||||
|
|
||||||
# self.rexx.button_re = re.compile('#SUMMARY\nDealer: (?P<BUTTONPNAME>.*)\n')
|
# self.rexx.button_re = re.compile('#SUMMARY\nDealer: (?P<BUTTONPNAME>.*)\n')
|
||||||
|
|
||||||
#Seat 1: .Lucchess ($4.17 in chips)
|
#Seat 1: .Lucchess ($4.17 in chips)
|
||||||
re_PlayerInfo = re.compile(u'Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \((\$(?P<CASH>[.0-9]+) in chips)\)')
|
re_PlayerInfo = re.compile(u'Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \((?P<CASH>[.0-9]+) \)')
|
||||||
|
|
||||||
#ANTES/BLINDS
|
def compilePlayerRegexs(self, hand):
|
||||||
#helander2222 posts blind ($0.25), lopllopl posts blind ($0.50).
|
players = set([player[1] for player in hand.players])
|
||||||
re_PostSB = re.compile('(?P<PNAME>.*) posts blind \(\$?(?P<SB>[.0-9]+)\), ')
|
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
|
||||||
re_PostBB = re.compile('\), (?P<PNAME>.*) posts blind \(\$?(?P<BB>[.0-9]+)\).')
|
# we need to recompile the player regexs.
|
||||||
re_PostBoth = re.compile('.*\n(?P<PNAME>.*): posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
|
# TODO: should probably rename re_HeroCards and corresponding method,
|
||||||
re_HeroCards = re.compile('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<CARDS>.*) \]')
|
# since they are used to find all cards on lines starting with "Dealt to:"
|
||||||
|
# They still identify the hero.
|
||||||
#lopllopl checks, Eurolll checks, .Lucchess checks.
|
|
||||||
re_Action = re.compile('(, )?(?P<PNAME>.*?)(?P<ATYPE> bets| checks| raises| calls| folds)( \$(?P<BET>\d*\.?\d*))?( and is all-in)?')
|
#ANTES/BLINDS
|
||||||
re_Board = re.compile(r"\[board cards (?P<CARDS>.+) \]")
|
#helander2222 posts blind ($0.25), lopllopl posts blind ($0.50).
|
||||||
|
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
|
||||||
#Uchilka shows [ KC,JD ]
|
subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]}
|
||||||
re_ShowdownAction = re.compile('(?P<PNAME>.*) shows \[ (?P<CARDS>.+) \]')
|
re_PostSB = re.compile('(?P<PNAME>.*) posts blind \(\$?(?P<SB>[.0-9]+)\), ')
|
||||||
|
re_PostBB = re.compile('\), (?P<PNAME>.*) posts blind \(\$?(?P<BB>[.0-9]+)\).')
|
||||||
# TODO: read SUMMARY correctly for collected pot stuff.
|
re_Antes = re.compile(r"^%(PLYR)s: posts the ante %(CUR)s(?P<ANTE>[.0-9]+)" % subst, re.MULTILINE)
|
||||||
#Uchilka, bets $11.75, collects $23.04, net $11.29
|
re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for %(CUR)s(?P<BRINGIN>[.0-9]+)" % subst, re.MULTILINE)
|
||||||
re_CollectPot = re.compile('(?P<PNAME>.*), bets.+, collects \$(?P<POT>\d*\.?\d*), net.* ')
|
re_PostBoth = re.compile('.*\n(?P<PNAME>.*): posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)')
|
||||||
re_sitsOut = re.compile('(?P<PNAME>.*) sits out')
|
re_HeroCards = re.compile('.*\nDealt\sto\s(?P<PNAME>.*)\s\[ (?P<CARDS>.*) \]')
|
||||||
|
|
||||||
|
#lopllopl checks, Eurolll checks, .Lucchess checks.
|
||||||
|
re_Action = re.compile('(, )?(?P<PNAME>.*?)(?P<ATYPE> bets| checks| raises| calls| folds)( \$(?P<BET>\d*\.?\d*))?( and is all-in)?')
|
||||||
|
re_Board = re.compile(r"\[board cards (?P<CARDS>.+) \]")
|
||||||
|
|
||||||
|
#Uchilka shows [ KC,JD ]
|
||||||
|
re_ShowdownAction = re.compile('(?P<PNAME>.*) shows \[ (?P<CARDS>.+) \]')
|
||||||
|
|
||||||
|
# TODO: read SUMMARY correctly for collected pot stuff.
|
||||||
|
#Uchilka, bets $11.75, collects $23.04, net $11.29
|
||||||
|
re_CollectPot = re.compile('(?P<PNAME>.*), bets.+, collects \$(?P<POT>\d*\.?\d*), net.* ')
|
||||||
|
re_sitsOut = re.compile('(?P<PNAME>.*) sits out')
|
||||||
|
|
||||||
def readSupportedGames(self):
|
def readSupportedGames(self):
|
||||||
pass
|
return [
|
||||||
|
["ring", "hold", "fl"],
|
||||||
|
["ring", "hold", "nl"],
|
||||||
|
]
|
||||||
|
|
||||||
def determineGameType(self, handText):
|
def determineGameType(self, handText):
|
||||||
# Cheating with this regex, only support nlhe at the moment
|
# Inspect the handText and return the gametype dict
|
||||||
gametype = ["ring", "hold", "nl"]
|
# gametype dict is: {'limitType': xxx, 'base': xxx, 'category': xxx}
|
||||||
|
info = {}
|
||||||
|
|
||||||
m = self.re_HandInfo.search(handText)
|
m = self.re_HandInfo.search(handText)
|
||||||
if not m:
|
if not m:
|
||||||
|
@ -90,36 +146,54 @@ class OnGame(HandHistoryConverter):
|
||||||
log.error(_("determineGameType: Raising FpdbParseError"))
|
log.error(_("determineGameType: Raising FpdbParseError"))
|
||||||
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
|
raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp)
|
||||||
|
|
||||||
gametype = gametype + [m.group('SB')]
|
mg = m.groupdict()
|
||||||
gametype = gametype + [m.group('BB')]
|
|
||||||
|
info['type'] = 'ring'
|
||||||
return gametype
|
info['currency'] = 'USD'
|
||||||
|
|
||||||
|
if 'LIMIT' in mg:
|
||||||
|
info['limitType'] = self.limits[mg['LIMIT']]
|
||||||
|
if 'GAME' in mg:
|
||||||
|
(info['base'], info['category']) = self.games[mg['GAME']]
|
||||||
|
if 'SB' in mg:
|
||||||
|
info['sb'] = mg['SB']
|
||||||
|
if 'BB' in mg:
|
||||||
|
info['bb'] = mg['BB']
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
def readHandInfo(self, hand):
|
def readHandInfo(self, hand):
|
||||||
m = self.re_HandInfo.search(hand.string)
|
info = {}
|
||||||
hand.handid = m.group('HID')
|
m = self.re_HandInfo.search(hand.handText)
|
||||||
hand.tablename = m.group('TABLE')
|
|
||||||
#hand.buttonpos = self.rexx.button_re.search(hand.string).group('BUTTONPNAME')
|
|
||||||
# These work, but the info is already in the Hand class - should be used for tourneys though.
|
|
||||||
# m.group('SB')
|
|
||||||
# m.group('BB')
|
|
||||||
# m.group('GAMETYPE')
|
|
||||||
|
|
||||||
# Believe Everleaf time is GMT/UTC, no transation necessary
|
if m:
|
||||||
# Stars format (Nov 10 2008): 2008/11/07 12:38:49 CET [2008/11/07 7:38:49 ET]
|
info.update(m.groupdict())
|
||||||
# or : 2008/11/07 12:38:49 ET
|
|
||||||
# Not getting it in my HH files yet, so using
|
log.debug("readHandInfo: %s" % info)
|
||||||
# 2008/11/10 3:58:52 ET
|
for key in info:
|
||||||
#TODO: Do conversion from GMT to ET
|
if key == 'DATETIME':
|
||||||
#TODO: Need some date functions to convert to different timezones (Date::Manip for perl rocked for this)
|
#'Wed Aug 18 19:45:30 GMT+0100 2010
|
||||||
|
# %a %b %d %H:%M:%S %z %Y
|
||||||
hand.startTime = time.strptime(m.group('DATETIME'), "%d %b %Y %I:%M %p")
|
#hand.startTime = time.strptime(m.group('DATETIME'), "%a %b %d %H:%M:%S GMT%z %Y")
|
||||||
#hand.starttime = "%d/%02d/%02d %d:%02d:%02d ET" %(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')),
|
# Stupid library doesn't seem to support %z (http://docs.python.org/library/time.html?highlight=strptime#time.strptime)
|
||||||
#int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
|
# So we need to re-interpret te string to be useful
|
||||||
|
m1 = self.re_DateTime.finditer(info[key])
|
||||||
|
for a in m1:
|
||||||
|
datetimestr = "%s %s %s %s:%s:%s" % (a.group('M'),a.group('D'), a.group('Y'), a.group('H'),a.group('MIN'),a.group('S'))
|
||||||
|
hand.startTime = time.strptime(datetimestr, "%b %d %Y %H:%M:%S")
|
||||||
|
# TODO: Manually adjust time against OFFSET
|
||||||
|
if key == 'HID':
|
||||||
|
hand.handid = info[key]
|
||||||
|
if key == 'TABLE':
|
||||||
|
hand.tablename = info[key]
|
||||||
|
|
||||||
|
# TODO: These
|
||||||
|
hand.buttonpos = 1
|
||||||
|
hand.maxseats = 10
|
||||||
|
hand.mixed = None
|
||||||
|
|
||||||
def readPlayerStacks(self, hand):
|
def readPlayerStacks(self, hand):
|
||||||
m = self.re_PlayerInf.finditer(hand.string)
|
m = self.re_PlayerInfo.finditer(hand.handText)
|
||||||
players = []
|
|
||||||
for a in m:
|
for a in m:
|
||||||
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
|
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
|
||||||
|
|
||||||
|
@ -128,13 +202,27 @@ class OnGame(HandHistoryConverter):
|
||||||
# This re fails if, say, river is missing; then we don't get the ** that starts the river.
|
# This re fails if, say, river is missing; then we don't get the ** that starts the river.
|
||||||
#m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.string,re.DOTALL)
|
#m = re.search('(\*\* Dealing down cards \*\*\n)(?P<PREFLOP>.*?\n\*\*)?( Dealing Flop \*\* \[ (?P<FLOP1>\S\S), (?P<FLOP2>\S\S), (?P<FLOP3>\S\S) \])?(?P<FLOP>.*?\*\*)?( Dealing Turn \*\* \[ (?P<TURN1>\S\S) \])?(?P<TURN>.*?\*\*)?( Dealing River \*\* \[ (?P<RIVER1>\S\S) \])?(?P<RIVER>.*)', hand.string,re.DOTALL)
|
||||||
|
|
||||||
m = re.search(r"PRE-FLOP(?P<PREFLOP>.+(?=FLOP)|.+(?=SHOWDOWN))"
|
#if hand.gametype['base'] in ("hold"):
|
||||||
r"(FLOP (?P<FLOP>\[board cards .+ \].+(?=TURN)|.+(?=SHOWDOWN)))?"
|
#elif hand.gametype['base'] in ("stud"):
|
||||||
r"(TURN (?P<TURN>\[board cards .+ \].+(?=RIVER)|.+(?=SHOWDOWN)))?"
|
#elif hand.gametype['base'] in ("draw"):
|
||||||
r"(RIVER (?P<RIVER>\[board cards .+ \].+(?=SHOWDOWN)))?", hand.string,re.DOTALL)
|
# only holdem so far:
|
||||||
|
m = re.search(r"pocket cards(?P<PREFLOP>.+(?=flop)|.+(?=Summary))"
|
||||||
|
r"(flop (?P<FLOP>\[\S\S, \S\S, \S\S\].+(?=turn)|.+(?=Summary)))?"
|
||||||
|
r"(turn (?P<TURN>\[\S\S, \S\S, \S\S\, \S\S\].+(?=river)|.+(?=Summary)))?"
|
||||||
|
r"(river (?P<RIVER>\[\S\S, \S\S, \S\S\, \S\S, \S\S\].+(?=Summary)))?", hand.handText, re.DOTALL)
|
||||||
|
|
||||||
hand.addStreets(m)
|
hand.addStreets(m)
|
||||||
|
|
||||||
|
#Needs to return a list in the format
|
||||||
|
# ['player1name', 'player2name', ...] where player1name is the sb and player2name is bb,
|
||||||
|
# addtional players are assumed to post a bb oop
|
||||||
|
|
||||||
|
def readButton(self, hand):
|
||||||
|
m = self.re_Button.search(hand.handText)
|
||||||
|
if m:
|
||||||
|
hand.buttonpos = int(m.group('BUTTON'))
|
||||||
|
else:
|
||||||
|
log.info(_('readButton: not found'))
|
||||||
|
|
||||||
def readCommunityCards(self, hand, street):
|
def readCommunityCards(self, hand, street):
|
||||||
print hand.streets.group(street)
|
print hand.streets.group(street)
|
||||||
|
@ -144,17 +232,30 @@ class OnGame(HandHistoryConverter):
|
||||||
|
|
||||||
def readBlinds(self, hand):
|
def readBlinds(self, hand):
|
||||||
try:
|
try:
|
||||||
m = self.re_PostSB.search(hand.string)
|
m = self.re_PostSB.search(hand.handText)
|
||||||
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
|
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
|
||||||
except: # no small blind
|
except: # no small blind
|
||||||
hand.addBlind(None, None, None)
|
hand.addBlind(None, None, None)
|
||||||
for a in self.re_PostBB.finditer(hand.string):
|
for a in self.re_PostBB.finditer(hand.handText):
|
||||||
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
|
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
|
||||||
for a in self.re_PostBoth.finditer(hand.string):
|
for a in self.re_PostBoth.finditer(hand.handText):
|
||||||
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
|
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
|
||||||
|
|
||||||
|
def readAntes(self, hand):
|
||||||
|
log.debug(_("reading antes"))
|
||||||
|
m = self.re_Antes.finditer(hand.handText)
|
||||||
|
for player in m:
|
||||||
|
#~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
|
||||||
|
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
|
||||||
|
|
||||||
|
def readBringIn(self, hand):
|
||||||
|
m = self.re_BringIn.search(hand.handText,re.DOTALL)
|
||||||
|
if m:
|
||||||
|
#~ logging.debug("readBringIn: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
|
||||||
|
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
|
||||||
|
|
||||||
def readHeroCards(self, hand):
|
def readHeroCards(self, hand):
|
||||||
m = self.re_HeroCards.search(hand.string)
|
m = self.re_HeroCards.search(hand.handText)
|
||||||
if(m == None):
|
if(m == None):
|
||||||
#Not involved in hand
|
#Not involved in hand
|
||||||
hand.involved = False
|
hand.involved = False
|
||||||
|
@ -185,13 +286,13 @@ class OnGame(HandHistoryConverter):
|
||||||
# TODO: Everleaf does not record uncalled bets.
|
# TODO: Everleaf does not record uncalled bets.
|
||||||
|
|
||||||
def readShowdownActions(self, hand):
|
def readShowdownActions(self, hand):
|
||||||
for shows in self.re_ShowdownAction.finditer(hand.string):
|
for shows in self.re_ShowdownAction.finditer(hand.handText):
|
||||||
cards = shows.group('CARDS')
|
cards = shows.group('CARDS')
|
||||||
cards = set(cards.split(','))
|
cards = set(cards.split(','))
|
||||||
hand.addShownCards(cards, shows.group('PNAME'))
|
hand.addShownCards(cards, shows.group('PNAME'))
|
||||||
|
|
||||||
def readCollectPot(self,hand):
|
def readCollectPot(self,hand):
|
||||||
for m in self.re_CollectPot.finditer(hand.string):
|
for m in self.re_CollectPot.finditer(hand.handText):
|
||||||
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
||||||
|
|
||||||
def readShownCards(self,hand):
|
def readShownCards(self,hand):
|
||||||
|
|
|
@ -1093,6 +1093,7 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
|
||||||
self.status_bar = None
|
self.status_bar = None
|
||||||
self.quitting = False
|
self.quitting = False
|
||||||
|
|
||||||
|
self.visible = False
|
||||||
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||||
self.window.connect("delete_event", self.delete_event)
|
self.window.connect("delete_event", self.delete_event)
|
||||||
self.window.connect("destroy", self.destroy)
|
self.window.connect("destroy", self.destroy)
|
||||||
|
@ -1130,6 +1131,7 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
|
||||||
self.tab_main_help(None, None)
|
self.tab_main_help(None, None)
|
||||||
|
|
||||||
self.window.show()
|
self.window.show()
|
||||||
|
self.visible = True # Flip on
|
||||||
self.load_profile(create_db = True)
|
self.load_profile(create_db = True)
|
||||||
|
|
||||||
if not options.errorsToConsole:
|
if not options.errorsToConsole:
|
||||||
|
@ -1165,21 +1167,31 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
|
||||||
self.window.connect('window-state-event', self.window_state_event_cb)
|
self.window.connect('window-state-event', self.window_state_event_cb)
|
||||||
sys.stderr.write(_("fpdb starting ..."))
|
sys.stderr.write(_("fpdb starting ..."))
|
||||||
|
|
||||||
|
|
||||||
|
def __iconify(self):
|
||||||
|
self.visible = False
|
||||||
|
self.window.set_skip_taskbar_hint(True)
|
||||||
|
self.window.set_skip_pager_hind(True)
|
||||||
|
|
||||||
|
def __deiconify(self):
|
||||||
|
self.visible = True
|
||||||
|
self.window.set_skip_taskbar_hint(False)
|
||||||
|
self.window.set_skip_pager_hind(False)
|
||||||
|
|
||||||
def window_state_event_cb(self, window, event):
|
def window_state_event_cb(self, window, event):
|
||||||
|
# Deal with iconification first
|
||||||
if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED:
|
if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED:
|
||||||
# -20 = GWL_EXSTYLE can't find it in the pywin32 libs
|
|
||||||
#bits = win32api.GetWindowLong(self.window.window.handle, -20)
|
|
||||||
#bits = bits ^ (win32con.WS_EX_TOOLWINDOW | win32con.WS_EX_APPWINDOW)
|
|
||||||
|
|
||||||
#win32api.SetWindowLong(self.window.window.handle, -20, bits)
|
|
||||||
|
|
||||||
if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
|
if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
|
||||||
self.window.hide()
|
self.__iconify()
|
||||||
self.window.set_skip_taskbar_hint(True)
|
|
||||||
self.window.set_skip_pager_hint(True)
|
|
||||||
else:
|
else:
|
||||||
self.window.set_skip_taskbar_hint(False)
|
self.__deiconify()
|
||||||
self.window.set_skip_pager_hint(False)
|
if not event.new_window_state & gtk.gdk.WINDOW_STATE_WITHDRAWN:
|
||||||
|
return True
|
||||||
|
# And then the tray icon click
|
||||||
|
if event.new_window_state & gtk.gdk.WINDOW_STATE_WITHDRAWN:
|
||||||
|
self.__iconify()
|
||||||
|
else:
|
||||||
|
self.__deiconify()
|
||||||
# Tell GTK not to propagate this signal any further
|
# Tell GTK not to propagate this signal any further
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -1197,11 +1209,9 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
|
||||||
def statusicon_activate(self, widget, data = None):
|
def statusicon_activate(self, widget, data = None):
|
||||||
# Let's allow the tray icon to toggle window visibility, the way
|
# Let's allow the tray icon to toggle window visibility, the way
|
||||||
# most other apps work
|
# most other apps work
|
||||||
shown = self.window.get_property('visible')
|
if self.visible:
|
||||||
if shown:
|
|
||||||
self.window.hide()
|
self.window.hide()
|
||||||
else:
|
else:
|
||||||
self.window.show()
|
|
||||||
self.window.present()
|
self.window.present()
|
||||||
|
|
||||||
def info_box(self, str1, str2):
|
def info_box(self, str1, str2):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user