parsing PS summary emails now. just need to write insert/update code now

This commit is contained in:
steffen123 2010-07-07 06:58:42 +02:00
parent e3ce1b8c2d
commit 92a4b105cc
4 changed files with 76 additions and 49 deletions

View File

@ -670,10 +670,10 @@ class Fulltilt(HandHistoryConverter):
heroName = n.group('HERO_NAME') heroName = n.group('HERO_NAME')
tourney.hero = heroName tourney.hero = heroName
# Is this really useful ? # Is this really useful ?
if heroName not in tourney.finishPositions: if heroName not in tourney.ranks:
print "FullTilt:", heroName, "not found in tourney.finishPositions ..." print "FullTilt:", heroName, "not found in tourney.ranks ..."
elif (tourney.finishPositions[heroName] != Decimal(n.group('HERO_FINISHING_POS'))): elif (tourney.ranks[heroName] != Decimal(n.group('HERO_FINISHING_POS'))):
print "FullTilt: Bad parsing : finish position incoherent : %s / %s" % (tourney.finishPositions[heroName], n.group('HERO_FINISHING_POS')) print "FullTilt: Bad parsing : finish position incoherent : %s / %s" % (tourney.ranks[heroName], n.group('HERO_FINISHING_POS'))
return True return True

View File

@ -19,14 +19,22 @@
#see http://docs.python.org/library/imaplib.html for the python interface #see http://docs.python.org/library/imaplib.html for the python interface
#see http://tools.ietf.org/html/rfc2060#section-6.4.4 for IMAP4 search criteria #see http://tools.ietf.org/html/rfc2060#section-6.4.4 for IMAP4 search criteria
#TODO: move all these into config file
#TODO: This is currently for PS only. If anyone wants to expand IMAP
configHost="schaumburger.info"
configUser="fpdb-test@schaumburger.info"
import sys import sys
configPw=sys.argv[1]
from imaplib import IMAP4_SSL from imaplib import IMAP4_SSL
import PokerStarsSummary
def splitPokerStarsSummaries(emailText):
splitSummaries=emailText.split("\nPokerStars Tournament #")[1:]
for i in range(len(splitSummaries)):
splitSummaries[i]="PokerStars Tournament #"+splitSummaries[i]
return splitSummaries
#end def emailText
#TODO: move all these into the config file. until then usage is: ./ImapSummaries.py YourImapHost YourImapUser YourImapPw
configHost=sys.argv[1]
configUser=sys.argv[2]
configPw=sys.argv[3]
#TODO: specify folder, whether to use SSL
server = IMAP4_SSL(configHost) #TODO: optionally non-SSL server = IMAP4_SSL(configHost) #TODO: optionally non-SSL
response = server.login(configUser, configPw) #TODO catch authentication error response = server.login(configUser, configPw) #TODO catch authentication error
@ -46,15 +54,22 @@ for messageNumber in searchData[0].split(" "):
if response!="OK": if response!="OK":
raise error #TODO: show error message raise error #TODO: show error message
if headerData[1].find("Subject: PokerStars Tournament History Request - Last x")!=1: if headerData[1].find("Subject: PokerStars Tournament History Request - Last x")!=1:
neededMessages.append(messageNumber) neededMessages.append(("PS", messageNumber))
if len(neededMessages)==0: if (len(neededMessages)==0):
raise error #TODO: show error message raise error #TODO: show error message
for messageNumber in neededMessages: for messageData in neededMessages:
response, bodyData = server.fetch(messageNumber, "(UID BODY[TEXT])") response, bodyData = server.fetch(messageData[1], "(UID BODY[TEXT])")
bodyData=bodyData[0][1]
if response!="OK": if response!="OK":
raise error #TODO: show error message raise error #TODO: show error message
print "bodyData",bodyData[0][1] if messageData[0]=="PS":
summaryTexts=(splitPokerStarsSummaries(bodyData))
for summaryText in summaryTexts:
result=PokerStarsSummary.PokerStarsSummary(sitename="PokerStars", gametype=None, summaryText=summaryText, builtFrom = "IMAP")
print "result:",result
#TODO: count results and output to shell like hand importer does
print "completed running Imap import, closing server connection"
server.close() server.close()
server.logout() server.logout()

