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.
@@ -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]