Merge branch 'master' of git://git.assembla.com/fpdboz.git
This commit is contained in:
		
						commit
						b79734167d
					
				
							
								
								
									
										91
									
								
								pyfpdb/DerivedStats.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								pyfpdb/DerivedStats.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | ||||||
|  | #!/usr/bin/python | ||||||
|  | 
 | ||||||
|  | #Copyright 2008 Carl Gherardi | ||||||
|  | #This program is free software: you can redistribute it and/or modify | ||||||
|  | #it under the terms of the GNU Affero General Public License as published by | ||||||
|  | #the Free Software Foundation, version 3 of the License. | ||||||
|  | # | ||||||
|  | #This program is distributed in the hope that it will be useful, | ||||||
|  | #but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
|  | #GNU General Public License for more details. | ||||||
|  | # | ||||||
|  | #You should have received a copy of the GNU Affero General Public License | ||||||
|  | #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 docs folder of the package. | ||||||
|  | 
 | ||||||
|  | class DerivedStats(): | ||||||
|  |     def __init__(self, hand): | ||||||
|  |         self.hand = hand | ||||||
|  | 
 | ||||||
|  |         self.activeSeats                     = 0 | ||||||
|  |         self.position                        = 0 | ||||||
|  |         self.tourneyTypeId                   = 0 | ||||||
|  | 
 | ||||||
|  |         self.HDs                             = 0 | ||||||
|  |         self.street0VPI                      = 0 | ||||||
|  |         self.street0Aggr                     = 0 | ||||||
|  |         self.street0_3B4BChance              = 0 | ||||||
|  |         self.street0_3B4BDone                = 0 | ||||||
|  | 
 | ||||||
|  |         self.street1Seen                     = 0 | ||||||
|  |         self.street2Seen                     = 0 | ||||||
|  |         self.street3Seen                     = 0 | ||||||
|  |         self.street4Seen                     = 0 | ||||||
|  |         self.sawShowdown                     = 0 | ||||||
|  | 
 | ||||||
|  |         self.street1Aggr                     = 0 | ||||||
|  |         self.street2Aggr                     = 0 | ||||||
|  |         self.street3Aggr                     = 0 | ||||||
|  |         self.street4Aggr                     = 0 | ||||||
|  | 
 | ||||||
|  |         self.otherRaisedStreet1              = 0 | ||||||
|  |         self.otherRaisedStreet2              = 0 | ||||||
|  |         self.otherRaisedStreet3              = 0 | ||||||
|  |         self.otherRaisedStreet4              = 0 | ||||||
|  |         self.foldToOtherRaisedStreet1        = 0 | ||||||
|  |         self.foldToOtherRaisedStreet2        = 0 | ||||||
|  |         self.foldToOtherRaisedStreet3        = 0 | ||||||
|  |         self.foldToOtherRaisedStreet4        = 0 | ||||||
|  |         self.wonWhenSeenStreet1              = 0 | ||||||
|  |         self.wonAtSD                         = 0 | ||||||
|  | 
 | ||||||
|  |         self.stealAttemptChance              = 0 | ||||||
|  |         self.stealAttempted                  = 0 | ||||||
|  |         self.foldBbToStealChance             = 0 | ||||||
|  |         self.foldedBbToSteal                 = 0 | ||||||
|  |         self.foldSbToStealChance             = 0 | ||||||
|  |         self.foldedSbToSteal                 = 0 | ||||||
|  | 
 | ||||||
|  |         self.street1CBChance                 = 0 | ||||||
|  |         self.street1CBDone                   = 0 | ||||||
|  |         self.street2CBChance                 = 0 | ||||||
|  |         self.street2CBDone                   = 0 | ||||||
|  |         self.street3CBChance                 = 0 | ||||||
|  |         self.street3CBDone                   = 0 | ||||||
|  |         self.street4CBChance                 = 0 | ||||||
|  |         self.street4CBDone                   = 0 | ||||||
|  | 
 | ||||||
|  |         self.foldToStreet1CBChance           = 0 | ||||||
|  |         self.foldToStreet1CBDone             = 0 | ||||||
|  |         self.foldToStreet2CBChance           = 0 | ||||||
|  |         self.foldToStreet2CBDone             = 0 | ||||||
|  |         self.foldToStreet3CBChance           = 0 | ||||||
|  |         self.foldToStreet3CBDone             = 0 | ||||||
|  |         self.foldToStreet4CBChance           = 0 | ||||||
|  |         self.foldToStreet4CBDone             = 0 | ||||||
|  | 
 | ||||||
|  |         self.totalProfit                     = 0 | ||||||
|  | 
 | ||||||
|  |         self.street1CheckCallRaiseChance     = 0 | ||||||
|  |         self.street1CheckCallRaiseDone       = 0 | ||||||
|  |         self.street2CheckCallRaiseChance     = 0 | ||||||
|  |         self.street2CheckCallRaiseDone       = 0 | ||||||
|  |         self.street3CheckCallRaiseChance     = 0 | ||||||
|  |         self.street3CheckCallRaiseDone       = 0 | ||||||
|  |         self.street4CheckCallRaiseChance     = 0 | ||||||
|  |         self.street4CheckCallRaiseDone       = 0 | ||||||
|  | 
 | ||||||
