Coverage for Stats.py: 0%

633 statements  

« 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"""Manage collecting and formatting of stats and tooltips.""" 

5# Copyright 2008-2011, Ray E. Barker 

6 

7#  

8# This program is free software; you can redistribute it and/or modify 

9# it under the terms of the GNU General Public License as published by 

10# the Free Software Foundation; either version 2 of the License, or 

11# (at your option) any later version. 

12#  

13# This program is distributed in the hope that it will be useful, 

14# but WITHOUT ANY WARRANTY; without even the implied warranty of 

15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

16# GNU General Public License for more details. 

17#  

18# You should have received a copy of the GNU General Public License 

19# along with this program; if not, write to the Free Software 

20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

21 

22######################################################################## 

23 

24# How to write a new stat: 

25# 0 Do not use a name like "xyz_2". Names ending in _ and a single digit are 

26# used to indicate the number of decimal places the user wants to see in the Hud. 

27# 1 You can see a listing of all the raw stats (e.g., from the HudCache table) 

28# by running Database.py as a stand along program. You need to combine  

29# those raw stats to get stats to present to the HUD. If you need more  

30# information than is in the HudCache table, then you have to write SQL. 

31# 2 The raw stats seen when you run Database.py are available in the Stats.py 

32# in the stat_dict dict. For example the number of vpips would be 

33# stat_dict[player]['vpip']. So the % vpip is  

34# float(stat_dict[player]['vpip'])/float(stat_dict[player]['n']). You can see how the  

35# keys of stat_dict relate to the column names in HudCache by inspecting 

36# the proper section of the SQL.py module. 

37# The stat_dict keys should be in lower case, i.e. vpip not VPIP, since 

38# postgres returns the column names in lower case. 

39# 3 You have to write a small function for each stat you want to add. See 

40# the vpip() function for example. This function has to be protected from 

41# exceptions, using something like the try:/except: paragraphs in vpip. 

42# 4 The name of the function has to be the same as the of the stat used 

43# in the config file. 

44# 5 The stat functions have a peculiar return value, which is outlined in 

45# the do_stat function. This format is useful for tool tips and maybe 

46# other stuff. 

47# 6 All stats receive two params (stat_dict and player) - if these parameters contain 

48# "None", the stat must return its description in tuple [5] and must not traceback 

49# 7 Stats needing values from the hand instance can find these in _global_hand_instance.foo 

50# attribute 

51 

52 

53import L10n 

54_ = L10n.get_translation() 

55 

56# Standard Library modules 

57import sys 

58from decimal import Decimal # needed by hand_instance in m_ratio 

59 

60 

61import re 

62 

63# FreePokerTools modules 

64import Configuration 

65import Database 

66import Charset 

67import Card 

68import Hand 

69 

70# String manipulation 

71import codecs 

72encoder = codecs.lookup(Configuration.LOCALE_ENCODING) 

73 

74import logging 

75if __name__ == "__main__": 

76 Configuration.set_logfile("fpdb-log.txt") 

77# logging has been set up in fpdb.py or HUD_main.py, use their settings: 

78log = logging.getLogger("db") 

79 

80re_Places = re.compile("_[0-9]$") 

81 

82 

83 

84# Since tuples are immutable, we have to create a new one when 

85# overriding any decimal placements. Copy old ones and recreate the 

86# second value in tuple to specified format- 

87def __stat_override(decimals, stat_vals): 

88 """ 

89 Returns a tuple with the first element of `stat_vals` as a float, the second element as a string 

90 with `decimals` number of decimal places, and the remaining elements of `stat_vals`. 

91 

92 Parameters: 

93 - decimals (int): The number of decimal places to round the first element of `stat_vals`. 

94 - stat_vals (tuple): A tuple of values. 

95 

96 Returns: 

97 - tuple: A tuple with the first element of `stat_vals` as a float, the second element as a string 

98 with `decimals` number of decimal places, and the remaining elements of `stat_vals`. 

99 """ 

100 s = '%.*f' % (decimals, 100.0*stat_vals[0]) 

101 return stat_vals[0], s, stat_vals[2], stat_vals[3], stat_vals[4], stat_vals[5] 

102 

103 

104def do_tip(widget, tip): 

105 """ 

106 Sets the tooltip of the given widget to the UTF-8 encoded version of the tip. 

107 

108 Parameters: 

109 - widget: The widget to set the tooltip for. 

110 - tip: The tip to encode and set as the tooltip. 

111 

112 Returns: 

113 - None 

114 """ 

115 _tip = Charset.to_utf8(tip) 

116 widget.setToolTip(_tip) 

117 

118 

119def do_stat(stat_dict, player = 24, stat = 'vpip', hand_instance = None): 

120 """ 

121 Calculates a specific statistic for a given player in a hand. 

122 

123 Args: 

124 stat_dict (dict): A dictionary containing statistics for all players in the hand. 

125 player (int, optional): The player for whom to calculate the statistic. Defaults to 24. 

126 stat (str, optional): The statistic to calculate. Defaults to 'vpip'. 

127 hand_instance (object, optional): An instance of the hand. Defaults to None. 

128 

129 Returns: 

130 The calculated statistic for the player, or None if the statistic is not in the list of available statistics. 

131 

132 Note: 

133 The hand instance is not needed for many stat functions, so it is stored in a global variable to avoid having to conditionally pass the extra value. 

134 If the statistic name ends with an underscore followed by a number, it is overridden with the specified number of decimal places. 

135 The decimal place override assumes the raw result is a fraction (x/100), and manual decimal places only make sense for percentage values. 

136 The profit/100 hands (bb/BB) already default to three decimal places anyhow, so they are unlikely override candidates. 

137 """ 

138 #hand instance is not needed for many stat functions 

139 #so this optional parameter will be stored in a global 

140 #to avoid having to conditionally pass the extra value 

141 global _global_hand_instance 

142 _global_hand_instance = hand_instance 

143 

144 statname = stat 

145 match = re_Places.search(stat) 

146 if match: # override if necessary 

147 statname = stat[0:-2] 

148 

149 if statname not in STATLIST: 

150 return None 

151 

152 result = eval("%(stat)s(stat_dict, %(player)d)" % 

153 {'stat': statname, 'player': player}) 

154 

155 # If decimal places have been defined, override result[1] 

156 # NOTE: decimal place override ALWAYS assumes the raw result is a 

157 # fraction (x/100); manual decimal places really only make sense for 

158 # percentage values. Also, profit/100 hands (bb/BB) already default 

159 # to three decimal places anyhow, so they are unlikely override 

160 # candidates. 

161 if match: 

162 places = int(stat[-1:]) 

163 result = __stat_override(places, result) 

164 return result 

165 

166# OK, for reference the tuple returned by the stat is: 

167# 0 - The stat, raw, no formating, eg 0.33333333 

168# 1 - formatted stat with appropriate precision, eg. 33; shown in HUD 

169# 2 - formatted stat with appropriate precision, punctuation and a hint, eg v=33% 

170# 3 - same as #2 except name of stat instead of hint, eg vpip=33% 

171# 4 - the calculation that got the stat, eg 9/27 

172# 5 - the name of the stat, useful for a tooltip, eg vpip 

173 

174###########################################  

175# functions that return individual stats 

176 

177 

178def totalprofit(stat_dict, player): 

179 """ 

180 Calculates the total profit for a given player. 

181 

182 Args: 

183 stat_dict (dict): A dictionary containing player statistics. 

184 player (int): The player for whom to calculate the total profit. 

185 

186 Returns: 

187 tuple: A tuple containing the following values: 

188 - stat (float): The total profit divided by 100. 

189 - formatted_stat (str): The formatted total profit with two decimal places. 

190 - tp_formatted_stat (str): The formatted total profit with two decimal places and a hint. 

191 - tot_prof_formatted_stat (str): The formatted total profit with two decimal places and a hint. 

192 - str_stat (str): The total profit as a string. 

193 - stat_name (str): The name of the statistic. 

194 

195 If the 'net' key is not present in the stat_dict for the given player, or if the value cannot be converted to a float, 

196 the function returns a tuple with default values: 

197 - ('0', '$0.00', 'tp=0', 'totalprofit=0', '0', 'Total Profit') 

198 """ 

199 try: 

200 stat = float(stat_dict[player]['net']) / 100 

201 return (stat/100.0, '$%.2f' % stat, 'tp=$%.2f' % stat, 'tot_prof=$%.2f' % stat, str(stat), 'Total Profit') 

202 except: 

203 return ('0', '$0.00', 'tp=0', 'totalprofit=0', '0', 'Total Profit') 

204 

205def playername(stat_dict, player): 

206 """ 

207 Retrieves the player's screen name from the stat dictionary. 

208 

209 Args: 

210 stat_dict (dict): A dictionary containing player statistics. 

211 player (int): The player for whom to retrieve the screen name. 

212 

213 Returns: 

214 tuple: A tuple containing the player's screen name repeated five times and a constant 'Player name' at the end. If the player's screen name is not found, it returns an empty string five times followed by 'Player name'. 

215 """ 

216 try: 

217 return (stat_dict[player]['screen_name'], 

218 stat_dict[player]['screen_name'], 

219 stat_dict[player]['screen_name'], 

220 stat_dict[player]['screen_name'], 

221 stat_dict[player]['screen_name'], 

222 'Player name') 

223 except: 

224 return ("", 

225 "", 

226 "", 

227 "", 

228 "", 

229 'Player name') 

230 

231def _calculate_end_stack(stat_dict, player, hand_instance): 

232 """ 

233 Calculate the end stack size for a given player in a hand instance. 

234 

235 Args: 

236 stat_dict (dict): A dictionary containing player statistics. 

237 player (int): The player for whom to calculate the end stack size. 

238 hand_instance (Hand): An instance of the Hand class representing the current hand. 

239 

240 Returns: 

241 float: The end stack size for the given player. 

242 

243 Note: 

244 This function is currently located in Stats.py but it should be moved to Hands.py since it belongs there. 

245 

246 Todo: 

247 - Find a better way to calculate the end stack size from the hand_instance. 

248 - Add a hand_instance "end_of_hand_stack" attribute. 

249 """ 

250 #fixme - move this code into Hands.py - it really belongs there 

251 

252 #To reflect the end-of-hand position, we need a end-stack calculation 

253 # fixme, is there an easier way to do this from the hand_instance??? 

254 # can't seem to find a hand_instance "end_of_hand_stack" attribute 

255 

256 #First, find player stack size at the start of the hand 

257 stack = 0.0 

258 for item in hand_instance.players: 

259 if item[1] == stat_dict[player]['screen_name']: 

260 stack = float(item[2]) 

261 

262 #Next, deduct all action from this player 

263 for street in hand_instance.bets: 

264 for item in hand_instance.bets[street]: 

265 if item == stat_dict[player]['screen_name']: 

266 for amount in hand_instance.bets[street][stat_dict[player]['screen_name']]: 

267 stack -= float(amount) 

268 

269 #Next, add back any money returned 

270 for p in hand_instance.pot.returned: 

271 if p == stat_dict[player]['screen_name']: 

272 stack += float(hand_instance.pot.returned[p]) 

273 

274 #Finally, add back any winnings 

275 for item in hand_instance.collectees: 

276 if item == stat_dict[player]['screen_name']: 

277 stack += float(hand_instance.collectees[item]) 

278 return stack 

279 

280def m_ratio(stat_dict, player): 

281 """ 

282 Calculate the M-ratio for a player in a tournament. 

283 

284 Args: 

285 stat_dict (dict): A dictionary containing player statistics. 

286 player (int): The player for whom to calculate the M-ratio. 

287 

288 Returns: 

289 tuple: A tuple containing the M-ratio value and formatted strings. 

290 

291 Note: 

292 This function calculates the M-ratio using the end-of-hand stack count versus the hand's antes/blinds. 

293 """ 

294 #Tournament M-ratio calculation 

295 # Using the end-of-hand stack count vs. that hand's antes/blinds 

296 

297 # sum all blinds/antes 

298 stat = 0.0 

299 compulsory_bets = 0.0 

300 hand_instance=_global_hand_instance 

301 

302 if not hand_instance: 

303 return ((stat/100.0), 

304 '%d' % (int(stat)), 

305 'M=%d' % (int(stat)), 

306 'M=%d' % (int(stat)), 

307 '(%d)' % (int(stat)), 

308 'M ratio') 

309 

310 for p in hand_instance.bets['BLINDSANTES']: 

311 for i in hand_instance.bets['BLINDSANTES'][p]: 

312 compulsory_bets += float(i) 

313 compulsory_bets += float(hand_instance.gametype['sb']) 

314 compulsory_bets += float(hand_instance.gametype['bb']) 

315 

316 stack = _calculate_end_stack(stat_dict, player, hand_instance) 

317 

318 if compulsory_bets != 0: 

319 stat = stack / compulsory_bets 

320 else: 

321 stat = 0 

322 

323 return ((int(stat)), 

324 '%d' % (int(stat)), 

325 'M=%d' % (int(stat)), 

326 'M=%d' % (int(stat)), 

327 '(%d)' % (int(stat)), 

328 'M ratio') 

329 

330def bbstack(stat_dict, player): 

331 """ 

332 Calculate the tournament stack size in Big Blinds. 

333 

334 Args: 

335 stat_dict (dict): A dictionary containing player statistics. 

336 player (int): The player for whom to calculate the stack size. 

337 

338 Returns: 

339 tuple: A tuple containing the stack size in Big Blinds and related information. 

340 

341 Note: 

342 This function calculates the stack size in Big Blinds based on the end of hand stack count and the current Big Blind limit. 

343 """ 

344 #Tournament Stack calculation in Big Blinds 

345 #Result is end of hand stack count / Current Big Blind limit 

346 stat=0.0 

347 hand_instance = _global_hand_instance 

348 if not(hand_instance): 

