#!/usr/bin/env python # -*- coding: utf-8 -*- # # Copyright 2011, Carl Gherardi # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # 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 General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ######################################################################## import L10n _ = L10n.get_translation() import sys import logging from HandHistoryConverter import * from decimal import Decimal class Everest(HandHistoryConverter): sitename = "Everest" filetype = "text" codepage = "utf8" siteID = 15 substitutions = { 'LS' : u"\$|\xe2\x82\xac|\u20ac|", 'TAB' : u"-\u2013'\s\da-zA-Z", # legal characters for tablename } # Static regexes re_SplitHands = re.compile(r'\n+(?=)') re_GameInfo = re.compile(u""" """ % substitutions, re.VERBOSE|re.MULTILINE) re_HandInfo = re.compile(r'[0-9]+)"\/>') re_PlayerInfo = re.compile(r'', re.MULTILINE) re_Board = re.compile(r'(?P.+)<\/COMMUNITY>', re.MULTILINE) # The following are also static regexes: there is no need to call # compilePlayerRegexes (which does nothing), since players are identified # not by name but by seat number re_PostXB = re.compile(r'', re.MULTILINE) #re_Antes = ??? #re_BringIn = ??? re_HeroCards = re.compile(r'FOLD|BET) position="(?P[0-9])"( amount="(?P[.0-9]+)")?\/>', re.MULTILINE) re_ShowdownAction = re.compile(r'', re.MULTILINE) re_CollectPot = re.compile(r'', re.MULTILINE) re_ShownCards = re.compile(r'', re.MULTILINE) def compilePlayerRegexs(self, hand): pass def playerNameFromSeatNo(self, seatNo, hand): # Actions recorded by seat number, not by the player's name for p in hand.players: if p[0] == seatNo: return p[1] def readSupportedGames(self): return [ ["ring", "hold", "nl"], ["ring", "hold", "pl"], #["tour", "hold", "nl"] ] def determineGameType(self, handText): m = self.re_GameInfo.search(handText) m2 = self.re_HandInfo.search(handText) if not m: # Information about the game type appears only at the beginning of # a hand history file; hence it is not supplied with the second # and subsequent hands. In these cases we use the value previously # stored. try: self.info return self.info except AttributeError: tmp = handText[0:100] log.error(_("determineGameType: Unable to recognise gametype from: '%s'") % tmp) log.error(_("determineGameType: Raising FpdbParseError")) raise FpdbParseError(_("Unable to recognise gametype from: '%s'") % tmp) if not m2: tmp = handText[0:100] raise FpdbParseError(_("Unable to recognise handinfo from: '%s'") % tmp) self.info = {} mg = m.groupdict() mg.update(m2.groupdict()) print "DEBUG: mg: %s" % mg limits = { 'No Limit':'nl', 'No Limit ':'nl', 'Limit':'fl', 'pot-limit':'pl' } games = { # base, category 'Holdem' : ('hold','holdem'), 'Holdem Tournament' : ('hold','holdem'), 'omaha-hi' : ('hold','omahahi'), } if 'LIMIT' in mg: self.info['limitType'] = limits[mg['LIMIT']] if 'GAME' in mg: (self.info['base'], self.info['category']) = games[mg['GAME']] if 'SB' in mg: self.info['sb'] = mg['SB'] if 'BB' in mg: self.info['bb'] = mg['BB'] self.info['type'] = 'ring' if mg['CURRENCY'] == u'\u20ac': self.info['currency'] = 'EUR' # HACK - tablename not in every hand. self.info['TABLENAME'] = mg['TABLE'] print "DEBUG: self.info: %s" % self.info return self.info def readHandInfo(self, hand): m = self.re_HandInfo.search(hand.handText) if m is None: logging.info(_("Didn't match re_HandInfo")) logging.info(hand.handText) raise FpdbParseError(_("No match in readHandInfo.")) hand.handid = m.group('HID') hand.tablename = self.info['TABLENAME'] hand.maxseats = None #FIXME: u'DATETIME': u'1291155932' hand.startTime = datetime.datetime.strptime('201102091158', '%Y%m%d%H%M') #hand.startTime = datetime.datetime.strptime(m.group('DATETIME')[:12], '%Y%m%d%H%M') def readPlayerStacks(self, hand): m = self.re_PlayerInfo.finditer(hand.handText) for a in m: hand.addPlayer(a.group('SEAT'), a.group('PNAME'), a.group('CASH')) def markStreets(self, hand): #if hand.gametype['base'] == 'hold': m = re.search(r".+?(?=)|.+)" r"((?P\S\S, \S\S, \S\S<\/COMMUNITY>.+?(?=)|.+))?" r"((?P\S\S<\/COMMUNITY>.+?(?=)|.+))?" r"((?P\S\S<\/COMMUNITY>.+))?", hand.handText,re.DOTALL) #import pprint #pp = pprint.PrettyPrinter(indent=4) #pp.pprint(m.groupdict()) hand.addStreets(m) def readCommunityCards(self, hand, street): m = self.re_Board.search(hand.streets[street]) if street == 'FLOP': hand.setCommunityCards(street, m.group('CARDS').split(',')) elif street in ('TURN','RIVER'): hand.setCommunityCards(street, [m.group('CARDS').split(',')[-1]]) def readAntes(self, hand): pass # ??? def readBringIn(self, hand): pass # ??? def readBlinds(self, hand): for a in self.re_PostXB.finditer(hand.handText): amount = "%.2f" % float(int(a.group('XB'))/100) print "DEBUG: readBlinds amount: %s" % amount if Decimal(a.group('XB'))/100 == Decimal(self.info['sb']): hand.addBlind(self.playerNameFromSeatNo(a.group('PSEAT'), hand),'small blind', amount) elif Decimal(a.group('XB'))/100 == Decimal(self.info['bb']): hand.addBlind(self.playerNameFromSeatNo(a.group('PSEAT'), hand),'big blind', amount) def readButton(self, hand): hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON')) def readHeroCards(self, hand): m = self.re_HeroCards.search(hand.handText) if m: hand.hero = self.playerNameFromSeatNo(m.group('PSEAT'), hand) cards = m.group('CARDS').split(',') hand.addHoleCards('PREFLOP', hand.hero, closed=cards, shown=False, mucked=False, dealt=True) def readAction(self, hand, street): print "DEBUG: readAction (%s)" % street m = self.re_Action.finditer(hand.streets[street]) curr_pot = Decimal('0') for action in m: print " DEBUG: %s %s" % (action.group('ATYPE'), action.groupdict()) player = self.playerNameFromSeatNo(action.group('PSEAT'), hand) if action.group('ATYPE') == 'BET': amount = Decimal(action.group('BET')) amountstr = "%.2f" % float(int(action.group('BET'))/100) #Gah! BET can mean check, bet, call or raise... if amount > 0 and curr_pot == 0: # Open curr_pot = amount hand.addBet(street, player, amountstr) elif Decimal(action.group('BET')) > 0 and curr_pot > 0: # Raise or call if amount > curr_pot: # Raise curr_pot = amount hand.addCallandRaise(street, player, amountstr) elif amount <= curr_pot: # Call hand.addCall(street, player, amountstr) if action.group('BET') == '0': hand.addCheck(street, player) elif action.group('ATYPE') in ('FOLD', 'SIT_OUT'): hand.addFold(street, player) else: print (_("Unimplemented readAction: %s %s" % (action.group('PSEAT'),action.group('ATYPE'),))) logging.debug(_("Unimplemented readAction: %s %s" % (action.group('PSEAT'),action.group('ATYPE'),))) def readShowdownActions(self, hand): for shows in self.re_ShowdownAction.finditer(hand.handText): cards = shows.group('CARDS').split(',') hand.addShownCards(cards, self.playerNameFromSeatNo(shows.group('PSEAT'), hand)) def readCollectPot(self, hand): for m in self.re_CollectPot.finditer(hand.handText): player = self.playerNameFromSeatNo(m.group('PSEAT'), hand) print "DEBUG: %s collects %s" % (player, m.group('POT')) hand.addCollectPot(player, str(int(m.group('POT'))/100)) def readShownCards(self, hand): for m in self.re_ShownCards.finditer(hand.handText): cards = m.group('CARDS').split(',') hand.addShownCards(cards=cards, player=self.playerNameFromSeatNo(m.group('PSEAT'), hand))