|  |     def getStats(): | ||||||
|  |         pass | ||||||
							
								
								
									
										312
									
								
								pyfpdb/Hand.py
									
									
									
									
									
								
							
							
						
						
									
										312
									
								
								pyfpdb/Hand.py
									
									
									
									
									
								
							|  | @ -27,11 +27,14 @@ import time | ||||||
| from copy import deepcopy | from copy import deepcopy | ||||||
| from Exceptions import * | from Exceptions import * | ||||||
| 
 | 
 | ||||||
|  | import DerivedStats | ||||||
|  | 
 | ||||||
| class Hand: | class Hand: | ||||||
|     UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} |     UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} | ||||||
|     LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} |     LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} | ||||||
|     def __init__(self, sitename, gametype, handText): |     def __init__(self, sitename, gametype, handText, builtFrom = "HHC"): | ||||||
|         self.sitename = sitename |         self.sitename = sitename | ||||||
|  |         self.stats = DerivedStats.DerivedStats(self) | ||||||
|         self.gametype = gametype |         self.gametype = gametype | ||||||
|         self.handText = handText |         self.handText = handText | ||||||
|         self.handid = 0 |         self.handid = 0 | ||||||
|  | @ -58,9 +61,9 @@ class Hand: | ||||||
|             self.actions[street] = [] |             self.actions[street] = [] | ||||||
|             self.board[street] = [] |             self.board[street] = [] | ||||||
|          |          | ||||||
|          |  | ||||||
|         # Collections indexed by player names |         # Collections indexed by player names | ||||||
|         self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards |         self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards | ||||||
|  |         self.discards = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards | ||||||
|         self.stacks = {} |         self.stacks = {} | ||||||
|         self.collected = [] #list of ? |         self.collected = [] #list of ? | ||||||
|         self.collectees = {} # dict from player names to amounts collected (?) |         self.collectees = {} # dict from player names to amounts collected (?) | ||||||
|  | @ -77,6 +80,27 @@ class Hand: | ||||||
|         self.rake = None |         self.rake = None | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |     def insert(self, db): | ||||||
|  |         """ Function to insert Hand into database | ||||||
|  | Should not commit, and do minimal selects. Callers may want to cache commits | ||||||
|  | db: a connected fpdb_db object""" | ||||||
|  |         # TODO: | ||||||
|  |         # Players - base playerid and siteid tuple | ||||||
|  |         # HudCache data to come from DerivedStats class | ||||||
|  |         # HandsActions - all actions for all players for all streets - self.actions | ||||||
|  |         # BoardCards - ? | ||||||
|  |         # Hands - Summary information of hand indexed by handId - gameinfo | ||||||
|  |         # HandsPlayers - ? ... Do we fix winnings? | ||||||
|  |         # Tourneys ? | ||||||
|  |         # TourneysPlayers | ||||||
|  | 
 | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  |     def select(self, handId): | ||||||
|  |         """ Function to create Hand object from database """ | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     def addPlayer(self, seat, name, chips): |     def addPlayer(self, seat, name, chips): | ||||||
|         """\ |         """\ | ||||||
| Adds a player to the hand, and initialises data structures indexed by player. | Adds a player to the hand, and initialises data structures indexed by player. | ||||||
|  | @ -89,10 +113,12 @@ If a player has None chips he won't be added.""" | ||||||
|             self.players.append([seat, name, chips]) |             self.players.append([seat, name, chips]) | ||||||
|             self.stacks[name] = Decimal(chips) |             self.stacks[name] = Decimal(chips) | ||||||
|             self.holecards[name] = [] |             self.holecards[name] = [] | ||||||
|  |             self.discards[name] = [] | ||||||
|             self.pot.addPlayer(name) |             self.pot.addPlayer(name) | ||||||
|             for street in self.streetList: |             for street in self.streetList: | ||||||
|                 self.bets[street][name] = [] |                 self.bets[street][name] = [] | ||||||
|                 self.holecards[name] = {} # dict from street names. |                 self.holecards[name] = {} # dict from street names. | ||||||
|  |                 self.discards[name] = {} # dict from street names. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def addStreets(self, match): |     def addStreets(self, match): | ||||||
|  | @ -247,6 +273,12 @@ Add a raise on [street] by [player] to [amountTo] | ||||||
|         self.pot.addMoney(player, Decimal(amount)) |         self.pot.addMoney(player, Decimal(amount)) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |     def addStandsPat(self, street, player): | ||||||
|  |         self.checkPlayerExists(player) | ||||||
|  |         act = (player, 'stands pat') | ||||||
|  |         self.actions[street].append(act) | ||||||
|  |          | ||||||
|  | 
 | ||||||
