Coverage for PacificPokerToFpdb.py: 0%
307 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-28 16:41 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-28 16:41 +0000
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Copyright 2008-2010, Carl Gherardi
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19########################################################################
22#import L10n
23#_ = L10n.get_translation()
25import sys
26from HandHistoryConverter import *
27from decimal_wrapper import Decimal
29# PacificPoker HH Format
31class PacificPoker(HandHistoryConverter):
33 # Class Variables
35 sitename = "PacificPoker"
36 filetype = "text"
37 codepage = ("utf8", "cp1252")
38 siteId = 10 # Needs to match id entry in Sites database
40 mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} # Legal mixed games
41 sym = {'USD': "\$", 'CAD': "\$", 'T$': "", "EUR": "€", "GBP": "\xa3", "play": ""} # ADD Euro, Sterling, etc HERE
42 substitutions = {
43 'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
44 'PLYR': r'(?P<PNAME>.+?)',
45 'LS' : u"\$|€|", # legal currency symbols - Euro(cp1252, utf-8)
46 'NUM' : u"\s.,\d\xa0",
47 'CUR' : u"(\$|€|)"
48 }
50 # translations from captured groups to fpdb info strings
51 # not needed for PacificPoker
52 #Lim_Blinds = { '0.01': ('0.01', '0.02'),
53 # '0.02': ('0.02', '0.04'),
54 # '0.03': ('0.03', '0.06'),
55 # '0.05': ('0.05', '0.10'),
56 # '0.12': ('0.12', '0.25'),
57 # '0.25': ('0.25', '0.50'),
58 # '0.50': ('0.50', '1.00'),
59 # '1.00': ('1.00', '2.00'), '1': ('1.00', '2.00'),
60 # '2.00': ('2.00', '4.00'), '2': ('2.00', '4.00'),
61 # '3.00': ('3.00', '6.00'), '3': ('3.00', '6.00'),
62 # '5.00': ('5.00', '10.00'), '5': ('5.00', '10.00'),
63 # '10.00': ('10.00', '20.00'), '10': ('10.00', '20.00'),
64 # '15.00': ('15.00', '30.00'), '15': ('15.00', '30.00'),
65 # '30.00': ('30.00', '60.00'), '30': ('30.00', '60.00'),
66 # '50.00': ('50.00', '100.00'), '50': ('50.00', '100.00'),
67 # '75.00': ('75.00', '150.00'), '75': ('75.00', '150.00'),
68 # '100.00': ('100.00', '200.00'), '100': ('100.00', '200.00'),
69 # '200.00': ('200.00', '400.00'), '200': ('200.00', '400.00'),
70 # '250.00': ('250.00', '500.00'), '250': ('250.00', '500.00')
71 # }
73 limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl', 'LIMIT':'fl', 'Fix Limit':'fl' }
75 games = { # base, category
76 "Hold'em" : ('hold','holdem'),
77 'Holdem' : ('hold','holdem'),
78 'Omaha' : ('hold','omahahi'),
79 'Omaha Hi/Lo' : ('hold','omahahilo'),
80 'OmahaHL' : ('hold','omahahilo')
81 }
83 currencies = { u'€':'EUR', '$':'USD', '':'T$' }
85 # Static regexes
86 re_GameInfo = re.compile(u"""
87 (\#Game\sNo\s:\s[0-9]+\\n)?
88 \*\*\*\*\*?\s(Cassava|888poker|888)(\.[a-z]{2})?(\-[a-z]{2})?\s(?P<FAST>Snap\sPoker\s)?(BLAST\s)?Hand\sHistory\sfor\sGame\s(?P<HID>[0-9]+)\s\*\*\*\*\*\\n
89 (?P<CURRENCY1>%(LS)s)?\s?(?P<SB>[%(NUM)s]+)\s?(?P<CURRENCY2>%(LS)s)?/(%(LS)s)?\s?(?P<BB>[%(NUM)s]+)\s?(%(LS)s)?\sBlinds\s
90 (?P<LIMIT>No\sLimit|Fix\sLimit|Pot\sLimit)\s
91 (?P<GAME>Holdem|Omaha|OmahaHL|Hold\'em|Omaha\sHi/Lo|OmahaHL)
92 (\sJackpot\stable)?
93 \s-\s\*\*\*\s
94 (?P<DATETIME>.*$)\s
95 (Tournament\s\#(?P<TOURNO>\d+))?
96 """ % substitutions, re.MULTILINE|re.VERBOSE)
98 re_PlayerInfo = re.compile(u"""
99 ^Seat\s(?P<SEAT>[0-9]+):\s
100 (?P<PNAME>.*)\s
101 \(\s(%(LS)s)?\s?(?P<CASH>[%(NUM)s]+)\s?(%(LS)s)?\s\)""" % substitutions,
102 re.MULTILINE|re.VERBOSE)
104 re_HandInfo = re.compile("""
105 ^(
106 (Table\s(?P<TABLE>[-\ \#a-zA-Z\d]+?)\s)
107 |
108 (Tournament\s\#(?P<TOURNO>\d+)\s
109 (
110 (?P<BUYIN>(
111 ((?P<BIAMT>(%(LS)s)?\s?[%(NUM)s]+\s?(%(LS)s)?)(\s\+\s?(?P<BIRAKE>(%(LS)s)?\s?[%(NUM)s]+\s?(%(LS)s)?))?)
112 |
113 (Free)
114 |
115 (.+?)
116 ))
117 )
118 (\s-\sTable\s\#(?P<TABLEID>\d+))?\s
119 )
120 )
121 ((?P<MAX>\d+)\sMax\s)?
122 (\(Real\sMoney\))?
123 (?P<PLAY>\((Practice\sPlay|Play\sMoney)\))?
124 \\n
125 Seat\s(?P<BUTTON>[0-9]+)\sis\sthe\sbutton
126 """ % substitutions, re.MULTILINE|re.VERBOSE)
128 re_Identify = re.compile(u'\*{4,5}\s(Cassava|888poker|888)(\.[a-z]{2})?(\-[a-z]{2})?\s(Snap\sPoker\s|BLAST\s)?Hand\sHistory\sfor\sGame\s\d+\s')
129 re_SplitHands = re.compile('\n\n+')
130 re_TailSplitHands = re.compile('(\n\n\n+)')
131 re_Button = re.compile('Seat (?P<BUTTON>\d+) is the button', re.MULTILINE)
132 re_Board = re.compile(u"\[\s(?P<CARDS>.+)\s\]")
133 re_Spanish_10 = re.compile(u'D([tpeo])')
135 re_DateTime = re.compile("""(?P<D>[0-9]{2})\s(?P<M>[0-9]{2})\s(?P<Y>[0-9]{4})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)""", re.MULTILINE)
137 short_subst = {'PLYR': r'(?P<PNAME>.+?)', 'CUR': '\$?', 'NUM' : u".,\d\xa0"}
138 re_PostSB = re.compile(r"^%(PLYR)s posts small blind \[(%(CUR)s)?\s?(?P<SB>[%(NUM)s]+)\s?(%(CUR)s)?\]" % substitutions, re.MULTILINE)
139 re_PostBB = re.compile(r"^%(PLYR)s posts big blind \[(%(CUR)s)?\s?(?P<BB>[%(NUM)s]+)\s?(%(CUR)s)?\]" % substitutions, re.MULTILINE)
140 re_Antes = re.compile(r"^%(PLYR)s posts (the\s)?ante \[(%(CUR)s)?\s?(?P<ANTE>[%(NUM)s]+)\s?(%(CUR)s)?\]" % substitutions, re.MULTILINE)
141 # TODO: unknown in available hand histories for pacificpoker:
142 re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for (%(CUR)s)?\s?(?P<BRINGIN>[%(NUM)s]+)\s?(%(CUR)s)?" % substitutions, re.MULTILINE)
143 re_PostBoth = re.compile(r"^%(PLYR)s posts dead blind \[(%(CUR)s)?\s?(?P<SB>[%(NUM)s]+)\s?(%(CUR)s)?\s\+\s(%(CUR)s)?\s?(?P<BB>[%(NUM)s]+)\s?(%(CUR)s)?\]" % substitutions, re.MULTILINE)
144 re_HeroCards = re.compile(r"^Dealt to %(PLYR)s( \[\s(?P<NEWCARDS>.+?)\s\])" % substitutions, re.MULTILINE)
145 re_Action = re.compile(r"""
146 ^%(PLYR)s(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat)
147 (\s\[(%(CUR)s)?\s?(?P<BET>[%(NUM)s]+)\s?(%(CUR)s)?\])?
148 (\s*and\sis\sall.in)?
149 (\s*and\shas\sreached\sthe\s[%(CUR)s\s?\d\.]+\scap)?
150 (\s*cards?(\s\[(?P<DISCARDED>.+?)\])?)?\s*$"""
151 % substitutions, re.MULTILINE|re.VERBOSE)
152 re_ShowdownAction = re.compile(r"^%s shows \[(?P<CARDS>.*)\]" % substitutions['PLYR'], re.MULTILINE)
153 re_sitsOut = re.compile("^%s sits out" % substitutions['PLYR'], re.MULTILINE)
154 re_ShownCards = re.compile("^%s ?(?P<SHOWED>shows|mucks) \[ (?P<CARDS>.*) \]$" % substitutions['PLYR'], re.MULTILINE)
155 re_CollectPot = re.compile(r"^%(PLYR)s collected \[ (%(CUR)s)?\s?(?P<POT>[%(NUM)s]+)\s?(%(CUR)s)? \]$" % substitutions, re.MULTILINE)
157 def compilePlayerRegexs(self, hand):
158 pass
160 def readSupportedGames(self):
161 return [["ring", "hold", "nl"],
162 ["ring", "hold", "pl"],
163 ["ring", "hold", "fl"],
165 ["tour", "hold", "nl"],
166 ["tour", "hold", "pl"],
167 ["tour", "hold", "fl"],
168 ]
170 def determineGameType(self, handText):
171 info = {}
172 m = self.re_GameInfo.search(handText)
173 if not m:
174 tmp = handText[0:200]
175 log.error(("PacificPokerToFpdb.determineGameType: '%s'") % tmp)
176 raise FpdbParseError
178 mg = m.groupdict()
179 #print "DEBUG: mg: ", mg
180 if 'LIMIT' in mg:
181 #print "DEBUG: re_GameInfo[LIMIT] \'", mg['LIMIT'], "\'"
182 info['limitType'] = self.limits[mg['LIMIT']]
183 if 'GAME' in mg:
184 #print "DEBUG: re_GameInfo[GAME] \'", mg['GAME'], "\'"
185 (info['base'], info['category']) = self.games[mg['GAME']]
186 if 'SB' in mg:
187 #print "DEBUG: re_GameInfo[SB] \'", mg['SB'], "\'"
188 info['sb'] = self.clearMoneyString(mg['SB'])
189 if 'BB' in mg:
190 #print "DEBUG: re_GameInfo[BB] \'", mg['BB'], "\'"
191 info['bb'] = self.clearMoneyString(mg['BB'])
192 if 'CURRENCY1' in mg:
193 #print "DEBUG: re_GameInfo[CURRENCY] \'", mg['CURRENCY'], "\'"
194 info['currency'] = self.currencies[mg['CURRENCY1']]
195 if 'CURRENCY2' in mg and mg['CURRENCY2']:
196 #print "DEBUG: re_GameInfo[CURRENCY] \'", mg['CURRENCY'], "\'"
197 info['currency'] = self.currencies[mg['CURRENCY2']]
198 if 'FAST' in mg and mg['FAST'] is not None:
199 info['fast'] = True
201 if 'TOURNO' in mg and mg['TOURNO'] is not None:
202 info['type'] = 'tour'
203 info['currency'] = 'T$'
204 else:
205 info['type'] = 'ring'
207 # Pacific Poker includes the blind levels in the gametype, the following is not needed.
208 #if info['limitType'] == 'fl' and info['bb'] is not None and info['type'] == 'ring' and info['base'] != 'stud':
209 # try:
210 # info['sb'] = self.Lim_Blinds[mg['BB']][0]
211 # info['bb'] = self.Lim_Blinds[mg['BB']][1]
212 # except KeyError:
213 # log.error(("determineGameType: Lim_Blinds has no lookup for '%s'" % mg['BB']))
214 # log.error(("determineGameType: Raising FpdbParseError"))
215 # raise FpdbParseError(("Lim_Blinds has no lookup for '%s'") % mg['BB'])
217 return info
219 def readHandInfo(self, hand):
220 info = {}
221 m = self.re_HandInfo.search(hand.handText,re.DOTALL)
222 if m is None:
223 log.error("re_HandInfo could not be parsed")
224 m2 = self.re_GameInfo.search(hand.handText)
225 if m2 is None:
226 log.error("re_GameInfo could not be parsed")
227 if m is None or m2 is None:
228 tmp = hand.handText[0:200]
229 log.error(("PacificPokerToFpdb.readHandInfo: '%s'") % tmp)
230 raise FpdbParseError
232 info.update(m.groupdict())
233 info.update(m2.groupdict())
235 #log.debug("readHandInfo: %s" % info)
236 for key in info:
237 if key == 'DATETIME':
238 # 28 11 2011 19:05:11
239 m1 = self.re_DateTime.finditer(info[key])
240 datetimestr = "2000/01/01 00:00:00" # default used if time not found
241 for a in m1:
242 datetimestr = "%s/%s/%s %s:%s:%s" % (a.group('Y'), a.group('M'),a.group('D'),a.group('H'),a.group('MIN'),a.group('S'))
243 hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S")
244 hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, "ET", "UTC")
245 hand.newFormat = datetime.datetime.strptime('20220908000000', '%Y%m%d%H%M%S') # this is a guess
246 hand.newFormat = HandHistoryConverter.changeTimezone(hand.newFormat, "ET", "UTC")
247 if key == 'HID':
248 hand.handid = info[key]
249 if key == 'TOURNO' and info['TOURNO'] != None:
250 hand.tourNo = info[key]
251 hand.isKO = False
252 if key == 'BUYIN' and info['BUYIN'] != None:
253 if info[key] == 'Free' or info['BIAMT'] is None:
254 hand.buyin = 0
255 hand.fee = 0
256 hand.buyinCurrency = "FREE"
257 else:
258 if info['BUYIN'].find("$")!=-1:
259 hand.buyinCurrency="USD"
260 elif info['BUYIN'].find(u"€")!=-1:
261 hand.buyinCurrency="EUR"
262 elif 'PLAY' in info and info['PLAY'] != "Practice Play" and info['PLAY'] != "Play Money":
263 hand.buyinCurrency="FREE"
264 else:
265 #FIXME: handle other currencies, FPP, play money
266 log.error(("PacificPokerToFpdb.readHandInfo: Failed to detect currency.") + " Hand ID: %s: '%s'" % (hand.handid, info[key]))
267 raise FpdbParseError
269 info['BIAMT'] = self.clearMoneyString(info['BIAMT'].strip(u'$€'))
270 hand.buyin = int(100*Decimal(info['BIAMT']))
272 if info['BIRAKE'] is None:
273 hand.fee = 0
274 else:
275 info['BIRAKE'] = self.clearMoneyString(info['BIRAKE'].strip(u'$€'))
276 hand.fee = int(100*Decimal(info['BIRAKE']))
278 if key == 'TABLE' and info['TABLE'] != None:
279 hand.tablename = info[key]
280 if key == 'TABLEID' and info['TABLEID'] != None:
281 hand.tablename = info[key]
282 if key == 'BUTTON':
283 hand.buttonpos = info[key]
284 if key == 'MAX' and info['MAX'] != None:
285 hand.maxseats = int(info[key])
287 if key == 'PLAY' and info['PLAY'] is not None:
288 #hand.currency = 'play' # overrides previously set value
289 hand.gametype['currency'] = 'play'
291 if 'TOURNO' in info and info['TOURNO'] is not None and hand.tablename == "":
292 hand.tablename = 1
294 def readButton(self, hand):
295 m = self.re_Button.search(hand.handText)
296 if m:
297 hand.buttonpos = int(m.group('BUTTON'))
298 else:
299 log.info('readButton: ' + ('not found'))
301 def readPlayerStacks(self, hand):
302 m = self.re_PlayerInfo.finditer(hand.handText)
303 for a in m:
304 if (len(a.group('PNAME'))==0):
305 log.error("PacificPokerToFpdb.readPlayerStacks: Player name empty %s" % hand.handid)
306 raise FpdbParseError
307 hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), self.clearMoneyString(a.group('CASH')))
309 def markStreets(self, hand):
310 # PREFLOP = ** Dealing down cards ** (observed hands don't have this line)
311 # This re fails if, say, river is missing; then we don't get the ** that starts the river.
312 if hand.gametype['base'] in ("hold"):
313 m = re.search(r"(?P<PREFLOP>.+(?=\*\* Dealing flop \*\*)|.+)"
314 r"(\*\* Dealing flop \*\* (?P<FLOP>\[ \S\S, \S\S, \S\S \].+(?=\*\* Dealing turn \*\*)|.+))?"
315 r"(\*\* Dealing turn \*\* (?P<TURN>\[ \S\S \].+(?=\*\* Dealing river \*\*)|.+))?"
316 r"(\*\* Dealing river \*\* (?P<RIVER>\[ \S\S \].+?(?=\*\* Summary \*\*)|.+))?"
317 , hand.handText,re.DOTALL)
318 if m is None:
319 log.error(("PacificPokerToFpdb.markStreets: Unable to recognise streets %s" % hand.handid))
320 raise FpdbParseError
321 else:
322 #print "DEBUG: Matched markStreets"
323 mg = m.groupdict()
324# if 'PREFLOP' in mg:
325# print "DEBUG: PREFLOP: ", [mg['PREFLOP']]
326# if 'FLOP' in mg:
327# print "DEBUG: FLOP: ", [mg['FLOP']]
328# if 'TURN' in mg:
329# print "DEBUG: TURN: ", [mg['TURN']]
330# if 'RIVER' in mg:
331# print "DEBUG: RIVER: ", [mg['RIVER']]
333 hand.addStreets(m)
335 def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
336 if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
337 #print "DEBUG readCommunityCards:", street, hand.streets.group(street)
338 m = self.re_Board.search(hand.streets[street])
339 cards = self.splitCards(m.group('CARDS'))
340 hand.setCommunityCards(street, cards)
342 def readAntes(self, hand):
343 m = self.re_Antes.finditer(hand.handText)
344 for player in m:
345 #~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
346 hand.addAnte(player.group('PNAME'), self.clearMoneyString(player.group('ANTE')))
347 self.allInBlind(hand, 'PREFLOP', player, 'ante')
349 def readBringIn(self, hand):
350 m = self.re_BringIn.search(hand.handText,re.DOTALL)
351 if m:
352 #~ logging.debug("readBringIn: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
353 hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
355 def readBlinds(self, hand):
356 if hand.startTime < hand.newFormat:
357 hand.setUncalledBets(True)
358 liveBlind, hand.allInBlind = True, False
359 for a in self.re_PostSB.finditer(hand.handText):
360 if a.group('PNAME') in hand.stacks:
361 if liveBlind:
362 hand.addBlind(a.group('PNAME'), 'small blind', self.clearMoneyString(a.group('SB')))
363 liveBlind = False
364 else:
365 # Post dead blinds as ante
366 hand.addBlind(a.group('PNAME'), 'secondsb', self.clearMoneyString(a.group('SB')))
367 self.allInBlind(hand, 'PREFLOP', a, 'secondsb')
368 else:
369 log.error("PacificPokerToFpdb.readBlinds (SB): '%s', '%s' not in hand.stacks" % (hand.handid, a.group('PNAME')))
370 raise FpdbParseError
371 for a in self.re_PostBB.finditer(hand.handText):
372 if a.group('PNAME') in hand.stacks:
373 hand.addBlind(a.group('PNAME'), 'big blind', self.clearMoneyString(a.group('BB')))
374 self.allInBlind(hand, 'PREFLOP', a, 'big blind')
375 else:
376 log.error("PacificPokerToFpdb.readBlinds (BB): '%s', '%s' not in hand.stacks" % (hand.handid, a.group('PNAME')))
377 raise FpdbParseError
378 for a in self.re_PostBoth.finditer(hand.handText):
379 if a.group('PNAME') in hand.stacks:
380 if Decimal(self.clearMoneyString(a.group('BB')))>0:
381 bb = self.clearMoneyString(a.group('BB'))
382 sb = self.clearMoneyString(a.group('SB'))
383 both = str(Decimal(bb) + Decimal(sb))
384 hand.addBlind(a.group('PNAME'), 'both', both)
385 else:
386 hand.addBlind(a.group('PNAME'), 'secondsb', self.clearMoneyString(a.group('SB')))
387 self.allInBlind(hand, 'PREFLOP', a, 'both')
388 else:
389 log.error("PacificPokerToFpdb.readBlinds (Both): '%s', '%s' not in hand.stacks" % (hand.handid, a.group('PNAME')))
390 raise FpdbParseError
392 def readHoleCards(self, hand):
393# streets PREFLOP, PREDRAW, and THIRD are special cases beacause
394# we need to grab hero's cards
395 for street in ('PREFLOP', 'DEAL'):
396 if street in list(hand.streets.keys()):
397 m = self.re_HeroCards.finditer(hand.streets[street])
398 for found in m:
399# if m == None:
400# hand.involved = False
401# else:
402 hand.hero = found.group('PNAME')
403 newcards = self.splitCards(found.group('NEWCARDS'))
404 hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
406 for street, text in list(hand.streets.items()):
407 if not text or street in ('PREFLOP', 'DEAL'): continue # already done these
408 m = self.re_HeroCards.finditer(hand.streets[street])
409 for found in m:
410 player = found.group('PNAME')
411 if found.group('NEWCARDS') is None:
412 newcards = []
413 else:
414 newcards = self.splitCards(found.group('NEWCARDS'))
415 if found.group('OLDCARDS') is None:
416 oldcards = []
417 else:
418 oldcards = self.splitCards(found.group('OLDCARDS'))
420 if street == 'THIRD' and len(newcards) == 3: # hero in stud game
421 hand.hero = player
422 hand.dealt.add(player) # need this for stud??
423 hand.addHoleCards(street, player, closed=newcards[0:2], open=[newcards[2]], shown=False, mucked=False, dealt=False)
424 else:
425 hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False)
428 def readAction(self, hand, street):
429 m = self.re_Action.finditer(hand.streets[street])
430 for action in m:
431 acts = action.groupdict()
432 if street not in ('PREFLOP', 'DEAL'):
433 hand.setUncalledBets(False)
434 #print "DEBUG: acts: %s" %acts
435 bet = self.clearMoneyString(action.group('BET')) if action.group('BET') else None
436 if action.group('PNAME') in hand.stacks:
437 if action.group('ATYPE') == ' folds':
438 hand.addFold( street, action.group('PNAME'))
439 elif action.group('ATYPE') == ' checks':
440 hand.addCheck( street, action.group('PNAME'))
441 elif action.group('ATYPE') == ' calls':
442 hand.addCall( street, action.group('PNAME'), bet)
443 elif action.group('ATYPE') == ' raises':
444 hand.addCallandRaise( street, action.group('PNAME'), bet)
445 elif action.group('ATYPE') == ' bets':
446 hand.addBet( street, action.group('PNAME'), bet )
447 elif action.group('ATYPE') == ' discards':
448 hand.addDiscard(street, action.group('PNAME'), bet, action.group('DISCARDED'))
449 elif action.group('ATYPE') == ' stands pat':
450 hand.addStandsPat( street, action.group('PNAME'))
451 else:
452 log.debug(("DEBUG:") + " " + "Unimplemented %s: '%s' '%s'") % ("readAction", action.group('PNAME'), action.group('ATYPE'))
454 if action.group('ATYPE') not in (' checks', ' folds'):
455 if not hand.allInBlind:
456 if not (hand.stacks[action.group('PNAME')]==0 and action.group('ATYPE') ==' calls' ):
457 hand.setUncalledBets(False)
458 if (hand.stacks[action.group('PNAME')]==0 and action.group('ATYPE') ==' raises' ):
459 hand.checkForUncalled = True
460 else:
461 log.error("PacificPokerToFpdb.readAction: '%s', '%s' not in hand.stacks" % (hand.handid, action.group('PNAME')))
462 raise FpdbParseError
464 def allInBlind(self, hand, street, action, actiontype):
465 if street in ('PREFLOP', 'DEAL'):
466 if hand.stacks[action.group('PNAME')]==0:
467 if actiontype=='ante':
468 if action.group('PNAME') in [p for (p,b) in hand.posted]:
469 hand.setUncalledBets(False)
470 hand.checkForUncalled = True
471 hand.allInBlind = True
472 elif actiontype in ('secondsb', 'big blind', 'both') and not self.re_Antes.search(hand.handText):
473 hand.setUncalledBets(False)
474 hand.checkForUncalled = True
475 hand.allInBlind = True
477 def readShowdownActions(self, hand):
478 # TODO: pick up mucks also??
479 for shows in self.re_ShowdownAction.finditer(hand.handText):
480 cards = shows.group('CARDS').split(', ')
481 hand.addShownCards(cards, shows.group('PNAME'))
483 def readCollectPot(self,hand):
484 for m in self.re_CollectPot.finditer(hand.handText):
485 #print "DEBUG: hand.addCollectPot(player=", m.group('PNAME'), ", pot=", m.group('POT'), ")"
486 hand.addCollectPot(player=m.group('PNAME'),pot=self.clearMoneyString(m.group('POT')))
488 def readShownCards(self,hand):
489 for m in self.re_ShownCards.finditer(hand.handText):
490 if m.group('CARDS') is not None:
491 cards = m.group('CARDS')
492 cards = self.splitCards(cards)
494 (shown, mucked) = (False, False)
495 if m.group('SHOWED') == "shows": shown = True
496 elif m.group('SHOWED') == "mucks": mucked = True
498 #print "DEBUG: hand.addShownCards(%s, %s, %s, %s)" %(cards, m.group('PNAME'), shown, mucked)
499 hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked)
501 def splitCards(self, cards):
502 #Polish
503 cards = cards.replace(u'Kreuz', 'c')
504 cards = cards.replace(u'Karo', 'd')
505 cards = cards.replace(u'Pik', 's')
506 cards = cards.replace(u'Herz', 'h')
507 cards = cards.replace(u'10', 'T')
508 #Russian
509 cards = cards.replace(u'\xd2', 'Q')
510 cards = cards.replace(u'\xc2', 'A')
511 cards = cards.replace(u'\xc4', 'J')
512 #Spanish
513 cards = self.re_Spanish_10.sub('T\g<1>', cards)
514 cards = cards.replace(u't', 'h')
515 cards = cards.replace(u'p', 's')
516 cards = cards.replace(u'e', 'd')
517 cards = cards.replace(u'o', 'h')
518 #Dutch
519 cards = cards.replace(u'B', 'J')
520 cards = cards.replace(u'V', 'Q')
521 cards = cards.replace(u'H', 'K')
522 #Swedish
523 cards = cards.replace(u'Kn', 'J')
524 cards = cards.replace(u'D', 'Q')
525 cards = cards.replace(u'E', 'A')
526 cards = cards.split(', ')
527 return cards
529 @staticmethod
530 def getTableTitleRe(type, table_name=None, tournament = None, table_number=None):
531 # Tournament tables look like:
532 # Tour NLH 50+5 Brouhaha ID #28353026 Table #7 Blinds: 200/400
533 log.info("Pacific.getTableTitleRe: table_name='%s' tournament='%s' table_number='%s'" % (table_name, tournament, table_number))
534 regex = "%s" % (table_name)
535 if tournament:
536 regex = "%s Table #%s" % (tournament, table_number)
538 log.info("Pacific.getTableTitleRe: returns: '%s'" % (regex))
539 return regex
541 def readSummaryInfo(self, summaryInfoList):
542 self.status = True
543 return self.status