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