349 return (stat, 

350 'NA', 

351 'v=NA', 

352 'vpip=NA', 

353 '(0/0)', 

354 'bb stack') 

355 

356 # current big blind limit 

357 

358 current_bigblindlimit = 0 

359 current_bigblindlimit += float(hand_instance.gametype['bb']) 

360 

361 stack = _calculate_end_stack(stat_dict, player, hand_instance) 

362 

363 if current_bigblindlimit != 0: 

364 stat = stack / current_bigblindlimit 

365 else: 

366 stat = 0 

367 

368 return ((stat/100.0), 

369 '%d' % (int(stat)), 

370 "bb's=%d" % (int(stat)), 

371 "#bb's=%d" % (int(stat)), 

372 '(%d)' % (int(stat)), 

373 'bb stack') 

374 

375def playershort(stat_dict, player): 

376 """ 

377 Retrieves the shortened screen name of a player from the given stat_dict. 

378 

379 Args: 

380 stat_dict (dict): A dictionary containing player statistics. 

381 player (int): The player for whom to retrieve the shortened screen name. 

382 

383 Returns: 

384 tuple: A tuple containing the shortened screen name and related information. 

385 

386 Raises: 

387 KeyError: If the player's screen name is not found in the stat_dict. 

388 

389 Note: 

390 If the length of the screen name is greater than 6, it is truncated to 5 characters and a dot is appended. 

391 The returned tuple contains the shortened screen name repeated 5 times and the player's full screen name. 

392 """ 

393 try: 

394 r = stat_dict[player]['screen_name'] 

395 except: 

396 return ("","","","","", 

397 ("Player Name")+" 1-5") 

398 

399 if (len(r) > 6): 

400 r = r[:5] + "." 

401 return (r, 

402 r, 

403 r, 

404 r, 

405 stat_dict[player]['screen_name'], 

406 ("Player Name")+" 1-5") 

407 

408 

409def vpip(stat_dict, player): 

410 """ 

411 A function to calculate and return VPIP (Voluntarily Put In Pot) percentage. 

412 

413 Args: 

414 stat_dict (dict): A dictionary containing player statistics. 

415 player (str): The player for whom to calculate the VPIP. 

416 

417 Returns: 

418 tuple: A tuple containing: 

419 - VPIP percentage (float) 

420 - VPIP percentage formatted as a string 

421 - 'v=' followed by VPIP percentage formatted as a percentage string 

422 - 'vpip=' followed by VPIP percentage formatted as a percentage string 

423 - '(x/y)' where x is the VPIP and y is VPIP opportunities 

424 - 'Voluntarily put in preflop/3rd street %' 

425 

426 If an error occurs, returns: 

427 - 0.0 

428 - 'NA' 

429 - 'v=NA' 

430 - 'vpip=NA' 

431 - '(0/0)' 

432 - 'Voluntarily put in preflop/3rd street %' 

433 """ 

434 stat = 0.0 

435 try: 

436 stat = float(stat_dict[player]['vpip'])/float(stat_dict[player]['vpip_opp']) 

437 return (stat, 

438 '%3.1f' % (100.0*stat), 

439 'v=%3.1f%%' % (100.0*stat), 

440 'vpip=%3.1f%%' % (100.0*stat), 

441 '(%d/%d)' % (stat_dict[player]['vpip'], stat_dict[player]['vpip_opp']), 

442 'Voluntarily put in preflop/3rd street %') 

443 

444 except: return (stat, 

445 'NA', 

446 'v=NA', 

447 'vpip=NA', 

448 '(0/0)', 

449 'Voluntarily put in preflop/3rd street %') 

450 

451 

452 

453def pfr(stat_dict, player): 

454 """ 

455 Calculate and return the preflop raise percentage (pfr) for a player. 

456 

457 Args: 

458 stat_dict (dict): A dictionary containing player statistics. 

459 player (int): The player for whom the pfr is calculated. 

460 

461 Returns: 

462 tuple: A tuple containing the pfr value, formatted pfr percentages, and related information. 

463 """ 

464 stat = 0.0 

465 try: 

466 stat = float(stat_dict[player]['pfr'])/float(stat_dict[player]['pfr_opp']) 

467 return (stat, 

468 '%3.1f' % (100.0*stat), 

469 'p=%3.1f%%' % (100.0*stat), 

470 'pfr=%3.1f%%' % (100.0*stat), 

471 '(%d/%d)' % (stat_dict[player]['pfr'], stat_dict[player]['pfr_opp']), 

472 'Preflop/3rd street raise %') 

473 

474 except: 

475 return (stat, 

476 'NA', 

477 'p=NA', 

478 'pfr=NA', 

479 '(0/0)', 

480 'Preflop/3rd street raise %') 

481 

482 

483def wtsd(stat_dict, player): 

484 """ 

485 Calculate and return the percentage of hands where a player went to showdown when seen flop/4th street. 

486 

487 Args: 

488 stat_dict (dict): A dictionary containing player statistics. 

489 player (int): The player for whom the percentage is calculated. 

490 

491 Returns: 

492 tuple: A tuple containing the percentage value, formatted percentage percentages, and related information. 

493 """ 

494 stat = 0.0 

495 try: 

496 stat = float(stat_dict[player]['sd'])/float(stat_dict[player]['saw_f']) 

497 return (stat, 

498 '%3.1f' % (100.0*stat), 

499 'w=%3.1f%%' % (100.0*stat), 

500 'wtsd=%3.1f%%' % (100.0*stat), 

501 '(%d/%d)' % (stat_dict[player]['sd'], stat_dict[player]['saw_f']), 

502 '% went to showdown when seen flop/4th street') 

503 

504 except: 

505 return (stat, 

506 'NA', 

507 'w=NA', 

508 'wtsd=NA', 

509 '(0/0)', 

510 '% went to showdown when seen flop/4th street') 

511 

512 

513def wmsd(stat_dict, player): 

514 """ 

515 Calculate and return the win money at showdown (wmsd) statistics for a player. 

516 

517 Args: 

518 stat_dict (dict): A dictionary containing player statistics. 

519 player (int): The player for whom the wmsd is calculated. 

520 

521 Returns: 

522 tuple: A tuple containing the wmsd value, formatted wmsd percentages, and related information. 

523 """ 

524 stat = 0.0 

525 try: 

526 stat = float(stat_dict[player]['wmsd'])/float(stat_dict[player]['sd']) 

527 return (stat, 

528 '%3.1f' % (100.0*stat), 

529 'w=%3.1f%%' % (100.0*stat), 

530 'wmsd=%3.1f%%' % (100.0*stat), 

531 '(%5.1f/%d)' % (float(stat_dict[player]['wmsd']), stat_dict[player]['sd']), 

532 '% won some money at showdown') 

533 

534 except: 

535 return (stat, 

536 'NA', 

537 'w=NA', 

538 'wmsd=NA', 

539 '(0/0)', 

540 '% won some money at showdown') 

541 

542 

543# Money is stored as pennies, so there is an implicit 100-multiplier 

544# already in place 

545def profit100(stat_dict, player): 

546 """ 

547 Calculate the profit per 100 hands for a given player. 

548 

549 Args: 

550 stat_dict (dict): A dictionary containing player statistics. 

551 player (int): The player for whom the profit per 100 hands is calculated. 

552 

553 Returns: 

554 tuple: A tuple containing the profit per 100 hands value, formatted profit percentages, and related information. 

555 

556 Raises: 

557 None 

558 

559 Notes: 

560 - The profit per 100 hands is calculated by dividing the net winnings by the number of hands played. 

561 - The function returns a tuple containing the profit per 100 hands value, formatted profit percentages, and related information. 

562 - If an exception occurs during the calculation, the function returns a tuple with default values. 

563 - The function logs an exception message if the stat_dict is not empty. 

564 """ 

565 stat = 0.0 

566 try: 

567 stat = float(stat_dict[player]['net'])/float(stat_dict[player]['n']) 

568 return (stat/100.0, 

569 '%.2f' % (stat), 

570 'p=%.2f' % (stat), 

571 'p/100=%.2f' % (stat), 

572 '%d/%d' % (stat_dict[player]['net'], stat_dict[player]['n']), 

573 'Profit per 100 hands') 

574 

575 except: 

576 if stat_dict: log.info("exception calculating %s") % ("p/100: 100 * %d / %d" % (stat_dict[player]['net'], stat_dict[player]['n'])) 

577 return (stat, 

578 'NA', 

579 'p=NA', 

580 'p/100=NA', 

581 '(0/0)', 

582 'Profit per 100 hands') 

583 

584 

585def bbper100(stat_dict, player): 

586 """ 

587 Calculate the number of big blinds won per 100 hands for a given player. 

588 

589 Args: 

590 stat_dict (dict): A dictionary containing player statistics. 

591 player (int): The player for whom the number of big blinds won per 100 hands is calculated. 

592 

593 Returns: 

594 tuple: A tuple containing the number of big blinds won per 100 hands value, formatted values, and related information. 

595 

596 Raises: 

597 None 

598 

599 Notes: 

600 - The number of big blinds won per 100 hands is calculated by dividing the net winnings by the number of hands played, multiplied by 100. 

601 - The function returns a tuple containing the number of big blinds won per 100 hands value, formatted values, and related information. 

602 - If an exception occurs during the calculation, the function returns a tuple with default values. 

603 - The function logs an exception message if the stat_dict is not empty. 

604 """ 

605 stat = 0.0 

606 #['bigblind'] is already containing number of hands * table's bigblind (e.g. 401 hands @ 5c BB = 2005) 

607 try: 

608 stat = 100.0 * float(stat_dict[player]['net']) / float(stat_dict[player]['bigblind']) 

609 return (stat/100.0, 

610 '%5.3f' % (stat), 

611 'bb100=%5.3f' % (stat), 

612 'bb100=%5.3f' % (stat), 

613 '(%d,%d)' % (100*stat_dict[player]['net'],stat_dict[player]['bigblind']), 

614 'Big blinds won per 100 hands') 

615 

616 except: 

617 if stat_dict: log.info("exception calculating %s") % ("bb/100: "+str(stat_dict[player])) 

618 return (stat, 

619 'NA', 

620 'bb100=NA', 

621 'bb100=NA', 

622 '(--)', 

623 'Big blinds won per 100 hands') 

624 

625 

626def BBper100(stat_dict, player): 

627 """ 

628 Calculate the number of big bets won per 100 hands for a given player. 

629 

630 Args: 

631 stat_dict (dict): A dictionary containing player statistics. 

632 player (int): The player for whom the number of big bets won per 100 hands is calculated. 

633 

634 Returns: 

635 tuple: A tuple containing the number of big bets won per 100 hands value, formatted values, and related information. 

636 

637 Notes: 

638 - The number of big bets won per 100 hands is calculated by dividing the net winnings by the big blind value, multiplied by 50. 

639 - The function returns a tuple containing the number of big bets won per 100 hands value, formatted values, and related information. 

640 - If an exception occurs during the calculation, the function returns a tuple with default values. 

641 - The function logs an exception message if the stat_dict is not empty. 

642 """ 

643 stat = 0.0 

644 #['bigblind'] is already containing number of hands * table's bigblind (e.g. 401 hands @ 5c BB = 2005) 

645 try: 

646 stat = 50 * float(stat_dict[player]['net']) / float(stat_dict[player]['bigblind']) 

647 return (stat/100.0, 

648 '%5.3f' % (stat), 

649 'BB100=%5.3f' % (stat), 

650 'BB100=%5.3f' % (stat), 

651 '(%d,%d)' % (100*stat_dict[player]['net'],2*stat_dict[player]['bigblind']), 

652 'Big bets won per 100 hands') 

653 

654 except: 

655 if stat_dict: log.info("exception calculating %s") % ("BB/100: "+str(stat_dict[player])) 

656 return (stat, 

657 'NA', 

658 'BB100=NA', 

659 'BB100=NA', 

660 '(--)', 

661 'Big bets won per 100 hands') 

662 

663 

664def saw_f(stat_dict, player): 

665 

666 """Calculate the saw flop percentage for a given player. 

667 

668 Args: 

669 stat_dict (dict): A dictionary containing player statistics. 

670 player (int): The player for whom the saw flop percentage is calculated. 

671 

672 Returns: 

673 tuple: A tuple containing the saw flop percentage in various formats. 

674 - The saw flop percentage as a float. 

675 - The saw flop percentage formatted to one decimal place. 

676 - The saw flop percentage with a label. 

677 - The saw flop percentage with a different label. 

678 - The count of times saw flop divided by total count. 

679 - A description of the statistic. 

680 

681 If an error occurs during calculation, default values are returned. 

682 """ 

683 try: 

684 num = float(stat_dict[player]['saw_f']) 

685 den = float(stat_dict[player]['n']) 

686 stat = num/den 

687 return (stat, 

688 '%3.1f' % (100.0*stat), 

689 'sf=%3.1f%%' % (100.0*stat), 

690 'saw_f=%3.1f%%' % (100.0*stat), 

691 '(%d/%d)' % (stat_dict[player]['saw_f'], stat_dict[player]['n']), 

692 'Flop/4th street seen %') 

693 

694 except: 

695 stat = 0.0 

696 return (stat, 

697 'NA', 

698 'sf=NA', 

699 'saw_f=NA', 

700 '(0/0)', 

701 'Flop/4th street seen %') 

702 

703 

704def n(stat_dict, player): 

705 ''' 

706 Calculate and format the number of hands seen for a player. 

707 

708 Args: 

709 stat_dict (dict): A dictionary containing player statistics. 

710 player (int): The player for whom the number of hands seen is calculated. 

711 

712 Returns: 

713 tuple: A tuple containing formatted strings representing the number of hands seen in different ways. 

714 ''' 

715 try: 

716 # If sample is large enough, use X.Yk notation instead 