|     def addFold(self, street, player): |     def addFold(self, street, player): | ||||||
|         logging.debug("%s %s folds" % (street, player)) |         logging.debug("%s %s folds" % (street, player)) | ||||||
|         self.checkPlayerExists(player) |         self.checkPlayerExists(player) | ||||||
|  | @ -303,7 +335,7 @@ Map the tuple self.gametype onto the pokerstars string describing it | ||||||
|               "fivedraw"   : "5 Card Draw", |               "fivedraw"   : "5 Card Draw", | ||||||
|               "27_1draw"   : "FIXME", |               "27_1draw"   : "FIXME", | ||||||
|               "27_3draw"   : "Triple Draw 2-7 Lowball", |               "27_3draw"   : "Triple Draw 2-7 Lowball", | ||||||
|               "badugi"     : "FIXME" |               "badugi"     : "Badugi" | ||||||
|              } |              } | ||||||
|         ls = {"nl"  : "No Limit", |         ls = {"nl"  : "No Limit", | ||||||
|               "pl"  : "Pot Limit", |               "pl"  : "Pot Limit", | ||||||
|  | @ -346,40 +378,49 @@ Map the tuple self.gametype onto the pokerstars string describing it | ||||||
|                 print >>fh, _("%s: posts small & big blinds $%s" %(act[0], act[3])) |                 print >>fh, _("%s: posts small & big blinds $%s" %(act[0], act[3])) | ||||||
|         elif act[1] == 'bringin': |         elif act[1] == 'bringin': | ||||||
|             print >>fh, _("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) |             print >>fh, _("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) | ||||||
|  |         elif act[1] == 'discards': | ||||||
|  |             print >>fh, _("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else '')) | ||||||
|  |         elif act[1] == 'stands pat': | ||||||
|  |             print >>fh, _("%s: stands pat" %(act[0])) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class HoldemOmahaHand(Hand): | class HoldemOmahaHand(Hand): | ||||||
|     def __init__(self, hhc, sitename, gametype, handText): |     def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): | ||||||
|         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") |         logging.debug("HoldemOmahaHand") | ||||||
|         self.streetList = ['BLINDSANTES', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order |         self.streetList = ['BLINDSANTES', 'DEAL', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order | ||||||
|         self.communityStreets = ['FLOP', 'TURN', 'RIVER'] |         self.communityStreets = ['FLOP', 'TURN', 'RIVER'] | ||||||
|         self.actionStreets = ['PREFLOP','FLOP','TURN','RIVER'] |         self.actionStreets = ['PREFLOP','FLOP','TURN','RIVER'] | ||||||
|         Hand.__init__(self, sitename, gametype, handText) |         Hand.__init__(self, sitename, gametype, handText, builtFrom = "HHC") | ||||||
|         self.sb = gametype['sb'] |         self.sb = gametype['sb'] | ||||||
|         self.bb = gametype['bb'] |         self.bb = gametype['bb'] | ||||||
|          |          | ||||||
|         #Populate a HoldemOmahaHand |         #Populate a HoldemOmahaHand | ||||||
|         #Generally, we call 'read' methods here, which get the info according to the particular filter (hhc)  |         #Generally, we call 'read' methods here, which get the info according to the particular filter (hhc)  | ||||||
|         # which then invokes a 'addXXX' callback |         # which then invokes a 'addXXX' callback | ||||||
|         hhc.readHandInfo(self) |         if builtFrom == "HHC": | ||||||
|         hhc.readPlayerStacks(self) |             hhc.readHandInfo(self) | ||||||
|         hhc.compilePlayerRegexs(self) |             hhc.readPlayerStacks(self) | ||||||
|         hhc.markStreets(self) |             hhc.compilePlayerRegexs(self) | ||||||
|         hhc.readBlinds(self) |             hhc.markStreets(self) | ||||||
|         hhc.readButton(self) |             hhc.readBlinds(self) | ||||||
|         hhc.readHeroCards(self) |             hhc.readButton(self) | ||||||
|         hhc.readShowdownActions(self) |             hhc.readHeroCards(self) | ||||||
|         # Read actions in street order |             hhc.readShowdownActions(self) | ||||||
|         for street in self.communityStreets: |             # Read actions in street order | ||||||
|             if self.streets[street]: |             for street in self.communityStreets: | ||||||
|                 hhc.readCommunityCards(self, street) |                 if self.streets[street]: | ||||||
|         for street in self.actionStreets: |                     hhc.readCommunityCards(self, street) | ||||||
|             if self.streets[street]: |             for street in self.actionStreets: | ||||||
|                 hhc.readAction(self, street) |                 if self.streets[street]: | ||||||
|         hhc.readCollectPot(self) |                     hhc.readAction(self, street) | ||||||
|         hhc.readShownCards(self) |             hhc.readCollectPot(self) | ||||||
|         self.totalPot() # finalise it (total the pot) |             hhc.readShownCards(self) | ||||||
|         hhc.getRake(self) |             self.totalPot() # finalise it (total the pot) | ||||||
|  |             hhc.getRake(self) | ||||||
|  |         elif builtFrom == "DB": | ||||||
|  |             self.select("dummy") # Will need a handId | ||||||
| 
 | 
 | ||||||
|     def addHoleCards(self, cards, player, shown=False): |     def addHoleCards(self, cards, player, shown=False): | ||||||
|         """\ |         """\ | ||||||
|  | @ -505,22 +546,188 @@ Card ranks will be uppercased | ||||||
|         print >>fh, "\n\n" |         print >>fh, "\n\n" | ||||||
|          |          | ||||||
| class DrawHand(Hand): | class DrawHand(Hand): | ||||||
|     def __init__(self, hhc, sitename, gametype, handText): |     def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): | ||||||
|         if gametype['base'] != 'draw': |         if gametype['base'] != 'draw': | ||||||
|             pass # or indeed don't pass and complain instead |             pass # or indeed don't pass and complain instead | ||||||
|  |         self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||||
|  |         self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||||
|  |         self.actionStreets =  ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||||
|  |         Hand.__init__(self, sitename, gametype, handText) | ||||||
|  |         self.sb = gametype['sb'] | ||||||
|  |         self.bb = gametype['bb'] | ||||||
|  |         # Populate the draw hand. | ||||||
|  |         if builtFrom == "HHC": | ||||||
|  |             hhc.readHandInfo(self) | ||||||
|  |             hhc.readPlayerStacks(self) | ||||||
|  |             hhc.compilePlayerRegexs(self) | ||||||
|  |             hhc.markStreets(self) | ||||||
|  |             hhc.readBlinds(self) | ||||||
|  |             hhc.readButton(self) | ||||||
|  |             hhc.readShowdownActions(self) | ||||||
|  |             # Read actions in street order | ||||||
|  |             for street in self.streetList: | ||||||
|  |                 if self.streets[street]: | ||||||
|  |                     # hhc.readCommunityCards(self, street) | ||||||
|  |                     hhc.readDrawCards(self, street) | ||||||
|  |                     hhc.readAction(self, street) | ||||||
|  |             hhc.readCollectPot(self) | ||||||
|  |             hhc.readShownCards(self) | ||||||
|  |             self.totalPot() # finalise it (total the pot) | ||||||
|  |             hhc.getRake(self) | ||||||
|  |         elif builtFrom == "DB": | ||||||
|  |             self.select("dummy") # Will need a handId | ||||||
| 
 | 
 | ||||||
|     def discardHoleCards(self, cards, player): |     # Draw games (at least Badugi has blinds - override default Holdem addBlind | ||||||
|  |     def addBlind(self, player, blindtype, amount): | ||||||
|  |         # if player is None, it's a missing small blind. | ||||||
|  |         # The situation we need to cover are: | ||||||
|  |         # Player in small blind posts | ||||||
|  |         #   - this is a bet of 1 sb, as yet uncalled. | ||||||
|  |         # Player in the big blind posts | ||||||
|  |         #   - this is a call of 1 sb and a raise to 1 bb | ||||||
|  |         #  | ||||||
|  |          | ||||||
|  |         logging.debug("addBlind: %s posts %s, %s" % (player, blindtype, amount)) | ||||||
|  |         if player is not None: | ||||||
|  |             self.bets['DEAL'][player].append(Decimal(amount)) | ||||||
|  |             self.stacks[player] -= Decimal(amount) | ||||||
|  |             #print "DEBUG %s posts, stack %s" % (player, self.stacks[player]) | ||||||
|  |             act = (player, 'posts', blindtype, amount, self.stacks[player]==0) | ||||||
|  |             self.actions['BLINDSANTES'].append(act) | ||||||
|  |             self.pot.addMoney(player, Decimal(amount)) | ||||||
|  |             if blindtype == 'big blind': | ||||||
|  |                 self.lastBet['DEAL'] = Decimal(amount)             | ||||||
|  |             elif blindtype == 'both': | ||||||
|  |                 # extra small blind is 'dead' | ||||||
|  |                 self.lastBet['DEAL'] = Decimal(self.bb) | ||||||
|  |         self.posted = self.posted + [[player,blindtype]] | ||||||
|  |         #print "DEBUG: self.posted: %s" %(self.posted) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False): | ||||||
|  |         """\ | ||||||
|  | Assigns observed holecards to a player. | ||||||
|  | cards   list of card bigrams e.g. ['2h','Jc'] | ||||||
|  | player  (string) name of player | ||||||
|  | """ | ||||||
|         try: |         try: | ||||||
|             self.checkPlayerExists(player) |             self.checkPlayerExists(player) | ||||||
|             for card in cards: | #            if shown and len(cardset) > 0: | ||||||
|                 self.holecards[player].remove(card) | #                self.shown.add(player) | ||||||
|  |             self.holecards[player][street] = (newcards,oldcards) | ||||||
|         except FpdbParseError, e: |         except FpdbParseError, e: | ||||||
|             pass |             print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) | ||||||
|         except ValueError: | 
 | ||||||
|             print "[ERROR] discardHoleCard tried to discard a card %s didn't have" % (player,) | 
 | ||||||
|  |     def discardDrawHoleCards(self, cards, player, street): | ||||||
|  |         logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street)) | ||||||
|  |         self.discards[player][street] = set([cards]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def addDiscard(self, street, player, num, cards): | ||||||
|  |         self.checkPlayerExists(player) | ||||||
|  |         if cards: | ||||||
|  |             act = (player, 'discards', num, cards) | ||||||
|  |             self.discardDrawHoleCards(cards, player, street) | ||||||
|  |         else: | ||||||
|  |             act = (player, 'discards', num) | ||||||
|  |         self.actions[street].append(act) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def addShownCards(self, cards, player, holeandboard=None): | ||||||
|  |         """\ | ||||||
|  | For when a player shows cards for any reason (for showdown or out of choice). | ||||||
|  | Card ranks will be uppercased | ||||||
|  | """ | ||||||
|  |         logging.debug("addShownCards %s hole=%s all=%s" % (player, cards,  holeandboard)) | ||||||
|  | #        if cards is not None: | ||||||
|  | #            self.shown.add(player) | ||||||
|  | #            self.addHoleCards(cards,player) | ||||||
|  | #        elif holeandboard is not None: | ||||||
|  | #            holeandboard = set([self.card(c) for c in holeandboard]) | ||||||
|  | #            board = set([c for s in self.board.values() for c in s]) | ||||||
|  | #            self.addHoleCards(holeandboard.difference(board),player,shown=True) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def writeHand(self, fh=sys.__stdout__): | ||||||
|  |         # PokerStars format. | ||||||
|  |         print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) | ||||||
|  |         print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) | ||||||
|  | 
 | ||||||
