Coverage for SealsWithClubsToFpdb.py: 0%
331 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-2013, 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, FpdbHandPartial
26from decimal import Decimal
27import re
28import logging
29import datetime
32# SealsWithClubs HH Format
33log = logging.getLogger("parser")
36class SealsWithClubs(HandHistoryConverter):
37 # Class Variables
39 sitename = "SealsWithClubs"
40 filetype = "text"
41 codepage = ("utf8", "cp1252")
42 siteId = 23 # Needs to match id entry in Sites database
43 substitutions = {
44 "PLYR": r"(?P<PNAME>\w+)",
45 "BRKTS": r"(\(button\) |\(small blind\) |\(big blind\) |\(button\) \(small blind\) |\(button\) \(big blind\) )?",
46 }
48 limits = {"NL": "nl", "No Limit": "nl", "PL": "pl", "Limit": "fl", "Fixed Limit": "fl", "Pot Limit": "pl"}
49 games = { # base, category
50 "Hold'em": ("hold", "holdem"),
51 "Omaha": ("hold", "omahahi"),
52 "Omaha Hi-Lo": ("hold", "omahahilo"),
53 "Short Deck Hold'em": ("hold", "6_holdem"),
54 "Omaha 5 Cards": ("hold", "5_omahahi"),
55 }
57 # Static regexes
58 re_GameInfo = re.compile(
59 r"""SwCPoker\sHand\s*\#(?P<HID>\d+):\s((Tournament|Cashgame|sitngo)\s\(((?P<TABLE2>.*?))\)\#(?P<TOURNO>\d+),\s(?P<BUYIN>(?P<BIAMT>\d+(\.\d+)?))\+(?P<BIRAKE>\d+(\.\d+)?)\s|\s)(?P<GAME>(Hold\'em|Omaha|Omaha\s5\sCards|Short\sDeck\sHold\'em))\s(?P<LIMIT>(NL|Fixed\sLimit|PL|Limit|Pot\sLimit|No\sLimit))\s((-\sLevel\s\w+\s)|)\((?P<SB>\d+(\.\d+)?(\,\d+)?)/(?P<BB>\d+(\.\d+)?(\,\d+)?)\)\s-\s(?P<DATETIME>.*)""",
60 re.VERBOSE,
61 )
63 re_PlayerInfo = re.compile(
64 r"""^Seat\s+(?P<SEAT>\d+):\s+(?P<PNAME>\w+)\s+\((?P<CASH>\d{1,3}(,\d{3})*(\.\d+)?)\sin\schips\)""",
65 re.MULTILINE | re.VERBOSE,
66 )
68 re_HandInfo = re.compile(
69 r"""^Table\s'(?P<TABLE>.*?)'\(\d+\)\s(?P<MAX>\d+)-max\s(?:\(Real Money\)\s)?Seat\s\#\d+\sis\sthe\sbutton""",
70 re.MULTILINE,
71 )
73 re_Identify = re.compile(r"SwCPoker\sHand\s")
74 re_SplitHands = re.compile("(?:\s?\n){2,}")
75 re_ButtonName = re.compile(r"""^(?P<BUTTONNAME>.*) has the dealer button""", re.MULTILINE)
76 re_ButtonPos = re.compile(r"""Seat\s+\#(?P<BUTTON>\d+)\sis\sthe\sbutton""", re.MULTILINE)
77 re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
78 re_DateTime = re.compile(
79 r"""(?P<Y>\d{4})-(?P<M>\d{2})-(?P<D>\d{2})[\-\s]+(?P<H>\d+):(?P<MIN>\d+):(?P<S>\d+)""", re.MULTILINE
80 )
82 # These used to be compiled per player, but regression tests say
83 # we don't have to, and it makes life faster.
84 re_PostSB = re.compile(r"^%(PLYR)s: posts small blind (?P<SB>[.0-9]+)" % substitutions, re.MULTILINE)
85 re_PostBB = re.compile(r"^%(PLYR)s: posts big blind (?P<BB>[.0-9]+)" % substitutions, re.MULTILINE)
86 re_Antes = re.compile(r"^%(PLYR)s: posts the ante (?P<ANTE>[.0-9]+)" % substitutions, re.MULTILINE)
87 re_PostBoth = re.compile(r"^%(PLYR)s: posts small \& big blind (?P<SBBB>[.0-9]+)" % substitutions, re.MULTILINE)
88 re_HeroCards = re.compile(
89 r"^Dealt to %(PLYR)s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % substitutions, re.MULTILINE
90 )
91 re_Action = re.compile(
92 r"""^%(PLYR)s:(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat)(?:\s(?P<BET>\d{1,3}(,\d{3})*(\.\d+)?))?(?:\sto\s(?P<POT>\d{1,3}(,\d{3})*(\.\d+)?))?\s*$"""
93 % substitutions,
94 re.MULTILINE | re.VERBOSE,
95 )
97 re_ShowdownAction = re.compile(
98 r"^(?P<PNAME>\w+): (shows \[(?P<CARDS>.*)\]\s\((?P<FHAND>.*?)\)|doesn't show hand|mucks hand)", re.MULTILINE
99 )
100 re_CollectPot = re.compile(
101 r"^Seat (?P<SEAT>[0-9]+): %(PLYR)s ((%(BRKTS)s(((((?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\]( and (lost|(won|collected) \((?P<POT>[.\d]+)\)) with (?P<STRING>.+?)(\s\sand\s(won\s\([.\d]+\)|lost)\swith\s(?P<STRING2>.*))?)?$)|collected\s\((?P<POT2>[.\d]+)\)))|folded ((on the (Flop|Turn|River))|before Flop)))|folded before Flop \(didn't bet\))"
102 % substitutions,
103 re.MULTILINE,
104 )
105 re_Cancelled = re.compile("Hand\scancelled", re.MULTILINE)
106 re_Uncalled = re.compile("Uncalled bet \((?P<BET>[,.\d]+)\) returned to %(PLYR)s" % substitutions, re.MULTILINE)
107 re_Flop = re.compile("\*\*\* FLOP \*\*\*")
108 re_Turn = re.compile("\*\*\* TURN \*\*\*")
109 re_River = re.compile("\*\*\* RIVER \*\*\*")
110 re_rake = re.compile(
111 "Total pot (?P<TOTALPOT>\\d{1,3}(,\\d{3})*(\\.\\d+)?)\\s\\|\\sRake\\s(?P<RAKE>\\d{1,3}(,\\d{3})*(\\.\\d+)?)",
112 re.MULTILINE,
113 )
114 re_Mucked = re.compile("^%(PLYR)s: mucks hand" % substitutions, re.MULTILINE)
116 def compilePlayerRegexs(self, hand):
117 """
118 Compiles regular expressions to match player names and cards shown in a poker hand.
120 Args:
121 - self: instance of the class containing the method
122 - hand: a Hand object representing the poker hand
124 Returns: None
125 """
126 log.info("Compiling player regexes")
127 # Get a set of player names in the hand
128 players = {player[1] for player in hand.players}
130 # Check if the set of players is a subset of compiledPlayers
131 if not players <= self.compiledPlayers:
132 # If not, update compiledPlayers
133 self.compiledPlayers = players
135 # Compile a regular expression to match the player's name
136 # The regular expression is of the form "(?P<PNAME>player1|player2|player3)"
137 player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
139 # Define substitutions for the regular expressions
140 subst = {
141 "PLYR": player_re,
142 "BRKTS": r"(\(button\) |\(small blind\) |\(big blind\) |\(button\) \(small blind\) |\(button\) \(big blind\) )?",
143 "CUR": "(\$|\xe2\x82\xac|\u20ac||\£|)",
144 }
146 # Compile a regular expression to match the cards dealt to the player
147 # The regular expression is of the form "^Dealt to %(PLYR)s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])"
148 self.re_HeroCards = re.compile(
149 r"^Dealt to %(PLYR)s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % subst, re.MULTILINE
150 )
152 # Compile a regular expression to match the cards shown by the player
153 # The regular expression is of the form "^Seat (?P<SEAT>[0-9]+): %(PLYR)s %(BRKTS)s(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\]( and (lost|(won|collected) \(%(CUR)s(?P<POT>[,\.\d]+)\)) with (?P<STRING>.+?)(,\sand\s(won\s\(%(CUR)s[\.\d]+\)|lost)\swith\s(?P<STRING2>.*))?)?$"
154 self.re_ShownCards = re.compile(
155 "^Seat (?P<SEAT>[0-9]+): %(PLYR)s %(BRKTS)s(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\]( and (lost|(won|collected) \(%(CUR)s(?P<POT>[,\.\d]+)\)) with (?P<STRING>.+?)(,\sand\s(won\s\(%(CUR)s[\.\d]+\)|lost)\swith\s(?P<STRING2>.*))?)?$"
156 % subst,
157 re.MULTILINE,
158 )
160 def readSupportedGames(self):
161 log.info("Reading supported games")
162 return [
163 ["ring", "hold", "fl"],
164 ["ring", "hold", "nl"],
165 ["ring", "hold", "pl"],
166 ["ring", "stud", "fl"],
167 ["ring", "draw", "fl"],
168 ["ring", "draw", "pl"],
169 ["ring", "draw", "nl"],
170 ["tour", "hold", "fl"],
171 ["tour", "hold", "nl"],
172 ["tour", "hold", "pl"],
173 ["tour", "stud", "fl"],
174 ["tour", "draw", "fl"],
175 ["tour", "draw", "pl"],
176 ["tour", "draw", "nl"],
177 ["tour", "hold", "6_holdem"],
178 ]
180 def determineGameType(self, handText):
181 log.info("Determining game type")
182 info = {}
183 m = self.re_GameInfo.search(handText)
184 if not m:
185 tmp = handText[:200]
186 log.error(f"SealsWithClubsToFpdb.determineGameType: '{tmp}'")
187 raise FpdbParseError
189 mg = m.groupdict()
190 log.debug(f"Matched groups: {mg}")
191 if "LIMIT" in mg:
192 info["limitType"] = self.limits[mg["LIMIT"]]
193 if "GAME" in mg:
194 (info["base"], info["category"]) = self.games[mg["GAME"]]
195 if "SB" in mg:
196 if "," in mg["SB"]:
197 mg["SB"] = mg["SB"].replace(",", "")
198 info["sb"] = mg["SB"]
199 if "BB" in mg:
200 if "," in mg["BB"]:
201 mg["BB"] = mg["BB"].replace(",", "")
202 info["bb"] = mg["BB"]
203 if "CURRENCY" in mg and mg["CURRENCY"] is not None:
204 info["currency"] = self.currencies[mg["CURRENCY"]]
206 info["type"] = "ring" if "TOURNO" in mg and mg["TOURNO"] is None else "tour"
207 if info["type"] == "ring":
208 info["currency"] = "mBTC"
209 else:
210 info["currency"] = "mBTC"
212 if info["limitType"] == "fl" and info["bb"] is not None:
213 info["sb"] = str((Decimal(mg["SB"]) / 2).quantize(Decimal("0.01")))
214 info["bb"] = str(Decimal(mg["SB"]).quantize(Decimal("0.01")))
216 log.debug(f"Game info: {info}")
217 return info
219 def readHandInfo(self, hand):
220 log.info("Reading hand info")
221 info = {}
222 m = self.re_HandInfo.search(hand.handText, re.DOTALL)
223 m2 = self.re_GameInfo.search(hand.handText)
225 if m is None or m2 is None:
226 tmp = hand.handText[:200]
227 log.error(f"SealsWithClubsToFpdb.readHandInfo: '{tmp}'")
228 raise FpdbParseError
230 info.update(m.groupdict())
231 log.debug(f"HandInfo groups: {m.groupdict()}")
232 info.update(m2.groupdict())
233 log.debug(f"GameInfo groups: {m2.groupdict()}")
235 if info["TOURNO"] is not None:
236 words = m["TABLE"].split()
237 new_string = words[1]
238 info["TABLE"] = f"{m2['TABLE2']} {new_string}"
239 log.debug(f"Table name updated to: {info['TABLE']}")
240 hand.tablename = f"{info['TABLE']}"
241 else:
242 # for cash game
243 info["TABLE"] = m["TABLE"]
244 log.debug(f"Table name for cash game: {info['TABLE']}")
245 hand.tablename = f"{info['TABLE']}"
247 for key in info:
248 if key == "DATETIME":
249 m1 = self.re_DateTime.finditer(info[key])
250 datetimestr = "2000-01-01 00:00:00"
251 for a in m1:
252 datetimestr = "%s-%s-%s %s:%s:%s" % (
253 a.group("Y"),
254 a.group("M"),
255 a.group("D"),
256 a.group("H"),
257 a.group("MIN"),
258 a.group("S"),
259 )
260 hand.startTime = datetime.datetime.strptime(datetimestr, "%Y-%m-%d %H:%M:%S")
261 hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, "ET", "UTC")
262 if key == "HID":
263 hand.handid = info[key]
264 log.debug(f"Hand ID: {hand.handid}")
265 if key == "TOURNO":
266 hand.tourNo = info[key]
267 if key == "BUYIN":
268 if hand.tourNo is not None:
269 if info[key] == "Freeroll":
270 hand.buyin = 0
271 hand.fee = 0
272 hand.buyinCurrency = "FREE"
273 else:
274 hand.buyinCurrency = "mBTC"
275 hand.buyin = int(100 * Decimal(info["BIAMT"]))
276 hand.fee = int(100 * Decimal(info["BIRAKE"]))
277 if key == "LEVEL":
278 hand.level = info[key]
279 if key == "MAX" and info[key] is not None:
280 hand.maxseats = int(info[key])
281 if key == "HU" and info[key] is not None:
282 hand.maxseats = 2
284 log.debug(f"Final hand info: {info}")
286 if not hand.handid:
287 log.error("Hand ID not found, unable to process hand.")
288 raise FpdbParseError("Hand ID not found.")
290 if self.re_Cancelled.search(hand.handText):
291 raise FpdbHandPartial(f"Hand '{hand.handid}' was cancelled.")
293 def readButton(self, hand):
294 log.info("Reading button position")
295 if m := self.re_ButtonPos.search(hand.handText):
296 hand.buttonpos = int(m.group("BUTTON"))
297 else:
298 log.debug("readButton: not found")
300 def readPlayerStacks(self, hand):
301 handsplit = hand.handText.split("*** SUMMARY ***")
302 if len(handsplit) != 2:
303 raise FpdbHandPartial(f"Hand is not cleanly split into pre and post Summary {hand.handid}.")
304 pre, post = handsplit
305 m = self.re_PlayerInfo.finditer(pre)
306 plist = {}
308 for a in m:
309 if plist.get(a.group("PNAME")) is None:
310 hand.addPlayer(int(a.group("SEAT")), a.group("PNAME"), a.group("CASH"))
311 plist[a.group("PNAME")] = [int(a.group("SEAT")), a.group("CASH")]
313 if len(plist.keys()) < 2:
314 raise FpdbHandPartial(f"Less than 2 players in hand! {hand.handid}.")
316 def markStreets(self, hand):
317 log.info("Marking streets")
318 if self.re_Turn.search(hand.handText) and not self.re_Flop.search(hand.handText):
319 raise FpdbParseError
320 if self.re_River.search(hand.handText) and not self.re_Turn.search(hand.handText):
321 raise FpdbParseError
323 m = re.search(
324 r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>[\s\S]*?(?=\*\*\* FLOP \*\*\*)|.+)"
325 r"(\*\*\* FLOP \*\*\*(?P<FLOP>[\s\S]*?(?=\*\*\* TURN \*\*\*)|.+))?"
326 r"(\*\*\* TURN \*\*\*(?P<TURN>[\s\S]*?(?=\*\*\* RIVER \*\*\*)|.+))?"
327 r"(\*\*\* RIVER \*\*\*(?P<RIVER>[\s\S]*?(?=\*\*\* SHOW DOWN \*\*\*)|.+))?",
328 hand.handText,
329 re.DOTALL,
330 )
332 if not m:
333 raise FpdbParseError
335 hand.addStreets(m)
337 def readCommunityCards(self, hand, street):
338 log.debug(f"Reading community cards for street: {street}")
339 if street in ("FLOP", "TURN", "RIVER"):
340 m = self.re_Board.search(hand.streets[street])
341 hand.setCommunityCards(street, m.group("CARDS").split(" "))
343 def readAntes(self, hand):
344 log.info("Reading antes")
345 m = self.re_Antes.finditer(hand.handText)
346 for player in m:
347 log.debug(f"hand.addAnte({player.group('PNAME')},{player.group('ANTE')})")
348 hand.addAnte(player.group("PNAME"), player.group("ANTE"))
350 def readBlinds(self, hand):
351 log.debug("Reading blinds")
352 liveBlind = True
353 for a in self.re_PostSB.finditer(hand.handText):
354 if liveBlind:
355 hand.addBlind(a.group("PNAME"), "small blind", a.group("SB"))
356 liveBlind = False
357 else:
358 hand.addBlind(a.group("PNAME"), "secondsb", a.group("SB"))
359 for a in self.re_PostBB.finditer(hand.handText):
360 hand.addBlind(a.group("PNAME"), "big blind", a.group("BB"))
361 for a in self.re_PostBoth.finditer(hand.handText):
362 hand.addBlind(a.group("PNAME"), "both", a.group("SBBB"))
364 def readHoleCards(self, hand):
365 log.debug("Reading hole cards")
366 for street in ("PREFLOP", "DEAL"):
367 if street in list(hand.streets.keys()):
368 m = self.re_HeroCards.finditer(hand.streets[street])
369 for found in m:
370 hand.hero = found.group("PNAME")
371 newcards = found.group("NEWCARDS").split(" ")
372 hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
374 def readAction(self, hand, street):
375 log.debug(f"Reading actions for street: {street}")
376 m = self.re_Action.finditer(hand.streets[street])
377 for action in m:
378 acts = action.groupdict()
379 log.debug(f"Action details: {acts}")
380 if action.group("ATYPE") == " folds":
381 hand.addFold(street, action.group("PNAME"))
382 elif action.group("ATYPE") == " checks":
383 hand.addCheck(street, action.group("PNAME"))
384 elif action.group("ATYPE") == " calls":
385 hand.addCall(street, action.group("PNAME"), action.group("BET"))
386 elif action.group("ATYPE") == " raises":
387 hand.addRaiseTo(street, action.group("PNAME"), action.group("BET"))
388 elif action.group("ATYPE") == " bets":
389 hand.addBet(street, action.group("PNAME"), action.group("BET"))
390 else:
391 log.debug(f"DEBUG: Unimplemented {action.group('ATYPE')}: '{action.group('PNAME')}'")
393 def readShownCards(self, hand):
394 log.info("Reading shown cards")
395 for m in self.re_ShownCards.finditer(hand.handText):
396 if m.group("CARDS") is not None:
397 cards = m.group("CARDS").split(" ")
398 string = m.group("STRING")
399 if m.group("STRING2"):
400 string += "|" + m.group("STRING2")
401 (shown, mucked) = (False, False)
402 if m.group("SHOWED") == "showed":
403 shown = True
404 elif m.group("SHOWED") == "mucked":
405 mucked = True
406 hand.addShownCards(cards=cards, player=m.group("PNAME"), shown=shown, mucked=mucked, string=string)
408 def readShowdownActions(self, hand):
409 log.info("Reading showdown actions")
410 for shows in self.re_ShowdownAction.finditer(hand.handText):
411 if shows.group("CARDS") is not None:
412 cards = shows.group("CARDS").split(" ")
413 hand.addShownCards(cards, shows.group("PNAME"))
414 for mucks in self.re_CollectPot.finditer(hand.handText):
415 if mucks.group("SHOWED") == "mucked" and mucks.group("CARDS") is not None:
416 cards = mucks.group("CARDS").split(" ")
417 hand.addShownCards(cards, mucks.group("PNAME"))
419 def readCollectPot(self, hand):
420 log.info("Reading collected pot")
421 if self.re_Uncalled.search(hand.handText) is None:
422 rake = Decimal(0)
423 totalpot = Decimal(0)
424 for m in self.re_CollectPot.finditer(hand.handText):
425 if m.group("POT") is not None:
426 hand.addCollectPot(player=m.group("PNAME"), pot=m.group("POT"))
427 elif m.group("POT2") is not None:
428 hand.addCollectPot(player=m.group("PNAME"), pot=m.group("POT2"))
429 if self.re_rake.search(hand.handText) is not None:
430 for m in self.re_rake.finditer(hand.handText):
431 rake = rake + Decimal(m.group("RAKE"))
432 if "," in m.group("TOTALPOT"):
433 newtotalpot = m.group("TOTALPOT").replace(",", "")
434 totalpot = totalpot + Decimal(newtotalpot)
435 else:
436 totalpot = totalpot + Decimal(m.group("TOTALPOT"))
437 if hand.rake is None:
438 hand.rake = rake
439 elif hand.rakes.get("rake"):
440 hand.rakes["rake"] += rake
441 else:
442 hand.rakes["rake"] = rake
443 hand.totalpot = totalpot
444 else:
445 hand.setUncalledBets(True)
446 rake = Decimal(0)
447 totalpot = Decimal(0)
448 if self.re_rake.search(hand.handText) is not None:
449 for m in self.re_rake.finditer(hand.handText):
450 rake = rake + Decimal(m.group("RAKE"))
451 if "," in m.group("TOTALPOT"):
452 newtotalpot = m.group("TOTALPOT").replace(",", "")
453 totalpot = totalpot + Decimal(newtotalpot)
454 else:
455 totalpot = totalpot + Decimal(m.group("TOTALPOT"))
456 if hand.rake is None:
457 hand.rake = rake
458 elif hand.rakes.get("rake"):
459 hand.rakes["rake"] += rake
460 else:
461 hand.rakes["rake"] = rake
462 hand.totalpot = totalpot
463 total = rake + totalpot
464 for m in self.re_CollectPot.finditer(hand.handText):
465 if m.group("POT") is not None:
466 if totalpot == Decimal(m.group("POT")):
467 uncalledpot = Decimal(0)
468 for m in self.re_Uncalled.finditer(hand.handText):
469 if "," in m.group("BET"):
470 newbet = m.group("BET").replace(",", "")
471 uncalledpot = uncalledpot + Decimal(newbet)
472 else:
473 uncalledpot = uncalledpot + Decimal(m.group("BET"))
474 collectpot = totalpot
475 total = total + uncalledpot
476 hand.totalpot = total
477 hand.addCollectPot(player=m.group("PNAME"), pot=collectpot)
478 else:
479 hand.addCollectPot(player=m.group("PNAME"), pot=m.group("POT"))
480 elif m.group("POT2") is not None:
481 if totalpot == Decimal(m.group("POT2")):
482 uncalledpot = Decimal(0)
483 for m in self.re_Uncalled.finditer(hand.handText):
484 if "," in m.group("BET"):
485 newbet = m.group("BET").replace(",", "")
486 uncalledpot = uncalledpot + Decimal(newbet)
487 else:
488 uncalledpot = uncalledpot + Decimal(m.group("BET"))
489 collectpot = totalpot
490 total = total + uncalledpot
491 hand.totalpot = total
492 hand.addCollectPot(player=m.group("PNAME"), pot=collectpot)
493 else:
494 hand.addCollectPot(player=m.group("PNAME"), pot=m.group("POT2"))
496 @staticmethod
497 def getTableTitleRe(type, table_name=None, tournament=None, table_number=None):
498 log.debug(
499 f"Seals.getTableTitleRe: table_name='{table_name}' tournament='{tournament}' table_number='{table_number}'"
500 )
502 if not table_name:
503 log.debug("Seals.getTableTitleRe: no valid input provided")
504 return ""
506 log.debug(f"Initial table_name: {table_name}")
508 regex = f"{table_name}"
509 words = regex.split()
511 if type in ["tour", "ring"]:
512 if len(words) > 2:
513 regex = " ".join(words[1:-1])
514 log.debug(f"Seals.getTableTitleRe: regex after processing='{regex}'")
515 return regex
517 if type == "tour":
518 match = re.match(r"(\d+)\s(.+)\s(\[\d+\sChips\])\s(\d+)", table_name)
519 if match:
520 tournament_id, game_type, chips_info, table_number = match.groups()
521 regex = f"{tournament_id} {game_type} {chips_info} {table_number}"
522 log.debug(f"Seals.getTableTitleRe: regex for tour='{regex}'")
523 return regex
525 regex = f"{table_name}"
526 log.debug(f"Seals.getTableTitleRe: regex='{regex}'")
527 return regex