717 _n = stat_dict[player]['n'] 

718 fmt = '%d' % _n 

719 if _n >= 10000: 

720 k = _n / 1000 

721 c = _n % 1000 

722 _c = float(c) / 100.0 

723 d = int(round(_c)) 

724 if d == 10: 

725 k += 1 

726 d = 0 

727 fmt = '%d.%dk' % (k, d) 

728 return (stat_dict[player]['n'], 

729 '%s' % fmt, 

730 'n=%d' % (stat_dict[player]['n']), 

731 'n=%d' % (stat_dict[player]['n']), 

732 '(%d)' % (stat_dict[player]['n']), 

733 'Number of hands seen') 

734 

735 except: 

736 # Number of hands shouldn't ever be "NA"; zeroes are better here 

737 return (0, 

738 '%d' % (0), 

739 'n=%d' % (0), 

740 'n=%d' % (0), 

741 '(%d)' % (0), 

742 'Number of hands seen') 

743 

744 

745def steal(stat_dict, player): 

746 """ 

747 Calculate and format the steal percentage for a player. 

748 

749 Args: 

750 stat_dict (dict): A dictionary containing player statistics. 

751 player (int): The player for whom the steal percentage is calculated. 

752 

753 Returns: 

754 tuple: A tuple containing formatted strings representing the steal percentage in different ways. 

755 - stat (float): The steal percentage. 

756 - '%3.1f' (str): The steal percentage formatted as a string with 3 decimal places. 

757 - 'st=%3.1f%%' (str): The steal percentage formatted as a string with 3 decimal places and a percentage sign. 

758 - 'steal=%3.1f%%' (str): The steal percentage formatted as a string with 3 decimal places and a percentage sign. 

759 - '(%d/%d)' (str): The steal count and steal opponent count formatted as a string. 

760 - '% steal attempted' (str): The description of the steal percentage. 

761 

762 Raises: 

763 None 

764 

765 Notes: 

766 - The steal percentage is calculated by dividing the steal count by the steal opponent count. 

767 - If any of the required statistics are missing, the function returns default values. 

768 """ 

769 stat = 0.0 

770 try: 

771 stat = float(stat_dict[player]['steal'])/float(stat_dict[player]['steal_opp']) 

772 return (stat, 

773 '%3.1f' % (100.0*stat), 

774 'st=%3.1f%%' % (100.0*stat), 

775 'steal=%3.1f%%' % (100.0*stat), 

776 '(%d/%d)' % (stat_dict[player]['steal'], stat_dict[player]['steal_opp']), 

777 '% steal attempted') 

778 

779 except: 

780 return (stat, 'NA', 'st=NA', 'steal=NA', '(0/0)', '% steal attempted') 

781 

782def s_steal(stat_dict, player): 

783 """ 

784 Calculate and format the steal success percentage for a player. 

785 

786 Args: 

787 stat_dict (dict): A dictionary containing player statistics. 

788 player (int): The player for whom the steal success percentage is calculated. 

789 

790 Returns: 

791 tuple: A tuple containing formatted strings representing the steal success percentage in different ways. 

792 - stat (float): The steal success percentage. 

793 - '%3.1f' (str): The steal success percentage formatted as a string with 3 decimal places. 

794 - 's_st=%3.1f%%' (str): The steal success percentage formatted with a specific label. 

795 - 's_steal=%3.1f%%' (str): The steal success percentage formatted with a specific label. 

796 - '(%d/%d)' (str): The steal success count and total steal count formatted as a string. 

797 - '% steal success' (str): The description of the steal success percentage. 

798 

799 Raises: 

800 None 

801 """ 

802 stat = 0.0 

803 try: 

804 stat = float(stat_dict[player]['suc_st'])/float(stat_dict[player]['steal']) 

805 return (stat, 

806 '%3.1f' % (100.0*stat), 

807 's_st=%3.1f%%' % (100.0*stat), 

808 's_steal=%3.1f%%' % (100.0*stat), 

809 '(%d/%d)' % (stat_dict[player]['suc_st'], stat_dict[player]['steal']), 

810 '% steal success') 

811 

812 except: 

813 return (stat, 'NA', 'st=NA', 's_steal=NA', '(0/0)', '% steal success') 

814 

815def f_SB_steal(stat_dict, player): 

816 """ 

817 Calculate the folded Small Blind (SB) to steal statistics for a player. 

818 

819 Args: 

820 stat_dict (dict): A dictionary containing player statistics. 

821 player (int): The player for whom the statistics are calculated. 

822 

823 Returns: 

824 tuple: A tuple containing the folded SB to steal statistics. 

825 - stat (float): The folded SB to steal percentage. 

826 - '%3.1f' (str): The folded SB to steal percentage formatted as a string with 3 decimal places. 

827 - 'fSB=%3.1f%%' (str): The folded SB to steal percentage formatted with a specific label. 

828 - 'fSB_s=%3.1f%%' (str): The folded SB to steal percentage formatted with a specific label. 

829 - '(%d/%d)' (str): The number of folded SB to steal and the total number of folded SB formatted as a string. 

830 - '% folded SB to steal' (str): The description of the folded SB to steal percentage. 

831 

832 Raises: 

833 None 

834 """ 

835 stat = 0.0 

836 try: 

837 stat = float(stat_dict[player]['sbnotdef'])/float(stat_dict[player]['sbstolen']) 

838 return (stat, 

839 '%3.1f' % (100.0*stat), 

840 'fSB=%3.1f%%' % (100.0*stat), 

841 'fSB_s=%3.1f%%' % (100.0*stat), 

842 '(%d/%d)' % (stat_dict[player]['sbnotdef'], stat_dict[player]['sbstolen']), 

843 '% folded SB to steal') 

844 except: 

845 return (stat, 

846 'NA', 

847 'fSB=NA', 

848 'fSB_s=NA', 

849 '(0/0)', 

850 '% folded SB to steal') 

851 

852def f_BB_steal(stat_dict, player): 

853 """Calculate the folded Big Blind (BB) to steal statistics for a player. 

854 

855 Args: 

856 stat_dict (dict): A dictionary containing player statistics. 

857 player (int): The player for whom the statistics are calculated. 

858 

859 Returns: 

860 tuple: A tuple containing the calculated statistics in different formats: 

861 - Float: The calculated statistic. 

862 - String: The statistic formatted as a percentage with one decimal place. 

863 - String: A formatted string representing the statistic. 

864 - String: A formatted string representing the statistic with a suffix. 

865 - String: A formatted string showing the count of BB not defended and BB stolen. 

866 - String: A description of the statistic. 

867 

868 If an exception occurs during the calculation, returns default values for the statistics. 

869 """ 

870 stat = 0.0 

871 try: 

872 stat = float(stat_dict[player]['bbnotdef'])/float(stat_dict[player]['bbstolen']) 

873 return (stat, 

874 '%3.1f' % (100.0*stat), 

875 'fBB=%3.1f%%' % (100.0*stat), 

876 'fBB_s=%3.1f%%' % (100.0*stat), 

877 '(%d/%d)' % (stat_dict[player]['bbnotdef'], stat_dict[player]['bbstolen']), 

878 '% folded BB to steal') 

879 except: 

880 return (stat, 

881 'NA', 

882 'fBB=NA', 

883 'fBB_s=NA', 

884 '(0/0)', 

885 '% folded BB to steal') 

886 

887def f_steal(stat_dict, player): 

888 """ 

889 Calculate the folded blind to steal statistics for a player. 

890 

891 Args: 

892 stat_dict (dict): A dictionary containing player statistics. 

893 player (int): The player for whom the statistics are calculated. 

894 

895 Returns: 

896 tuple: A tuple containing the calculated statistics in different formats: 

897 - Float: The calculated statistic. 

898 - String: The statistic formatted as a percentage with one decimal place. 

899 - String: A formatted string representing the statistic. 

900 - String: A formatted string representing the statistic with a suffix. 

901 - String: A formatted string showing the count of folded blind not defended and blind stolen. 

902 - String: A description of the statistic. 

903 

904 If an exception occurs during the calculation, returns default values for the statistics. 

905 """ 

906 stat = 0.0 

907 try: 

908 folded_blind = stat_dict[player]['sbnotdef'] + stat_dict[player]['bbnotdef'] 

909 blind_stolen = stat_dict[player]['sbstolen'] + stat_dict[player]['bbstolen'] 

910 

911 stat = float(folded_blind)/float(blind_stolen) 

912 return (stat, 

913 '%3.1f' % (100.0*stat), 

914 'fB=%3.1f%%' % (100.0*stat), 

915 'fB_s=%3.1f%%' % (100.0*stat), 

916 '(%d/%d)' % (folded_blind, blind_stolen), 

917 '% folded blind to steal') 

918 except: 

919 return (stat, 

920 'NA', 

921 'fB=NA', 

922 'fB_s=NA', 

923 '(0/0)', 

924 '% folded blind to steal') 

925 

926def three_B(stat_dict, player): 

927 """ 

928 Calculate the three bet statistics for a player. 

929 

930 Args: 

931 stat_dict (dict): A dictionary containing player statistics. 

932 player (int): The player for whom the statistics are calculated. 

933 

934 Returns: 

935 tuple: A tuple containing the calculated statistics in different formats: 

936 - Float: The calculated statistic. 

937 - String: The statistic formatted as a percentage with one decimal place. 

938 - String: A formatted string representing the statistic. 

939 - String: A formatted string representing the statistic with a suffix. 

940 - String: A formatted string showing the count of three bets made and opponent's three bets. 

941 - String: A description of the statistic. 

942 

943 If an exception occurs during the calculation, returns default values for the statistics. 

944 """ 

945 stat = 0.0 

946 try: 

947 stat = float(stat_dict[player]['tb_0'])/float(stat_dict[player]['tb_opp_0']) 

948 return (stat, 

949 '%3.1f' % (100.0*stat), 

950 '3B=%3.1f%%' % (100.0*stat), 

951 '3B_pf=%3.1f%%' % (100.0*stat), 

952 '(%d/%d)' % (stat_dict[player]['tb_0'], stat_dict[player]['tb_opp_0']), 

953 '% 3 bet preflop/3rd street') 

954 except: 

955 return (stat, 

956 'NA', 

957 '3B=NA', 

958 '3B_pf=NA', 

959 '(0/0)', 

960 '% 3 bet preflop/3rd street') 

961 

962def four_B(stat_dict, player): 

963 """ 

964 

965 Calculate the four bet statistics for a player. 

966 

967 Args: 

968 stat_dict (dict): A dictionary containing player statistics. 

969 player (int): The player for whom the statistics are calculated. 

970 

971 Returns: 

972 tuple: A tuple containing the calculated statistics in different formats: 

973 - Float: The calculated statistic. 

974 - String: The statistic formatted as a percentage with one decimal place. 

975 - String: A formatted string representing the statistic. 

976 - String: A formatted string representing the statistic with a suffix. 

977 - String: A formatted string showing the count of four bets made and opponent's four bets. 

978 - String: A description of the statistic. 

979 

980 If an exception occurs during the calculation, returns default values for the statistics. 

981  

982 """ 

983 stat = 0.0 

984 try: 

985 stat = float(stat_dict[player]['fb_0'])/float(stat_dict[player]['fb_opp_0']) 

986 return (stat, 

987 '%3.1f' % (100.0*stat), 

988 '4B=%3.1f%%' % (100.0*stat), 

989 '4B=%3.1f%%' % (100.0*stat), 

990 '(%d/%d)' % (stat_dict[player]['fb_0'], stat_dict[player]['fb_opp_0']), 

991 '% 4 bet preflop/3rd street') 

992 except: 

993 return (stat, 

994 'NA', 

995 '4B=NA', 

996 '4B=NA', 

997 '(0/0)', 

998 '% 4 bet preflop/3rd street') 

999 

1000def cfour_B(stat_dict, player): 

1001 """ 

1002 Calculate the cold 4 bet statistics for a player. 

1003 

1004 Args: 

1005 stat_dict (dict): A dictionary containing player statistics. 

1006 player (int): The player for whom the statistics are calculated. 

1007 

1008 Returns: 

1009 tuple: A tuple containing the calculated statistics in different formats: 

1010 - Float: The calculated statistic. 

1011 - String: The statistic formatted as a percentage with one decimal place. 

1012 - String: A formatted string representing the statistic. 

1013 - String: A formatted string representing the statistic with a suffix. 

1014 - String: A formatted string showing the count of cold 4 bets made and opponent's cold 4 bets. 

1015 - String: A description of the statistic. 

1016 

1017 If an exception occurs during the calculation, returns default values for the statistics. 

1018 """ 

1019 stat = 0.0 

1020 try: 

1021 stat = float(stat_dict[player]['cfb_0'])/float(stat_dict[player]['cfb_opp_0']) 

1022 return (stat, 

1023 '%3.1f' % (100.0*stat), 

1024 'C4B=%3.1f%%' % (100.0*stat), 

1025 'C4B_pf=%3.1f%%' % (100.0*stat), 

1026 '(%d/%d)' % (stat_dict[player]['cfb_0'], stat_dict[player]['cfb_opp_0']), 

1027 '% cold 4 bet preflop/3rd street') 

1028 except: 

1029 return (stat, 

1030 'NA', 

1031 'C4B=NA', 

1032 'C4B_pf=NA', 

1033 '(0/0)', 

1034 '% cold 4 bet preflop/3rd street') 

1035 

1036# Four Bet Range 

1037def fbr(stat_dict, player): 

