2 # -*- coding: utf-8 -*-
4 """Manage collecting and formatting of stats and tooltips."""
5 # Copyright 2008-2011, Ray E. Barker
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.
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.
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
22 ########################################################################
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
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
47 # 6 For each stat you make add a line to the __main__ function to test it.
50 _
= L10n
.get_translation()
52 # Standard Library modules
60 # FreePokerTools modules
67 if __name__
== "__main__":
68 Configuration
.set_logfile("fpdb-log.txt")
69 # logging has been set up in fpdb.py or HUD_main.py, use their settings:
70 log
= logging
.getLogger("db")
73 re_Places
= re
.compile("_[0-9]$")
77 encoder
= codecs
.lookup(Configuration
.LOCALE_ENCODING
)
79 stat_descriptions
= {}
81 # Since tuples are immutable, we have to create a new one when
82 # overriding any decimal placements. Copy old ones and recreate the
83 # second value in tuple to specified format-
84 def __stat_override(decimals
, stat_vals
):
85 s
= '%.*f' % (decimals
, 100.0*stat_vals
[0])
86 res
= (stat_vals
[0], s
, stat_vals
[2],
87 stat_vals
[3], stat_vals
[4], stat_vals
[5])
91 def do_tip(widget
, tip
):
92 _tip
= Charset
.to_utf8(tip
)
93 widget
.set_tooltip_text(_tip
)
96 def do_stat(stat_dict
, player
= 24, stat
= 'vpip', handid
= -1):
98 match
= re_Places
.search(stat
)
99 if match
: # override if necessary
100 statname
= stat
[0:-2]
102 if stat
== 'starthands':
103 result
= eval("%(stat)s(stat_dict, %(player)d, %(handid)d)" % {'stat': statname
, 'player': player
, 'handid': int(handid
)})
105 result
= eval("%(stat)s(stat_dict, %(player)d)" % {'stat': statname
, 'player': player
})
107 # If decimal places have been defined, override result[1]
108 # NOTE: decimal place override ALWAYS assumes the raw result is a
109 # fraction (x/100); manual decimal places really only make sense for
110 # percentage values. Also, profit/100 hands (bb/BB) already default
111 # to three decimal places anyhow, so they are unlikely override
114 places
= int(stat
[-1:])
115 result
= __stat_override(places
, result
)
118 # OK, for reference the tuple returned by the stat is:
119 # 0 - The stat, raw, no formating, eg 0.33333333
120 # 1 - formatted stat with appropriate precision, eg. 33; shown in HUD
121 # 2 - formatted stat with appropriate precision, punctuation and a hint, eg v=33%
122 # 3 - same as #2 except name of stat instead of hint, eg vpip=33%
123 # 4 - the calculation that got the stat, eg 9/27
124 # 5 - the name of the stat, useful for a tooltip, eg vpip
126 ###########################################
127 # functions that return individual stats
129 def blank(stat_dict
, player
):
130 stat_descriptions
["blank"] = _(" -----")
131 return (0, ' ', ' ', ' ', ' ', ' ')
133 def totalprofit(stat_dict
, player
):
134 stat_descriptions
["totalprofit"] = _("Total Profit") + " (totalprofit)"
135 if stat_dict
[player
]['net'] != 0:
136 stat
= float(stat_dict
[player
]['net']) / 100
137 return (stat
, '$%.2f' % stat
, 'tp=$%.2f' % stat
, 'totalprofit=$%.2f' % stat
, str(stat
), _('Total Profit'))
138 return ('0', '$0.00', 'tp=0', 'totalprofit=0', '0', _('Total Profit'))
140 def playername(stat_dict
, player
):
141 stat_descriptions
["playername"] = _("Player Name") + " (playername)"
142 return (stat_dict
[player
]['screen_name'],
143 stat_dict
[player
]['screen_name'],
144 stat_dict
[player
]['screen_name'],
145 stat_dict
[player
]['screen_name'],
146 stat_dict
[player
]['screen_name'],
147 stat_dict
[player
]['screen_name'])
149 def playershort(stat_dict
, player
):
150 stat_descriptions
["playershort"] = (_("Player Name")+" 1-5") + " (playershort)"
151 r
= stat_dict
[player
]['screen_name']
158 stat_dict
[player
]['screen_name'],
159 (_("Player Name")+" 1-5")
162 def vpip(stat_dict
, player
):
163 stat_descriptions
["vpip"] = _("Voluntarily put in preflop/3rd street %") + " (vpip)"
166 stat
= float(stat_dict
[player
]['vpip'])/float(stat_dict
[player
]['n'])
168 '%3.1f' % (100.0*stat
),
169 'v=%3.1f%%' % (100.0*stat
),
170 'vpip=%3.1f%%' % (100.0*stat
),
171 '(%d/%d)' % (stat_dict
[player
]['vpip'], stat_dict
[player
]['n']),
172 _('Voluntarily put in preflop/3rd street %')
174 except: return (stat
,
179 _('Voluntarily put in preflop/3rd street %')
182 def pfr(stat_dict
, player
):
183 stat_descriptions
["pfr"] = _("Preflop/3rd street raise %") + " (pfr)"
186 stat
= float(stat_dict
[player
]['pfr'])/float(stat_dict
[player
]['n'])
188 '%3.1f' % (100.0*stat
),
189 'p=%3.1f%%' % (100.0*stat
),
190 'pfr=%3.1f%%' % (100.0*stat
),
191 '(%d/%d)' % (stat_dict
[player
]['pfr'], stat_dict
[player
]['n']),
192 _('Preflop/3rd street raise %')
200 _('Preflop/3rd street raise %')
203 def wtsd(stat_dict
, player
):
204 stat_descriptions
["wtsd"] = _("% went to showdown when seen flop/4th street") + " (wtsd)"
207 stat
= float(stat_dict
[player
]['sd'])/float(stat_dict
[player
]['saw_f'])
209 '%3.1f' % (100.0*stat
),
210 'w=%3.1f%%' % (100.0*stat
),
211 'wtsd=%3.1f%%' % (100.0*stat
),
212 '(%d/%d)' % (stat_dict
[player
]['sd'], stat_dict
[player
]['saw_f']),
213 _('% went to showdown when seen flop/4th street')
221 _('% went to showdown when seen flop/4th street')
224 def wmsd(stat_dict
, player
):
225 stat_descriptions
["wmsd"] = _("% won some money at showdown") + " (wmsd)"
228 stat
= float(stat_dict
[player
]['wmsd'])/float(stat_dict
[player
]['sd'])
230 '%3.1f' % (100.0*stat
),
231 'w=%3.1f%%' % (100.0*stat
),
232 'wmsd=%3.1f%%' % (100.0*stat
),
233 '(%5.1f/%d)' % (float(stat_dict
[player
]['wmsd']), stat_dict
[player
]['sd']),
234 _('% won some money at showdown')
242 _('% won some money at showdown')
245 # Money is stored as pennies, so there is an implicit 100-multiplier
247 def profit100(stat_dict
, player
):
248 stat_descriptions
["profit100"] = _("Profit per 100 hands") + " (profit100)"
251 stat
= float(stat_dict
[player
]['net'])/float(stat_dict
[player
]['n'])
255 'p/100=%.2f' % (stat
),
256 '%d/%d' % (stat_dict
[player
]['net'], stat_dict
[player
]['n']),
257 _('Profit per 100 hands')
260 log
.info(_("exception calculating %s") % ("p/100: 100 * %d / %d" % (stat_dict
[player
]['net'], stat_dict
[player
]['n'])))
266 _('Profit per 100 hands')
269 def bbper100(stat_dict
, player
):
270 stat_descriptions
["bbper100"] = _("Big blinds won per 100 hands") + " (bbper100)"
273 stat
= 100.0 * float(stat_dict
[player
]['net']) / float(stat_dict
[player
]['bigblind'])
276 'bb100=%5.3f' % (stat
),
277 'bb100=%5.3f' % (stat
),
278 '(%d,%d)' % (100*stat_dict
[player
]['net'],stat_dict
[player
]['bigblind']),
279 _('Big blinds won per 100 hands')
282 log
.info(_("exception calculating %s") % ("bb/100: "+str(stat_dict
[player
])))
288 _('Big blinds won per 100 hands')
291 def BBper100(stat_dict
, player
):
292 stat_descriptions
["BBper100"] = _("Big bets won per 100 hands") + " (BBper100)"
295 stat
= 50 * float(stat_dict
[player
]['net']) / float(stat_dict
[player
]['bigblind'])
298 'BB100=%5.3f' % (stat
),
299 'BB100=%5.3f' % (stat
),
300 '(%d,%d)' % (100*stat_dict
[player
]['net'],2*stat_dict
[player
]['bigblind']),
301 _('Big bets won per 100 hands')
304 log
.info(_("exception calculating %s") % ("BB/100: "+str(stat_dict
[player
])))
310 _('Big bets won per 100 hands')
313 def saw_f(stat_dict
, player
):
314 stat_descriptions
["saw_f"] = _("Flop/4th street seen %") + " (saw_f)"
316 num
= float(stat_dict
[player
]['saw_f'])
317 den
= float(stat_dict
[player
]['n'])
320 '%3.1f' % (100.0*stat
),
321 'sf=%3.1f%%' % (100.0*stat
),
322 'saw_f=%3.1f%%' % (100.0*stat
),
323 '(%d/%d)' % (stat_dict
[player
]['saw_f'], stat_dict
[player
]['n']),
324 _('Flop/4th street seen %')
333 _('Flop/4th street seen %')
336 def n(stat_dict
, player
):
337 stat_descriptions
["n"] = _("Number of hands seen") + " (n)"
339 # If sample is large enough, use X.Yk notation instead
340 _n
= stat_dict
[player
]['n']
345 _c
= float(c
) / 100.0
350 fmt
= '%d.%dk' % (k
, d
)
351 return (stat_dict
[player
]['n'],
353 'n=%d' % (stat_dict
[player
]['n']),
354 'n=%d' % (stat_dict
[player
]['n']),
355 '(%d)' % (stat_dict
[player
]['n']),
356 _('Number of hands seen')
359 # Number of hands shouldn't ever be "NA"; zeroes are better here
365 _('Number of hands seen')
368 def fold_f(stat_dict
, player
):
372 stat
= float(stat_dict
[player
]['fold_2'])/float(stat_dict
[player
]['saw_f'])
374 '%3.1f' % (100.0*stat
),
375 'ff=%3.1f%%' % (100.0*stat
),
376 'fold_f=%3.1f%%' % (100.0*stat
),
377 '(%d/%d)' % (stat_dict
[player
]['fold_2'], stat_dict
[player
]['saw_f']),
389 def steal(stat_dict
, player
):
390 stat_descriptions
["steal"] = _("% steal attempted") + " (steal)"
393 stat
= float(stat_dict
[player
]['steal'])/float(stat_dict
[player
]['steal_opp'])
395 '%3.1f' % (100.0*stat
),
396 'st=%3.1f%%' % (100.0*stat
),
397 'steal=%3.1f%%' % (100.0*stat
),
398 '(%d/%d)' % (stat_dict
[player
]['steal'], stat_dict
[player
]['steal_opp']),
399 _('% steal attempted')
402 return (stat
, 'NA', 'st=NA', 'steal=NA', '(0/0)', '% steal attempted')
404 def s_steal(stat_dict
, player
):
405 stat_descriptions
["s_steal"] = _("% steal success") + " (s_steal)"
408 stat
= float(stat_dict
[player
]['suc_st'])/float(stat_dict
[player
]['steal'])
410 '%3.1f' % (100.0*stat
),
411 's_st=%3.1f%%' % (100.0*stat
),
412 's_steal=%3.1f%%' % (100.0*stat
),
413 '(%d/%d)' % (stat_dict
[player
]['suc_st'], stat_dict
[player
]['steal']),
417 return (stat
, 'NA', 'st=NA', 's_steal=NA', '(0/0)', '% steal success')
419 def f_SB_steal(stat_dict
, player
):
420 stat_descriptions
["f_SB_steal"] = _("% folded SB to steal") + " (f_SB_steal)"
423 stat
= float(stat_dict
[player
]['sbnotdef'])/float(stat_dict
[player
]['sbstolen'])
425 '%3.1f' % (100.0*stat
),
426 'fSB=%3.1f%%' % (100.0*stat
),
427 'fSB_s=%3.1f%%' % (100.0*stat
),
428 '(%d/%d)' % (stat_dict
[player
]['sbnotdef'], stat_dict
[player
]['sbstolen']),
429 _('% folded SB to steal'))
436 _('% folded SB to steal'))
438 def f_BB_steal(stat_dict
, player
):
439 stat_descriptions
["f_BB_steal"] = _("% folded BB to steal") + " (f_BB_steal)"
442 stat
= float(stat_dict
[player
]['bbnotdef'])/float(stat_dict
[player
]['bbstolen'])
444 '%3.1f' % (100.0*stat
),
445 'fBB=%3.1f%%' % (100.0*stat
),
446 'fBB_s=%3.1f%%' % (100.0*stat
),
447 '(%d/%d)' % (stat_dict
[player
]['bbnotdef'], stat_dict
[player
]['bbstolen']),
448 _('% folded BB to steal'))
455 _('% folded BB to steal'))
457 def f_steal(stat_dict
, player
):
458 stat_descriptions
["f_steal"] = _("% folded blind to steal") + " (f_steal)"
461 folded_blind
= stat_dict
[player
]['sbnotdef'] + stat_dict
[player
]['bbnotdef']
462 blind_stolen
= stat_dict
[player
]['sbstolen'] + stat_dict
[player
]['bbstolen']
464 stat
= float(folded_blind
)/float(blind_stolen
)
466 '%3.1f' % (100.0*stat
),
467 'fB=%3.1f%%' % (100.0*stat
),
468 'fB_s=%3.1f%%' % (100.0*stat
),
469 '(%d/%d)' % (folded_blind
, blind_stolen
),
470 _('% folded blind to steal'))
477 _('% folded blind to steal'))
479 def three_B(stat_dict
, player
):
480 stat_descriptions
["three_B"] = _("% 3 bet preflop/3rd street") + " (three_B)"
483 stat
= float(stat_dict
[player
]['tb_0'])/float(stat_dict
[player
]['tb_opp_0'])
485 '%3.1f' % (100.0*stat
),
486 '3B=%3.1f%%' % (100.0*stat
),
487 '3B_pf=%3.1f%%' % (100.0*stat
),
488 '(%d/%d)' % (stat_dict
[player
]['tb_0'], stat_dict
[player
]['tb_opp_0']),
489 _('% 3 bet preflop/3rd street'))
496 _('% 3 bet preflop/3rd street'))
498 def four_B(stat_dict
, player
):
499 stat_descriptions
["four_B"] = _("% 4 bet preflop/3rd street") + " (four_B)"
502 stat
= float(stat_dict
[player
]['fb_0'])/float(stat_dict
[player
]['fb_opp_0'])
504 '%3.1f' % (100.0*stat
),
505 '4B=%3.1f%%' % (100.0*stat
),
506 '4B=%3.1f%%' % (100.0*stat
),
507 '(%d/%d)' % (stat_dict
[player
]['fb_0'], stat_dict
[player
]['fb_opp_0']),
508 _('% 4 bet preflop/3rd street'))
515 _('% 4 bet preflop/3rd street'))
517 def cfour_B(stat_dict
, player
):
518 stat_descriptions
["cfour_B"] = _("% cold 4 bet preflop/3rd street") + " (cfour_B)"
521 stat
= float(stat_dict
[player
]['cfb_0'])/float(stat_dict
[player
]['cfb_opp_0'])
523 '%3.1f' % (100.0*stat
),
524 'C4B=%3.1f%%' % (100.0*stat
),
525 'C4B_pf=%3.1f%%' % (100.0*stat
),
526 '(%d/%d)' % (stat_dict
[player
]['cfb_0'], stat_dict
[player
]['cfb_opp_0']),
527 _('% cold 4 bet preflop/3rd street'))
534 _('% cold 4 bet preflop/3rd street'))
536 def squeeze(stat_dict
, player
):
537 stat_descriptions
["squeeze"] = _("% squeeze preflop") + " (squeeze)"
540 stat
= float(stat_dict
[player
]['sqz_0'])/float(stat_dict
[player
]['sqz_opp_0'])
542 '%3.1f' % (100.0*stat
),
543 'SQZ=%3.1f%%' % (100.0*stat
),
544 'SQZ_pf=%3.1f%%' % (100.0*stat
),
545 '(%d/%d)' % (stat_dict
[player
]['sqz_0'], stat_dict
[player
]['sqz_opp_0']),
546 _('% squeeze preflop'))
553 _('% squeeze preflop'))
556 def raiseToSteal(stat_dict
, player
):
557 stat_descriptions
["raiseToSteal"] = _("% raise to steal") + " (raiseToSteal)"
560 stat
= float(stat_dict
[player
]['rts'])/float(stat_dict
[player
]['rts_opp'])
562 '%3.1f' % (100.0*stat
),
563 'RST=%3.1f%%' % (100.0*stat
),
564 'RST_pf=%3.1f%%' % (100.0*stat
),
565 '(%d/%d)' % (stat_dict
[player
]['rts'], stat_dict
[player
]['rts_opp']),
566 _('% raise to steal'))
573 _('% raise to steal'))
575 def car0(stat_dict
, player
):
576 stat_descriptions
["car_0"] = _("% called a raise preflop") + " (car_0)"
579 stat
= float(stat_dict
[player
]['car_0'])/float(stat_dict
[player
]['car_opp_0'])
581 '%3.1f' % (100.0*stat
),
582 'CAR0=%3.1f%%' % (100.0*stat
),
583 'CAR_pf=%3.1f%%' % (100.0*stat
),
584 '(%d/%d)' % (stat_dict
[player
]['car_0'], stat_dict
[player
]['car_opp_0']),
585 _('% called a raise preflop'))
592 _('% called a raise preflop'))
594 def f_3bet(stat_dict
, player
):
595 stat_descriptions
["f_3bet"] = _("% fold to 3 bet preflop/3rd street") + " (f_3bet)"
598 stat
= float(stat_dict
[player
]['f3b_0'])/float(stat_dict
[player
]['f3b_opp_0'])
600 '%3.1f' % (100.0*stat
),
601 'F3B=%3.1f%%' % (100.0*stat
),
602 'F3B_pf=%3.1f%%' % (100.0*stat
),
603 '(%d/%d)' % (stat_dict
[player
]['f3b_0'], stat_dict
[player
]['f3b_opp_0']),
604 _('% fold to 3 bet preflop/3rd street'))
611 _('% fold to 3 bet preflop/3rd street'))
613 def f_4bet(stat_dict
, player
):
614 stat_descriptions
["f_4bet"] = _("% fold to 4 bet preflop/3rd street") + " (f_4bet)"
617 stat
= float(stat_dict
[player
]['f4b_0'])/float(stat_dict
[player
]['f4b_opp_0'])
619 '%3.1f' % (100.0*stat
),
620 'F4B=%3.1f%%' % (100.0*stat
),
621 'F4B_pf=%3.1f%%' % (100.0*stat
),
622 '(%d/%d)' % (stat_dict
[player
]['f4b_0'], stat_dict
[player
]['f4b_opp_0']),
623 _('% fold to 4 bet preflop/3rd street'))
630 _('% fold to 4 bet preflop/3rd street'))
632 def WMsF(stat_dict
, player
):
633 stat_descriptions
["WMsF"] = _("% won money when seen flop/4th street") + " (WMsF)"
636 stat
= float(stat_dict
[player
]['w_w_s_1'])/float(stat_dict
[player
]['saw_1'])
638 '%3.1f' % (100.0*stat
),
639 'wf=%3.1f%%' % (100.0*stat
),
640 'w_w_f=%3.1f%%' % (100.0*stat
),
641 '(%d/%d)' % (stat_dict
[player
]['w_w_s_1'], stat_dict
[player
]['saw_f']),
642 _('% won money when seen flop/4th street'))
649 _('% won money when seen flop/4th street'))
651 def a_freq1(stat_dict
, player
):
652 stat_descriptions
["a_freq1"] = _("Aggression frequency flop/4th street") + " (a_freq1)"
655 stat
= float(stat_dict
[player
]['aggr_1'])/float(stat_dict
[player
]['saw_f'])
657 '%3.1f' % (100.0*stat
),
658 'a1=%3.1f%%' % (100.0*stat
),
659 'a_fq_1=%3.1f%%' % (100.0*stat
),
660 '(%d/%d)' % (stat_dict
[player
]['aggr_1'], stat_dict
[player
]['saw_f']),
661 _('Aggression frequency flop/4th street'))
668 _('Aggression frequency flop/4th street'))
670 def a_freq2(stat_dict
, player
):
671 stat_descriptions
["a_freq2"] = _("Aggression frequency turn/5th street") + " (a_freq2)"
674 stat
= float(stat_dict
[player
]['aggr_2'])/float(stat_dict
[player
]['saw_2'])
676 '%3.1f' % (100.0*stat
),
677 'a2=%3.1f%%' % (100.0*stat
),
678 'a_fq_2=%3.1f%%' % (100.0*stat
),
679 '(%d/%d)' % (stat_dict
[player
]['aggr_2'], stat_dict
[player
]['saw_2']),
680 _('Aggression frequency turn/5th street'))
687 _('Aggression frequency turn/5th street'))
689 def a_freq3(stat_dict
, player
):
690 stat_descriptions
["a_freq3"] = _("Aggression frequency river/6th street") + " (a_freq3)"
693 stat
= float(stat_dict
[player
]['aggr_3'])/float(stat_dict
[player
]['saw_3'])
695 '%3.1f' % (100.0*stat
),
696 'a3=%3.1f%%' % (100.0*stat
),
697 'a_fq_3=%3.1f%%' % (100.0*stat
),
698 '(%d/%d)' % (stat_dict
[player
]['aggr_3'], stat_dict
[player
]['saw_3']),
699 _('Aggression frequency river/6th street'))
706 _('Aggression frequency river/6th street'))
708 def a_freq4(stat_dict
, player
):
709 stat_descriptions
["a_freq4"] = _("Aggression frequency 7th street") + " (a_freq4)"
712 stat
= float(stat_dict
[player
]['aggr_4'])/float(stat_dict
[player
]['saw_4'])
714 '%3.1f' % (100.0*stat
),
715 'a4=%3.1f%%' % (100.0*stat
),
716 'a_fq_4=%3.1f%%' % (100.0*stat
),
717 '(%d/%d)' % (stat_dict
[player
]['aggr_4'], stat_dict
[player
]['saw_4']),
718 _('Aggression frequency 7th street'))
725 _('Aggression frequency 7th street'))
727 def a_freq_123(stat_dict
, player
):
728 stat_descriptions
["a_freq_123"] = _("Post-flop aggression frequency") + " (a_freq_123)"
731 stat
= float( stat_dict
[player
]['aggr_1'] + stat_dict
[player
]['aggr_2'] + stat_dict
[player
]['aggr_3']
732 ) / float( stat_dict
[player
]['saw_1'] + stat_dict
[player
]['saw_2'] + stat_dict
[player
]['saw_3']);
734 '%3.1f' % (100.0*stat
),
735 'afq=%3.1f%%' % (100.0*stat
),
736 'postf_aggfq=%3.1f%%' % (100.0*stat
),
737 '(%d/%d)' % ( stat_dict
[player
]['aggr_1']
738 + stat_dict
[player
]['aggr_2']
739 + stat_dict
[player
]['aggr_3']
740 , stat_dict
[player
]['saw_1']
741 + stat_dict
[player
]['saw_2']
742 + stat_dict
[player
]['saw_3']
744 _('Post-flop aggression frequency'))
751 _('Post-flop aggression frequency'))
753 def agg_freq(stat_dict
, player
):
754 #TODO: remove, dupe of a_freq_123
757 #Agression on the flop and all streets
758 bet_raise
= stat_dict
[player
]['aggr_1'] + stat_dict
[player
]['aggr_2'] + stat_dict
[player
]['aggr_3'] + stat_dict
[player
]['aggr_4']
759 #number post flop streets seen, this must be number of post-flop calls !!
760 post_call
= stat_dict
[player
]['call_1'] + stat_dict
[player
]['call_2'] + stat_dict
[player
]['call_3'] + stat_dict
[player
]['call_4']
761 #Number of post flop folds this info is not yet in the database
762 post_fold
= stat_dict
[player
]['f_freq_1'] + stat_dict
[player
]['f_freq_2'] + stat_dict
[player
]['f_freq_3'] + stat_dict
[player
]['f_freq_4']
764 stat
= float (bet_raise
) / float(post_call
+ post_fold
+ bet_raise
)
767 '%3.1f' % (100.0*stat
),
768 'afr=%3.1f%%' % (100.0*stat
),
769 'agg_fr=%3.1f%%' % (100.0*stat
),
770 '(%d/%d)' % (bet_raise
, (post_call
+ post_fold
+ bet_raise
)),
780 def agg_fact(stat_dict
, player
):
781 stat_descriptions
["agg_fact"] = _("Aggression factor") + " (agg_fact)"
784 bet_raise
= stat_dict
[player
]['aggr_1'] + stat_dict
[player
]['aggr_2'] + stat_dict
[player
]['aggr_3'] + stat_dict
[player
]['aggr_4']
785 post_call
= stat_dict
[player
]['call_1'] + stat_dict
[player
]['call_2'] + stat_dict
[player
]['call_3'] + stat_dict
[player
]['call_4']
788 stat
= float (bet_raise
) / float(post_call
)
790 stat
= float (bet_raise
)
793 'afa=%2.2f' % (stat
) ,
794 'agg_fa=%2.2f' % (stat
) ,
795 '(%d/%d)' % (bet_raise
, post_call
),
796 _('Aggression factor'))
803 _('Aggression factor'))
805 def agg_fact_pct(stat_dict
, player
):
806 stat_descriptions
["agg_fact_pct"] = _("Aggression factor pct") + " (agg_fact_pct)"
809 bet_raise
= stat_dict
[player
]['aggr_1'] + stat_dict
[player
]['aggr_2'] + stat_dict
[player
]['aggr_3'] + stat_dict
[player
]['aggr_4']
810 post_call
= stat_dict
[player
]['call_1'] + stat_dict
[player
]['call_2'] + stat_dict
[player
]['call_3'] + stat_dict
[player
]['call_4']
812 stat
= float (bet_raise
) / float(post_call
+ bet_raise
)
815 'afap=%2.2f' % (stat
) ,
816 'agg_fa_pct=%2.2f' % (stat
) ,
817 '(%d/%d)' % (bet_raise
, post_call
),
818 _('Aggression factor pct'))
825 _('Aggression factor pct'))
827 def cbet(stat_dict
, player
):
828 stat_descriptions
["cbet"] = _("% continuation bet") + " (cbet)"
831 cbets
= stat_dict
[player
]['cb_1']+stat_dict
[player
]['cb_2']+stat_dict
[player
]['cb_3']+stat_dict
[player
]['cb_4']
832 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']
833 stat
= float(cbets
)/float(oppt
)
835 '%3.1f' % (100.0*stat
),
836 'cbet=%3.1f%%' % (100.0*stat
),
837 'cbet=%3.1f%%' % (100.0*stat
),
838 '(%d/%d)' % (cbets
, oppt
),
839 _('% continuation bet'))
846 _('% continuation bet'))
848 def cb1(stat_dict
, player
):
849 stat_descriptions
["cb1"] = _("% continuation bet flop/4th street") + " (cb1)"
852 stat
= float(stat_dict
[player
]['cb_1'])/float(stat_dict
[player
]['cb_opp_1'])
854 '%3.1f' % (100.0*stat
),
855 'cb1=%3.1f%%' % (100.0*stat
),
856 'cb_1=%3.1f%%' % (100.0*stat
),
857 '(%d/%d)' % (stat_dict
[player
]['cb_1'], stat_dict
[player
]['cb_opp_1']),
858 _('% continuation bet flop/4th street'))
865 _('% continuation bet flop/4th street'))
867 def cb2(stat_dict
, player
):
868 stat_descriptions
["cb2"] = _("% continuation bet turn/5th street") + " (cb2)"
871 stat
= float(stat_dict
[player
]['cb_2'])/float(stat_dict
[player
]['cb_opp_2'])
873 '%3.1f' % (100.0*stat
),
874 'cb2=%3.1f%%' % (100.0*stat
),
875 'cb_2=%3.1f%%' % (100.0*stat
),
876 '(%d/%d)' % (stat_dict
[player
]['cb_2'], stat_dict
[player
]['cb_opp_2']),
877 _('% continuation bet turn/5th street'))
884 _('% continuation bet turn/5th street'))
886 def cb3(stat_dict
, player
):
887 stat_descriptions
["cb3"] = _("% continuation bet river/6th street") + " (cb3)"
890 stat
= float(stat_dict
[player
]['cb_3'])/float(stat_dict
[player
]['cb_opp_3'])
892 '%3.1f' % (100.0*stat
),
893 'cb3=%3.1f%%' % (100.0*stat
),
894 'cb_3=%3.1f%%' % (100.0*stat
),
895 '(%d/%d)' % (stat_dict
[player
]['cb_3'], stat_dict
[player
]['cb_opp_3']),
896 _('% continuation bet river/6th street'))
903 _('% continuation bet river/6th street'))
905 def cb4(stat_dict
, player
):
906 stat_descriptions
["cb4"] = _("% continuation bet 7th street") + " (cb4)"
909 stat
= float(stat_dict
[player
]['cb_4'])/float(stat_dict
[player
]['cb_opp_4'])
911 '%3.1f' % (100.0*stat
),
912 'cb4=%3.1f%%' % (100.0*stat
),
913 'cb_4=%3.1f%%' % (100.0*stat
),
914 '(%d/%d)' % (stat_dict
[player
]['cb_4'], stat_dict
[player
]['cb_opp_4']),
915 _('% continuation bet 7th street'))
922 _('% continuation bet 7th street'))
924 def ffreq1(stat_dict
, player
):
925 stat_descriptions
["ffreq1"] = _("% fold frequency flop/4th street") + " (ffreq1)"
928 stat
= float(stat_dict
[player
]['f_freq_1'])/float(stat_dict
[player
]['was_raised_1'])
930 '%3.1f' % (100.0*stat
),
931 'ff1=%3.1f%%' % (100.0*stat
),
932 'ff_1=%3.1f%%' % (100.0*stat
),
933 '(%d/%d)' % (stat_dict
[player
]['f_freq_1'], stat_dict
[player
]['was_raised_1']),
934 _('% fold frequency flop/4th street'))
941 _('% fold frequency flop/4th street'))
943 def ffreq2(stat_dict
, player
):
944 stat_descriptions
["ffreq2"] = _("% fold frequency turn/5th street") + " (ffreq2)"
947 stat
= float(stat_dict
[player
]['f_freq_2'])/float(stat_dict
[player
]['was_raised_2'])
949 '%3.1f' % (100.0*stat
),
950 'ff2=%3.1f%%' % (100.0*stat
),
951 'ff_2=%3.1f%%' % (100.0*stat
),
952 '(%d/%d)' % (stat_dict
[player
]['f_freq_2'], stat_dict
[player
]['was_raised_2']),
953 _('% fold frequency turn/5th street'))
960 _('% fold frequency turn/5th street'))
962 def ffreq3(stat_dict
, player
):
963 stat_descriptions
["ffreq3"] = _("% fold frequency river/6th street") + " (ffreq3)"
966 stat
= float(stat_dict
[player
]['f_freq_3'])/float(stat_dict
[player
]['was_raised_3'])
968 '%3.1f' % (100.0*stat
),
969 'ff3=%3.1f%%' % (100.0*stat
),
970 'ff_3=%3.1f%%' % (100.0*stat
),
971 '(%d/%d)' % (stat_dict
[player
]['f_freq_3'], stat_dict
[player
]['was_raised_3']),
972 _('% fold frequency river/6th street'))
979 _('% fold frequency river/6th street'))
981 def ffreq4(stat_dict
, player
):
982 stat_descriptions
["ffreq4"] = _("% fold frequency 7th street") + " (ffreq4)"
985 stat
= float(stat_dict
[player
]['f_freq_4'])/float(stat_dict
[player
]['was_raised_4'])
987 '%3.1f' % (100.0*stat
),
988 'ff4=%3.1f%%' % (100.0*stat
),
989 'ff_4=%3.1f%%' % (100.0*stat
),
990 '(%d/%d)' % (stat_dict
[player
]['f_freq_4'], stat_dict
[player
]['was_raised_4']),
991 _('% fold frequency 7th street'))
998 _('% fold frequency 7th street'))
1000 def f_cb1(stat_dict
, player
):
1001 stat_descriptions
["f_cb1"] = _("% fold to continuation bet flop/4th street") + " (f_cb1)"
1004 stat
= float(stat_dict
[player
]['f_cb_1'])/float(stat_dict
[player
]['f_cb_opp_1'])
1006 '%3.1f' % (100.0*stat
),
1007 'f_cb1=%3.1f%%' % (100.0*stat
),
1008 'f_cb_1=%3.1f%%' % (100.0*stat
),
1009 '(%d/%d)' % (stat_dict
[player
]['f_cb_1'], stat_dict
[player
]['f_cb_opp_1']),
1010 _('% fold to continuation bet flop/4th street'))
1017 _('% fold to continuation bet flop/4th street'))
1019 def f_cb2(stat_dict
, player
):
1020 stat_descriptions
["f_cb2"] = _("% fold to continuation bet turn/5th street") + " (f_cb2)"
1023 stat
= float(stat_dict
[player
]['f_cb_2'])/float(stat_dict
[player
]['f_cb_opp_2'])
1025 '%3.1f' % (100.0*stat
),
1026 'f_cb2=%3.1f%%' % (100.0*stat
),
1027 'f_cb_2=%3.1f%%' % (100.0*stat
),
1028 '(%d/%d)' % (stat_dict
[player
]['f_cb_2'], stat_dict
[player
]['f_cb_opp_2']),
1029 _('% fold to continuation bet turn/5th street'))
1036 _('% fold to continuation bet turn/5th street'))
1038 def f_cb3(stat_dict
, player
):
1039 stat_descriptions
["f_cb3"] = _("% fold to continuation bet river/6th street") + " (f_cb3)"
1042 stat
= float(stat_dict
[player
]['f_cb_3'])/float(stat_dict
[player
]['f_cb_opp_3'])
1044 '%3.1f' % (100.0*stat
),
1045 'f_cb3=%3.1f%%' % (100.0*stat
),
1046 'f_cb_3=%3.1f%%' % (100.0*stat
),
1047 '(%d/%d)' % (stat_dict
[player
]['f_cb_3'], stat_dict
[player
]['f_cb_opp_3']),
1048 _('% fold to continuation bet river/6th street'))
1055 _('% fold to continuation bet river/6th street'))
1057 def f_cb4(stat_dict
, player
):
1058 stat_descriptions
["f_cb4"] = _("% fold to continuation bet 7th street") + " (f_cb4)"
1061 stat
= float(stat_dict
[player
]['f_cb_4'])/float(stat_dict
[player
]['f_cb_opp_4'])
1063 '%3.1f' % (100.0*stat
),
1064 'f_cb4=%3.1f%%' % (100.0*stat
),
1065 'f_cb_4=%3.1f%%' % (100.0*stat
),
1066 '(%d/%d)' % (stat_dict
[player
]['f_cb_4'], stat_dict
[player
]['f_cb_opp_4']),
1067 _('% fold to continuation bet 7th street'))
1074 _('% fold to continuation bet 7th street'))
1076 def starthands(stat_dict
, player
, handid
):
1079 #summary of known starting hands+position
1080 # data volumes could get crazy here,so info is limited to hands
1081 # in the current HH file only
1083 # this info is NOT read from the cache, so does not obey aggregation
1084 # parameters for other stats
1086 #display shows 3 categories
1087 # PFcall - limp or coldcall preflop
1088 # PFaggr - raise preflop
1089 # PFdefBB - defended in BB
1091 # hand is shown, followed by position indicator
1092 # (b=SB/BB. l=Button/cutoff m=previous 3 seats to that, e=remainder)
1094 # due to screen space required for this stat, it should only
1095 # be used in the popup section i.e.
1096 # <pu_stat pu_stat_name="starthands"> </pu_stat>
1098 stat_descriptions
["starthands"] = _("starting hands at this table") + " (starting hands)"
1102 PFdefend
=" PFdefBB:"
1103 count_pfl
= count_pfa
= count_pfc
= count_pfd
= 2
1113 c
= Configuration
.Config()
1114 db_connection
= Database
.Database(c
)
1115 sc
= db_connection
.get_cursor()
1117 sc
.execute(("SELECT distinct startCards, street0Aggr, street0CalledRaiseDone, " +
1118 "case when HandsPlayers.position = 'B' then 'b' " +
1119 "when HandsPlayers.position = 'S' then 'b' " +
1120 "when HandsPlayers.position = '0' then 'l' " +
1121 "when HandsPlayers.position = '1' then 'l' " +
1122 "when HandsPlayers.position = '2' then 'm' " +
1123 "when HandsPlayers.position = '3' then 'm' " +
1124 "when HandsPlayers.position = '4' then 'm' " +
1125 "when HandsPlayers.position = '5' then 'e' " +
1126 "when HandsPlayers.position = '6' then 'e' " +
1127 "when HandsPlayers.position = '7' then 'e' " +
1128 "when HandsPlayers.position = '8' then 'e' " +
1129 "when HandsPlayers.position = '9' then 'e' " +
1131 "FROM Hands, HandsPlayers, Gametypes " +
1132 "WHERE HandsPlayers.handId = Hands.id " +
1133 " AND Gametypes.id = Hands.gametypeid "+
1134 " AND Gametypes.type = " +
1135 " (SELECT Gametypes.type FROM Gametypes, Hands " +
1136 " WHERE Hands.gametypeid = Gametypes.id and Hands.id = %d) " +
1137 " AND Gametypes.Limittype = " +
1138 " (SELECT Gametypes.limitType FROM Gametypes, Hands " +
1139 " WHERE Hands.gametypeid = Gametypes.id and Hands.id = %d) " +
1140 "AND Gametypes.category = 'holdem' " +
1141 "AND fileId = (SELECT fileId FROM Hands " +
1142 " WHERE Hands.id = %d) " +
1143 "AND HandsPlayers.playerId = %d " +
1145 "AND startCards > 0 " +
1146 "ORDER BY startCards DESC " +
1148 % (int(handid
), int(handid
), int(handid
), int(player
)))
1150 for (qstartcards
, qstreet0Aggr
, qstreet0CalledRaiseDone
, qposition
) in sc
.fetchall():
1151 humancards
= Card
.decodeStartHandValue("holdem", qstartcards
)
1153 if qposition
== "B" and qstreet0Aggr
== False:
1154 PFdefend
=PFdefend
+"/"+humancards
1156 if (count_pfd
/ 8.0 == int(count_pfd
/ 8.0)):
1157 PFdefend
=PFdefend
+"\n"
1158 elif qstreet0Aggr
== True:
1159 PFaggr
=PFaggr
+"/"+humancards
+"."+qposition
1161 if (count_pfa
/ 8.0 == int(count_pfa
/ 8.0)):
1163 elif qstreet0CalledRaiseDone
:
1164 PFcar
=PFcar
+"/"+humancards
+"."+qposition
1166 if (count_pfc
/ 8.0 == int(count_pfc
/ 8.0)):
1169 PFlimp
=PFlimp
+"/"+humancards
+"."+qposition
1171 if (count_pfl
/ 8.0 == int(count_pfl
/ 8.0)):
1175 returnstring
= PFlimp
+ "\n" + PFaggr
+ "\n" + PFcar
+ "\n" + PFdefend
#+ "\n" + str(handid)
1177 return ((returnstring
),
1185 def build_stat_descriptions(stats_file
):
1186 for method
in dir(stats_file
):
1187 if method
in ("Charset", "Configuration", "Database", "GInitiallyUnowned", "gtk", "pygtk",
1188 "player", "c", "db_connection", "do_stat", "do_tip", "stat_dict", "h", "re",
1189 "re_Percent", "re_Places", "L10n", "sys", "_", "log", "encoder", "codecs",
1192 if method
.startswith('__'):
1195 eval(method
+"(None, None)")
1199 return stat_descriptions
1201 if __name__
== "__main__":
1204 misslist
= [ "Configuration", "Database", "Charset", "codecs", "encoder"
1205 , "do_stat", "do_tip", "GInitiallyUnowned", "gtk", "pygtk", "Card"
1206 , "L10n", "_", "__stat_override", "build_stat_descriptions", "log"
1207 , "logging", "stat_descriptions"
1210 statlist
= [ x
for x
in statlist
if x
not in dir(sys
) ]
1211 statlist
= [ x
for x
in statlist
if x
not in dir(codecs
) ]
1212 statlist
= [ x
for x
in statlist
if x
not in misslist
]
1213 #print "statlist is", statlist
1215 c
= Configuration
.Config()
1216 #TODO: restore the below code. somehow it creates a version 119 DB but commenting this out makes it print a stat list
1217 db_connection
= Database
.Database(c
)
1218 h
= db_connection
.get_last_hand()
1219 stat_dict
= db_connection
.get_stats_from_hand(h
, "ring")
1221 for player
in stat_dict
.keys():
1222 print (_("Example stats. Player = %s, Hand = %s:") % (player
, h
))
1223 for attr
in statlist
:
1224 print " ", do_stat(stat_dict
, player
=player
, stat
=attr
)
1227 print _("Legal stats:")
1228 print _("(add _0 to name to display with 0 decimal places, _1 to display with 1, etc)")
1229 for attr
in statlist
:
1230 print "%-14s %s" % (attr
, eval("%s.__doc__" % (attr
)))
1231 # print " <pu_stat pu_stat_name = \"%s\"> </pu_stat>" % (attr)
1234 #db_connection.close_connection