|  |         players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']])) | ||||||
|  | 
 | ||||||
|  |         for player in [x for x in self.players if x[1] in players_who_act_ondeal]: | ||||||
|  |             #Only print stacks of players who do something on deal | ||||||
|  |             print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2])) | ||||||
|  | 
 | ||||||
|  |         if 'BLINDSANTES' in self.actions: | ||||||
|  |             for act in self.actions['BLINDSANTES']: | ||||||
|  |                 print >>fh, _("%s: %s %s $%s" %(act[0], act[1], act[2], act[3])) | ||||||
|  | 
 | ||||||
|  |         if 'DEAL' in self.actions: | ||||||
|  |             print >>fh, _("*** DEALING HANDS ***") | ||||||
|  |             for player in [x[1] for x in self.players if x[1] in players_who_act_ondeal]: | ||||||
|  |                 if 'DEAL' in self.holecards[player]: | ||||||
|  |                     (nc,oc) = self.holecards[player]['DEAL'] | ||||||
|  |                     print >>fh, _("Dealt to %s: [%s]") % (player, " ".join(nc)) | ||||||
|  |             for act in self.actions['DEAL']: | ||||||
|  |                 self.printActionLine(act, fh) | ||||||
|  | 
 | ||||||
|  |         if 'DRAWONE' in self.actions: | ||||||
|  |             print >>fh, _("*** FIRST DRAW ***") | ||||||
|  |             for act in self.actions['DRAWONE']: | ||||||
|  |                 self.printActionLine(act, fh) | ||||||
|  |                 if act[0] == self.hero and act[1] == 'discards': | ||||||
|  |                     (nc,oc) = self.holecards[act[0]]['DRAWONE'] | ||||||
|  |                     dc = self.discards[act[0]]['DRAWONE'] | ||||||
|  |                     kc = oc - dc | ||||||
|  |                     print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) | ||||||
|  | 
 | ||||||