1038 """ 

1039 A function to calculate the four bet range statistics for a player. 

1040 

1041 Args: 

1042 stat_dict (dict): A dictionary containing player statistics. 

1043 player (int): The player for whom the statistics are calculated. 

1044 

1045 Returns: 

1046 tuple: A tuple containing the calculated statistics in different formats: 

1047 - Float: The calculated statistic. 

1048 - String: The statistic formatted as a percentage with one decimal place. 

1049 - String: A formatted string representing the statistic. 

1050 - String: A formatted string representing the statistic with a suffix. 

1051 - String: A formatted string showing the product of 'pfr' and 'four_B'. 

1052 - String: A description of the statistic. 

1053 

1054 If an exception occurs during the calculation, returns default values for the statistics. 

1055 """ 

1056 stat = 0.0 

1057 try: 

1058 stat = float(stat_dict[player]['fb_0'])/float(stat_dict[player]['fb_opp_0']) 

1059 stat *= float(stat_dict[player]['pfr'])/float(stat_dict[player]['n']) 

1060 return (stat, 

1061 '%3.1f' % (100.0*stat), 

1062 'fbr=%3.1f%%' % (100.0*stat), 

1063 '4Brange=%3.1f%%' % (100.0*stat), 

1064 '(pfr*four_B)', 

1065 '4 bet range') 

1066 except: 

1067 return (stat, 

1068 'NA', 

1069 'fbr=NA', 

1070 'fbr=NA', 

1071 '(pfr*four_B)', 

1072 '4 bet range') 

1073 

1074# Call 3 Bet 

1075def ctb(stat_dict, player): 

1076 """ 

1077 A function to calculate the four bet range statistics for a player. 

1078 

1079 Args: 

1080 stat_dict (dict): A dictionary containing player statistics. 

1081 player (int): The player for whom the statistics are calculated. 

1082 

1083 Returns: 

1084 tuple: A tuple containing the calculated statistics in different formats: 

1085 - Float: The calculated statistic. 

1086 - String: The statistic formatted as a percentage with one decimal place. 

1087 - String: A formatted string representing the statistic. 

1088 - String: A formatted string representing the statistic with a suffix. 

1089 - String: A formatted string showing the product of 'pfr' and 'four_B'. 

1090 - String: A description of the statistic. 

1091 

1092 If an exception occurs during the calculation, returns default values for the statistics. 

1093 """ 

1094 stat = 0.0 

1095 try: 

1096 stat = (float(stat_dict[player]['f3b_opp_0'])-float(stat_dict[player]['f3b_0'])-float(stat_dict[player]['fb_0']))/float(stat_dict[player]['f3b_opp_0']) 

1097 return (stat, 

1098 '%3.1f' % (100.0*stat), 

1099 'ctb=%3.1f%%' % (100.0*stat), 

1100 'call3B=%3.1f%%' % (100.0*stat), 

1101 '(%d/%d)' % (float(stat_dict[player]['f3b_opp_0'])-stat_dict[player]['fb_0']-stat_dict[player]['f3b_0'], stat_dict[player]['fb_opp_0']), 

1102 '% call 3 bet') 

1103 except: 

1104 return (stat, 

1105 'NA', 

1106 'ctb=NA', 

1107 'ctb=NA', 

1108 '(0/0)', 

1109 '% call 3 bet') 

1110 

1111def dbr1(stat_dict, player): 

1112 """Calculate and return the Donk Bet and Raise statistic for a given player on flop/4th street. 

1113 

1114 Args: 

1115 stat_dict (dict): A dictionary containing player statistics. 

1116 player (int): The player for whom the statistic is calculated. 

1117 

1118 Returns: 

1119 tuple: A tuple containing the calculated statistic, percentage representation, formatted strings, and additional information. 

1120 

1121 Example: 

1122 dbr1(stat_dict, player) 

1123 """ 

1124 stat = 0.0 

1125 try: 

1126 stat = float(stat_dict[player]['aggr_1']) - float(stat_dict[player]['cb_1']) 

1127 stat /= float(stat_dict[player]['saw_f']) - float(stat_dict[player]['cb_opp_1']) 

1128 return (stat, 

1129 '%3.1f' % (100.0*stat), 

1130 'dbr1=%3.1f%%' % (100.0*stat), 

1131 'dbr1=%3.1f%%' % (100.0*stat), 

1132 '(%d/%d)' % (float(stat_dict[player]['aggr_1']) - float(stat_dict[player]['cb_1']), float(stat_dict[player]['saw_f']) - float(stat_dict[player]['cb_opp_1'])), 

1133 '% DonkBetAndRaise flop/4th street') 

1134 except: 

1135 return (stat, 

1136 'NA', 

1137 'dbr1=NA', 

1138 'dbr1=NA', 

1139 '(0/0)', 

1140 '% DonkBetAndRaise flop/4th street') 

1141 

1142def dbr2(stat_dict, player): 

1143 """Calculate and return the Donk Bet and Raise statistic for a given player on turn/5th street. 

1144 

1145 Args: 

1146 stat_dict (dict): A dictionary containing player statistics. 

1147 player (int): The player for whom the statistic is calculated. 

1148 

1149 Returns: 

1150 tuple: A tuple containing the calculated statistic, percentage representation, formatted strings, and additional information. 

1151 

1152 Example: 

1153 dbr1(stat_dict, player) 

1154 """ 

1155 stat = 0.0 

1156 try: 

1157 stat = float(stat_dict[player]['aggr_2']) - float(stat_dict[player]['cb_2']) 

1158 stat /= float(stat_dict[player]['saw_2']) - float(stat_dict[player]['cb_opp_2']) 

1159 return (stat, 

1160 '%3.1f' % (100.0*stat), 

1161 'dbr2=%3.1f%%' % (100.0*stat), 

1162 'dbr2=%3.1f%%' % (100.0*stat), 

1163 '(%d/%d)' % (float(stat_dict[player]['aggr_2']) - float(stat_dict[player]['cb_2']), float(stat_dict[player]['saw_2']) - float(stat_dict[player]['cb_opp_2'])), 

1164 '% DonkBetAndRaise turn/5th street') 

1165 except: 

1166 return (stat, 

1167 'NA', 

1168 'dbr2=NA', 

1169 'dbr2=NA', 

1170 '(0/0)', 

1171 '% DonkBetAndRaise turn/5th street') 

1172 

1173def dbr3(stat_dict, player): 

1174 """Calculate and return the Donk Bet and Raise statistic for a given player on river/6th street. 

1175 

1176 Args: 

1177 stat_dict (dict): A dictionary containing player statistics. 

1178 player (int): The player for whom the statistic is calculated. 

1179 

1180 Returns: 

1181 tuple: A tuple containing the calculated statistic, percentage representation, formatted strings, and additional information. 

1182 

1183 Example: 

1184 dbr1(stat_dict, player) 

1185 """ 

1186 stat = 0.0 

1187 try: 

1188 stat = float(stat_dict[player]['aggr_3']) - float(stat_dict[player]['cb_3']) 

1189 stat /= float(stat_dict[player]['saw_3']) - float(stat_dict[player]['cb_opp_3']) 

1190 return (stat, 

1191 '%3.1f' % (100.0*stat), 

1192 'dbr3=%3.1f%%' % (100.0*stat), 

1193 'dbr3=%3.1f%%' % (100.0*stat), 

1194 '(%d/%d)' % (float(stat_dict[player]['aggr_3']) - float(stat_dict[player]['cb_3']), float(stat_dict[player]['saw_3']) - float(stat_dict[player]['cb_opp_3'])), 

1195 '% DonkBetAndRaise river/6th street') 

1196 except: 

1197 return (stat, 

1198 'NA', 

1199 'dbr3=NA', 

1200 'dbr3=NA', 

1201 '(0/0)', 

1202 '% DonkBetAndRaise river/6th street') 

1203 

1204 

1205def f_dbr1(stat_dict, player): 

1206 """Calculate and return the fold to DonkBetAndRaise statistic for a given player on flop/4th street. 

1207 

1208 Args: 

1209 stat_dict (dict): A dictionary containing player statistics. 

1210 player (int): The player for whom the statistic is calculated. 

1211 

1212 Returns: 

1213 tuple: A tuple containing the calculated statistic, formatted strings, and additional information. 

1214 

1215 Example: 

1216 f_dbr1(stat_dict, player) 

1217 

1218 Note: 

1219 If an exception occurs during calculation, 'NA' values are returned. 

1220 """ 

1221 stat = 0.0 

1222 try: 

1223 stat = float(stat_dict[player]['f_freq_1']) - float(stat_dict[player]['f_cb_1']) 

1224 stat /= float(stat_dict[player]['was_raised_1']) - float(stat_dict[player]['f_cb_opp_1']) 

1225 return (stat, 

1226 '%3.1f' % (100.0*stat), 

1227 'f_dbr1=%3.1f%%' % (100.0*stat), 

1228 'f_dbr1=%3.1f%%' % (100.0*stat), 

1229 '(%d/%d)' % (float(stat_dict[player]['f_freq_1']) - float(stat_dict[player]['f_cb_1']), float(stat_dict[player]['was_raised_1']) - float(stat_dict[player]['f_cb_opp_1'])), 

1230 '% Fold to DonkBetAndRaise flop/4th street') 

1231 except: 

1232 return (stat, 

1233 'NA', 

1234 'f_dbr1=NA', 

1235 'f_dbr1=NA', 

1236 '(0/0)', 

1237 '% Fold DonkBetAndRaise flop/4th street') 

1238 

1239def f_dbr2(stat_dict, player): 

1240 """Calculate and return the fold to DonkBetAndRaise statistic for a given player on turn/5th street. 

1241 

1242 Args: 

1243 stat_dict (dict): A dictionary containing player statistics. 

1244 player (int): The player for whom the statistic is calculated. 

1245 

1246 Returns: 

1247 tuple: A tuple containing the calculated statistic, formatted strings, and additional information. 

1248 

1249 Example: 

1250 f_dbr1(stat_dict, player) 

1251 

1252 Note: 

1253 If an exception occurs during calculation, 'NA' values are returned. 

1254 """ 

1255 stat = 0.0 

1256 try: 

1257 stat = float(stat_dict[player]['f_freq_2']) - float(stat_dict[player]['f_cb_2']) 

1258 stat /= float(stat_dict[player]['was_raised_2']) - float(stat_dict[player]['f_cb_opp_2']) 

1259 return (stat, 

1260 '%3.1f' % (100.0*stat), 

1261 'f_dbr2=%3.1f%%' % (100.0*stat), 

1262 'f_dbr2=%3.1f%%' % (100.0*stat), 

1263 '(%d/%d)' % (float(stat_dict[player]['f_freq_2']) - float(stat_dict[player]['f_cb_2']), float(stat_dict[player]['was_raised_2']) - float(stat_dict[player]['f_cb_opp_2'])), 

1264 '% Fold to DonkBetAndRaise turn') 

1265 except: 

1266 return (stat, 

1267 'NA', 

1268 'f_dbr2=NA', 

1269 'f_dbr2=NA', 

1270 '(0/0)', 

1271 '% Fold DonkBetAndRaise turn') 

1272 

1273 

1274def f_dbr3(stat_dict, player): 

1275 """Calculate and return the fold to DonkBetAndRaise statistic for a given player on river/6th street. 

1276 

1277 Args: 

1278 stat_dict (dict): A dictionary containing player statistics. 

1279 player (int): The player for whom the statistic is calculated. 

1280 

1281 Returns: 

1282 tuple: A tuple containing the calculated statistic, formatted strings, and additional information. 

1283 

1284 Example: 

1285 f_dbr1(stat_dict, player) 

1286 

1287 Note: 

1288 If an exception occurs during calculation, 'NA' values are returned. 

1289 """ 

1290 stat = 0.0 

1291 try: 

1292 stat = float(stat_dict[player]['f_freq_3']) - float(stat_dict[player]['f_cb_3']) 

1293 stat /= float(stat_dict[player]['was_raised_3']) - float(stat_dict[player]['f_cb_opp_3']) 

1294 return (stat, 

1295 '%3.1f' % (100.0*stat), 

1296 'f_dbr3=%3.1f%%' % (100.0*stat), 

1297 'f_dbr3=%3.1f%%' % (100.0*stat), 

1298 '(%d/%d)' % (float(stat_dict[player]['f_freq_3']) - float(stat_dict[player]['f_cb_3']), float(stat_dict[player]['was_raised_3']) - float(stat_dict[player]['f_cb_opp_3'])), 

1299 '% Fold to DonkBetAndRaise river') 

1300 except: 

1301 return (stat, 

1302 'NA', 

1303 'f_dbr3=NA', 

1304 'f_dbr3=NA', 

1305 '(0/0)', 

1306 '% Fold DonkBetAndRaise river') 

1307 

1308 

1309def squeeze(stat_dict, player): 

1310 """ 

1311 Calculate the squeeze statistic for a player. 

1312 

1313 Args: 

1314 stat_dict (dict): A dictionary containing player statistics. 

1315 player (int): The player for whom the statistic is calculated. 

1316 

1317 Returns: 

1318 tuple: A tuple containing the calculated statistic, percentage values, and formatted strings. 

1319 """ 

1320 stat = 0.0 

1321 try: 

1322 stat = float(stat_dict[player]['sqz_0'])/float(stat_dict[player]['sqz_opp_0']) 

1323 return (stat, 

1324 '%3.1f' % (100.0*stat), 

1325 'SQZ=%3.1f%%' % (100.0*stat), 

1326 'SQZ_pf=%3.1f%%' % (100.0*stat), 

1327 '(%d/%d)' % (stat_dict[player]['sqz_0'], stat_dict[player]['sqz_opp_0']), 

1328 '% squeeze preflop') 

1329 except: 

1330 return (stat, 

1331 'NA', 

1332 'SQZ=NA', 

1333 'SQZ_pf=NA', 

1334 '(0/0)', 

1335 '% squeeze preflop') 

1336 

1337 

1338def raiseToSteal(stat_dict, player): 

