From d08e9a1ea317830c3c40dc79802e775d1f00b10c Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 22 Nov 2009 12:34:11 +0800 Subject: [PATCH 1/3] Add support for UTF-8 HH type. Able to parse and import an EUR hh file --- pyfpdb/PokerStarsToFpdb.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 7f242789..7e63cee6 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -31,18 +31,18 @@ class PokerStars(HandHistoryConverter): sitename = "PokerStars" filetype = "text" - codepage = "cp1252" + codepage = ("utf8", "cp1252") siteId = 2 # Needs to match id entry in Sites database 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": "\xe2\x82\xac", "GBP": "\xa3"} # ADD Euro, Sterling, etc HERE substitutions = { 'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes - 'LS' : "\$|\x80|\xa3" # legal currency symbols ADD Euro, Sterling, etc HERE + 'LS' : "\$|\xe2\x82\xac|" # legal currency symbols - Euro(cp1252, utf-8) } # Static regexes - re_GameInfo = re.compile(""" + re_GameInfo = re.compile(u""" PokerStars\sGame\s\#(?P[0-9]+):\s+ (Tournament\s\# # open paren of tournament info (?P\d+),\s @@ -62,7 +62,7 @@ class PokerStars(HandHistoryConverter): (?P.*$)""" % substitutions, re.MULTILINE|re.VERBOSE) - re_PlayerInfo = re.compile(""" + re_PlayerInfo = re.compile(u""" ^Seat\s(?P[0-9]+):\s (?P.*)\s \((%(LS)s)?(?P[.0-9]+)\sin\schips\)""" % substitutions, @@ -373,12 +373,9 @@ if __name__ == "__main__": parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/stars/horse/HH20090226 Natalie V - $0.10-$0.20 - HORSE.txt") parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-") parser.add_option("-f", "--follow", dest="follow", help="follow (tail -f) the input", action="store_true", default=False) - parser.add_option("-q", "--quiet", - action="store_const", const=logging.CRITICAL, dest="verbosity", default=logging.INFO) - parser.add_option("-v", "--verbose", - action="store_const", const=logging.INFO, dest="verbosity") - parser.add_option("--vv", - action="store_const", const=logging.DEBUG, dest="verbosity") + #parser.add_option("-q", "--quiet", action="store_const", const=logging.CRITICAL, dest="verbosity", default=logging.INFO) + #parser.add_option("-v", "--verbose", action="store_const", const=logging.INFO, dest="verbosity") + #parser.add_option("--vv", action="store_const", const=logging.DEBUG, dest="verbosity") (options, args) = parser.parse_args() From 943e188a4d3b45319a2d637ad81ecbf23cd8eba9 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 23 Nov 2009 00:05:23 +0800 Subject: [PATCH 2/3] [NEWIMPORT] Hole card data for flop games Take some code from Grindi to calculate playersAtStreetX and streetXRaises --- pyfpdb/Database.py | 16 ++++++--- pyfpdb/DerivedStats.py | 73 ++++++++++++++++++++++++++++++++---------- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 84c2d7a7..040b1417 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1385,6 +1385,10 @@ class Database: pids[p], pdata[p]['startCash'], pdata[p]['seatNo'], + pdata[p]['card1'], + pdata[p]['card2'], + pdata[p]['card3'], + pdata[p]['card4'], pdata[p]['winnings'], pdata[p]['street0VPI'], pdata[p]['street1Seen'], @@ -1403,6 +1407,10 @@ class Database: playerId, startCash, seatNo, + card1, + card2, + card3, + card4, winnings, street0VPI, street1Seen, @@ -1416,6 +1424,7 @@ class Database: street4Aggr ) VALUES ( + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s @@ -1423,10 +1432,9 @@ class Database: # position, # tourneyTypeId, -# card1, -# card2, -# card3, -# card4, +# card5, +# card6, +# card7, # startCards, # rake, # totalProfit, diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 43220c4b..c8dcfef8 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -81,12 +81,13 @@ class DerivedStats(): self.hands['boardcard5'] = cards[4] #print "DEBUG: self.getStreetTotals = (%s, %s, %s, %s, %s)" % hand.getStreetTotals() - #FIXME: Pot size still in decimal, needs to be converted to cents - (self.hands['street1Pot'], - self.hands['street2Pot'], - self.hands['street3Pot'], - self.hands['street4Pot'], - self.hands['showdownPot']) = hand.getStreetTotals() + totals = hand.getStreetTotals() + totals = [int(100*i) for i in totals] + self.hands['street1Pot'] = totals[0] + self.hands['street2Pot'] = totals[1] + self.hands['street3Pot'] = totals[2] + self.hands['street4Pot'] = totals[3] + self.hands['showdownPot'] = totals[4] self.vpip(hand) # Gives playersVpi (num of players vpip) #print "DEBUG: vpip: %s" %(self.hands['playersVpi']) @@ -115,6 +116,26 @@ class DerivedStats(): for i, street in enumerate(hand.actionStreets[1:]): self.aggr(self.hand, i) + default_holecards = ["Xx", "Xx", "Xx", "Xx"] + for street in hand.holeStreets: + for player in hand.players: + if player[1] in hand.holecards[street].keys(): + self.handsplayers[player[1]]['card1'] = Card.encodeCard(hand.holecards[street][player[1]][1][0]) + self.handsplayers[player[1]]['card2'] = Card.encodeCard(hand.holecards[street][player[1]][1][1]) + try: + self.handsplayers[player[1]]['card3'] = Card.encodeCard(hand.holecards[street][player[1]][1][2]) + self.handsplayers[player[1]]['card4'] = Card.encodeCard(hand.holecards[street][player[1]][1][3]) + except IndexError: + self.handsplayers[player[1]]['card3'] = 0 + self.handsplayers[player[1]]['card4'] = 0 + #print "DEBUG: hand.holecards[%s][%s][0]: %s" % (street, player[1], hand.holecards[street][player[1]][1]) + else: + #print "DEBUG: player doesn't exist, setting card1-4 to 0" + self.handsplayers[player[1]]['card1'] = 0 + self.handsplayers[player[1]]['card2'] = 0 + self.handsplayers[player[1]]['card3'] = 0 + self.handsplayers[player[1]]['card4'] = 0 + def assembleHudCache(self, hand): pass @@ -147,14 +168,19 @@ class DerivedStats(): self.hands['playersAtStreet4'] = 0 self.hands['playersAtShowdown'] = 0 + alliners = set() for (i, street) in enumerate(hand.actionStreets[2:]): - actors = {} - for act in hand.actions[street]: - actors[act[0]] = 1 - self.hands['playersAtStreet%s' % str(i+1)] = len(actors.keys()) - - #Need playersAtShowdown + actors = set() + for action in hand.actions[street]: + if len(action) > 2 and action[-1]: # allin + alliners.add(action[0]) + actors.add(action[0]) + if len(actors)==0 and len(alliners)<2: + alliners = set() + self.hands['playersAtStreet%d' % (i+1)] = len(set.union(alliners, actors)) + actions = hand.actions[hand.actionStreets[-1]] + self.hands['playersAtShowdown'] = len(set.union(self.pfba(actions) - self.pfba(actions, l=('folds',)), alliners)) def streetXRaises(self, hand): # self.actions[street] is a list of all actions in a tuple, contining the action as the second element @@ -162,11 +188,11 @@ class DerivedStats(): # No idea what this value is actually supposed to be # In theory its "num small bets paid to see flop/street4, including blind" which makes sense for limit. Not so useful for nl # Leaving empty for the moment, - self.hands['street0Raises'] = 0 # /* num small bets paid to see flop/street4, including blind */ - self.hands['street1Raises'] = 0 # /* num small bets paid to see turn/street5 */ - self.hands['street2Raises'] = 0 # /* num big bets paid to see river/street6 */ - self.hands['street3Raises'] = 0 # /* num big bets paid to see sd/street7 */ - self.hands['street4Raises'] = 0 # /* num big bets paid to see showdown */ + + for i in range(5): self.hands['street%dRaises' % i] = 0 + + for (i, street) in enumerate(hand.actionStreets[1:]): + self.hands['street%dRaises' % i] = len(filter( lambda action: action[1] in ('raises','bets'), hand.actions[street])) def seen(self, hand, i): pas = set() @@ -193,3 +219,16 @@ class DerivedStats(): def countPlayers(self, hand): pass + + def pfba(self, actions, f=None, l=None): + """Helper method. Returns set of PlayersFilteredByActions + + f - forbidden actions + l - limited to actions + """ + players = set() + for action in actions: + if l is not None and action[1] not in l: continue + if f is not None and action[1] in f: continue + players.add(action[0]) + return players From 34e7fb0459232bea8d8206fabb0af7f75111896e Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 23 Nov 2009 00:20:51 +0800 Subject: [PATCH 3/3] [NEWIMPORT] Fix HandsPlayers.cardX init --- pyfpdb/Database.py | 12 ++++++++---- pyfpdb/DerivedStats.py | 14 ++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 040b1417..dbd7afe1 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1389,6 +1389,9 @@ class Database: pdata[p]['card2'], pdata[p]['card3'], pdata[p]['card4'], + pdata[p]['card5'], + pdata[p]['card6'], + pdata[p]['card7'], pdata[p]['winnings'], pdata[p]['street0VPI'], pdata[p]['street1Seen'], @@ -1411,6 +1414,9 @@ class Database: card2, card3, card4, + card5, + card6, + card7, winnings, street0VPI, street1Seen, @@ -1424,7 +1430,8 @@ class Database: street4Aggr ) VALUES ( - %s, %s, %s, %s, + %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s @@ -1432,9 +1439,6 @@ class Database: # position, # tourneyTypeId, -# card5, -# card6, -# card7, # startCards, # rake, # totalProfit, diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index c8dcfef8..e4d59336 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -117,8 +117,10 @@ class DerivedStats(): self.aggr(self.hand, i) default_holecards = ["Xx", "Xx", "Xx", "Xx"] + for street in hand.holeStreets: for player in hand.players: + for i in range(1,8): self.handsplayers[player[1]]['card%d' % i] = 0 if player[1] in hand.holecards[street].keys(): self.handsplayers[player[1]]['card1'] = Card.encodeCard(hand.holecards[street][player[1]][1][0]) self.handsplayers[player[1]]['card2'] = Card.encodeCard(hand.holecards[street][player[1]][1][1]) @@ -126,16 +128,8 @@ class DerivedStats(): self.handsplayers[player[1]]['card3'] = Card.encodeCard(hand.holecards[street][player[1]][1][2]) self.handsplayers[player[1]]['card4'] = Card.encodeCard(hand.holecards[street][player[1]][1][3]) except IndexError: - self.handsplayers[player[1]]['card3'] = 0 - self.handsplayers[player[1]]['card4'] = 0 - #print "DEBUG: hand.holecards[%s][%s][0]: %s" % (street, player[1], hand.holecards[street][player[1]][1]) - else: - #print "DEBUG: player doesn't exist, setting card1-4 to 0" - self.handsplayers[player[1]]['card1'] = 0 - self.handsplayers[player[1]]['card2'] = 0 - self.handsplayers[player[1]]['card3'] = 0 - self.handsplayers[player[1]]['card4'] = 0 - + # Just means no player cards for that street/game - continue + pass def assembleHudCache(self, hand): pass