|  |         if 'DRAWTWO' in self.actions: | ||||||
|  |             print >>fh, _("*** SECOND DRAW ***") | ||||||
|  |             for act in self.actions['DRAWTWO']: | ||||||
|  |                 self.printActionLine(act, fh) | ||||||
|  |                 if act[0] == self.hero and act[1] == 'discards': | ||||||
|  |                     (nc,oc) = self.holecards[act[0]]['DRAWTWO'] | ||||||
|  |                     dc = self.discards[act[0]]['DRAWTWO'] | ||||||
|  |                     kc = oc - dc | ||||||
|  |                     print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) | ||||||
|  | 
 | ||||||
|  |         if 'DRAWTHREE' in self.actions: | ||||||
|  |             print >>fh, _("*** THIRD DRAW ***") | ||||||
|  |             for act in self.actions['DRAWTHREE']: | ||||||
|  |                 self.printActionLine(act, fh) | ||||||
|  |                 if act[0] == self.hero and act[1] == 'discards': | ||||||
|  |                     (nc,oc) = self.holecards[act[0]]['DRAWTHREE'] | ||||||
|  |                     dc = self.discards[act[0]]['DRAWTHREE'] | ||||||
|  |                     kc = oc - dc | ||||||
|  |                     print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) | ||||||
|  | 
 | ||||||
|  |         if 'SHOWDOWN' in self.actions: | ||||||
|  |             print >>fh, _("*** SHOW DOWN ***") | ||||||
|  |             #TODO: Complete SHOWDOWN | ||||||
|  | 
 | ||||||
|  |         # Current PS format has the lines: | ||||||
|  |         # Uncalled bet ($111.25) returned to s0rrow | ||||||
|  |         # s0rrow collected $5.15 from side pot | ||||||
|  |         # stervels: shows [Ks Qs] (two pair, Kings and Queens) | ||||||
|  |         # stervels collected $45.35 from main pot | ||||||
|  |         # Immediately before the summary. | ||||||
|  |         # The current importer uses those lines for importing winning rather than the summary | ||||||
|  |         for name in self.pot.returned: | ||||||
|  |             print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name)) | ||||||
|  |         for entry in self.collected: | ||||||
|  |             print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1])) | ||||||
|  | 
 | ||||||