1339 """Calculate the raise to steal stat for a player. 

1340 

1341 Args: 

1342 stat_dict (dict): A dictionary containing stats for each player. 

1343 player (int): The player for whom the stat is calculated. 

1344 

1345 Returns: 

1346 tuple: A tuple containing the raise to steal stat, formatted percentages, and additional information. 

1347 """ 

1348 stat = 0.0 

1349 try: 

1350 stat = float(stat_dict[player]['rts'])/float(stat_dict[player]['rts_opp']) 

1351 return (stat, 

1352 '%3.1f' % (100.0*stat), 

1353 'RST=%3.1f%%' % (100.0*stat), 

1354 'RST_pf=%3.1f%%' % (100.0*stat), 

1355 '(%d/%d)' % (stat_dict[player]['rts'], stat_dict[player]['rts_opp']), 

1356 '% raise to steal') 

1357 except: 

1358 return (stat, 

1359 'NA', 

1360 'RST=NA', 

1361 'RST_pf=NA', 

1362 '(0/0)', 

1363 '% raise to steal') 

1364 

1365def car0(stat_dict, player): 

1366 """Calculate the pourcent of called a raise preflop stat for a player based on the provided stat dictionary. 

1367 

1368 Args: 

1369 stat_dict (dict): A dictionary containing stats for each player. 

1370 player (int): The player for whom the CAR0 stat is calculated. 

1371 

1372 Returns: 

1373 tuple: A tuple containing various formatted strings representing the CAR0 stat. 

1374 If an exception occurs during calculation, returns default 'NA' values. 

1375 """ 

1376 stat = 0.0 

1377 try: 

1378 stat = float(stat_dict[player]['car_0'])/float(stat_dict[player]['car_opp_0']) 

1379 return (stat, 

1380 '%3.1f' % (100.0*stat), 

1381 'CAR0=%3.1f%%' % (100.0*stat), 

1382 'CAR_pf=%3.1f%%' % (100.0*stat), 

1383 '(%d/%d)' % (stat_dict[player]['car_0'], stat_dict[player]['car_opp_0']), 

1384 '% called a raise preflop') 

1385 except: 

1386 return (stat, 

1387 'NA', 

1388 'CAR0=NA', 

1389 'CAR_pf=NA', 

1390 '(0/0)', 

1391 '% called a raise preflop') 

1392 

1393def f_3bet(stat_dict, player): 

1394 """Calculate the Fold to 3-Bet statistic for a player. 

1395 

1396 Args: 

1397 stat_dict (dict): A dictionary containing player statistics. 

1398 player (int): The player for whom the statistic is calculated. 

1399 

1400 Returns: 

1401 tuple: A tuple containing various representations of the Fold to 3-Bet statistic. 

1402 The tuple includes the statistic value, percentage, labels, and counts. 

1403 If an error occurs during calculation, returns 'NA' values. 

1404 """ 

1405 stat = 0.0 

1406 try: 

1407 stat = float(stat_dict[player]['f3b_0'])/float(stat_dict[player]['f3b_opp_0']) 

1408 return (stat, 

1409 '%3.1f' % (100.0*stat), 

1410 'F3B=%3.1f%%' % (100.0*stat), 

1411 'F3B_pf=%3.1f%%' % (100.0*stat), 

1412 '(%d/%d)' % (stat_dict[player]['f3b_0'], stat_dict[player]['f3b_opp_0']), 

1413 '% fold to 3 bet preflop/3rd street') 

1414 except: 

1415 return (stat, 

1416 'NA', 

1417 'F3B=NA', 

1418 'F3B_pf=NA', 

1419 '(0/0)', 

1420 '% fold to 3 bet preflop/3rd street') 

1421 

1422def f_4bet(stat_dict, player): 

1423 """ 

1424 Calculate and return fold to 4-bet statistics for a player. 

1425 

1426 Args: 

1427 stat_dict (dict): Dictionary containing player statistics. 

1428 player (int): Player identifier. 

1429 

1430 Returns: 

1431 tuple: Tuple containing various statistics related to fold to 4-bet. 

1432 """ 

1433 stat = 0.0 

1434 try: 

1435 stat = float(stat_dict[player]['f4b_0'])/float(stat_dict[player]['f4b_opp_0']) 

1436 return (stat, 

1437 '%3.1f' % (100.0*stat), 

1438 'F4B=%3.1f%%' % (100.0*stat), 

1439 'F4B_pf=%3.1f%%' % (100.0*stat), 

1440 '(%d/%d)' % (stat_dict[player]['f4b_0'], stat_dict[player]['f4b_opp_0']), 

1441 '% fold to 4 bet preflop/3rd street') 

1442 except: 

1443 return (stat, 

1444 'NA', 

1445 'F4B=NA', 

1446 'F4B_pf=NA', 

1447 '(0/0)', 

1448 '% fold to 4 bet preflop/3rd street') 

1449 

1450def WMsF(stat_dict, player): 

1451 """Calculate the win money percentage when seeing the flop or 4th street. 

1452 

1453 Args: 

1454 stat_dict (dict): A dictionary containing player statistics. 

1455 player (int): The player for whom the statistics are calculated. 

1456 

1457 Returns: 

1458 tuple: A tuple containing various win money percentage statistics and descriptions. 

1459 """ 

1460 stat = 0.0 

1461 try: 

1462 stat = float(stat_dict[player]['w_w_s_1'])/float(stat_dict[player]['saw_1']) 

1463 return (stat, 

1464 '%3.1f' % (100.0*stat), 

1465 'wf=%3.1f%%' % (100.0*stat), 

1466 'w_w_f=%3.1f%%' % (100.0*stat), 

1467 '(%d/%d)' % (stat_dict[player]['w_w_s_1'], stat_dict[player]['saw_f']), 

1468 '% won money when seen flop/4th street') 

1469 except: 

1470 return (stat, 

1471 'NA', 

1472 'wf=NA', 

1473 'w_w_f=NA', 

1474 '(0/0)', 

1475 '% won money when seen flop/4th street') 

1476 

1477def a_freq1(stat_dict, player): 

1478 """Calculate aggression frequency for a specific player based on their stats on flop/4th street. 

1479 

1480 Args: 

1481 stat_dict (dict): A dictionary containing player statistics. 

1482 player (int): The player for whom the aggression frequency is calculated. 

1483 

1484 Returns: 

1485 tuple: A tuple containing the calculated aggression frequency, formatted strings, and related information. 

1486 """ 

1487 stat = 0.0 

1488 try: 

1489 stat = float(stat_dict[player]['aggr_1'])/float(stat_dict[player]['saw_f']) 

1490 return (stat, 

1491 '%3.1f' % (100.0*stat), 

1492 'a1=%3.1f%%' % (100.0*stat), 

1493 'a_fq_1=%3.1f%%' % (100.0*stat), 

1494 '(%d/%d)' % (stat_dict[player]['aggr_1'], stat_dict[player]['saw_f']), 

1495 'Aggression frequency flop/4th street') 

1496 except: 

1497 return (stat, 

1498 'NA', 

1499 'a1=NA', 

1500 'a_fq_1=NA', 

1501 '(0/0)', 

1502 'Aggression frequency flop/4th street') 

1503 

1504def a_freq2(stat_dict, player): 

1505 """Calculate aggression frequency for a specific player based on their stats on turn/5th street. 

1506 

1507 Args: 

1508 stat_dict (dict): A dictionary containing player statistics. 

1509 player (int): The player for whom the aggression frequency is calculated. 

1510 

1511 Returns: 

1512 tuple: A tuple containing the calculated aggression frequency, formatted strings, and related information. 

1513 """ 

1514 stat = 0.0 

1515 try: 

1516 stat = float(stat_dict[player]['aggr_2'])/float(stat_dict[player]['saw_2']) 

1517 return (stat, 

1518 '%3.1f' % (100.0*stat), 

1519 'a2=%3.1f%%' % (100.0*stat), 

1520 'a_fq_2=%3.1f%%' % (100.0*stat), 

1521 '(%d/%d)' % (stat_dict[player]['aggr_2'], stat_dict[player]['saw_2']), 

1522 'Aggression frequency turn/5th street') 

1523 except: 

1524 return (stat, 

1525 'NA', 

1526 'a2=NA', 

1527 'a_fq_2=NA', 

1528 '(0/0)', 

1529 'Aggression frequency turn/5th street') 

1530 

1531def a_freq3(stat_dict, player): 

1532 """Calculate aggression frequency for a specific player based on their stats on river/6th street. 

1533 

1534 Args: 

1535 stat_dict (dict): A dictionary containing player statistics. 

1536 player (int): The player for whom the aggression frequency is calculated. 

1537 

1538 Returns: 

1539 tuple: A tuple containing the calculated aggression frequency, formatted strings, and related information. 

1540 """ 

1541 stat = 0.0 

1542 try: 

1543 stat = float(stat_dict[player]['aggr_3'])/float(stat_dict[player]['saw_3']) 

1544 return (stat, 

1545 '%3.1f' % (100.0*stat), 

1546 'a3=%3.1f%%' % (100.0*stat), 

1547 'a_fq_3=%3.1f%%' % (100.0*stat), 

1548 '(%d/%d)' % (stat_dict[player]['aggr_3'], stat_dict[player]['saw_3']), 

1549 'Aggression frequency river/6th street') 

1550 except: 

1551 return (stat, 

1552 'NA', 

1553 'a3=NA', 

1554 'a_fq_3=NA', 

1555 '(0/0)', 

1556 'Aggression frequency river/6th street') 

1557 

1558def a_freq4(stat_dict, player): 

1559 """Calculate aggression frequency for a specific player based on their stats on 7th street. 

1560 

1561 Args: 

1562 stat_dict (dict): A dictionary containing player statistics. 

1563 player (int): The player for whom the aggression frequency is calculated. 

1564 

1565 Returns: 

1566 tuple: A tuple containing the calculated aggression frequency, formatted strings, and related information. 

1567 """ 

1568 stat = 0.0 

1569 try: 

1570 stat = float(stat_dict[player]['aggr_4'])/float(stat_dict[player]['saw_4']) 

1571 return (stat, 

1572 '%3.1f' % (100.0*stat), 

1573 'a4=%3.1f%%' % (100.0*stat), 

1574 'a_fq_4=%3.1f%%' % (100.0*stat), 

1575 '(%d/%d)' % (stat_dict[player]['aggr_4'], stat_dict[player]['saw_4']), 

1576 'Aggression frequency 7th street') 

1577 except: 

1578 return (stat, 

1579 'NA', 

1580 'a4=NA', 

1581 'a_fq_4=NA', 

1582 '(0/0)', 

1583 'Aggression frequency 7th street') 

1584 

1585def a_freq_123(stat_dict, player): 

1586 """Calculate aggression frequency for a specific player based on their stats post flop. 

1587 

1588 Args: 

1589 stat_dict (dict): A dictionary containing player statistics. 

1590 player (int): The player for whom the aggression frequency is calculated. 

1591 

1592 Returns: 

1593 tuple: A tuple containing the calculated aggression frequency, formatted strings, and related information. 

1594 """ 

1595 stat = 0.0 

1596 try: 

1597 stat = float( stat_dict[player]['aggr_1'] + stat_dict[player]['aggr_2'] + stat_dict[player]['aggr_3'] 

1598 ) / float( stat_dict[player]['saw_1'] + stat_dict[player]['saw_2'] + stat_dict[player]['saw_3']); 

1599 return (stat, 

1600 '%3.1f' % (100.0*stat), 

1601 'afq=%3.1f%%' % (100.0*stat), 

1602 'post_a_fq=%3.1f%%' % (100.0*stat), 

1603 '(%d/%d)' % ( stat_dict[player]['aggr_1'] 

1604 + stat_dict[player]['aggr_2'] 

1605 + stat_dict[player]['aggr_3'] 

1606 , stat_dict[player]['saw_1'] 

1607 + stat_dict[player]['saw_2'] 

1608 + stat_dict[player]['saw_3'] 

1609 ), 

1610 'Post-flop aggression frequency') 

1611 except: 

1612 return (stat, 

1613 'NA', 

1614 'a3=NA', 

1615 'a_fq_3=NA', 

1616 '(0/0)', 

1617 'Post-flop aggression frequency') 

1618 

1619def agg_fact(stat_dict, player): 

1620 """Calculate the aggression factor based on the given player's statistics. 

1621 

1622 Args: 

1623 stat_dict (dict): A dictionary containing the player's statistics. 

1624 player (str): The player for whom the aggression factor is calculated. 

1625 

1626 Returns: 

1627 tuple: A tuple containing the calculated aggression factor in different formats. 

1628 The formats include percentage, float, and string representations. 

1629 If an exception occurs during calculation, default values are returned. 

1630 """ 

1631 stat = 0.0 

1632 try: 

1633 bet_raise = stat_dict[player]['aggr_1'] + stat_dict[player]['aggr_2'] + stat_dict[player]['aggr_3'] + stat_dict[player]['aggr_4'] 

1634 post_call = stat_dict[player]['call_1'] + stat_dict[player]['call_2'] + stat_dict[player]['call_3'] + stat_dict[player]['call_4'] 

1635 

1636 if post_call > 0: 

1637 stat = float (bet_raise) / float(post_call) 

1638 else: 

1639 stat = float (bet_raise) 

1640 return (stat/100.0, 

1641 '%2.2f' % (stat) , 

1642 'afa=%2.2f' % (stat) , 

1643 'agg_fa=%2.2f' % (stat) , 

1644 '(%d/%d)' % (bet_raise, post_call), 

1645 'Aggression factor') 

1646 except: 

1647 return (stat, 

1648 'NA', 

1649 'afa=NA', 

1650 'agg_fa=NA', 

1651 '(0/0)', 

1652 'Aggression factor') 

1653 

1654def agg_fact_pct(stat_dict, player): 

