pokerdf 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pokerdf/__init__.py +0 -0
- pokerdf/core/read_and_convert.py +254 -0
- pokerdf/main.py +79 -0
- pokerdf/regex/regex_execution.py +89 -0
- pokerdf/regex/regex_patterns.py +814 -0
- pokerdf/utils/strings.py +1 -0
- pokerdf/validation/pydantic_modules.py +42 -0
- pokerdf-1.0.0.dist-info/LICENSE +21 -0
- pokerdf-1.0.0.dist-info/METADATA +113 -0
- pokerdf-1.0.0.dist-info/RECORD +12 -0
- pokerdf-1.0.0.dist-info/WHEEL +4 -0
- pokerdf-1.0.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,814 @@
|
|
1
|
+
import re
|
2
|
+
from typing import Any
|
3
|
+
import pandas as pd
|
4
|
+
|
5
|
+
|
6
|
+
class RegexPatterns:
|
7
|
+
"""
|
8
|
+
Contains all functions with regex patterns to extract data from the text files
|
9
|
+
"""
|
10
|
+
|
11
|
+
def __init__(self) -> None:
|
12
|
+
"""
|
13
|
+
Initialize the RegexPatterns class.
|
14
|
+
"""
|
15
|
+
# Initialize the class
|
16
|
+
# This class does not need any specific initialization
|
17
|
+
pass
|
18
|
+
|
19
|
+
def _guarantee_unicity(
|
20
|
+
self, result: list[Any], fill: str | int | None = "Unknown"
|
21
|
+
) -> list[Any]:
|
22
|
+
"""
|
23
|
+
Guarantee that the returned result is a list with just one element.
|
24
|
+
|
25
|
+
Args:
|
26
|
+
result (list): List of strings extracted with regex.
|
27
|
+
fill (str | int): Value to fill if nothing is captured by the regex. Default is "Unknown".
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
list: List with exactly one string.
|
31
|
+
"""
|
32
|
+
# If nothing is found, it is set as "Unkown"
|
33
|
+
if result == []:
|
34
|
+
return [fill]
|
35
|
+
|
36
|
+
# If more than one info is found, only the first is considered
|
37
|
+
elif len(result) > 1:
|
38
|
+
result = [result[0]]
|
39
|
+
|
40
|
+
return result
|
41
|
+
|
42
|
+
def get_modality(self, hand: list[str]) -> list[str]:
|
43
|
+
"""
|
44
|
+
Get name of poker modality (for example, "Hold'em No Limit").
|
45
|
+
|
46
|
+
Args:
|
47
|
+
hand (list): List of texts from a specific hand.
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
list: List with just one string, i.e. the name of the modality.
|
51
|
+
"""
|
52
|
+
# Pattern to extract
|
53
|
+
regex = r",\s+\S+\s+(.*?)\s+-\s+(?:Level|Match)"
|
54
|
+
|
55
|
+
# Get the first content of a played hand
|
56
|
+
target = hand[0]
|
57
|
+
|
58
|
+
# Apply regex
|
59
|
+
result = re.findall(regex, target)
|
60
|
+
|
61
|
+
# Normalize output
|
62
|
+
result = self._guarantee_unicity(result)
|
63
|
+
|
64
|
+
# Return list with exactly one element
|
65
|
+
return result
|
66
|
+
|
67
|
+
def get_tourn_id(self, hand: list[str]) -> list[str]:
|
68
|
+
"""
|
69
|
+
Get ID of a specific tournament (for example, "3285336035").
|
70
|
+
|
71
|
+
Args:
|
72
|
+
hand (list): List of texts from a specific hand.
|
73
|
+
|
74
|
+
Returns:
|
75
|
+
list: List with just one string, i.e. the ID of the tournament.
|
76
|
+
"""
|
77
|
+
# Pattern to extract
|
78
|
+
regex = r"Tournament #(\d+),.*"
|
79
|
+
|
80
|
+
# Get the first content of a played hand
|
81
|
+
target = hand[0]
|
82
|
+
|
83
|
+
# Apply regex
|
84
|
+
result = re.findall(regex, target)
|
85
|
+
|
86
|
+
# Normalize output
|
87
|
+
result = self._guarantee_unicity(result)
|
88
|
+
|
89
|
+
# Return list with exactly one element
|
90
|
+
return result
|
91
|
+
|
92
|
+
def get_hand_id(self, hand: list[str]) -> list[str]:
|
93
|
+
"""
|
94
|
+
Get ID of a specific hand (for example, "230689290677").
|
95
|
+
|
96
|
+
Args:
|
97
|
+
hand (list): List of texts from a specific hand.
|
98
|
+
|
99
|
+
Returns:
|
100
|
+
list: List with just one string, i.e. the ID of the hand.
|
101
|
+
"""
|
102
|
+
# Pattern to extract
|
103
|
+
regex = r"Hand #(\d+):.*"
|
104
|
+
|
105
|
+
# Get the first content of a played hand
|
106
|
+
target = hand[0]
|
107
|
+
|
108
|
+
# Apply regex
|
109
|
+
result = re.findall(regex, target)
|
110
|
+
|
111
|
+
# Normalize output
|
112
|
+
result = self._guarantee_unicity(result)
|
113
|
+
|
114
|
+
return result
|
115
|
+
|
116
|
+
def get_players(self, hand: list[str]) -> list[str]:
|
117
|
+
"""
|
118
|
+
Get list of active players in a specific hand.
|
119
|
+
|
120
|
+
Args:
|
121
|
+
hand (list): List of texts from a specific hand.
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
list: List with the names of the active players.
|
125
|
+
"""
|
126
|
+
# Pattern to extract
|
127
|
+
regex = r"\nSeat \d{1}: (.*) \(\S+ in chips"
|
128
|
+
|
129
|
+
# Get the first content of a played hand
|
130
|
+
target = hand[0]
|
131
|
+
|
132
|
+
# Apply regex
|
133
|
+
players = re.findall(regex, target)
|
134
|
+
|
135
|
+
# Normalize output
|
136
|
+
players = [re.escape(x) for x in players]
|
137
|
+
|
138
|
+
return players
|
139
|
+
|
140
|
+
def get_number_of_active_players(self, hand: list[str]) -> list[int]:
|
141
|
+
"""
|
142
|
+
Get the number of active players in a specific hand.
|
143
|
+
|
144
|
+
Args:
|
145
|
+
hand (list): List of texts from a specific hand.
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
list: List with one integer element, the number of players.
|
149
|
+
"""
|
150
|
+
# Pattern to extract
|
151
|
+
regex = r"\nSeat \d{1}: (.*) \(.*"
|
152
|
+
|
153
|
+
# Get the first content of a played hand
|
154
|
+
target = hand[0]
|
155
|
+
|
156
|
+
# Apply regex and count the items found
|
157
|
+
n = len(re.findall(regex, target))
|
158
|
+
|
159
|
+
# Normalize output
|
160
|
+
result = [n]
|
161
|
+
|
162
|
+
return result
|
163
|
+
|
164
|
+
def get_buyin(self, hand: list[str]) -> list[str]:
|
165
|
+
"""
|
166
|
+
Get buy-in paid.
|
167
|
+
|
168
|
+
Args:
|
169
|
+
hand (list): List of texts from a specific hand.
|
170
|
+
|
171
|
+
Returns:
|
172
|
+
list: List with the value of the buy-in paid.
|
173
|
+
"""
|
174
|
+
# Pattern to extract
|
175
|
+
regex = r"\d+, (\S+) .*"
|
176
|
+
|
177
|
+
# Get the first content of a played hand
|
178
|
+
target = hand[0]
|
179
|
+
|
180
|
+
# Apply regex
|
181
|
+
buyin = re.findall(regex, target)
|
182
|
+
|
183
|
+
# Normalize output
|
184
|
+
buyin = self._guarantee_unicity(buyin)
|
185
|
+
|
186
|
+
return buyin
|
187
|
+
|
188
|
+
def get_level(self, hand: list[str]) -> list[str]:
|
189
|
+
"""
|
190
|
+
Get level of the tournament.
|
191
|
+
|
192
|
+
Args:
|
193
|
+
hand (list): List of texts from a specific hand.
|
194
|
+
|
195
|
+
Returns:
|
196
|
+
list: List with the level of the tournament (for example, ["IV"]).
|
197
|
+
"""
|
198
|
+
# Pattern to extract
|
199
|
+
regex = r" Level (\S+) .*"
|
200
|
+
|
201
|
+
# Get the first content of a played hand
|
202
|
+
target = hand[0]
|
203
|
+
|
204
|
+
# Apply regex
|
205
|
+
result = re.findall(regex, target)
|
206
|
+
|
207
|
+
return result
|
208
|
+
|
209
|
+
def get_blinds(self, hand: list[str]) -> list[list[float]]:
|
210
|
+
"""
|
211
|
+
Get current blinds of the tournament.
|
212
|
+
|
213
|
+
Args:
|
214
|
+
hand (list): List of texts from a specific hand.
|
215
|
+
|
216
|
+
Returns:
|
217
|
+
list: List with the list of blinds (for example, [['10', '20']]).
|
218
|
+
"""
|
219
|
+
# Pattern to extract
|
220
|
+
regex = r" Level \w+ \((\d+)/(\d+)\).*"
|
221
|
+
|
222
|
+
# Get the first content of a played hand
|
223
|
+
target = hand[0]
|
224
|
+
|
225
|
+
# Apply regex
|
226
|
+
result = [[float(x) for x in re.findall(regex, target)[0]]]
|
227
|
+
|
228
|
+
return result
|
229
|
+
|
230
|
+
def get_ante(self, hand: list[str]) -> list[float | None]:
|
231
|
+
"""
|
232
|
+
Get current ante of the tournament.
|
233
|
+
|
234
|
+
Args:
|
235
|
+
hand (list): List of texts from a specific hand.
|
236
|
+
|
237
|
+
Returns:
|
238
|
+
list: List with the current ante of the tournament (for example, [10]).
|
239
|
+
"""
|
240
|
+
# Pattern to extract
|
241
|
+
regex = r"posts the ante (\d+)"
|
242
|
+
|
243
|
+
# Get the first content of a played hand
|
244
|
+
target = hand[0]
|
245
|
+
|
246
|
+
# Apply regex
|
247
|
+
result = re.findall(regex, target)
|
248
|
+
|
249
|
+
# Convert to integer
|
250
|
+
result = [float(x) for x in result if x.isdigit()]
|
251
|
+
|
252
|
+
# This list cannot be empty
|
253
|
+
if result == []:
|
254
|
+
return [None]
|
255
|
+
|
256
|
+
# Get the maximum value and return in a list
|
257
|
+
result = [max(result)]
|
258
|
+
|
259
|
+
return result
|
260
|
+
|
261
|
+
def get_time(self, hand: list[str]) -> list[pd.Timestamp]:
|
262
|
+
"""
|
263
|
+
Get current datetime of the tournament.
|
264
|
+
|
265
|
+
Args:
|
266
|
+
hand (list): List of texts from a specific hand.
|
267
|
+
|
268
|
+
Returns:
|
269
|
+
list: List with the current datetime (for example, ['2020-11-06 10:02:19']).
|
270
|
+
"""
|
271
|
+
# Pattern to extract
|
272
|
+
regex = r"(\d{4}/\d{2}/\d{2} \d{1,2}:\d{1,2}:\d{1,2})"
|
273
|
+
|
274
|
+
# Get the first content of a played hand
|
275
|
+
target = hand[0]
|
276
|
+
|
277
|
+
# Apply regex
|
278
|
+
result = re.findall(regex, target)
|
279
|
+
|
280
|
+
# Normalize string
|
281
|
+
result = [pd.to_datetime(x) for x in result]
|
282
|
+
|
283
|
+
# Normalize output
|
284
|
+
result = self._guarantee_unicity(result)
|
285
|
+
|
286
|
+
return result
|
287
|
+
|
288
|
+
def get_table_size(self, hand: list[str]) -> list[int]:
|
289
|
+
"""
|
290
|
+
Get total number of players per table in the tournament.
|
291
|
+
|
292
|
+
Args:
|
293
|
+
hand (list): List of texts from a specific hand.
|
294
|
+
|
295
|
+
Returns:
|
296
|
+
list: List with the number of players per table (for example, ['9']).
|
297
|
+
"""
|
298
|
+
# Pattern to extract
|
299
|
+
regex = r"(\d)-max"
|
300
|
+
|
301
|
+
# Get the first content of a played hand
|
302
|
+
target = hand[0]
|
303
|
+
|
304
|
+
# Apply regex
|
305
|
+
result = [int(re.findall(regex, target)[0])]
|
306
|
+
|
307
|
+
return result
|
308
|
+
|
309
|
+
def get_table_id(self, hand: list[str]) -> list[str]:
|
310
|
+
"""
|
311
|
+
Get ID of a specific hand (for example, "1").
|
312
|
+
|
313
|
+
Args:
|
314
|
+
hand (list): List of texts from a specific hand.
|
315
|
+
|
316
|
+
Returns:
|
317
|
+
list: List with just one string, i.e. the ID of the table.
|
318
|
+
"""
|
319
|
+
# Pattern to extract
|
320
|
+
regex = r"Table \'\d+ (\d+)\' .*"
|
321
|
+
|
322
|
+
# Get the first content of a played hand
|
323
|
+
target = hand[0]
|
324
|
+
|
325
|
+
# Apply regex
|
326
|
+
result = re.findall(regex, target)
|
327
|
+
|
328
|
+
return result
|
329
|
+
|
330
|
+
def get_owner_cards(self, hand: list[str]) -> list[str]:
|
331
|
+
"""
|
332
|
+
Get cards from the owner of the logs (for example, ['As', '5s']).
|
333
|
+
|
334
|
+
Args:
|
335
|
+
hand (list): List of texts from a specific hand.
|
336
|
+
|
337
|
+
Returns:
|
338
|
+
list: List with a list of the owners' cards, like [['As', '5s']].
|
339
|
+
"""
|
340
|
+
# Pattern to extract
|
341
|
+
regex = r"Dealt to .* \[(\S+) (\S+)\]"
|
342
|
+
|
343
|
+
# Get the first content of a played hand
|
344
|
+
target = hand[1]
|
345
|
+
|
346
|
+
# Apply regex
|
347
|
+
result = re.findall(regex, target)
|
348
|
+
|
349
|
+
return result
|
350
|
+
|
351
|
+
def get_owner(self, hand: list[str]) -> list[str]:
|
352
|
+
"""
|
353
|
+
Get name of the owner of the logs (for example, 'garciamurilo').
|
354
|
+
|
355
|
+
Args:
|
356
|
+
hand (list): List of texts from a specific hand.
|
357
|
+
|
358
|
+
Returns:
|
359
|
+
list: List with the name of the owner, like ['garciamurilo'].
|
360
|
+
"""
|
361
|
+
# Pattern to extract
|
362
|
+
regex = r"Dealt to (.*) \[.*"
|
363
|
+
|
364
|
+
# Get the first content of a played hand
|
365
|
+
target = hand[1]
|
366
|
+
|
367
|
+
# Apply regex
|
368
|
+
result = re.findall(regex, target)
|
369
|
+
|
370
|
+
return result
|
371
|
+
|
372
|
+
def get_stack(self, player: str, hand: list[str]) -> list[float | None]:
|
373
|
+
"""
|
374
|
+
Get the current stack of the player (for example, '500').
|
375
|
+
|
376
|
+
Args:
|
377
|
+
player (str): Name of the player.
|
378
|
+
hand (list): List of texts from a specific hand.
|
379
|
+
|
380
|
+
Returns:
|
381
|
+
list: List with the stack of the player (for example, ['500']).
|
382
|
+
"""
|
383
|
+
# Pattern to extract
|
384
|
+
regex = rf"Seat \d+: {player} \((\d+) in chips\)"
|
385
|
+
|
386
|
+
# Get the first content of a played hand
|
387
|
+
target = hand[0]
|
388
|
+
|
389
|
+
# Apply regex
|
390
|
+
result = re.findall(regex, target)
|
391
|
+
|
392
|
+
# Normalize output
|
393
|
+
result = [float(x) for x in result if x.isdigit()]
|
394
|
+
result = self._guarantee_unicity(result, fill=None)
|
395
|
+
|
396
|
+
return result
|
397
|
+
|
398
|
+
def get_posted_blind(self, player: str, hand: list[str]) -> list[float | None]:
|
399
|
+
"""
|
400
|
+
Get blind posted by the player (for example, '30').
|
401
|
+
|
402
|
+
Args:
|
403
|
+
player (str): Name of the player.
|
404
|
+
hand (list): List of texts from a specific hand.
|
405
|
+
|
406
|
+
Returns:
|
407
|
+
list: List with the blide posted by the player (for example, ['30']).
|
408
|
+
"""
|
409
|
+
# Pattern to extract
|
410
|
+
regex = rf"{player}: posts \w+ blind (\d+)"
|
411
|
+
|
412
|
+
# Get the first content of a played hand
|
413
|
+
target = hand[0]
|
414
|
+
|
415
|
+
# Apply regex
|
416
|
+
result = re.findall(regex, target)
|
417
|
+
|
418
|
+
# Normalize output
|
419
|
+
result = [float(x) for x in result if x.isdigit()]
|
420
|
+
result = self._guarantee_unicity(result, fill=None)
|
421
|
+
|
422
|
+
return result
|
423
|
+
|
424
|
+
def get_posted_ante(self, player: str, hand: list[str]) -> list[float | None]:
|
425
|
+
"""
|
426
|
+
Get ante posted by the player (for example, '10').
|
427
|
+
|
428
|
+
Args:
|
429
|
+
player (str): Name of the player.
|
430
|
+
hand (list): List of texts from a specific hand.
|
431
|
+
|
432
|
+
Returns:
|
433
|
+
list: List with the ante posted by the player (for example, ['10']).
|
434
|
+
"""
|
435
|
+
# Pattern to extract
|
436
|
+
regex = rf"{player}: posts the ante (\d+)"
|
437
|
+
|
438
|
+
# Get the first content of a played hand
|
439
|
+
target = hand[0]
|
440
|
+
|
441
|
+
# Apply regex
|
442
|
+
result = re.findall(regex, target)
|
443
|
+
|
444
|
+
# Normalize output
|
445
|
+
result = [float(x) for x in result if x.isdigit()]
|
446
|
+
result = self._guarantee_unicity(result, fill=None)
|
447
|
+
|
448
|
+
return result
|
449
|
+
|
450
|
+
def get_actions(
|
451
|
+
self, player: str, hand: list[str], stage: str
|
452
|
+
) -> list[list[tuple[str, str]]]:
|
453
|
+
"""
|
454
|
+
Get action the player (for example, ('call', '50')).
|
455
|
+
|
456
|
+
Args:
|
457
|
+
player (str): Name of the player.
|
458
|
+
hand (list): List of texts from a specific hand.
|
459
|
+
stage (str): Name of the stage to be considered
|
460
|
+
|
461
|
+
Returns:
|
462
|
+
list: List of actions in a stage, like [('call', '50'), ('fold', '')].
|
463
|
+
"""
|
464
|
+
# Initial value to be returned
|
465
|
+
fill_empty = [[("", "")]]
|
466
|
+
|
467
|
+
# Filter relevant data of a specific stage
|
468
|
+
hand = [x for x in hand if stage in x]
|
469
|
+
if hand == []:
|
470
|
+
return fill_empty
|
471
|
+
|
472
|
+
# Get the first content of a played hand for a specific stage
|
473
|
+
target = hand[0]
|
474
|
+
|
475
|
+
# Pattern to extract
|
476
|
+
regex = rf"{player}: (\w+) (\d+)?"
|
477
|
+
|
478
|
+
# Apply regex
|
479
|
+
result = re.findall(regex, target)
|
480
|
+
|
481
|
+
# Guarantee that empty list will not be return
|
482
|
+
if result == []:
|
483
|
+
return fill_empty
|
484
|
+
|
485
|
+
return [result]
|
486
|
+
|
487
|
+
def get_allin(self, player: str, hand: list[str], stage: str) -> list[bool]:
|
488
|
+
"""
|
489
|
+
Get if the player is all-in (it is boolean, True or False).
|
490
|
+
|
491
|
+
Args:
|
492
|
+
player (str): Name of the player.
|
493
|
+
hand (list): List of texts from a specific hand.
|
494
|
+
stage (str): Name of the stage to be considered
|
495
|
+
|
496
|
+
Returns:
|
497
|
+
list: List containing True or False, like [True].
|
498
|
+
"""
|
499
|
+
# Filter relevant data of a specific stage
|
500
|
+
hand = [x for x in hand if stage in x]
|
501
|
+
|
502
|
+
# If a specific stage is not available, return False
|
503
|
+
if hand == []:
|
504
|
+
return [False]
|
505
|
+
|
506
|
+
# Pattern to extract
|
507
|
+
regex = rf"{player}: .* (all-in)"
|
508
|
+
|
509
|
+
# Get the first content of a played hand for a specific stage
|
510
|
+
target = hand[0]
|
511
|
+
|
512
|
+
# Apply regex
|
513
|
+
all_in_data = re.findall(regex, target)
|
514
|
+
|
515
|
+
# Was some all-in action found? (True/False)
|
516
|
+
result = all_in_data != []
|
517
|
+
|
518
|
+
return [result]
|
519
|
+
|
520
|
+
def get_showed_card(
|
521
|
+
self, player: str, hand: list[str]
|
522
|
+
) -> list[list[str]] | list[list[None]]:
|
523
|
+
"""
|
524
|
+
Get cards, if the player showed them.
|
525
|
+
|
526
|
+
Args:
|
527
|
+
player (str): Name of the player.
|
528
|
+
hand (list): List of texts from a specific hand.
|
529
|
+
|
530
|
+
Returns:
|
531
|
+
list: List containing the cards of the player, like [['As', 'Ks']].
|
532
|
+
"""
|
533
|
+
# Pattern to extract
|
534
|
+
regex = rf"{player} .*(?:mucked|showed) \[(\S+) (\S+)\]"
|
535
|
+
|
536
|
+
# Defauld value for empty values
|
537
|
+
fill_empty = [[None, None]]
|
538
|
+
|
539
|
+
# Get the last content of a played hand
|
540
|
+
target = hand[-1]
|
541
|
+
|
542
|
+
# Apply regex
|
543
|
+
result = re.findall(regex, target)
|
544
|
+
|
545
|
+
# Guarantee that empty list will not be return
|
546
|
+
if result == []:
|
547
|
+
return fill_empty
|
548
|
+
|
549
|
+
return result
|
550
|
+
|
551
|
+
def get_card_combination(self, player: str, hand: list[str]) -> list[str]:
|
552
|
+
"""
|
553
|
+
Get cards combination, if the player went to showdown.
|
554
|
+
|
555
|
+
Args:
|
556
|
+
player (str): Name of the player.
|
557
|
+
hand (list): List of texts from a specific hand.
|
558
|
+
|
559
|
+
Returns:
|
560
|
+
list: List containing the card combination, like ['a pair of Kings'].
|
561
|
+
"""
|
562
|
+
# Pattern to extract
|
563
|
+
regex = rf"{player}.*showed.*with (.*)"
|
564
|
+
|
565
|
+
# Get the last content of a played hand
|
566
|
+
target = hand[-1]
|
567
|
+
|
568
|
+
# Apply regex
|
569
|
+
result = re.findall(regex, target)
|
570
|
+
|
571
|
+
# Normalize output
|
572
|
+
result = self._guarantee_unicity(result, fill=None)
|
573
|
+
|
574
|
+
return result
|
575
|
+
|
576
|
+
def get_result(self, player: str, hand: list[str]) -> list[str]:
|
577
|
+
"""
|
578
|
+
Get the result of a showdown for a player.
|
579
|
+
|
580
|
+
Args:
|
581
|
+
player (str): Name of the player.
|
582
|
+
hand (list): List of texts from a specific hand.
|
583
|
+
|
584
|
+
Returns:
|
585
|
+
list: List containing the result, like ['won'].
|
586
|
+
"""
|
587
|
+
# Pattern to extract
|
588
|
+
regex = rf"Seat \d+: {player} .*(\bfolded\b|\bwon\b|\blost\b|\bmucked\b).*"
|
589
|
+
|
590
|
+
# Get the last content of a played hand
|
591
|
+
target = hand[-1]
|
592
|
+
|
593
|
+
# Apply regex
|
594
|
+
result = re.findall(regex, target)
|
595
|
+
|
596
|
+
# Normalize output
|
597
|
+
result = self._guarantee_unicity(result, fill="non-sd win")
|
598
|
+
|
599
|
+
return result
|
600
|
+
|
601
|
+
def get_balance(self, player: str, hand: list[str]) -> list[float | None]:
|
602
|
+
"""
|
603
|
+
Get how much a player won from the pot.
|
604
|
+
|
605
|
+
Args:
|
606
|
+
player (str): Name of the player.
|
607
|
+
hand (list): List of texts from a specific hand.
|
608
|
+
|
609
|
+
Returns:
|
610
|
+
list: List containing the balance, like ['320'].
|
611
|
+
"""
|
612
|
+
# Pattern to extract
|
613
|
+
regex = rf"Seat \d: {player}.*(?:collected|won) \((\d+)\)"
|
614
|
+
|
615
|
+
# Get the last content of a played hand
|
616
|
+
target = hand[-1]
|
617
|
+
|
618
|
+
# Apply regex
|
619
|
+
result = re.findall(regex, target)
|
620
|
+
|
621
|
+
# Normalize output
|
622
|
+
result = [
|
623
|
+
float(x) if x is not None else None
|
624
|
+
for x in self._guarantee_unicity(result, fill=None)
|
625
|
+
]
|
626
|
+
|
627
|
+
return result
|
628
|
+
|
629
|
+
def get_board(
|
630
|
+
self, hand: list[str], stage: str
|
631
|
+
) -> (
|
632
|
+
list[tuple[str, str, str]] # Flop
|
633
|
+
| list[tuple[str, str, str, str]] # Turn
|
634
|
+
| list[tuple[str, str, str, str, str]] # River
|
635
|
+
| list[tuple[()]]
|
636
|
+
):
|
637
|
+
"""
|
638
|
+
Get the cards on the board.
|
639
|
+
|
640
|
+
Args:
|
641
|
+
hand (list): List of texts from a specific hand.
|
642
|
+
stage (str): Name of the stage to be considered
|
643
|
+
|
644
|
+
Returns:
|
645
|
+
list: List containing the cards on the board, like [('As', 'Ks', '2h')].
|
646
|
+
"""
|
647
|
+
# Defauld value for empty values
|
648
|
+
fill_empty = [()]
|
649
|
+
|
650
|
+
# Filter hands and reduce strings (to speed up the search)
|
651
|
+
hand = [x[0:30] for x in hand if stage in x]
|
652
|
+
|
653
|
+
# If no info for a specific stage is found, return empty values
|
654
|
+
if hand == []:
|
655
|
+
return fill_empty
|
656
|
+
|
657
|
+
# Pattern to extract board, that is between [ and ]
|
658
|
+
pre_regex = r"\[(.*)\]"
|
659
|
+
|
660
|
+
# Pattern to extract cards on the board
|
661
|
+
regex_cards = r"\b([\dTJQKA]{1}[shdc]{1})\b"
|
662
|
+
|
663
|
+
# Get the first content of a played hand for a specific stage
|
664
|
+
target = hand[0]
|
665
|
+
|
666
|
+
# Apply regex
|
667
|
+
pre_selection = re.findall(pre_regex, target)
|
668
|
+
if pre_selection == []:
|
669
|
+
return fill_empty
|
670
|
+
else:
|
671
|
+
result = re.findall(regex_cards, pre_selection[0])
|
672
|
+
|
673
|
+
return [tuple(result)]
|
674
|
+
|
675
|
+
def get_seat(self, player: str, hand: list[str]) -> list[int]:
|
676
|
+
"""
|
677
|
+
Get the seat number of the player.
|
678
|
+
|
679
|
+
Args:
|
680
|
+
player (str): Name of the player.
|
681
|
+
hand (list): List of texts from a specific hand.
|
682
|
+
|
683
|
+
Returns:
|
684
|
+
list: List containing the number of the seat, like ['1'].
|
685
|
+
"""
|
686
|
+
# Pattern to extract
|
687
|
+
regex = rf"\nSeat (\d+): {player}.*"
|
688
|
+
|
689
|
+
# Get the first content of a played hand for a specific stage
|
690
|
+
target = hand[0]
|
691
|
+
|
692
|
+
# Apply regex
|
693
|
+
result = re.findall(regex, target)
|
694
|
+
|
695
|
+
# Normalize output
|
696
|
+
result = [int(x) for x in self._guarantee_unicity(result, fill=None)]
|
697
|
+
|
698
|
+
return result
|
699
|
+
|
700
|
+
def get_position(self, player: str, hand: list[str]) -> list[str]:
|
701
|
+
"""
|
702
|
+
Get position of the player (for example, 'button').
|
703
|
+
|
704
|
+
Args:
|
705
|
+
player (str): Name of the player.
|
706
|
+
hand (list): List of texts from a specific hand.
|
707
|
+
|
708
|
+
Returns:
|
709
|
+
list: List containing the position of the player, like ['small blind'].
|
710
|
+
"""
|
711
|
+
# Pattern to extract
|
712
|
+
regex = rf"Seat \d+\: {player} \((button|small blind|big blind)\) "
|
713
|
+
|
714
|
+
# Get the last content of a played hand
|
715
|
+
target = hand[-1]
|
716
|
+
|
717
|
+
# Apply regex
|
718
|
+
result = re.findall(regex, target)
|
719
|
+
|
720
|
+
# Normalize output
|
721
|
+
result = self._guarantee_unicity(result, fill=None)
|
722
|
+
|
723
|
+
return result
|
724
|
+
|
725
|
+
def get_final_rank(self, player: str, hand: list[str]) -> list[int]:
|
726
|
+
"""
|
727
|
+
Get final rank of the player (for example, '14').
|
728
|
+
|
729
|
+
Args:
|
730
|
+
player (str): Name of the player.
|
731
|
+
hand (list): List of texts from a specific hand.
|
732
|
+
|
733
|
+
Returns:
|
734
|
+
list: List containing the final rank of the player, like ['1'].
|
735
|
+
"""
|
736
|
+
# Filter content from SHOW_DOWN
|
737
|
+
hand = [x for x in hand if "SHOW DOWN ***" in x]
|
738
|
+
|
739
|
+
if hand != []:
|
740
|
+
|
741
|
+
# Pattern to extract
|
742
|
+
regex = rf"{player} finished the tournament in (\d+).*"
|
743
|
+
|
744
|
+
# Get the first SHOW_DOWN content of a played hand
|
745
|
+
target = hand[0]
|
746
|
+
|
747
|
+
# Apply regex
|
748
|
+
list_of_results = re.findall(regex, target)
|
749
|
+
|
750
|
+
# Normalize
|
751
|
+
list_of_int = [
|
752
|
+
int(x) if x.replace(".", "").isdigit() else -1 for x in list_of_results
|
753
|
+
]
|
754
|
+
|
755
|
+
# Try another pattern, if nothing is found
|
756
|
+
if list_of_int == []:
|
757
|
+
|
758
|
+
# Pattern to extract
|
759
|
+
regex = rf"{player} (wins) the tournament"
|
760
|
+
|
761
|
+
# Apply regex again
|
762
|
+
result_of_regex = re.findall(regex, target)
|
763
|
+
|
764
|
+
# Position 1, if wins
|
765
|
+
if result_of_regex == ["wins"]:
|
766
|
+
return [1]
|
767
|
+
else:
|
768
|
+
return [-1]
|
769
|
+
else:
|
770
|
+
# Get the maximum value and return in a list
|
771
|
+
result = [max(list_of_int)]
|
772
|
+
|
773
|
+
return result
|
774
|
+
|
775
|
+
# If no SHOW_DOWN content is found, return -1
|
776
|
+
else:
|
777
|
+
return [-1]
|
778
|
+
|
779
|
+
def get_prize(self, player: str, hand: list[str]) -> list[float] | list[None]:
|
780
|
+
"""
|
781
|
+
Get prize of the player (for example, '$50.00').
|
782
|
+
|
783
|
+
Args:
|
784
|
+
player (str): Name of the player.
|
785
|
+
hand (list): List of texts from a specific hand.
|
786
|
+
|
787
|
+
Returns:
|
788
|
+
list: List containing the prize, like ['$50.00'].
|
789
|
+
"""
|
790
|
+
# Filter content from SHOW_DOWN
|
791
|
+
hand = [x for x in hand if "SHOW DOWN ***" in x]
|
792
|
+
|
793
|
+
if hand != []:
|
794
|
+
|
795
|
+
# Pattern to extract
|
796
|
+
regex = rf"{player} .* (?:and receives|and received) (\S+)"
|
797
|
+
|
798
|
+
# Get the first SHOW_DOWN content of a played hand
|
799
|
+
target = hand[0]
|
800
|
+
|
801
|
+
# Apply regex
|
802
|
+
result_of_regex = re.findall(regex, target)
|
803
|
+
|
804
|
+
# Normalize
|
805
|
+
final_result = [float(x) for x in result_of_regex if str(x).isdigit()]
|
806
|
+
|
807
|
+
# Normalize output
|
808
|
+
if final_result == []:
|
809
|
+
return [None]
|
810
|
+
else:
|
811
|
+
return final_result
|
812
|
+
|
813
|
+
else:
|
814
|
+
return [None]
|