diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 6f1183b6..3fd51c7b 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -227,9 +227,10 @@ class Database: #self.hud_hero_days = 30 # but last T days or last H hands for yourself # vars for hand ids or dates fetched according to above config: - self.hand_1day_ago = 0 # max hand id more than 24 hrs earlier than now - self.date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) - self.date_nhands_ago = {} # dates N hands ago per player - not used yet + self.hand_1day_ago = 0 # max hand id more than 24 hrs earlier than now + self.date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) + self.h_date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) for hero + self.date_nhands_ago = {} # dates N hands ago per player - not used yet self.cursor = self.fdb.cursor @@ -371,10 +372,11 @@ class Database: winners[row[0]] = row[1] return winners - def init_hud_stat_vars(self, hud_days): + def init_hud_stat_vars(self, hud_days, h_hud_days): """Initialise variables used by Hud to fetch stats: - self.hand_1day_ago handId of latest hand played more than a day ago - self.date_ndays_ago date n days ago + self.hand_1day_ago handId of latest hand played more than a day ago + self.date_ndays_ago date n days ago + self.h_date_ndays_ago date n days ago for hero (different n) """ self.hand_1day_ago = 1 @@ -393,6 +395,10 @@ class Database: now = datetime.utcnow() - d self.date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day) + d = timedelta(days=h_hud_days) + now = datetime.utcnow() - d + self.h_date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day) + def init_player_hud_stat_vars(self, playerid): # not sure if this is workable, to be continued ... try: @@ -413,33 +419,46 @@ class Database: def get_stats_from_hand( self, hand , hud_params = {'aggregate_tour':False, 'aggregate_ring':False, 'hud_style':'A', 'agg_bb_mult':100} - , hero_ids = {} + , hero_id = -1 ): - aggregate = hud_params['aggregate_tour'] if type == "tour" else hud_params['aggregate_ring'] - hud_style = hud_params['hud_style'] - agg_bb_mult = hud_params['agg_bb_mult'] + aggregate = hud_params['aggregate_tour'] if type == "tour" else hud_params['aggregate_ring'] + hud_style = hud_params['hud_style'] + agg_bb_mult = hud_params['agg_bb_mult'] if aggregate else 1 + h_aggregate = hud_params['h_aggregate_tour'] if type == "tour" else hud_params['h_aggregate_ring'] + h_hud_style = hud_params['h_hud_style'] + h_agg_bb_mult = hud_params['h_agg_bb_mult'] if h_aggregate else 1 stat_dict = {} - if hud_style == 'S': + if hud_style == 'S' or h_hud_style == 'S': + self.get_stats_from_hand_session(hand, stat_dict, hero_id, hud_style, h_hud_style) + if hud_style == 'S' and h_hud_style == 'S': + return stat_dict - self.get_stats_from_hand_session(hand, stat_dict) - return stat_dict + if hud_style == 'T': + stylekey = self.date_ndays_ago + elif hud_style == 'A': + stylekey = '0000000' # all stylekey values should be higher than this + elif hud_style == 'S': + stylekey = 'zzzzzzz' # all stylekey values should be lower than this + #elif hud_style == 'H': + # stylekey = date_nhands_ago needs array by player here ... - else: # hud_style == A + if h_hud_style == 'T': + h_stylekey = self.h_date_ndays_ago + elif h_hud_style == 'A': + h_stylekey = '0000000' # all stylekey values should be higher than this + elif h_hud_style == 'S': + h_stylekey = 'zzzzzzz' # all stylekey values should be lower than this + #elif h_hud_style == 'H': + # h_stylekey = date_nhands_ago needs array by player here ... - if hud_style == 'T': - stylekey = self.date_ndays_ago - #elif hud_style == 'H': - # stylekey = date_nhands_ago needs array by player here ... - else: # assume A (all-time) - stylekey = '0000000' # all stylekey values should be higher than this - - if aggregate: - query = 'get_stats_from_hand_aggregated' - subs = (hand, stylekey, agg_bb_mult, agg_bb_mult) - else: - query = 'get_stats_from_hand' - subs = (hand, stylekey) + #if aggregate: always use aggreagte query now: use agg_bb_mult of 1 for no aggregation: + query = 'get_stats_from_hand_aggregated' + subs = (hand, hero_id, stylekey, agg_bb_mult, agg_bb_mult, hero_id, h_stylekey, h_agg_bb_mult, h_agg_bb_mult) + print "agg query subs:", subs + #else: + # query = 'get_stats_from_hand' + # subs = (hand, stylekey) #print "get stats: hud style =", hud_style, "query =", query, "subs =", subs c = self.connection.cursor() @@ -457,7 +476,13 @@ class Database: return stat_dict # uses query on handsplayers instead of hudcache to get stats on just this session - def get_stats_from_hand_session(self, hand, stat_dict): + def get_stats_from_hand_session(self, hand, stat_dict, hero_id, hud_style, h_hud_style): + """Get stats for just this session (currently defined as any play in the last 24 hours - to + be improved at some point ...) + h_hud_style and hud_style params indicate whether to get stats for hero and/or others + - only fetch heros stats if h_hud_style == 'S', + and only fetch others stats if hud_style == 'S' + """ query = self.sql.query['get_stats_from_hand_session'] if self.db_server == 'mysql': @@ -478,18 +503,20 @@ class Database: if colnames[0].lower() == 'player_id': playerid = row[0] + # Loop through stats adding them to appropriate stat_dict: while row: - for name, val in zip(colnames, row): - if not playerid in stat_dict: - stat_dict[playerid] = {} - stat_dict[playerid][name.lower()] = val - elif not name.lower() in stat_dict[playerid]: - stat_dict[playerid][name.lower()] = val - elif name.lower() not in ('hand_id', 'player_id', 'seat', 'screen_name', 'seats'): - stat_dict[playerid][name.lower()] += val - n += 1 - if n >= 10000: break # todo: don't think this is needed so set nice and high - # for now - comment out or remove? + if (playerid == hero_id and h_hud_style == 'S') or (playerid != hero_id and hud_style == 'S'): + for name, val in zip(colnames, row): + if not playerid in stat_dict: + stat_dict[playerid] = {} + stat_dict[playerid][name.lower()] = val + elif not name.lower() in stat_dict[playerid]: + stat_dict[playerid][name.lower()] = val + elif name.lower() not in ('hand_id', 'player_id', 'seat', 'screen_name', 'seats'): + stat_dict[playerid][name.lower()] += val + n += 1 + if n >= 10000: break # todo: don't think this is needed so set nice and high + # for now - comment out or remove? row = c.fetchone() else: log.error("ERROR: query %s result does not have player_id as first column" % (query,)) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index bf1beef3..0f332b5e 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -56,25 +56,8 @@ import Database import Tables import Hud -# To add to config: *** these vars now replaced by def_hud_params list -#aggregate_stats = {"ring": False, "tour": False} # uses agg_bb_mult -#hud_style = 'A' # A=All-time - # S=Session - # T=timed (last n days - set hud_days to required value) - # Future values may also include: - # H=Hands (last n hands) -#hud_days = 90 # Max number of days from each player to use for hud stats -#agg_bb_mult = 100 # 1 = no aggregation. When aggregating stats across levels larger blinds - # must be < (agg_bb_mult * smaller blinds) to be aggregated - # ie. 100 will aggregate almost everything, 2 will probably agg just the - # next higher and lower levels into the current one, try 3/10/30/100 -#hud_session_gap = 30 # Gap (minutes) between hands that indicates a change of session - # (hands every 2 mins for 1 hour = one session, if followed - # by a 40 minute gap and then more hands on same table that is - # a new session) -#hud_hands = 0 # Max number of hands from each player to use for hud stats (not used) -# New list to hold all HUD params +# HUD params: # - Set aggregate_ring and/or aggregate_tour to True is you want to include stats from other blind levels in the HUD display # - If aggregation is used, the value of agg_bb_mult determines how what levels are included, e.g. # if agg_bb_mult is 100, almost all levels are included in all HUD displays @@ -88,14 +71,14 @@ def_hud_params = { # Settings for all players apart from program owner ('hero') , 'aggregate_tour' : True , 'hud_style' : 'A' , 'hud_days' : 90 - , 'agg_bb_mult' : 1 # 1 means no aggregation + , 'agg_bb_mult' : 1 # 1 means no aggregation # , 'hud_session_gap' : 30 not currently used # Second set of variables for hero - these settings only apply to the program owner , 'h_aggregate_ring' : False , 'h_aggregate_tour' : True - , 'h_hud_style' : 'A' - , 'h_hud_days' : 90 - , 'h_agg_bb_mult' : 1 # 1 means no aggregation + , 'h_hud_style' : 'S' # A(ll) / S(ession) / T(ime in days) + , 'h_hud_days' : 30 + , 'h_agg_bb_mult' : 1 # 1 means no aggregation # , 'h_hud_session_gap' : 30 not currently used } @@ -243,8 +226,9 @@ class HUD_main(object): if temp_key in self.hud_dict: try: # get stats using hud's specific params - self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] ) - stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, self.hud_dict[temp_key].hud_params, self.hero_ids) + self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] + , self.hud_dict[temp_key].hud_params['h_hud_days']) + stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, self.hud_dict[temp_key].hud_params, self.hero_ids[site_id]) except: err = traceback.extract_tb(sys.exc_info()[2])[-1] print "db get_stats error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) @@ -260,8 +244,8 @@ class HUD_main(object): else: try: # get stats using default params - self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'] ) - stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, self.hud_params, self.hero_ids) + self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] ) + stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, self.hud_params, self.hero_ids[site_id]) except: err = traceback.extract_tb(sys.exc_info()[2])[-1] print "db get_stats error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index f58d2d79..7e161f4a 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -147,42 +147,64 @@ class Hud: aggitem = gtk.MenuItem('Show Stats') menu.append(aggitem) - aggMenu = gtk.Menu() - aggitem.set_submenu(aggMenu) + self.aggMenu = gtk.Menu() + aggitem.set_submenu(self.aggMenu) # set agg_bb_mult to 1 to stop aggregation item = gtk.MenuItem('For This Blind Level') item.ms = 1 - aggMenu.append(item) + self.aggMenu.append(item) item.connect("activate", self.set_aggregation) setattr(self, 'showStatsMenuItem1', item) # item = gtk.MenuItem('For Multiple Blind Levels:') - aggMenu.append(item) + self.aggMenu.append(item) setattr(self, 'showStatsMenuItem2', item) # item = gtk.MenuItem(' 0.5 to 2.0 x Current Blinds') item.ms = 2.01 - aggMenu.append(item) + self.aggMenu.append(item) item.connect("activate", self.set_aggregation) setattr(self, 'showStatsMenuItem3', item) # item = gtk.MenuItem(' 0.33 to 3.0 x Current Blinds') item.ms = 3.01 - aggMenu.append(item) + self.aggMenu.append(item) item.connect("activate", self.set_aggregation) setattr(self, 'showStatsMenuItem4', item) # item = gtk.MenuItem(' 0.1 to 10 x Current Blinds') item.ms = 10.01 - aggMenu.append(item) + self.aggMenu.append(item) item.connect("activate", self.set_aggregation) setattr(self, 'showStatsMenuItem5', item) # item = gtk.MenuItem(' All Levels') item.ms = 10000 - aggMenu.append(item) + self.aggMenu.append(item) item.connect("activate", self.set_aggregation) setattr(self, 'showStatsMenuItem6', item) + # + item = gtk.MenuItem('For Hero:') + self.aggMenu.append(item) + setattr(self, 'showStatsMenuItem7', item) + # + item = gtk.MenuItem(' All Time') + item.ms = 'HA' + self.aggMenu.append(item) + item.connect("activate", self.set_hud_style) + setattr(self, 'showStatsMenuItem8', item) + # + item = gtk.MenuItem(' Session') + item.ms = 'HS' + self.aggMenu.append(item) + item.connect("activate", self.set_hud_style) + setattr(self, 'showStatsMenuItem9', item) + # + item = gtk.MenuItem(' %s Days' % (self.hud_params['h_hud_days'])) + item.ms = 'HT' + self.aggMenu.append(item) + item.connect("activate", self.set_hud_style) + setattr(self, 'showStatsMenuItem11', item) eventbox.connect_object("button-press-event", self.on_button_press, menu) @@ -230,6 +252,15 @@ class Hud: print 'set_aggregation', widget.ms self.hud_params['agg_bb_mult'] = widget.ms + def set_hud_style(self, widget): + # try setting these to true all the time, and set the multiplier to 1 to turn agg off: + if widget.ms[0] == 'H': + param = 'h_hud_style' + else: + param = 'hud_style' + self.hud_params[param] = widget.ms[1] + print "setting self.hud_params[%s] = %s" % (param,widget.ms[1]) + def update_table_position(self): if os.name == 'nt': if not win32gui.IsWindow(self.table.number): diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index abef4b76..0c551634 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1384,28 +1384,45 @@ class Sql: INNER JOIN HudCache hc ON (hc.playerId = hp.playerId) INNER JOIN Players p ON (p.id = hc.playerId) WHERE h.id = %s - AND hc.styleKey > %s - /* styleKey is currently 'd' (for date) followed by a yyyymmdd - date key. Set it to 0000000 or similar to get all records */ - /* Note: s means the placeholder 'percent's but we can't include that - in comments. (db api thinks they are actual arguments) - Could also check activeseats here even if only 3 groups eg 2-3/4-6/7+ - e.g. could use a multiplier: - AND h.seats > s / 1.25 and hp.seats < s * 1.25 - where s is the number of active players at the current table (and - 1.25 would be a config value so user could change it) - */ - AND hc.gametypeId+0 in - (SELECT gt1.id from Gametypes gt1, Gametypes gt2 - WHERE gt1.siteid = gt2.siteid /* find gametypes where these match: */ - AND gt1.type = gt2.type /* ring/tourney */ - AND gt1.category = gt2.category /* holdem/stud*/ - AND gt1.limittype = gt2.limittype /* fl/nl */ - AND gt1.bigblind < gt2.bigblind * %s /* bigblind similar size */ - AND gt1.bigblind > gt2.bigblind / %s - AND gt2.id = h.gametypeId) + AND ( /* 2 separate parts for hero and opponents */ + ( hp.playerId != %s + AND hc.styleKey > %s + AND hc.gametypeId+0 in + (SELECT gt1.id from Gametypes gt1, Gametypes gt2 + WHERE gt1.siteid = gt2.siteid /* find gametypes where these match: */ + AND gt1.type = gt2.type /* ring/tourney */ + AND gt1.category = gt2.category /* holdem/stud*/ + AND gt1.limittype = gt2.limittype /* fl/nl */ + AND gt1.bigblind <= gt2.bigblind * %s /* bigblind similar size */ + AND gt1.bigblind >= gt2.bigblind / %s + AND gt2.id = h.gametypeId) + ) + OR + ( hp.playerId = %s + AND hc.styleKey > %s + AND hc.gametypeId+0 in + (SELECT gt1.id from Gametypes gt1, Gametypes gt2 + WHERE gt1.siteid = gt2.siteid /* find gametypes where these match: */ + AND gt1.type = gt2.type /* ring/tourney */ + AND gt1.category = gt2.category /* holdem/stud*/ + AND gt1.limittype = gt2.limittype /* fl/nl */ + AND gt1.bigblind <= gt2.bigblind * %s /* bigblind similar size */ + AND gt1.bigblind >= gt2.bigblind / %s + AND gt2.id = h.gametypeId) + ) + ) GROUP BY hc.PlayerId, p.name """ + # NOTES on above cursor: + # - Do NOT include %s inside query in a comment - the db api thinks + # they are actual arguments. + # - styleKey is currently 'd' (for date) followed by a yyyymmdd + # date key. Set it to 0000000 or similar to get all records + # Could also check activeseats here even if only 3 groups eg 2-3/4-6/7+ + # e.g. could use a multiplier: + # AND h.seats > %s / 1.25 and hp.seats < %s * 1.25 + # where %s is the number of active players at the current table (and + # 1.25 would be a config value so user could change it) if db_server == 'mysql': self.query['get_stats_from_hand_session'] = """