1655 """Calculate the aggression factor percentage based on the given player's stats. 

1656 

1657 Args: 

1658 stat_dict (dict): A dictionary containing the player's statistics. 

1659 player (int): The player for whom the aggression factor percentage is calculated. 

1660 

1661 Returns: 

1662 tuple: A tuple containing the aggression factor percentage, formatted strings, and related information. 

1663 

1664 Raises: 

1665 Exception: If an error occurs during the calculation, returns default values. 

1666 """ 

1667 stat = 0.0 

1668 try: 

1669 bet_raise = stat_dict[player]['aggr_1'] + stat_dict[player]['aggr_2'] + stat_dict[player]['aggr_3'] + stat_dict[player]['aggr_4'] 

1670 post_call = stat_dict[player]['call_1'] + stat_dict[player]['call_2'] + stat_dict[player]['call_3'] + stat_dict[player]['call_4'] 

1671 

1672 if float(post_call + bet_raise) > 0.0: 

1673 stat = float (bet_raise) / float(post_call + bet_raise) 

1674 

1675 return (stat/100.0, 

1676 '%2.2f' % (stat) , 

1677 'afap=%2.2f' % (stat) , 

1678 'agg_fa_pct=%2.2f' % (stat) , 

1679 '(%d/%d)' % (bet_raise, post_call), 

1680 'Aggression factor pct') 

1681 except: 

1682 return (stat, 

1683 'NA', 

1684 'afap=NA', 

1685 'agg_fa_pct=NA', 

1686 '(0/0)', 

1687 'Aggression factor pct') 

1688 

1689def cbet(stat_dict, player): 

1690 """Calculate the continuation bet (cbet) percentage for a player. 

1691 

1692 Args: 

1693 stat_dict (dict): A dictionary containing statistics for the player. 

1694 player (int): The player for whom the cbet percentage is calculated. 

1695 

1696 Returns: 

1697 tuple: A tuple containing the cbet percentage, formatted strings, and stats. 

1698 

1699 Raises: 

1700 Exception: If there is an issue with calculating the cbet percentage. 

1701 """ 

1702 stat = 0.0 

1703 try: 

1704 cbets = stat_dict[player]['cb_1']+stat_dict[player]['cb_2']+stat_dict[player]['cb_3']+stat_dict[player]['cb_4'] 

1705 oppt = stat_dict[player]['cb_opp_1']+stat_dict[player]['cb_opp_2']+stat_dict[player]['cb_opp_3']+stat_dict[player]['cb_opp_4'] 

1706 stat = float(cbets)/float(oppt) 

1707 return (stat, 

1708 '%3.1f' % (100.0*stat), 

1709 'cbet=%3.1f%%' % (100.0*stat), 

1710 'cbet=%3.1f%%' % (100.0*stat), 

1711 '(%d/%d)' % (cbets, oppt), 

1712 '% continuation bet') 

1713 except: 

1714 return (stat, 

1715 'NA', 

1716 'cbet=NA', 

1717 'cbet=NA', 

1718 '(0/0)', 

1719 '% continuation bet') 

1720 

1721def cb1(stat_dict, player): 

1722 """Calculate the continuation bet statistic for a given player on flop/4th street. 

1723 

1724 Args: 

1725 stat_dict (dict): A dictionary containing player statistics. 

1726 player (int): The player for whom the statistic is calculated. 

1727 

1728 Returns: 

1729 tuple: A tuple containing various formatted strings representing the continuation bet statistic. 

1730 """ 

1731 stat = 0.0 

1732 try: 

1733 stat = float(stat_dict[player]['cb_1'])/float(stat_dict[player]['cb_opp_1']) 

1734 return (stat, 

1735 '%3.1f' % (100.0*stat), 

1736 'cb1=%3.1f%%' % (100.0*stat), 

1737 'cb_1=%3.1f%%' % (100.0*stat), 

1738 '(%d/%d)' % (stat_dict[player]['cb_1'], stat_dict[player]['cb_opp_1']), 

1739 '% continuation bet flop/4th street') 

1740 except: 

1741 return (stat, 

1742 'NA', 

1743 'cb1=NA', 

1744 'cb_1=NA', 

1745 '(0/0)', 

1746 '% continuation bet flop/4th street') 

1747 

1748def cb2(stat_dict, player): 

1749 """Calculate the continuation bet statistic for a given player on turn/5th street. 

1750 

1751 Args: 

1752 stat_dict (dict): A dictionary containing player statistics. 

1753 player (int): The player for whom the statistic is calculated. 

1754 

1755 Returns: 

1756 tuple: A tuple containing various formatted strings representing the continuation bet statistic. 

1757 """ 

1758 stat = 0.0 

1759 try: 

1760 stat = float(stat_dict[player]['cb_2'])/float(stat_dict[player]['cb_opp_2']) 

1761 return (stat, 

1762 '%3.1f' % (100.0*stat), 

1763 'cb2=%3.1f%%' % (100.0*stat), 

1764 'cb_2=%3.1f%%' % (100.0*stat), 

1765 '(%d/%d)' % (stat_dict[player]['cb_2'], stat_dict[player]['cb_opp_2']), 

1766 '% continuation bet turn/5th street') 

1767 except: 

1768 return (stat, 

1769 'NA', 

1770 'cb2=NA', 

1771 'cb_2=NA', 

1772 '(0/0)', 

1773 '% continuation bet turn/5th street') 

1774 

1775def cb3(stat_dict, player): 

1776 """Calculate the continuation bet statistic for a given player on river/6th street. 

1777 

1778 Args: 

1779 stat_dict (dict): A dictionary containing player statistics. 

1780 player (int): The player for whom the statistic is calculated. 

1781 

1782 Returns: 

1783 tuple: A tuple containing various formatted strings representing the continuation bet statistic. 

1784 """ 

1785 stat = 0.0 

1786 try: 

1787 stat = float(stat_dict[player]['cb_3'])/float(stat_dict[player]['cb_opp_3']) 

1788 return (stat, 

1789 '%3.1f' % (100.0*stat), 

1790 'cb3=%3.1f%%' % (100.0*stat), 

1791 'cb_3=%3.1f%%' % (100.0*stat), 

1792 '(%d/%d)' % (stat_dict[player]['cb_3'], stat_dict[player]['cb_opp_3']), 

1793 '% continuation bet river/6th street') 

1794 except: 

1795 return (stat, 

1796 'NA', 

1797 'cb3=NA', 

1798 'cb_3=NA', 

1799 '(0/0)', 

1800 '% continuation bet river/6th street') 

1801 

1802def cb4(stat_dict, player): 

1803 """Calculate the continuation bet statistic for a given player on 7th street. 

1804 

1805 Args: 

1806 stat_dict (dict): A dictionary containing player statistics. 

1807 player (int): The player for whom the statistic is calculated. 

1808 

1809 Returns: 

1810 tuple: A tuple containing various formatted strings representing the continuation bet statistic. 

1811 """ 

1812 stat = 0.0 

1813 try: 

1814 stat = float(stat_dict[player]['cb_4'])/float(stat_dict[player]['cb_opp_4']) 

1815 return (stat, 

1816 '%3.1f' % (100.0*stat), 

1817 'cb4=%3.1f%%' % (100.0*stat), 

1818 'cb_4=%3.1f%%' % (100.0*stat), 

1819 '(%d/%d)' % (stat_dict[player]['cb_4'], stat_dict[player]['cb_opp_4']), 

1820 '% continuation bet 7th street') 

1821 except: 

1822 return (stat, 

1823 'NA', 

1824 'cb4=NA', 

1825 'cb_4=NA', 

1826 '(0/0)', 

1827 '% continuation bet 7th street') 

1828 

1829def ffreq1(stat_dict, player): 

1830 """ 

1831 Calculate the fold frequency statistic for a given player on the flop/4th street. 

1832 

1833 Args: 

1834 stat_dict (dict): A dictionary containing player statistics. 

1835 player (int): The player for whom the statistic is calculated. 

1836 

1837 Returns: 

1838 tuple: A tuple containing various formatted strings representing the fold frequency statistic. 

1839 """ 

1840 stat = 0.0 

1841 try: 

1842 stat = float(stat_dict[player]['f_freq_1'])/float(stat_dict[player]['was_raised_1']) 

1843 return (stat, 

1844 '%3.1f' % (100.0*stat), 

1845 'ff1=%3.1f%%' % (100.0*stat), 

1846 'ff_1=%3.1f%%' % (100.0*stat), 

1847 '(%d/%d)' % (stat_dict[player]['f_freq_1'], stat_dict[player]['was_raised_1']), 

1848 '% fold frequency flop/4th street') 

1849 except: 

1850 return (stat, 

1851 'NA', 

1852 'ff1=NA', 

1853 'ff_1=NA', 

1854 '(0/0)', 

1855 '% fold frequency flop/4th street') 

1856 

1857def ffreq2(stat_dict, player): 

1858 """ 

1859 Calculate the fold frequency statistic for a given player on the turn/5th street. 

1860 

1861 Args: 

1862 stat_dict (dict): A dictionary containing player statistics. 

1863 player (int): The player for whom the statistic is calculated. 

1864 

1865 Returns: 

1866 tuple: A tuple containing various formatted strings representing the fold frequency statistic. 

1867 """ 

1868 stat = 0.0 

1869 try: 

1870 stat = float(stat_dict[player]['f_freq_2'])/float(stat_dict[player]['was_raised_2']) 

1871 return (stat, 

1872 '%3.1f' % (100.0*stat), 

1873 'ff2=%3.1f%%' % (100.0*stat), 

1874 'ff_2=%3.1f%%' % (100.0*stat), 

1875 '(%d/%d)' % (stat_dict[player]['f_freq_2'], stat_dict[player]['was_raised_2']), 

1876 '% fold frequency turn/5th street') 

1877 except: 

1878 return (stat, 

1879 'NA', 

1880 'ff2=NA', 

1881 'ff_2=NA', 

1882 '(0/0)', 

1883 '% fold frequency turn/5th street') 

1884 

1885def ffreq3(stat_dict, player): 

1886 """ 

1887 Calculate the fold frequency statistic for a given player on the river/6th street. 

1888 

1889 Args: 

1890 stat_dict (dict): A dictionary containing player statistics. 

1891 player (int): The player for whom the statistic is calculated. 

1892 

1893 Returns: 

1894 tuple: A tuple containing various formatted strings representing the fold frequency statistic. 

1895 """ 

1896 stat = 0.0 

1897 try: 

1898 stat = float(stat_dict[player]['f_freq_3'])/float(stat_dict[player]['was_raised_3']) 

1899 return (stat, 

1900 '%3.1f' % (100.0*stat), 

1901 'ff3=%3.1f%%' % (100.0*stat), 

1902 'ff_3=%3.1f%%' % (100.0*stat), 

1903 '(%d/%d)' % (stat_dict[player]['f_freq_3'], stat_dict[player]['was_raised_3']), 

1904 '% fold frequency river/6th street') 

1905 except: 

1906 return (stat, 

1907 'NA', 

1908 'ff3=NA', 

1909 'ff_3=NA', 

1910 '(0/0)', 

1911 '% fold frequency river/6th street') 

1912 

1913def ffreq4(stat_dict, player): 

1914 """ 

1915 Calculate the fold frequency statistic for a given player on the 7th street. 

1916 

1917 Args: 

1918 stat_dict (dict): A dictionary containing player statistics. 

1919 player (int): The player for whom the statistic is calculated. 

1920 

1921 Returns: 

1922 tuple: A tuple containing various formatted strings representing the fold frequency statistic. 

1923 """ 

1924 stat = 0.0 

1925 try: 

1926 stat = float(stat_dict[player]['f_freq_4'])/float(stat_dict[player]['was_raised_4']) 

1927 return (stat, 

1928 '%3.1f' % (100.0*stat), 

1929 'ff4=%3.1f%%' % (100.0*stat), 

1930 'ff_4=%3.1f%%' % (100.0*stat), 

1931 '(%d/%d)' % (stat_dict[player]['f_freq_4'], stat_dict[player]['was_raised_4']), 

1932 '% fold frequency 7th street') 

1933 except: 

1934 return (stat, 

1935 'NA', 

1936 'ff4=NA', 

1937 'ff_4=NA', 

1938 '(0/0)', 

1939 '% fold frequency 7th street') 

1940 

1941def f_cb1(stat_dict, player): 

1942 """ 

1943 Calculate the fold to continuation bet statistic for a given player on the flop/4th street. 

1944 

1945 Args: 

1946 stat_dict (dict): A dictionary containing player statistics. 

1947 player (int): The player for whom the statistic is calculated. 

1948 

1949 Returns: 

1950 tuple: A tuple containing various formatted strings representing the fold to continuation bet statistic. 

1951 The tuple contains the following elements: 

1952 - stat (float): The calculated statistic value. 

1953 - percent (str): The calculated statistic value formatted as a percentage. 

1954 - f_cb1 (str): The calculated statistic value formatted as a percentage with a specific format. 

1955 - f_cb_1 (str): The calculated statistic value formatted as a percentage with a specific format. 

1956 - count (str): The count of occurrences divided by the count of opponent's continuation bets. 

1957 - description (str): A description of the statistic. 

1958 """ 

1959 stat = 0.0 

1960 try: 

1961 stat = float(stat_dict[player]['f_cb_1'])/float(stat_dict[player]['f_cb_opp_1']) 

1962 return (stat, 

1963 '%3.1f' % (100.0*stat), 

1964 'f_cb1=%3.1f%%' % (100.0*stat), 

1965 'f_cb_1=%3.1f%%' % (100.0*stat), 

1966 '(%d/%d)' % (stat_dict[player]['f_cb_1'], stat_dict[player]['f_cb_opp_1']), 

1967 '% fold to continuation bet flop/4th street') 

1968 except: 

1969 return (stat, 

1970 'NA', 

1971 'f_cb1=NA', 

1972 'f_cb_1=NA', 

1973 '(0/0)', 

1974 '% fold to continuation bet flop/4th street') 

