Coverage for PacificPokerToFpdb.py: 0%
313 statements
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-14 11:07 +0000
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-14 11:07 +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()
25from HandHistoryConverter import HandHistoryConverter, FpdbParseError
26from decimal import Decimal
27import re
28import logging
29import datetime
32# PacificPoker(888) HH Format
33log = logging.getLogger("parser")
36class PacificPoker(HandHistoryConverter):
37 # Class Variables
39 sitename = "PacificPoker"
40 filetype = "text"
41 codepage = ("utf8", "cp1252")
42 siteId = 10 # Needs to match id entry in Sites database
44 mixes = {"HORSE": "horse", "8-Game": "8game", "HOSE": "hose"} # Legal mixed games
45 sym = {"USD": "\$", "CAD": "\$", "T$": "", "EUR": "€", "GBP": "\xa3", "play": ""} # ADD Euro, Sterling, etc HERE
46 substitutions = {
47 "LEGAL_ISO": "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
48 "PLYR": r"(?P<PNAME>.+?)",
49 "LS": "\$|€|", # legal currency symbols - Euro(cp1252, utf-8)
50 "NUM": "\s.,\d\xa0",
51 "CUR": "(\$|€|)",
52 }
54 # translations from captured groups to fpdb info strings
55 # not needed for PacificPoker
56 # Lim_Blinds = { '0.01': ('0.01', '0.02'),
57 # '0.02': ('0.02', '0.04'),
58 # '0.03': ('0.03', '0.06'),
59 # '0.05': ('0.05', '0.10'),
60 # '0.12': ('0.12', '0.25'),
61 # '0.25': ('0.25', '0.50'),
62 # '0.50': ('0.50', '1.00'),
63 # '1.00': ('1.00', '2.00'), '1': ('1.00', '2.00'),
64 # '2.00': ('2.00', '4.00'), '2': ('2.00', '4.00'),
65 # '3.00': ('3.00', '6.00'), '3': ('3.00', '6.00'),
66 # '5.00': ('5.00', '10.00'), '5': ('5.00', '10.00'),
67 # '10.00': ('10.00', '20.00'), '10': ('10.00', '20.00'),
68 # '15.00': ('15.00', '30.00'), '15': ('15.00', '30.00'),
69 # '30.00': ('30.00', '60.00'), '30': ('30.00', '60.00'),
70 # '50.00': ('50.00', '100.00'), '50': ('50.00', '100.00'),
71 # '75.00': ('75.00', '150.00'), '75': ('75.00', '150.00'),
72 # '100.00': ('100.00', '200.00'), '100': ('100.00', '200.00'),
73 # '200.00': ('200.00', '400.00'), '200': ('200.00', '400.00'),
74 # '250.00': ('250.00', '500.00'), '250': ('250.00', '500.00')
75 # }
77 limits = {"No Limit": "nl", "Pot Limit": "pl", "Limit": "fl", "LIMIT": "fl", "Fix Limit": "fl"}
79 games = { # base, category
80 "Hold'em": ("hold", "holdem"),
81 "Holdem": ("hold", "holdem"),
82 "Omaha": ("hold", "omahahi"),
83 "Omaha Hi/Lo": ("hold", "omahahilo"),
84 "OmahaHL": ("hold", "omahahilo"),
85 }
87 currencies = {"€": "EUR", "$": "USD", "": "T$"}
89 # Static regexes
90 re_GameInfo = re.compile(
91 """
92 (\#Game\sNo\s:\s[0-9]+\\n)?
93 \*\*\*\*\*?\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
94 (?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
95 (?P<LIMIT>No\sLimit|Fix\sLimit|Pot\sLimit)\s
96 (?P<GAME>Holdem|Omaha|OmahaHL|Hold\'em|Omaha\sHi/Lo|OmahaHL)
97 (\sJackpot\stable)?
98 \s-\s\*\*\*\s
99 (?P<DATETIME>.*$)\s
100 (Tournament\s\#(?P<TOURNO>\d+))?
101 """
102 % substitutions,
103 re.MULTILINE | re.VERBOSE,
104 )
106 re_PlayerInfo = re.compile(
107 """
108 ^Seat\s(?P<SEAT>[0-9]+):\s
109 (?P<PNAME>.*)\s
110 \(\s(%(LS)s)?\s?(?P<CASH>[%(NUM)s]+)\s?(%(LS)s)?\s\)"""
111 % substitutions,
112 re.MULTILINE | re.VERBOSE,
113 )
115 re_HandInfo = re.compile(
116 """
117 ^(
118 (Table\s(?P<TABLE>[-\ \#a-zA-Z\d]+?)\s)
119 |
120 (Tournament\s\#(?P<TOURNO>\d+)\s
121 (
122 (?P<BUYIN>(
123 ((?P<BIAMT>(%(LS)s)?\s?[%(NUM)s]+\s?(%(LS)s)?)(\s\+\s?(?P<BIRAKE>(%(LS)s)?\s?[%(NUM)s]+\s?(%(LS)s)?))?)
124 |
125 (Free)
126 |
127 (.+?)
128 ))
129 )
130 (\s-\sTable\s\#(?P<TABLEID>\d+))?\s
131 )
132 )
133 ((?P<MAX>\d+)\sMax\s)?
134 (\(Real\sMoney\))?
135 (?P<PLAY>\((Practice\sPlay|Play\sMoney)\))?
136 \\n
137 Seat\s(?P<BUTTON>[0-9]+)\sis\sthe\sbutton
138 """
139 % substitutions,
140 re.MULTILINE | re.VERBOSE,
141 )
143 re_Identify = re.compile(
144 "\*{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"
145 )
146 re_SplitHands = re.compile("\n\n+")
147 re_TailSplitHands = re.compile("(\n\n\n+)")
148 re_Button = re.compile("Seat (?P<BUTTON>\d+) is the button", re.MULTILINE)
149 re_Board = re.compile("\[\s(?P<CARDS>.+)\s\]")
150 re_Spanish_10 = re.compile("D([tpeo])")
152 re_DateTime = re.compile(
153 """(?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]+)""",
154 re.MULTILINE,
155 )
157 short_subst = {"PLYR": r"(?P<PNAME>.+?)", "CUR": "\$?", "NUM": ".,\d\xa0"}
158 re_PostSB = re.compile(
159 r"^%(PLYR)s posts small blind \[(%(CUR)s)?\s?(?P<SB>[%(NUM)s]+)\s?(%(CUR)s)?\]" % substitutions, re.MULTILINE
160 )
161 re_PostBB = re.compile(
162 r"^%(PLYR)s posts big blind \[(%(CUR)s)?\s?(?P<BB>[%(NUM)s]+)\s?(%(CUR)s)?\]" % substitutions, re.MULTILINE
163 )
164 re_Antes = re.compile(
165 r"^%(PLYR)s posts (the\s)?ante \[(%(CUR)s)?\s?(?P<ANTE>[%(NUM)s]+)\s?(%(CUR)s)?\]" % substitutions, re.MULTILINE
166 )
167 # TODO: unknown in available hand histories for pacificpoker:
168 re_BringIn = re.compile(
169 r"^%(PLYR)s: brings[- ]in( low|) for (%(CUR)s)?\s?(?P<BRINGIN>[%(NUM)s]+)\s?(%(CUR)s)?" % substitutions,
170 re.MULTILINE,
171 )
172 re_PostBoth = re.compile(
173 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)?\]"
174 % substitutions,
175 re.MULTILINE,
176 )
177 re_HeroCards = re.compile(r"^Dealt to %(PLYR)s( \[\s(?P<NEWCARDS>.+?)\s\])" % substitutions, re.MULTILINE)
178 re_Action = re.compile(
179 r"""
180 ^%(PLYR)s(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat)
181 (\s\[(%(CUR)s)?\s?(?P<BET>[%(NUM)s]+)\s?(%(CUR)s)?\])?
182 (\s*and\sis\sall.in)?
183 (\s*and\shas\sreached\sthe\s[%(CUR)s\s?\d\.]+\scap)?
184 (\s*cards?(\s\[(?P<DISCARDED>.+?)\])?)?\s*$"""
185 % substitutions,
186 re.MULTILINE | re.VERBOSE,
187 )
188 re_ShowdownAction = re.compile(r"^%s shows \[(?P<CARDS>.*)\]" % substitutions["PLYR"], re.MULTILINE)
189 re_sitsOut = re.compile("^%s sits out" % substitutions["PLYR"], re.MULTILINE)
190 re_ShownCards = re.compile(
191 "^%s ?(?P<SHOWED>shows|mucks) \[ (?P<CARDS>.*) \]$" % substitutions["PLYR"], re.MULTILINE
192 )
193 re_CollectPot = re.compile(
194 r"^%(PLYR)s collected \[ (%(CUR)s)?\s?(?P<POT>[%(NUM)s]+)\s?(%(CUR)s)? \]$" % substitutions, re.MULTILINE
195 )
197 def compilePlayerRegexs(self, hand):
198 pass
200 def readSupportedGames(self):
201 return [
202 ["ring", "hold", "nl"],
203 ["ring", "hold", "pl"],
204 ["ring", "hold", "fl"],
205 ["tour", "hold", "nl"],
206 ["tour", "hold", "pl"],
207 ["tour", "hold", "fl"],
208 ]
210 def determineGameType(self, handText):
211 info = {}
212 m = self.re_GameInfo.search(handText)
213 if not m:
214 tmp = handText[0:200]
215 log.error(("PacificPokerToFpdb.determineGameType: '%s'") % tmp)
216 raise FpdbParseError
218 mg = m.groupdict()
219 # print "DEBUG: mg: ", mg
220 if "LIMIT" in mg:
221 # print "DEBUG: re_GameInfo[LIMIT] \'", mg['LIMIT'], "\'"
222 info["limitType"] = self.limits[mg["LIMIT"]]
223 if "GAME" in mg:
224 # print "DEBUG: re_GameInfo[GAME] \'", mg['GAME'], "\'"
225 (info["base"], info["category"]) = self.games[mg["GAME"]]
226 if "SB" in mg:
227 # print "DEBUG: re_GameInfo[SB] \'", mg['SB'], "\'"
228 info["sb"] = self.clearMoneyString(mg["SB"])
229 if "BB" in mg:
230 # print "DEBUG: re_GameInfo[BB] \'", mg['BB'], "\'"
231 info["bb"] = self.clearMoneyString(mg["BB"])
232 if "CURRENCY1" in mg:
233 # print "DEBUG: re_GameInfo[CURRENCY] \'", mg['CURRENCY'], "\'"
234 info["currency"] = self.currencies[mg["CURRENCY1"]]
235 if "CURRENCY2" in mg and mg["CURRENCY2"]:
236 # print "DEBUG: re_GameInfo[CURRENCY] \'", mg['CURRENCY'], "\'"
237 info["currency"] = self.currencies[mg["CURRENCY2"]]
238 if "FAST" in mg and mg["FAST"] is not None:
239 info["fast"] = True
241 if "TOURNO" in mg and mg["TOURNO"] is not None:
242 info["type"] = "tour"
243 info["currency"] = "T$"
244 else:
245 info["type"] = "ring"
247 # Pacific Poker includes the blind levels in the gametype, the following is not needed.
248 # if info['limitType'] == 'fl' and info['bb'] is not None and info['type'] == 'ring' and info['base'] != 'stud':
249 # try:
250 # info['sb'] = self.Lim_Blinds[mg['BB']][0]
251 # info['bb'] = self.Lim_Blinds[mg['BB']][1]
252 # except KeyError:
253 # log.error(("determineGameType: Lim_Blinds has no lookup for '%s'" % mg['BB']))
254 # log.error(("determineGameType: Raising FpdbParseError"))
255 # raise FpdbParseError(("Lim_Blinds has no lookup for '%s'") % mg['BB'])
257 return info
259 def readHandInfo(self, hand):
260 info = {}
261 m = self.re_HandInfo.search(hand.handText, re.DOTALL)
262 if m is None:
263 log.error("re_HandInfo could not be parsed")
264 m2 = self.re_GameInfo.search(hand.handText)
265 if m2 is None:
266 log.error("re_GameInfo could not be parsed")
267 if m is None or m2 is None:
268 tmp = hand.handText[0:200]
269 log.error(("PacificPokerToFpdb.readHandInfo: '%s'") % tmp)
270 raise FpdbParseError
272 info.update(m.groupdict())
273 info.update(m2.groupdict())
275 # log.debug("readHandInfo: %s" % info)
276 for key in info:
277 if key == "DATETIME":
278 # 28 11 2011 19:05:11
279 m1 = self.re_DateTime.finditer(info[key])
280 datetimestr = "2000/01/01 00:00:00" # default used if time not found
281 for a in m1:
282 datetimestr = "%s/%s/%s %s:%s:%s" % (
283 a.group("Y"),
284 a.group("M"),
285 a.group("D"),
286 a.group("H"),
287 a.group("MIN"),
288 a.group("S"),
289 )
290 hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S")
291 hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, "ET", "UTC")
292 hand.newFormat = datetime.datetime.strptime("20220908000000", "%Y%m%d%H%M%S") # this is a guess
293 hand.newFormat = HandHistoryConverter.changeTimezone(hand.newFormat, "ET", "UTC")
294 if key == "HID":
295 hand.handid = info[key]
296 if key == "TOURNO" and info["TOURNO"] is not None:
297 hand.tourNo = info[key]
298 hand.isKO = False
299 if key == "BUYIN" and info["BUYIN"] is not None:
300 if info[key] == "Free" or info["BIAMT"] is None:
301 hand.buyin = 0
302 hand.fee = 0
303 hand.buyinCurrency = "FREE"
304 else:
305 if info["BUYIN"].find("$") != -1:
306 hand.buyinCurrency = "USD"
307 elif info["BUYIN"].find("€") != -1:
308 hand.buyinCurrency = "EUR"
309 elif "PLAY" in info and info["PLAY"] != "Practice Play" and info["PLAY"] != "Play Money":
310 hand.buyinCurrency = "FREE"
311 else:
312 # FIXME: handle other currencies, FPP, play money
313 log.error(
314 ("PacificPokerToFpdb.readHandInfo: Failed to detect currency.")
315 + " Hand ID: %s: '%s'" % (hand.handid, info[key])
316 )
317 raise FpdbParseError
319 info["BIAMT"] = self.clearMoneyString(info["BIAMT"].strip("$€"))
320 hand.buyin = int(100 * Decimal(info["BIAMT"]))
322 if info["BIRAKE"] is None:
323 hand.fee = 0
324 else:
325 info["BIRAKE"] = self.clearMoneyString(info["BIRAKE"].strip("$€"))
326 hand.fee = int(100 * Decimal(info["BIRAKE"]))
328 if key == "TABLE" and info["TABLE"] is not None:
329 hand.tablename = info[key]
330 if key == "TABLEID" and info["TABLEID"] is not None:
331 hand.tablename = info[key]
332 if key == "BUTTON":
333 hand.buttonpos = info[key]
334 if key == "MAX" and info["MAX"] is not None:
335 hand.maxseats = int(info[key])
337 if key == "PLAY" and info["PLAY"] is not None:
338 # hand.currency = 'play' # overrides previously set value
339 hand.gametype["currency"] = "play"
341 if "TOURNO" in info and info["TOURNO"] is not None and hand.tablename == "":
342 hand.tablename = 1
344 def readButton(self, hand):
345 m = self.re_Button.search(hand.handText)
346 if m:
347 hand.buttonpos = int(m.group("BUTTON"))
348 else:
349 log.info("readButton: " + ("not found"))
351 def readPlayerStacks(self, hand):
352 m = self.re_PlayerInfo.finditer(hand.handText)
353 for a in m:
354 if len(a.group("PNAME")) == 0:
355 log.error("PacificPokerToFpdb.readPlayerStacks: Player name empty %s" % hand.handid)
356 raise FpdbParseError
357 hand.addPlayer(int(a.group("SEAT")), a.group("PNAME"), self.clearMoneyString(a.group("CASH")))
359 def markStreets(self, hand):
360 # PREFLOP = ** Dealing down cards ** (observed hands don't have this line)
361 # This re fails if, say, river is missing; then we don't get the ** that starts the river.
362 if hand.gametype["base"] in ("hold"):
363 m = re.search(
364 r"(?P<PREFLOP>.+(?=\*\* Dealing flop \*\*)|.+)"
365 r"(\*\* Dealing flop \*\* (?P<FLOP>\[ \S\S, \S\S, \S\S \].+(?=\*\* Dealing turn \*\*)|.+))?"
366 r"(\*\* Dealing turn \*\* (?P<TURN>\[ \S\S \].+(?=\*\* Dealing river \*\*)|.+))?"
367 r"(\*\* Dealing river \*\* (?P<RIVER>\[ \S\S \].+?(?=\*\* Summary \*\*)|.+))?",
368 hand.handText,
369 re.DOTALL,
370 )
371 if m is None:
372 log.error(("PacificPokerToFpdb.markStreets: Unable to recognise streets %s" % hand.handid))
373 raise FpdbParseError
374 else:
375 # print "DEBUG: Matched markStreets"
376 m.groupdict()
377 # if 'PREFLOP' in mg:
378 # print "DEBUG: PREFLOP: ", [mg['PREFLOP']]
379 # if 'FLOP' in mg:
380 # print "DEBUG: FLOP: ", [mg['FLOP']]
381 # if 'TURN' in mg:
382 # print "DEBUG: TURN: ", [mg['TURN']]
383 # if 'RIVER' in mg:
384 # print "DEBUG: RIVER: ", [mg['RIVER']]
386 hand.addStreets(m)
388 def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
389 if street in (
390 "FLOP",
391 "TURN",
392 "RIVER",
393 ): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
394 # print "DEBUG readCommunityCards:", street, hand.streets.group(street)
395 m = self.re_Board.search(hand.streets[street])
396 cards = self.splitCards(m.group("CARDS"))
397 hand.setCommunityCards(street, cards)
399 def readAntes(self, hand):
400 m = self.re_Antes.finditer(hand.handText)
401 for player in m:
402 # ~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
403 hand.addAnte(player.group("PNAME"), self.clearMoneyString(player.group("ANTE")))
404 self.allInBlind(hand, "PREFLOP", player, "ante")
406 def readBringIn(self, hand):
407 m = self.re_BringIn.search(hand.handText, re.DOTALL)
408 if m:
409 # ~ logging.debug("readBringIn: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
410 hand.addBringIn(m.group("PNAME"), m.group("BRINGIN"))
412 def readBlinds(self, hand):
413 if hand.startTime < hand.newFormat:
414 hand.setUncalledBets(True)
415 liveBlind, hand.allInBlind = True, False
416 for a in self.re_PostSB.finditer(hand.handText):
417 if a.group("PNAME") in hand.stacks:
418 if liveBlind:
419 hand.addBlind(a.group("PNAME"), "small blind", self.clearMoneyString(a.group("SB")))
420 liveBlind = False
421 else:
422 # Post dead blinds as ante
423 hand.addBlind(a.group("PNAME"), "secondsb", self.clearMoneyString(a.group("SB")))
424 self.allInBlind(hand, "PREFLOP", a, "secondsb")
425 else:
426 log.error(
427 "PacificPokerToFpdb.readBlinds (SB): '%s', '%s' not in hand.stacks"
428 % (hand.handid, a.group("PNAME"))
429 )
430 raise FpdbParseError
431 for a in self.re_PostBB.finditer(hand.handText):
432 if a.group("PNAME") in hand.stacks:
433 hand.addBlind(a.group("PNAME"), "big blind", self.clearMoneyString(a.group("BB")))
434 self.allInBlind(hand, "PREFLOP", a, "big blind")
435 else:
436 log.error(
437 "PacificPokerToFpdb.readBlinds (BB): '%s', '%s' not in hand.stacks"
438 % (hand.handid, a.group("PNAME"))
439 )
440 raise FpdbParseError
441 for a in self.re_PostBoth.finditer(hand.handText):
442 if a.group("PNAME") in hand.stacks:
443 if Decimal(self.clearMoneyString(a.group("BB"))) > 0:
444 bb = self.clearMoneyString(a.group("BB"))
445 sb = self.clearMoneyString(a.group("SB"))
446 both = str(Decimal(bb) + Decimal(sb))
447 hand.addBlind(a.group("PNAME"), "both", both)
448 else:
449 hand.addBlind(a.group("PNAME"), "secondsb", self.clearMoneyString(a.group("SB")))
450 self.allInBlind(hand, "PREFLOP", a, "both")
451 else:
452 log.error(
453 "PacificPokerToFpdb.readBlinds (Both): '%s', '%s' not in hand.stacks"
454 % (hand.handid, a.group("PNAME"))
455 )
456 raise FpdbParseError
458 def readHoleCards(self, hand):
459 # streets PREFLOP, PREDRAW, and THIRD are special cases beacause
460 # we need to grab hero's cards
461 for street in ("PREFLOP", "DEAL"):
462 if street in list(hand.streets.keys()):
463 m = self.re_HeroCards.finditer(hand.streets[street])
464 for found in m:
465 # if m == None:
466 # hand.involved = False
467 # else:
468 hand.hero = found.group("PNAME")
469 newcards = self.splitCards(found.group("NEWCARDS"))
470 hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
472 for street, text in list(hand.streets.items()):
473 if not text or street in ("PREFLOP", "DEAL"):
474 continue # already done these
475 m = self.re_HeroCards.finditer(hand.streets[street])
476 for found in m:
477 player = found.group("PNAME")
478 if found.group("NEWCARDS") is None:
479 newcards = []
480 else:
481 newcards = self.splitCards(found.group("NEWCARDS"))
482 if found.group("OLDCARDS") is None:
483 oldcards = []
484 else:
485 oldcards = self.splitCards(found.group("OLDCARDS"))
487 if street == "THIRD" and len(newcards) == 3: # hero in stud game
488 hand.hero = player
489 hand.dealt.add(player) # need this for stud??
490 hand.addHoleCards(
491 street, player, closed=newcards[0:2], open=[newcards[2]], shown=False, mucked=False, dealt=False
492 )
493 else:
494 hand.addHoleCards(
495 street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False
496 )
498 def readAction(self, hand, street):
499 m = self.re_Action.finditer(hand.streets[street])
500 for action in m:
501 action.groupdict()
502 if street not in ("PREFLOP", "DEAL"):
503 hand.setUncalledBets(False)
504 # print "DEBUG: acts: %s" %acts
505 bet = self.clearMoneyString(action.group("BET")) if action.group("BET") else None
506 if action.group("PNAME") in hand.stacks:
507 if action.group("ATYPE") == " folds":
508 hand.addFold(street, action.group("PNAME"))
509 elif action.group("ATYPE") == " checks":
510 hand.addCheck(street, action.group("PNAME"))
511 elif action.group("ATYPE") == " calls":
512 hand.addCall(street, action.group("PNAME"), bet)
513 elif action.group("ATYPE") == " raises":
514 hand.addCallandRaise(street, action.group("PNAME"), bet)
515 elif action.group("ATYPE") == " bets":
516 hand.addBet(street, action.group("PNAME"), bet)
517 elif action.group("ATYPE") == " discards":
518 hand.addDiscard(street, action.group("PNAME"), bet, action.group("DISCARDED"))
519 elif action.group("ATYPE") == " stands pat":
520 hand.addStandsPat(street, action.group("PNAME"))
521 else:
522 log.debug(("DEBUG:") + " " + "Unimplemented %s: '%s' '%s'") % (
523 "readAction",
524 action.group("PNAME"),
525 action.group("ATYPE"),
526 )
528 if action.group("ATYPE") not in (" checks", " folds"):
529 if not hand.allInBlind:
530 if not (hand.stacks[action.group("PNAME")] == 0 and action.group("ATYPE") == " calls"):
531 hand.setUncalledBets(False)
532 if hand.stacks[action.group("PNAME")] == 0 and action.group("ATYPE") == " raises":
533 hand.checkForUncalled = True
534 else:
535 log.error(
536 "PacificPokerToFpdb.readAction: '%s', '%s' not in hand.stacks"
537 % (hand.handid, action.group("PNAME"))
538 )
539 raise FpdbParseError
541 def allInBlind(self, hand, street, action, actiontype):
542 if street in ("PREFLOP", "DEAL"):
543 if hand.stacks[action.group("PNAME")] == 0:
544 if actiontype == "ante":
545 if action.group("PNAME") in [p for (p, b) in hand.posted]:
546 hand.setUncalledBets(False)
547 hand.checkForUncalled = True
548 hand.allInBlind = True
549 elif actiontype in ("secondsb", "big blind", "both") and not self.re_Antes.search(hand.handText):
550 hand.setUncalledBets(False)
551 hand.checkForUncalled = True
552 hand.allInBlind = True
554 def readShowdownActions(self, hand):
555 # TODO: pick up mucks also??
556 for shows in self.re_ShowdownAction.finditer(hand.handText):
557 cards = shows.group("CARDS").split(", ")
558 hand.addShownCards(cards, shows.group("PNAME"))
560 def readCollectPot(self, hand):
561 for m in self.re_CollectPot.finditer(hand.handText):
562 # print "DEBUG: hand.addCollectPot(player=", m.group('PNAME'), ", pot=", m.group('POT'), ")"
563 hand.addCollectPot(player=m.group("PNAME"), pot=self.clearMoneyString(m.group("POT")))
565 def readShownCards(self, hand):
566 for m in self.re_ShownCards.finditer(hand.handText):
567 if m.group("CARDS") is not None:
568 cards = m.group("CARDS")
569 cards = self.splitCards(cards)
571 (shown, mucked) = (False, False)
572 if m.group("SHOWED") == "shows":
573 shown = True
574 elif m.group("SHOWED") == "mucks":
575 mucked = True
577 # print "DEBUG: hand.addShownCards(%s, %s, %s, %s)" %(cards, m.group('PNAME'), shown, mucked)
578 hand.addShownCards(cards=cards, player=m.group("PNAME"), shown=shown, mucked=mucked)
580 def splitCards(self, cards):
581 # Polish
582 cards = cards.replace("Kreuz", "c")
583 cards = cards.replace("Karo", "d")
584 cards = cards.replace("Pik", "s")
585 cards = cards.replace("Herz", "h")
586 cards = cards.replace("10", "T")
587 # Russian
588 cards = cards.replace("\xd2", "Q")
589 cards = cards.replace("\xc2", "A")
590 cards = cards.replace("\xc4", "J")
591 # Spanish
592 cards = self.re_Spanish_10.sub("T\g<1>", cards)
593 cards = cards.replace("t", "h")
594 cards = cards.replace("p", "s")
595 cards = cards.replace("e", "d")
596 cards = cards.replace("o", "h")
597 # Dutch
598 cards = cards.replace("B", "J")
599 cards = cards.replace("V", "Q")
600 cards = cards.replace("H", "K")
601 # Swedish
602 cards = cards.replace("Kn", "J")
603 cards = cards.replace("D", "Q")
604 cards = cards.replace("E", "A")
605 cards = cards.split(", ")
606 return cards
608 @staticmethod
609 def getTableTitleRe(type, table_name=None, tournament=None, table_number=None):
610 # Tournament tables look like:
611 # Tour NLH 50+5 Brouhaha ID #28353026 Table #7 Blinds: 200/400
612 log.info(
613 "Pacific.getTableTitleRe: table_name='%s' tournament='%s' table_number='%s'"
614 % (table_name, tournament, table_number)
615 )
616 regex = "%s" % (table_name)
617 if tournament:
618 regex = "%s Table #%s" % (tournament, table_number)
620 log.info("Pacific.getTableTitleRe: returns: '%s'" % (regex))
621 return regex
623 def readSummaryInfo(self, summaryInfoList):
624 self.status = True
625 return self.status