|  |         print >>fh, _("*** SUMMARY ***") | ||||||
|  |         print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) | ||||||
|  |         print >>fh, "\n\n" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class StudHand(Hand): | class StudHand(Hand): | ||||||
|     def __init__(self, hhc, sitename, gametype, handText): |     def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): | ||||||
|         if gametype['base'] != 'stud': |         if gametype['base'] != 'stud': | ||||||
|             pass # or indeed don't pass and complain instead |             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.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order | ||||||
|  | @ -531,24 +738,27 @@ class StudHand(Hand): | ||||||
|         #Populate the StudHand |         #Populate the StudHand | ||||||
|         #Generally, we call a 'read' method here, which gets the info according to the particular filter (hhc)  |         #Generally, we call a 'read' method here, which gets the info according to the particular filter (hhc)  | ||||||
|         # which then invokes a 'addXXX' callback |         # which then invokes a 'addXXX' callback | ||||||
|         hhc.readHandInfo(self) |         if builtFrom == "HHC": | ||||||
|         hhc.readPlayerStacks(self) |             hhc.readHandInfo(self) | ||||||
|         hhc.compilePlayerRegexs(self) |             hhc.readPlayerStacks(self) | ||||||
|         hhc.markStreets(self) |             hhc.compilePlayerRegexs(self) | ||||||
|         hhc.readAntes(self) |             hhc.markStreets(self) | ||||||
|         hhc.readBringIn(self) |             hhc.readAntes(self) | ||||||
| #        hhc.readShowdownActions(self) # not done yet |             hhc.readBringIn(self) | ||||||
|         # Read actions in street order |             #hhc.readShowdownActions(self) # not done yet | ||||||
|         for street in self.streetList:             |             # Read actions in street order | ||||||
|             if self.streets[street]: |             for street in self.streetList: | ||||||
|                 logging.debug(street) |                 if self.streets[street]: | ||||||
|                 logging.debug(self.streets[street]) |                     logging.debug(street) | ||||||
|                 hhc.readStudPlayerCards(self, street) |                     logging.debug(self.streets[street]) | ||||||
|                 hhc.readAction(self, street) |                     hhc.readStudPlayerCards(self, street) | ||||||
|         hhc.readCollectPot(self) |                     hhc.readAction(self, street) | ||||||
| #        hhc.readShownCards(self) # not done yet |             hhc.readCollectPot(self) | ||||||
|         self.totalPot() # finalise it (total the pot) |             #hhc.readShownCards(self) # not done yet | ||||||
|         hhc.getRake(self) |             self.totalPot() # finalise it (total the pot) | ||||||
|  |             hhc.getRake(self) | ||||||
|  |         elif builtFrom == "DB": | ||||||
|  |             self.select("dummy") # Will need a handId | ||||||
| 
 | 
 | ||||||
|     def addPlayerCards(self, player,  street,  open=[],  closed=[]): |     def addPlayerCards(self, player,  street,  open=[],  closed=[]): | ||||||
|         """\ |         """\ | ||||||
|  |  | ||||||
|  | @ -23,49 +23,6 @@ from HandHistoryConverter import * | ||||||
| 
 | 
 | ||||||
| # PokerStars HH Format | # PokerStars HH Format | ||||||
| 
 | 
 | ||||||