1975 

1976def f_cb2(stat_dict, player): 

1977 """ 

1978 Calculate the fold to continuation bet statistic for a given player on the turn/5th street. 

1979 

1980 Args: 

1981 stat_dict (dict): A dictionary containing player statistics. 

1982 player (int): The player for whom the statistic is calculated. 

1983 

1984 Returns: 

1985 tuple: A tuple containing various formatted strings representing the fold to continuation bet statistic. 

1986 The tuple contains the following elements: 

1987 - stat (float): The calculated statistic value. 

1988 - percent (str): The calculated statistic value formatted as a percentage. 

1989 - f_cb2 (str): The calculated statistic value formatted as a percentage with a specific format. 

1990 - f_cb_2 (str): The calculated statistic value formatted as a percentage with a specific format. 

1991 - count (str): The count of occurrences divided by the count of opponent's continuation bets. 

1992 - description (str): A description of the statistic. 

1993 

1994 Raises: 

1995 None 

1996 """ 

1997 stat = 0.0 

1998 try: 

1999 stat = float(stat_dict[player]['f_cb_2'])/float(stat_dict[player]['f_cb_opp_2']) 

2000 return (stat, 

2001 '%3.1f' % (100.0*stat), 

2002 'f_cb2=%3.1f%%' % (100.0*stat), 

2003 'f_cb_2=%3.1f%%' % (100.0*stat), 

2004 '(%d/%d)' % (stat_dict[player]['f_cb_2'], stat_dict[player]['f_cb_opp_2']), 

2005 '% fold to continuation bet turn/5th street') 

2006 except: 

2007 return (stat, 

2008 'NA', 

2009 'f_cb2=NA', 

2010 'f_cb_2=NA', 

2011 '(0/0)', 

2012 '% fold to continuation bet turn/5th street') 

2013 

2014def f_cb3(stat_dict, player): 

2015 """ 

2016 Calculate the fold to continuation bet statistic for a given player on the river/6th street. 

2017 

2018 Args: 

2019 stat_dict (dict): A dictionary containing player statistics. 

2020 player (int): The player for whom the statistic is calculated. 

2021 

2022 Returns: 

2023 tuple: A tuple containing various formatted strings representing the fold to continuation bet statistic. 

2024 The tuple contains the following elements: 

2025 - stat (float): The calculated statistic value. 

2026 - percent (str): The calculated statistic value formatted as a percentage. 

2027 - f_cb3 (str): The calculated statistic value formatted as a percentage with a specific format. 

2028 - f_cb_3 (str): The calculated statistic value formatted as a percentage with a specific format. 

2029 - count (str): The count of occurrences divided by the count of opponent's continuation bets. 

2030 - description (str): A description of the statistic. 

2031 

2032 Raises: 

2033 None 

2034 """ 

2035 stat = 0.0 

2036 try: 

2037 stat = float(stat_dict[player]['f_cb_3'])/float(stat_dict[player]['f_cb_opp_3']) 

2038 return (stat, 

2039 '%3.1f' % (100.0*stat), 

2040 'f_cb3=%3.1f%%' % (100.0*stat), 

2041 'f_cb_3=%3.1f%%' % (100.0*stat), 

2042 '(%d/%d)' % (stat_dict[player]['f_cb_3'], stat_dict[player]['f_cb_opp_3']), 

2043 '% fold to continuation bet river/6th street') 

2044 except: 

2045 return (stat, 

2046 'NA', 

2047 'f_cb3=NA', 

2048 'f_cb_3=NA', 

2049 '(0/0)', 

2050 '% fold to continuation bet river/6th street') 

2051 

2052def f_cb4(stat_dict, player): 

2053 """ 

2054 Calculate the fold to continuation bet statistic for a given player on the 7th street. 

2055 

2056 Args: 

2057 stat_dict (dict): A dictionary containing player statistics. 

2058 player (int): The player for whom the statistic is calculated. 

2059 

2060 Returns: 

2061 tuple: A tuple containing various formatted strings representing the fold to continuation bet statistic. 

2062 The tuple contains the following elements: 

2063 - stat (float): The calculated statistic value. 

2064 - percent (str): The calculated statistic value formatted as a percentage. 

2065 - f_cb4 (str): The calculated statistic value formatted as a percentage with a specific format. 

2066 - f_cb_4 (str): The calculated statistic value formatted as a percentage with a specific format. 

2067 - count (str): The count of occurrences divided by the count of opponent's continuation bets. 

2068 - description (str): A description of the statistic. 

2069 

2070 Raises: 

2071 None 

2072 """ 

2073 stat = 0.0 

2074 try: 

2075 stat = float(stat_dict[player]['f_cb_4'])/float(stat_dict[player]['f_cb_opp_4']) 

2076 return (stat, 

2077 '%3.1f' % (100.0*stat), 

2078 'f_cb4=%3.1f%%' % (100.0*stat), 

2079 'f_cb_4=%3.1f%%' % (100.0*stat), 

2080 '(%d/%d)' % (stat_dict[player]['f_cb_4'], stat_dict[player]['f_cb_opp_4']), 

2081 '% fold to continuation bet 7th street') 

2082 except: 

2083 return (stat, 

2084 'NA', 

2085 'f_cb4=NA', 

2086 'f_cb_4=NA', 

2087 '(0/0)', 

2088 '% fold to continuation bet 7th street') 

2089 

2090def cr1(stat_dict, player): 

2091 """ 

2092 Calculate the check-raise flop/4th street statistic for a given player. 

2093 

2094 Args: 

2095 stat_dict (dict): A dictionary containing player statistics. 

2096 player (int): The player for whom the statistic is calculated. 

2097 

2098 Returns: 

2099 tuple: A tuple containing various formatted strings representing the check-raise flop/4th street statistic. 

2100 The tuple contains the following elements: 

2101 - stat (float): The calculated statistic value. 

2102 - percent (str): The calculated statistic value formatted as a percentage. 

2103 - cr1 (str): The calculated statistic value formatted with a specific format. 

2104 - cr_1 (str): The calculated statistic value formatted with a specific format. 

2105 - count (str): The count of occurrences divided by the count of opponent's check-raises. 

2106 - description (str): A description of the statistic. 

2107 

2108 Raises: 

2109 None 

2110 """ 

2111 stat = 0.0 

2112 try: 

2113 stat = float(stat_dict[player]['cr_1'])/float(stat_dict[player]['ccr_opp_1']) 

2114 return (stat, 

2115 '%3.1f' % (100.0*stat), 

2116 'cr1=%3.1f%%' % (100.0*stat), 

2117 'cr_1=%3.1f%%' % (100.0*stat), 

2118 '(%d/%d)' % (stat_dict[player]['cr_1'], stat_dict[player]['ccr_opp_1']), 

2119 '% check-raise flop/4th street') 

2120 except: 

2121 return (stat, 

2122 'NA', 

2123 'cr1=NA', 

2124 'cr_1=NA', 

2125 '(0/0)', 

2126 '% check-raise flop/4th street') 

2127 

2128def cr2(stat_dict, player): 

2129 """ 

2130 Calculates the check-raise turn/5th street for a given player. 

2131 

2132 Args: 

2133 stat_dict (dict): A dictionary containing player statistics. 

2134 player (int): The player for whom the statistic is calculated. 

2135 

2136 Returns: 

2137 tuple: A tuple containing various formatted strings representing the check-raise to fold ratio. 

2138 The tuple contains the following elements: 

2139 - stat (float): The calculated statistic value. 

2140 - percent (str): The calculated statistic value formatted as a percentage. 

2141 - cr2 (str): The calculated statistic value formatted with a specific format. 

2142 - cr_2 (str): The calculated statistic value formatted with a specific format. 

2143 - count (str): The count of occurrences divided by the count of opponent's check-raises. 

2144 - description (str): A description of the statistic. 

2145 

2146 Raises: 

2147 None 

2148 """ 

2149 stat = 0.0 

2150 try: 

2151 stat = float(stat_dict[player]['cr_2'])/float(stat_dict[player]['ccr_opp_2']) 

2152 return (stat, 

2153 '%3.1f' % (100.0*stat), 

2154 'cr2=%3.1f%%' % (100.0*stat), 

2155 'cr_2=%3.1f%%' % (100.0*stat), 

2156 '(%d/%d)' % (stat_dict[player]['cr_2'], stat_dict[player]['ccr_opp_2']), 

2157 '% check-raise turn/5th street') 

2158 except: 

2159 return (stat, 

2160 'NA', 

2161 'cr2=NA', 

2162 'cr_2=NA', 

2163 '(0/0)', 

2164 '% check-raise turn/5th street') 

2165 

2166def cr3(stat_dict, player): 

2167 """ 

2168 Calculate the river/6th street street for a given player on the river (6th street). 

2169 

2170 Args: 

2171 stat_dict (dict): A dictionary containing player statistics. 

2172 player (int): The player for whom the statistic is calculated. 

2173 

2174 Returns: 

2175 tuple: A tuple containing various formatted strings representing the check-raise to fold ratio. 

2176 The tuple contains the following elements: 

2177 - stat (float): The calculated statistic value. 

2178 - percent (str): The calculated statistic value formatted as a percentage. 

2179 - cr3 (str): The calculated statistic value formatted with a specific format. 

2180 - cr_3 (str): The calculated statistic value formatted with a specific format. 

2181 - count (str): The count of occurrences divided by the count of opponent's check-raises. 

2182 - description (str): A description of the statistic. 

2183 

2184 Raises: 

2185 None 

2186 """ 

2187 stat = 0.0 

2188 try: 

2189 stat = float(stat_dict[player]['cr_3'])/float(stat_dict[player]['ccr_opp_3']) 

2190 return (stat, 

2191 '%3.1f' % (100.0*stat), 

2192 'cr3=%3.1f%%' % (100.0*stat), 

2193 'cr_3=%3.1f%%' % (100.0*stat), 

2194 '(%d/%d)' % (stat_dict[player]['cr_3'], stat_dict[player]['ccr_opp_3']), 

2195 '% check-raise river/6th street') 

2196 except: 

2197 return (stat, 

2198 'NA', 

2199 'cr3=NA', 

2200 'cr_3=NA', 

2201 '(0/0)', 

2202 '% check-raise river/6th street') 

2203 

2204def cr4(stat_dict, player): 

2205 """ 

2206 Calculate the 7th street check-raise statistics for a given player on the 7th street. 

2207 

2208 Args: 

2209 stat_dict (dict): A dictionary containing player statistics. 

2210 player (int): The player for whom the statistic is calculated. 

2211 

2212 Returns: 

2213 tuple: A tuple containing various formatted strings representing the check-raise to fold ratio. 

2214 The tuple contains the following elements: 

2215 - stat (float): The calculated statistic value. 

2216 - percent (str): The calculated statistic value formatted as a percentage. 

2217 - cr4 (str): The calculated statistic value formatted with a specific format. 

2218 - cr_4 (str): The calculated statistic value formatted with a specific format. 

2219 - count (str): The count of occurrences divided by the count of opponent's check-raises. 

2220 - description (str): A description of the statistic. 

2221 

2222 Raises: 

2223 None 

2224 """ 

2225 stat = 0.0 

2226 try: 

2227 stat = float(stat_dict[player]['cr_4'])/float(stat_dict[player]['ccr_opp_4']) 

2228 return (stat, 

2229 '%3.1f' % (100.0*stat), 

2230 'cr4=%3.1f%%' % (100.0*stat), 

2231 'cr_4=%3.1f%%' % (100.0*stat), 

2232 '(%d/%d)' % (stat_dict[player]['cr_4'], stat_dict[player]['ccr_opp_4']), 

2233 '% check-raise 7th street') 

2234 except: 

2235 return (stat, 

2236 'NA', 

2237 'cr4=NA', 

2238 'cr_4=NA', 

2239 '(0/0)', 

2240 '% check-raise 7th street') 

2241 

2242 

2243def game_abbr(stat_dict, player): 

2244 ''' 

2245 Function to retrieve the abbreviation for a specific poker game based on the game category and limit type. 

2246 

2247 Parameters: 

2248 - stat_dict: Dictionary containing statistics related to the game. 

2249 - player: Integer representing the player number. 

2250 

2251 Returns: 

2252 - Tuple containing various representations of the game abbreviation. 

2253 ''' 

2254 hand_instance = _global_hand_instance 

2255 stat = '' 

2256 try: 

2257 cat_plus_limit = hand_instance.gametype['category'] + '.' + hand_instance.gametype['limitType'] 

2258 stat = { 

2259 # ftp's 10-game with official abbreviations 

2260 'holdem.fl': 'H', 

2261 'studhilo.fl': 'E', 

2262 'omahahi.pl': 'P', 

2263 '27_3draw.fl': 'T', 

2264 'razz.fl': 'R', 

2265 'holdem.nl': 'N', 

2266 'omahahilo.fl': 'O', 

2267 'studhi.fl': 'S', 

2268 '27_1draw.nl': 'K', 

2269 'badugi.fl': 'B', 

2270 # other common games with dubious abbreviations 

2271 'fivedraw.fl': 'F', 

2272 'fivedraw.pl': 'Fp', 

2273 'fivedraw.nl': 'Fn', 

2274 '27_3draw.pl': 'Tp', 

2275 '27_3draw.nl': 'Tn', 

2276 'badugi.pl': 'Bp', 

2277 'badugi.hp': 'Bh', 

2278 'omahahilo.pl': 'Op', 

2279 'omahahilo.nl': 'On', 

2280 'holdem.pl': 'Hp', 

2281 'studhi.nl': 'Sn', 

2282 }[cat_plus_limit] 

2283 return (stat, 

2284 '%s' % stat, 

2285 'game=%s' % stat, 

2286 'game_abbr=%s' % stat, 

2287 '(%s)' % stat, 

2288 'Game abbreviation') 