View File

@ -41,6 +41,30 @@ class PokerStars(HandHistoryConverter):
'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes 'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8) 'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8)
} }
# translations from captured groups to fpdb info strings
Lim_Blinds = { '0.04': ('0.01', '0.02'), '0.10': ('0.02', '0.05'), '0.20': ('0.05', '0.10'),
'0.40': ('0.10', '0.20'), '0.50': ('0.10', '0.25'), '1.00': ('0.25', '0.50'),
'2.00': ('0.50', '1.00'), '2': ('0.50', '1.00'), '4' : ('1.00', '2.00'),
'4.00': ('1.00', '2.00'), '6': ('1.00', '3.00'), '6.00': ('1.00', '3.00'),
'10.00': ('2.00', '5.00'), '20.00': ('5.00', '10.00'), '30.00': ('10.00', '15.00'),
'60.00': ('15.00', '30.00'), '100.00': ('25.00', '50.00'), '200.00': ('50.00', '100.00'),
'400.00': ('100.00', '200.00'), '1000.00': ('250.00', '500.00')}
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl', 'LIMIT':'fl' }
games = { # base, category
"Hold'em" : ('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')
}
currencies = { u'':'EUR', '$':'USD', '':'T$' }
# Static regexes # Static regexes
re_GameInfo = re.compile(u""" re_GameInfo = re.compile(u"""
@ -144,43 +168,20 @@ class PokerStars(HandHistoryConverter):
raise FpdbParseError("Unable to recognise gametype from: '%s'" % tmp) raise FpdbParseError("Unable to recognise gametype from: '%s'" % tmp)
mg = m.groupdict() mg = m.groupdict()
# translations from captured groups to fpdb info strings
Lim_Blinds = { '0.04': ('0.01', '0.02'), '0.10': ('0.02', '0.05'), '0.20': ('0.05', '0.10'),
'0.40': ('0.10', '0.20'), '0.50': ('0.10', '0.25'), '1.00': ('0.25', '0.50'),
'2.00': ('0.50', '1.00'), '2': ('0.50', '1.00'), '4' : ('1.00', '2.00'),
'4.00': ('1.00', '2.00'), '6': ('1.00', '3.00'), '6.00': ('1.00', '3.00'),
'10.00': ('2.00', '5.00'), '20.00': ('5.00', '10.00'), '30.00': ('10.00', '15.00'),
'60.00': ('15.00', '30.00'), '100.00': ('25.00', '50.00'), '200.00': ('50.00', '100.00'),
'400.00': ('100.00', '200.00'), '1000.00': ('250.00', '500.00')}
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl', 'LIMIT':'fl' }
games = { # base, category
"Hold'em" : ('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')
}
currencies = { u'':'EUR', '$':'USD', '':'T$' }
# I don't think this is doing what we think. mg will always have all # I don't think this is doing what we think. mg will always have all
# the expected keys, but the ones that didn't match in the regex will # the expected keys, but the ones that didn't match in the regex will
# have a value of None. It is OK if it throws an exception when it # have a value of None. It is OK if it throws an exception when it
# runs across an unknown game or limit or whatever. # runs across an unknown game or limit or whatever.
if 'LIMIT' in mg: if 'LIMIT' in mg:
info['limitType'] = limits[mg['LIMIT']] info['limitType'] = self.limits[mg['LIMIT']]
if 'GAME' in mg: if 'GAME' in mg:
(info['base'], info['category']) = games[mg['GAME']] (info['base'], info['category']) = self.games[mg['GAME']]
if 'SB' in mg: if 'SB' in mg:
info['sb'] = mg['SB'] info['sb'] = mg['SB']
if 'BB' in mg: if 'BB' in mg:
info['bb'] = mg['BB'] info['bb'] = mg['BB']
if 'CURRENCY' in mg: if 'CURRENCY' in mg:
info['currency'] = currencies[mg['CURRENCY']] info['currency'] = self.currencies[mg['CURRENCY']]
if 'TOURNO' in mg and mg['TOURNO'] is None: if 'TOURNO' in mg and mg['TOURNO'] is None:
info['type'] = 'ring' info['type'] = 'ring'
@ -189,8 +190,8 @@ class PokerStars(HandHistoryConverter):
if info['limitType'] == 'fl' and info['bb'] is not None and info['type'] == 'ring' and info['base'] != 'stud': if info['limitType'] == 'fl' and info['bb'] is not None and info['type'] == 'ring' and info['base'] != 'stud':
try: try:
info['sb'] = Lim_Blinds[mg['BB']][0] info['sb'] = self.Lim_Blinds[mg['BB']][0]
info['bb'] = Lim_Blinds[mg['BB']][1] info['bb'] = self.Lim_Blinds[mg['BB']][1]
except KeyError: except KeyError:
log.error("determineGameType: Lim_Blinds has no lookup for '%s'" % mg['BB']) log.error("determineGameType: Lim_Blinds has no lookup for '%s'" % mg['BB'])
log.error("determineGameType: Raising FpdbParseError") log.error("determineGameType: Raising FpdbParseError")

View File

@ -15,6 +15,8 @@
#along with this program. If not, see <http://www.gnu.org/licenses/>. #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 "official" distribution you can find the license in agpl-3.0.txt.
"""parses and stores summary sections from e.g. eMail or summary files"""
# TODO: check to keep only the needed modules # TODO: check to keep only the needed modules
import re import re
@ -90,16 +92,21 @@ class TourneySummary(object):
self.guarantee = 0 self.guarantee = 0
# Collections indexed by player names # Collections indexed by player names
self.finishPositions = {} self.ranks = {}
self.winnings = {} self.winnings = {}
self.winningsCurrency = {} self.winningsCurrency = {}
self.rebuyCounts = {} self.rebuyCounts = {}
self.addOnCounts = {} self.addOnCounts = {}
self.koCounts = {} self.koCounts = {}
# currency symbol for this summary # currency symbol for this summary
self.sym = None self.sym = None
#self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done #self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done
if builtFrom=="IMAP":
self.parseSummary()
#TODO: self.insert()
#end def __init__
def __str__(self): def __str__(self):
#TODO : Update #TODO : Update
@ -143,7 +150,7 @@ class TourneySummary(object):
structs = ( ("GAMETYPE", self.gametype), structs = ( ("GAMETYPE", self.gametype),
("PLAYERS", self.players), ("PLAYERS", self.players),
("POSITIONS", self.finishPositions), ("RANKS", self.ranks),
("WINNINGS", self.winnings), ("WINNINGS", self.winnings),
("COUNT REBUYS", self.rebuyCounts), ("COUNT REBUYS", self.rebuyCounts),
("COUNT ADDONS", self.addOnCounts), ("COUNT ADDONS", self.addOnCounts),
@ -156,6 +163,10 @@ class TourneySummary(object):
for (name, struct) in structs: for (name, struct) in structs:
str = str + "\n%s =\n" % name + pprint.pformat(struct, 4) str = str + "\n%s =\n" % name + pprint.pformat(struct, 4)
return str return str
#end def __str__
def parseSummary(self): abstract
"""should fill the class variables with the parsed information"""
def getSummaryText(self): def getSummaryText(self):
return self.summaryText return self.summaryText
@ -203,7 +214,7 @@ winnings (decimal) the money the player ended the tourney with (can be 0, or
""" """
log.debug("addPlayer: rank:%s - name : '%s' - Winnings (%s)" % (rank, name, winnings)) log.debug("addPlayer: rank:%s - name : '%s' - Winnings (%s)" % (rank, name, winnings))
self.players.append(name) self.players.append(name)
self.finishPositions.update( { name : Decimal(rank) } ) self.ranks.update( { name : Decimal(rank) } )
self.winnings.update( { name : Decimal(winnings) } ) self.winnings.update( { name : Decimal(winnings) } )
self.winningsCurrency.update( { name : winningsCurrency } ) self.winningsCurrency.update( { name : winningsCurrency } )
self.rebuyCounts.update( {name: Decimal(rebuyCount) } ) self.rebuyCounts.update( {name: Decimal(rebuyCount) } )