| #PokerStars Game #20461877044:  Hold'em No Limit ($1/$2) - 2008/09/16 18:58:01 ET |  | ||||||
| #Table 'Gianfar IV' 6-max Seat #1 is the button |  | ||||||
| #Seat 1: ZeKGB ($224 in chips) |  | ||||||
| #Seat 2: quimboavida ($107.75 in chips) |  | ||||||
| #Seat 3: tropical100 ($190 in chips) |  | ||||||
| #Seat 4: jackhama33 ($54.95 in chips) |  | ||||||
| #Seat 5: Olubanu ($196 in chips) |  | ||||||
| #Seat 6: LSgambler ($205.35 in chips) |  | ||||||
| #quimboavida: posts small blind $1 |  | ||||||
| #tropical100: posts big blind $2 |  | ||||||
| #*** HOLE CARDS *** |  | ||||||
| #jackhama33: folds |  | ||||||
| #Olubanu: folds |  | ||||||
| #LSgambler: folds |  | ||||||
| #ZeKGB: folds |  | ||||||
| #quimboavida: calls $1 |  | ||||||
| #tropical100: raises $5 to $7 |  | ||||||
| #quimboavida: calls $5 |  | ||||||
| #*** FLOP *** [3d Qs Kd] |  | ||||||
| #quimboavida: bets $10 |  | ||||||
| #tropical100: calls $10 |  | ||||||
| #*** TURN *** [3d Qs Kd] [Ah] |  | ||||||
| #quimboavida: checks |  | ||||||
| #tropical100: checks |  | ||||||
| #*** RIVER *** [3d Qs Kd Ah] [7c] |  | ||||||
| #quimboavida: bets $30 |  | ||||||
| #tropical100: folds |  | ||||||
| #quimboavida collected $32.35 from pot |  | ||||||
| #*** SUMMARY *** |  | ||||||
| #Total pot $34 | Rake $1.65 |  | ||||||
| #Board [3d Qs Kd Ah 7c] |  | ||||||
| #Seat 1: ZeKGB (button) folded before Flop (didn't bet) |  | ||||||
| #Seat 2: quimboavida (small blind) collected ($32.35) |  | ||||||
| #Seat 3: tropical100 (big blind) folded on the River |  | ||||||
| #Seat 4: jackhama33 folded before Flop (didn't bet) |  | ||||||
| #Seat 5: Olubanu folded before Flop (didn't bet) |  | ||||||
| #Seat 6: LSgambler folded before Flop (didn't bet) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #PokerStars Game #25381215423:  HORSE (Razz Limit, $0.10/$0.20) - 2009/02/26 15:20:19 ET |  | ||||||
| #Table 'Natalie V' 8-max |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class PokerStars(HandHistoryConverter): | class PokerStars(HandHistoryConverter): | ||||||
|      |      | ||||||
|     # Static regexes |     # Static regexes | ||||||
|  | @ -103,7 +60,7 @@ follow :  whether to tail -f the input""" | ||||||
|             self.re_BringIn          = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE) |             self.re_BringIn          = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE) | ||||||
|             self.re_PostBoth         = re.compile(r"^%s: posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" %  player_re, re.MULTILINE) |             self.re_PostBoth         = re.compile(r"^%s: posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" %  player_re, re.MULTILINE) | ||||||
|             self.re_HeroCards        = re.compile(r"^Dealt to %s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE) |             self.re_HeroCards        = re.compile(r"^Dealt to %s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE) | ||||||
|             self.re_Action           = re.compile(r"^%s:(?P<ATYPE> bets| checks| raises| calls| folds)( \$(?P<BET>[.\d]+))?( to \$(?P<BETTO>[.\d]+))?" %  player_re, re.MULTILINE) |             self.re_Action           = re.compile(r"^%s:(?P<ATYPE> bets| checks| raises| calls| folds| discards| stands pat)( \$(?P<BET>[.\d]+))?( to \$(?P<BETTO>[.\d]+))?( (?P<NODISCARDED>\d) cards?( \[(?P<DISCARDED>.+?)\])?)?" %  player_re, re.MULTILINE) | ||||||
|             self.re_ShowdownAction   = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" %  player_re, re.MULTILINE) |             self.re_ShowdownAction   = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" %  player_re, re.MULTILINE) | ||||||
|             self.re_CollectPot       = re.compile(r"Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*|)" %  player_re, re.MULTILINE) |             self.re_CollectPot       = re.compile(r"Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*|)" %  player_re, re.MULTILINE) | ||||||
|             self.re_sitsOut          = re.compile("^%s sits out" %  player_re, re.MULTILINE) |             self.re_sitsOut          = re.compile("^%s sits out" %  player_re, re.MULTILINE) | ||||||
|  | @ -111,7 +68,13 @@ follow :  whether to tail -f the input""" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def readSupportedGames(self): |     def readSupportedGames(self): | ||||||
|         return [] |         return [["ring", "hold", "nl"], | ||||||
|  |                 ["ring", "hold", "pl"], | ||||||
|  |                 ["ring", "hold", "fl"], | ||||||
|  |                 ["ring", "stud", "fl"], | ||||||
|  |                 ["ring", "draw", "fl"], | ||||||
|  |                 ["ring", "omaha", "pl"] | ||||||
|  |                ] | ||||||
| 
 | 
 | ||||||
|     def determineGameType(self, handText): |     def determineGameType(self, handText): | ||||||
|         info = {'type':'ring'} |         info = {'type':'ring'} | ||||||
|  | @ -200,6 +163,12 @@ follow :  whether to tail -f the input""" | ||||||
|                            r"(\*\*\* 5th STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6th STREET \*\*\*)|.+))?" |                            r"(\*\*\* 5th STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6th STREET \*\*\*)|.+))?" | ||||||
|                            r"(\*\*\* 6th STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* RIVER \*\*\*)|.+))?" |                            r"(\*\*\* 6th STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* RIVER \*\*\*)|.+))?" | ||||||
|                            r"(\*\*\* RIVER \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL) |                            r"(\*\*\* RIVER \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL) | ||||||
|  |         elif hand.gametype['base'] in ("draw"): | ||||||
|  |             m =  re.search(r"(?P<PREDEAL>.+(?=\*\*\* DEALING HANDS \*\*\*)|.+)" | ||||||
|  |                            r"(\*\*\* DEALING HANDS \*\*\*(?P<DEAL>.+(?=\*\*\* FIRST DRAW \*\*\*)|.+))?" | ||||||
|  |                            r"(\*\*\* FIRST DRAW \*\*\*(?P<DRAWONE>.+(?=\*\*\* SECOND DRAW \*\*\*)|.+))?" | ||||||
|  |                            r"(\*\*\* SECOND DRAW \*\*\*(?P<DRAWTWO>.+(?=\*\*\* THIRD DRAW \*\*\*)|.+))?" | ||||||
|  |                            r"(\*\*\* THIRD DRAW \*\*\*(?P<DRAWTHREE>.+))?", hand.handText,re.DOTALL) | ||||||
|         hand.addStreets(m) |         hand.addStreets(m) | ||||||
| 
 | 
 | ||||||
|     def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand |     def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand | ||||||
|  | @ -245,6 +214,27 @@ follow :  whether to tail -f the input""" | ||||||
|             cards = set(cards.split(' ')) |             cards = set(cards.split(' ')) | ||||||
|             hand.addHoleCards(cards, m.group('PNAME')) |             hand.addHoleCards(cards, m.group('PNAME')) | ||||||
| 
 | 
 | ||||||