2289 except: 

2290 return ("","","","","", 

2291 'Game abbreviation') 

2292 

2293def blank(stat_dict, player): 

2294 # blank space on the grid 

2295 stat = " " 

2296 return ("", "", "", "", "", "<blank>") 

2297 

2298 

2299################################################################################################ 

2300# NEW STATS 

2301 

2302def vpip_pfr_ratio(stat_dict, player): 

2303 """ 

2304 Calculate the VPIP/PFR ratio for a player. 

2305 

2306 This statistic represents the ratio between a player's VPIP (Voluntarily Put money In Pot)  

2307 and PFR (Pre-Flop Raise) percentages, which gives an indication of the player's preflop aggression. 

2308 

2309 Args: 

2310 stat_dict (dict): A dictionary containing player statistics. 

2311 player (int): The player for whom the statistic is calculated. 

2312 

2313 Returns: 

2314 tuple: A tuple containing the calculated statistic, formatted strings, and related information. 

2315 """ 

2316 try: 

2317 vpip = float(stat_dict[player]['vpip']) / float(stat_dict[player]['vpip_opp']) 

2318 pfr = float(stat_dict[player]['pfr']) / float(stat_dict[player]['pfr_opp']) 

2319 

2320 if pfr > 0: 

2321 stat = vpip / pfr 

2322 else: 

2323 stat = float('inf') # Avoid division by zero 

2324 

2325 return (stat, 

2326 '%2.2f' % (stat), 

2327 'v/p=%2.2f' % (stat), 

2328 'vpip/pfr=%2.2f' % (stat), 

2329 '(%d/%d)/(%d/%d)' % (stat_dict[player]['vpip'], stat_dict[player]['vpip_opp'], 

2330 stat_dict[player]['pfr'], stat_dict[player]['pfr_opp']), 

2331 'VPIP/PFR ratio') 

2332 except: 

2333 return (float('inf'), 

2334 'NA', 

2335 'v/p=NA', 

2336 'vpip/pfr=NA', 

2337 '(0/0)/(0/0)', 

2338 'VPIP/PFR ratio') 

2339 

2340 

2341 

2342 

2343def three_bet_range(stat_dict, player): 

2344 try: 

2345 pfr = float(stat_dict[player]['pfr']) / float(stat_dict[player]['pfr_opp']) 

2346 three_bet = float(stat_dict[player]['tb_0']) / float(stat_dict[player]['tb_opp_0']) 

2347 stat = pfr * three_bet 

2348 return (stat, 

2349 '%3.1f' % (100.0*stat), 

2350 '3BR=%3.1f%%' % (100.0*stat), 

2351 '3BetRange=%3.1f%%' % (100.0*stat), 

2352 '(%d/%d)*(%d/%d)' % (stat_dict[player]['pfr'], stat_dict[player]['pfr_opp'], 

2353 stat_dict[player]['tb_0'], stat_dict[player]['tb_opp_0']), 

2354 '3-Bet Range') 

2355 except: 

2356 return (0, 'NA', '3BR=NA', '3BetRange=NA', '(0/0)*(0/0)', '3-Bet Range') 

2357 

2358 

2359def check_raise_frequency(stat_dict, player): 

2360 try: 

2361 total_cr = (stat_dict[player]['cr_1'] + stat_dict[player]['cr_2'] + 

2362 stat_dict[player]['cr_3']) 

2363 total_opp = (stat_dict[player]['ccr_opp_1'] + stat_dict[player]['ccr_opp_2'] + 

2364 stat_dict[player]['ccr_opp_3']) 

2365 stat = float(total_cr) / float(total_opp) 

2366 return (stat, 

2367 '%3.1f' % (100.0*stat), 

2368 'CRF=%3.1f%%' % (100.0*stat), 

2369 'CheckRaiseFreq=%3.1f%%' % (100.0*stat), 

2370 '(%d/%d)' % (total_cr, total_opp), 

2371 'Check-Raise Frequency') 

2372 except: 

2373 return (0, 'NA', 'CRF=NA', 'CheckRaiseFreq=NA', '(0/0)', 'Check-Raise Frequency') 

2374 

2375 

2376 

2377def river_call_efficiency(stat_dict, player): 

2378 try: 

2379 river_calls = stat_dict[player]['call_3'] 

2380 showdowns_won = stat_dict[player]['wmsd'] 

2381 stat = float(showdowns_won) / float(river_calls) if river_calls > 0 else 0 

2382 return (stat, 

2383 '%3.1f' % (100.0*stat), 

2384 'RCE=%3.1f%%' % (100.0*stat), 

2385 'RiverCallEff=%3.1f%%' % (100.0*stat), 

2386 '(%d/%d)' % (showdowns_won, river_calls), 

2387 'River Call Efficiency') 

2388 except: 

2389 return (0, 'NA', 'RCE=NA', 'RiverCallEff=NA', '(0/0)', 'River Call Efficiency') 

2390# 

2391# 

2392# 

2393################################################################################################# 

2394 

2395def starthands(stat_dict, player): 

2396 """ 

2397 Retrieves the starting hands and their positions for a specific player in a hand. 

2398 

2399 Args: 

2400 stat_dict (dict): A dictionary containing the statistics. 

2401 player (int): The ID of the player. 

2402 

2403 Returns: 

2404 tuple: A tuple containing the following: 

2405 - A string representing the starting hands and their positions. 

2406 - A string representing the starting hands and their positions. 

2407 - A string representing the starting hands and their positions. 

2408 - A string representing the starting hands and their positions. 

2409 - A string representing the starting hands and their positions. 

2410 - A string representing the title of the statistic. 

2411 

2412 Raises: 

2413 None. 

2414 

2415 Notes: 

2416 - This function retrieves the starting hands and their positions for a specific player in a hand. 

2417 - The starting hands and their positions are displayed in a specific format. 

2418 - The function uses a global variable `_global_hand_instance` to get the hand instance. 

2419 - The function executes a SQL query to retrieve the starting hands and their positions from the database. 

2420 - The function formats the retrieved data and returns it as a tuple. 

2421 

2422 """ 

2423 

2424 hand_instance = _global_hand_instance 

2425 if not hand_instance: 

2426 return ("","","","","", 

2427 'Hands seen at this table') 

2428 

2429 #summary of known starting hands+position 

2430 # data volumes could get crazy here,so info is limited to hands 

2431 # in the current HH file only 

2432 

2433 # this info is NOT read from the cache, so does not obey aggregation 

2434 # parameters for other stats 

2435 

2436 #display shows 5 categories 

2437 # PFcall - limp or coldcall preflop 

2438 # PFaggr - raise preflop 

2439 # PFdefend - defended in BB 

2440 # PFcar 

2441 

2442 # hand is shown, followed by position indicator 

2443 # (b=SB/BB. l=Button/cutoff m=previous 3 seats to that, e=remainder) 

2444 

2445 # due to screen space required for this stat, it should only 

2446 # be used in the popup section i.e. 

2447 # <pu_stat pu_stat_name="starthands"> </pu_stat> 

2448 handid = int(hand_instance.handid_selected) 

2449 PFlimp="Limped:" 

2450 PFaggr="Raised:" 

2451 PFcar="Called raise:" 

2452 PFdefendBB="Defend BB:" 

2453 count_pfl = count_pfa = count_pfc = count_pfd = 5 

2454 

2455 c = Configuration.Config() 

2456 db_connection = Database.Database(c) 

2457 sc = db_connection.get_cursor() 

2458 

2459 query = ("SELECT distinct startCards, street0Aggr, street0CalledRaiseDone, " + 

2460 "case when HandsPlayers.position = 'B' then 'b' " + 

2461 "when HandsPlayers.position = 'S' then 'b' " + 

2462 "when HandsPlayers.position = '0' then 'l' " + 

2463 "when HandsPlayers.position = '1' then 'l' " + 

2464 "when HandsPlayers.position = '2' then 'm' " + 

2465 "when HandsPlayers.position = '3' then 'm' " + 

2466 "when HandsPlayers.position = '4' then 'm' " + 

2467 "when HandsPlayers.position = '5' then 'e' " + 

2468 "when HandsPlayers.position = '6' then 'e' " + 

2469 "when HandsPlayers.position = '7' then 'e' " + 

2470 "when HandsPlayers.position = '8' then 'e' " + 

2471 "when HandsPlayers.position = '9' then 'e' " + 

2472 "else 'X' end " + 

2473 "FROM Hands, HandsPlayers, Gametypes " + 

2474 "WHERE HandsPlayers.handId = Hands.id " + 

2475 " AND Gametypes.id = Hands.gametypeid "+ 

2476 " AND Gametypes.type = " + 

2477 " (SELECT Gametypes.type FROM Gametypes, Hands " + 

2478 " WHERE Hands.gametypeid = Gametypes.id and Hands.id = %d) " + 

2479 " AND Gametypes.Limittype = " + 

2480 " (SELECT Gametypes.limitType FROM Gametypes, Hands " + 

2481 " WHERE Hands.gametypeid = Gametypes.id and Hands.id = %d) " + 

2482 "AND Gametypes.category = 'holdem' " + 

2483 "AND fileId = (SELECT fileId FROM Hands " + 

2484 " WHERE Hands.id = %d) " + 

2485 "AND HandsPlayers.playerId = %d " + 

2486 "AND street0VPI " + 

2487 "AND startCards > 0 AND startCards <> 170 " + 

2488 "ORDER BY startCards DESC " + 

2489 ";") % (int(handid), int(handid), int(handid), int(player)) 

2490 

2491 #print query 

2492 sc.execute(query) 

2493 for (qstartcards, qstreet0Aggr, qstreet0CalledRaiseDone, qposition) in sc.fetchall(): 

2494 humancards = Card.decodeStartHandValue("holdem", qstartcards) 

2495 #print humancards, qstreet0Aggr, qstreet0CalledRaiseDone, qposition 

2496 if qposition == "b" and qstreet0CalledRaiseDone: 

2497 PFdefendBB=PFdefendBB+"/"+humancards 

2498 count_pfd += 1 

2499 if (count_pfd / 8.0 == int(count_pfd / 8.0)): 

2500 PFdefendBB=PFdefendBB+"\n" 

2501 elif qstreet0Aggr == True: 

2502 PFaggr=PFaggr+"/"+humancards+"."+qposition 

2503 count_pfa += 1 

2504 if (count_pfa / 8.0 == int(count_pfa / 8.0)): 

2505 PFaggr=PFaggr+"\n" 

2506 elif qstreet0CalledRaiseDone: 

2507 PFcar=PFcar+"/"+humancards+"."+qposition 

2508 count_pfc += 1 

2509 if (count_pfc / 8.0 == int(count_pfc / 8.0)): 

2510 PFcar=PFcar+"\n" 

2511 else: 

2512 PFlimp=PFlimp+"/"+humancards+"."+qposition 

2513 count_pfl += 1 

2514 if (count_pfl / 8.0 == int(count_pfl / 8.0)): 

2515 PFlimp=PFlimp+"\n" 

2516 sc.close() 

2517 

2518 returnstring = PFlimp + "\n" + PFaggr + "\n" + PFcar + "\n" + PFdefendBB #+ "\n" + str(handid) 

2519 

2520 return ((returnstring), 

2521 (returnstring), 

2522 (returnstring), 

2523 (returnstring), 

2524 (returnstring), 

2525 'Hands seen at this table\n') 

2526 

2527 

2528def get_valid_stats(): 

2529 ''' 

2530 Function to retrieve valid stats descriptions. 

2531 

2532 Returns: 

2533 dict: A dictionary containing descriptions of valid stats. 

2534 ''' 

2535 global _global_hand_instance 

2536 _global_hand_instance = None 

2537 

2538 stat_descriptions = {} 

2539 for function in STATLIST: 

2540 function_instance = getattr(__import__(__name__), function) 

2541 res=function_instance(None, None) 

2542 stat_descriptions[function] = res[5] 

2543 

2544 return stat_descriptions 

2545 

2546STATLIST = sorted(dir()) 

2547misslist = [ "Configuration", "Database", "Charset", "codecs", "encoder" 

2548 , "GInitiallyUnowned", "gtk", "pygtk", "Card", "L10n" 

2549 , "log", "logging", 'Decimal', 'GFileDescriptorBased' 

2550 , 'GPollableInputStream', 'GPollableOutputStream' 

2551 , "re", "re_Places", 'Hand' 

2552 ] 

2553STATLIST = [ x for x in STATLIST if x not in ("do_stat", "do_tip","get_valid_stats")] 

2554STATLIST = [ x for x in STATLIST if not x.startswith('_')] 

2555STATLIST = [ x for x in STATLIST if x not in dir(sys) ] 

2556STATLIST = [ x for x in STATLIST if x not in dir(codecs) ] 

2557STATLIST = [ x for x in STATLIST if x not in misslist ] 

2558#print "STATLIST is", STATLIST 

2559 

2560if __name__== "__main__": 

2561 

2562 c = Configuration.Config() 

2563 db_connection = Database.Database(c) 

2564 h = db_connection.get_last_hand() 

2565 stat_dict = db_connection.get_stats_from_hand(h, "ring") 

2566 hand_instance = Hand.hand_factory(h, c, db_connection) 

2567 

2568 for player in stat_dict.keys(): 

2569 print(f"Example stats. Player = {player}, Hand = {h}:") 

2570 for attr in STATLIST: 

2571 print(attr, " : ", do_stat(stat_dict, player=player, stat=attr, hand_instance=hand_instance)) 

2572 break 

2573 

2574 print() 

2575 print("Legal stats:") 

2576 print("(add _0 to name to display with 0 decimal places, _1 to display with 1, etc)") 

2577 stat_descriptions = get_valid_stats() 

2578 for stat in STATLIST: 

2579 print(stat, " : ", stat_descriptions[stat])