|  |     def readDrawCards(self, hand, street): | ||||||
|  |         logging.debug("readDrawCards") | ||||||
|  |         m = self.re_HeroCards.finditer(hand.streets[street]) | ||||||
|  |         if m == None: | ||||||
|  |             hand.involved = False | ||||||
|  |         else: | ||||||
|  |             for player in m: | ||||||
|  |                 hand.hero = player.group('PNAME') # Only really need to do this once | ||||||
|  |                 newcards = player.group('NEWCARDS') | ||||||
|  |                 oldcards = player.group('OLDCARDS') | ||||||
|  |                 if newcards == None: | ||||||
|  |                     newcards = set() | ||||||
|  |                 else: | ||||||
|  |                     newcards = set(newcards.split(' ')) | ||||||
|  |                 if oldcards == None: | ||||||
|  |                     oldcards = set() | ||||||
|  |                 else: | ||||||
|  |                     oldcards = set(oldcards.split(' ')) | ||||||
|  |                 hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     def readStudPlayerCards(self, hand, street): |     def readStudPlayerCards(self, hand, street): | ||||||
|         # See comments of reference implementation in FullTiltToFpdb.py |         # See comments of reference implementation in FullTiltToFpdb.py | ||||||
|         logging.debug("readStudPlayerCards") |         logging.debug("readStudPlayerCards") | ||||||
|  | @ -293,8 +283,12 @@ follow :  whether to tail -f the input""" | ||||||
|                 hand.addFold( street, action.group('PNAME')) |                 hand.addFold( street, action.group('PNAME')) | ||||||
|             elif action.group('ATYPE') == ' checks': |             elif action.group('ATYPE') == ' checks': | ||||||
|                 hand.addCheck( street, action.group('PNAME')) |                 hand.addCheck( street, action.group('PNAME')) | ||||||
|  |             elif action.group('ATYPE') == ' discards': | ||||||
|  |                 hand.addDiscard(street, action.group('PNAME'), action.group('NODISCARDED'), action.group('DISCARDED')) | ||||||
|  |             elif action.group('ATYPE') == ' stands pat': | ||||||
|  |                 hand.addStandsPat( street, action.group('PNAME')) | ||||||
|             else: |             else: | ||||||
|                 print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),) |                 print "DEBUG: unimplemented readAction: '%s' '%s'" %(action.group('PNAME'),action.group('ATYPE'),) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def readShowdownActions(self, hand): |     def readShowdownActions(self, hand): | ||||||
|  |  | ||||||
|  | @ -2,6 +2,8 @@ | ||||||
| import FulltiltToFpdb | import FulltiltToFpdb | ||||||
| import py | import py | ||||||
| 
 | 
 | ||||||
|  | # regression-test-files/fulltilt/nlhe/NLHE-6max-1.txt | ||||||
|  | #   Sorrowful: start: $8.85 end: $14.70 total: $5.85  | ||||||
|      |      | ||||||
| def checkGameInfo(hhc, header, info): | def checkGameInfo(hhc, header, info): | ||||||
|     assert hhc.determineGameType(header) == info |     assert hhc.determineGameType(header) == info | ||||||
|  |  | ||||||
|  | @ -1,7 +1,21 @@ | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| import PokerStarsToFpdb | import PokerStarsToFpdb | ||||||
|  | from Hand import * | ||||||
| import py | import py | ||||||
| 
 | 
 | ||||||
|  | #regression-test-files/stars/badugi/ring-fl-badugi.txt | ||||||
|  | #   s0rrow: start $30.00 end: $22.65 total: ($7.35) | ||||||
|  | 
 | ||||||
|  | gametype = {'type':'ring', 'base':'draw', 'category':'badugi', 'limitType':'fl', 'sb':'0.25', 'bb':'0.50','currency':'USD'} | ||||||
|  | text = "" | ||||||
|  | 
 | ||||||
|  | hhc = PokerStarsToFpdb.PokerStars(autostart=False) | ||||||
|  | 
 | ||||||
|  | h = HoldemOmahaHand(None, "ASite", gametype, text, builtFrom = "Test") | ||||||
|  | h.addPlayer("1", "s0rrow", "100000") | ||||||
|  | 
 | ||||||
|  | hhc.compilePlayerRegexs(h) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| def checkGameInfo(hhc, header, info): | def checkGameInfo(hhc, header, info): | ||||||
|     assert hhc.determineGameType(header) == info |     assert hhc.determineGameType(header) == info | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user