From 16d53f1502171647a1eb5625a49d0cd2e30b955b Mon Sep 17 00:00:00 2001 From: PassThePeas Date: Sat, 12 Sep 2009 23:14:55 +0200 Subject: [PATCH 01/52] Patch for HUD and FTP tourneys modified: Hand.py - writeTableLine : adds the tourneyNo in tourney context modified: Tables.py - discover_nt_by_name : add filter for HUD and chat windows --- pyfpdb/Hand.py | 6 +++++- pyfpdb/Tables.py | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 7a95f78a..31b9ec89 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -596,7 +596,11 @@ Map the tuple self.gametype onto the pokerstars string describing it def writeTableLine(self): - table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats) + table_string = "Table " + if self.gametype['type'] == 'tour': + table_string = table_string + "\'%s %s\' %s-max" % (self.tourNo, self.tablename, self.maxseats) + else: + table_string = table_string + "\'%s\' %s-max" % (self.tablename, self.maxseats) if self.gametype['currency'] == 'play': table_string = table_string + " (Play Money)" if self.buttonpos != None and self.buttonpos != 0: diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index 082bc171..09510536 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -253,6 +253,10 @@ def discover_nt_tournament(c, tour_number, tab_number): titles ={} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: + if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows + if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window + if 'HUD:' in titles[hwnd]: continue # FPDB HUD window + if re.search(search_string, titles[hwnd]): return decode_windows(c, titles[hwnd], hwnd) return None From 00f8b34fffa5cc81dbca6d7a62d8accf8e9598bc Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Wed, 23 Sep 2009 23:36:17 +0300 Subject: [PATCH 02/52] Simplify database creation Database.py : fillDefaultData() Sql-coder had fixed the default data insert, and in the process changed the default type ID. Since his works in general case, I can remove my modifications. --- pyfpdb/Database.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 341a1434..9a22c472 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1011,8 +1011,6 @@ class Database: c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')") if self.backend == self.SQLITE: c.execute("INSERT INTO TourneyTypes (id, siteId, buyin, fee) VALUES (NULL, 1, 0, 0);") - elif self.backend == self.PGSQL: - c.execute("insert into TourneyTypes values (0,1,0,0,0,False,False,null,False,False,False);") else: c.execute("""insert into TourneyTypes(id, siteId, buyin, fee, maxSeats, knockout ,rebuyOrAddon, speed, headsUp, shootout, matrix) From df71dcf2c7c7a06104c0ed62af5b78d9a6fa3460 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Wed, 23 Sep 2009 23:44:57 +0300 Subject: [PATCH 03/52] Fix knockout variable type fpdb_parse_logic.py : recogniseTourneyTypeId() The column in table is of type 'boolean' but the default value was integer '0'; this triggered an error --- pyfpdb/fpdb_parse_logic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index 4ce1f678..1972fc30 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -81,7 +81,7 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non fee = fpdb_simple.parseFee(hand[0]) entries = -1 #todo: parse this prizepool = -1 #todo: parse this - knockout = 0 + knockout = False tourneyStartTime= handStartTime #todo: read tourney start time rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0]) From 6f536d29e7282e9c9be35fde45b8a33f885bca9e Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Thu, 24 Sep 2009 07:08:32 +0300 Subject: [PATCH 04/52] Fix import on PostgreSQL Database.py : fillDefaultData() Remove manual 'id' from INSERT command. In database schema, TourneyTypes.id is a primary key and thus autoincrement. In postgres, autoincrements are implemented as sequences - inserting a value "manually" bypasses the sequence generation, which resulted in a remarkably weird error. Namely, upon the first hand to import, the insert fails due to primary key violation. The default value from an unused sequence is 1, but a row with such an id already exists. The solution is to create the single row of default data values with unspecified TourneyTypes.id, hence allowing postgres to generate the correct id from the sequence. This way the import works again. --- pyfpdb/Database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 9a22c472..22630fb6 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1012,9 +1012,9 @@ class Database: if self.backend == self.SQLITE: c.execute("INSERT INTO TourneyTypes (id, siteId, buyin, fee) VALUES (NULL, 1, 0, 0);") else: - c.execute("""insert into TourneyTypes(id, siteId, buyin, fee, maxSeats, knockout + c.execute("""insert into TourneyTypes(siteId, buyin, fee, maxSeats, knockout ,rebuyOrAddon, speed, headsUp, shootout, matrix) - values (1, 1, 0, 0, 0, False, False, null, False, False, False);""") + values (1, 0, 0, 0, False, False, null, False, False, False);""") #end def fillDefaultData From 7eb368f2212b22b357a76fe48f1e9b3af15707ae Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 3 Oct 2009 08:17:41 +0300 Subject: [PATCH 05/52] Debian package: architecture any -> all The installed files are scripts and even the bytecode versions are generated on install. There is no need to build arch-dependent packages. --- packaging/debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/debian/control b/packaging/debian/control index 93660791..784c4b40 100644 --- a/packaging/debian/control +++ b/packaging/debian/control @@ -6,7 +6,7 @@ Build-Depends: debhelper, python-support Standards-Version: 3.8.0 Package: python-fpdb -Architecture: any +Architecture: all Section: games Priority: extra Depends: ${python:Depends}, python-gtk2, python-matplotlib, From 18cc51ba7aa1751a93d0bbcb2ec47267ea276def Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 3 Oct 2009 21:05:41 +0300 Subject: [PATCH 06/52] Make hud's menu-area text configurable By default the hud positions a little box on top-left corner of each table. Make the text in this box user-modifiable without touching the source. Most likely useful for active users and those who play with smaller tables. On shrunk table the default box may cover some of the players' cards. --- pyfpdb/Configuration.py | 26 ++++++++++++++++++++++++++ pyfpdb/Hud.py | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index b8022a45..dbe973c1 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -278,6 +278,15 @@ class Import: return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s\n saveActions = %s\n fastStoreHudCache = %s\n" \ % (self.interval, self.callFpdbHud, self.hhArchiveBase, self.saveActions, self.fastStoreHudCache) +class HudUI: + def __init__(self, node): + self.node = node + self.label = node.getAttribute('label') + + def __str__(self): + return " label = %s\n" % self.label + + class Tv: def __init__(self, node): self.combinedStealFold = node.getAttribute("combinedStealFold") @@ -389,6 +398,10 @@ class Config: imp = Import(node = imp_node) self.imp = imp + for hui_node in doc.getElementsByTagName('hud_ui'): + hui = HudUI(node = hui_node) + self.ui = hui + for tv_node in doc.getElementsByTagName("tv"): tv = Tv(node = tv_node) self.tv = tv @@ -598,6 +611,19 @@ class Config: try: tv['combinedPostflop'] = self.tv.combinedPostflop except: tv['combinedPostflop'] = True return tv + + # Allow to change the menu appearance + def get_hud_ui_parameters(self): + hui = {} + default_text = 'FPDB Menu - Right click\nLeft-Drag to Move' + try: + hui['label'] = self.ui.label + if self.ui.label == '': # Empty menu label is a big no-no + hui['label'] = default_text + except: + hui['label'] = default_text + return hui + def get_import_parameters(self): imp = {} diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 2c83ccd0..ce8c7c9f 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -82,6 +82,7 @@ class Hud: (font, font_size) = config.get_default_font(self.table.site) self.colors = config.get_default_colors(self.table.site) + self.hud_ui = config.get_hud_ui_parameters() self.backgroundcolor = gtk.gdk.color_parse(self.colors['hudbgcolor']) self.foregroundcolor = gtk.gdk.color_parse(self.colors['hudfgcolor']) @@ -116,7 +117,7 @@ class Hud: win.set_opacity(self.colors["hudopacity"]) eventbox = gtk.EventBox() - label = gtk.Label("FPDB Menu - Right click\nLeft-Drag to Move") + label = gtk.Label(self.hud_ui['label']) win.add(eventbox) eventbox.add(label) From c77e1434365d9c742f16a4556a181f89ea72be1c Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sat, 3 Oct 2009 21:10:09 +0300 Subject: [PATCH 07/52] Add the default box text to example config Now that the text on HUD's box is configurable, move the default text from code to default/sample config. --- pyfpdb/HUD_config.xml.example | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index adc8141c..de2f1bba 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -4,6 +4,9 @@ + + Date: Sat, 3 Oct 2009 23:11:45 +0100 Subject: [PATCH 08/52] debug session stats --- pyfpdb/Database.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index b9ec62f4..c923517e 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -467,11 +467,13 @@ class Database: c.execute(self.sql.query[query], subs) colnames = [desc[0] for desc in c.description] for row in c.fetchall(): - t_dict = {} - for name, val in zip(colnames, row): - t_dict[name.lower()] = val -# print t_dict - stat_dict[t_dict['player_id']] = t_dict + playerid = row[0] + if (playerid == hero_id and h_hud_style != 'S') or (playerid != hero_id and hud_style != 'S'): + t_dict = {} + for name, val in zip(colnames, row): + t_dict[name.lower()] = val +# print t_dict + stat_dict[t_dict['player_id']] = t_dict return stat_dict @@ -501,10 +503,10 @@ class Database: row = c.fetchone() if colnames[0].lower() == 'player_id': - playerid = row[0] # Loop through stats adding them to appropriate stat_dict: while row: + playerid = row[0] 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: From 5e3644d8d9755eb898ad6ec83822c787eb168ce0 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 4 Oct 2009 12:26:37 +0100 Subject: [PATCH 09/52] make separate hud menus for player and opponents stats --- pyfpdb/Hud.py | 165 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 123 insertions(+), 42 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 2c83ccd0..ad42bb59 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -146,14 +146,65 @@ class Hud: menu.append(repositem) repositem.connect("activate", self.reposition_windows) - aggitem = gtk.MenuItem('Show Stats') + aggitem = gtk.MenuItem('Show Player Stats') menu.append(aggitem) self.aggMenu = gtk.Menu() aggitem.set_submenu(self.aggMenu) # set agg_bb_mult to 1 to stop aggregation item = gtk.CheckMenuItem('For This Blind Level Only') self.aggMenu.append(item) - item.connect("activate", self.set_aggregation, 1) + item.connect("activate", self.set_aggregation, ('P',1)) + setattr(self, 'h_aggBBmultItem1', item) + # + item = gtk.MenuItem('For Multiple Blind Levels:') + self.aggMenu.append(item) + # + item = gtk.CheckMenuItem(' 0.5 to 2.0 x Current Blinds') + self.aggMenu.append(item) + item.connect("activate", self.set_aggregation, ('P',2)) + setattr(self, 'h_aggBBmultItem2', item) + # + item = gtk.CheckMenuItem(' 0.33 to 3.0 x Current Blinds') + self.aggMenu.append(item) + item.connect("activate", self.set_aggregation, ('P',3)) + setattr(self, 'h_aggBBmultItem3', item) + # + item = gtk.CheckMenuItem(' 0.1 to 10 x Current Blinds') + self.aggMenu.append(item) + item.connect("activate", self.set_aggregation, ('P',10)) + setattr(self, 'h_aggBBmultItem10', item) + # + item = gtk.CheckMenuItem(' All Levels') + self.aggMenu.append(item) + item.connect("activate", self.set_aggregation, ('P',10000)) + setattr(self, 'h_aggBBmultItem10000', item) + # + item = gtk.MenuItem('Since:') + self.aggMenu.append(item) + # + item = gtk.CheckMenuItem(' All Time') + self.aggMenu.append(item) + item.connect("activate", self.set_hud_style, ('P','A')) + setattr(self, 'h_hudStyleOptionA', item) + # + item = gtk.CheckMenuItem(' Session') + self.aggMenu.append(item) + item.connect("activate", self.set_hud_style, ('P','S')) + setattr(self, 'h_hudStyleOptionS', item) + # + item = gtk.CheckMenuItem(' %s Days' % (self.hud_params['h_hud_days'])) + self.aggMenu.append(item) + item.connect("activate", self.set_hud_style, ('P','T')) + setattr(self, 'h_hudStyleOptionT', item) + + aggitem = gtk.MenuItem('Show Opponent Stats') + menu.append(aggitem) + self.aggMenu = gtk.Menu() + aggitem.set_submenu(self.aggMenu) + # set agg_bb_mult to 1 to stop aggregation + item = gtk.CheckMenuItem('For This Blind Level Only') + self.aggMenu.append(item) + item.connect("activate", self.set_aggregation, ('O',1)) setattr(self, 'aggBBmultItem1', item) # item = gtk.MenuItem('For Multiple Blind Levels:') @@ -161,44 +212,54 @@ class Hud: # item = gtk.CheckMenuItem(' 0.5 to 2.0 x Current Blinds') self.aggMenu.append(item) - item.connect("activate", self.set_aggregation, 2) + item.connect("activate", self.set_aggregation, ('O',2)) setattr(self, 'aggBBmultItem2', item) # item = gtk.CheckMenuItem(' 0.33 to 3.0 x Current Blinds') self.aggMenu.append(item) - item.connect("activate", self.set_aggregation, 3) + item.connect("activate", self.set_aggregation, ('O',3)) setattr(self, 'aggBBmultItem3', item) # item = gtk.CheckMenuItem(' 0.1 to 10 x Current Blinds') self.aggMenu.append(item) - item.connect("activate", self.set_aggregation, 10) + item.connect("activate", self.set_aggregation, ('O',10)) setattr(self, 'aggBBmultItem10', item) # item = gtk.CheckMenuItem(' All Levels') self.aggMenu.append(item) - item.connect("activate", self.set_aggregation, 10000) + item.connect("activate", self.set_aggregation, ('O',10000)) setattr(self, 'aggBBmultItem10000', item) # - item = gtk.MenuItem('For Hero:') + item = gtk.MenuItem('Since:') self.aggMenu.append(item) - setattr(self, 'showStatsMenuItem7', item) # item = gtk.CheckMenuItem(' All Time') self.aggMenu.append(item) - item.connect("activate", self.set_hud_style, 'HA') - setattr(self, 'HAStyleOption', item) + item.connect("activate", self.set_hud_style, ('O','A')) + setattr(self, 'hudStyleOptionA', item) # item = gtk.CheckMenuItem(' Session') self.aggMenu.append(item) - item.connect("activate", self.set_hud_style, 'HS') - setattr(self, 'HSStyleOption', item) + item.connect("activate", self.set_hud_style, ('O','S')) + setattr(self, 'hudStyleOptionS', item) # item = gtk.CheckMenuItem(' %s Days' % (self.hud_params['h_hud_days'])) self.aggMenu.append(item) - item.connect("activate", self.set_hud_style, 'HT') - setattr(self, 'HTStyleOption', item) + item.connect("activate", self.set_hud_style, ('O','T')) + setattr(self, 'hudStyleOptionT', item) # set active on current options: + if self.hud_params['h_agg_bb_mult'] == 1: + getattr(self, 'h_aggBBmultItem1').set_active(True) + elif self.hud_params['h_agg_bb_mult'] == 2: + getattr(self, 'h_aggBBmultItem2').set_active(True) + elif self.hud_params['h_agg_bb_mult'] == 3: + getattr(self, 'h_aggBBmultItem3').set_active(True) + elif self.hud_params['h_agg_bb_mult'] == 10: + getattr(self, 'h_aggBBmultItem10').set_active(True) + elif self.hud_params['h_agg_bb_mult'] > 9000: + getattr(self, 'h_aggBBmultItemAll').set_active(True) + # if self.hud_params['agg_bb_mult'] == 1: getattr(self, 'aggBBmultItem1').set_active(True) elif self.hud_params['agg_bb_mult'] == 2: @@ -209,12 +270,20 @@ class Hud: getattr(self, 'aggBBmultItem10').set_active(True) elif self.hud_params['agg_bb_mult'] > 9000: getattr(self, 'aggBBmultItemAll').set_active(True) + # if self.hud_params['h_hud_style'] == 'A': - getattr(self, 'HAStyleOption').set_active(True) + getattr(self, 'h_hudStyleOptionA').set_active(True) elif self.hud_params['h_hud_style'] == 'S': - getattr(self, 'HSStyleOption').set_active(True) + getattr(self, 'h_hudStyleOptionS').set_active(True) elif self.hud_params['h_hud_style'] == 'T': - getattr(self, 'HTStyleOption').set_active(True) + getattr(self, 'h_hudStyleOptionT').set_active(True) + # + if self.hud_params['hud_style'] == 'A': + getattr(self, 'hudStyleOptionA').set_active(True) + elif self.hud_params['hud_style'] == 'S': + getattr(self, 'hudStyleOptionS').set_active(True) + elif self.hud_params['hud_style'] == 'T': + getattr(self, 'hudStyleOptionT').set_active(True) eventbox.connect_object("button-press-event", self.on_button_press, menu) @@ -254,41 +323,53 @@ class Hud: pass def set_aggregation(self, widget, val): - # try setting these to true all the time, and set the multiplier to 1 to turn agg off: - self.hud_params['aggregate_ring'] = True - self.hud_params['aggregate_tour'] = True - self.hud_params['h_aggregate_ring'] = True - self.hud_params['h_aggregate_tour'] = True + (player_opp, num) = val + if player_opp == 'P': + # set these true all the time, set the multiplier to 1 to turn agg off: + self.hud_params['h_aggregate_ring'] = True + self.hud_params['h_aggregate_tour'] = True - if self.hud_params['agg_bb_mult'] != val \ - and getattr(self, 'aggBBmultItem'+str(val)).get_active(): - print 'set_aggregation', val - self.hud_params['agg_bb_mult'] = val - self.hud_params['h_agg_bb_mult'] = val - for mult in ('1', '2', '3', '10', '10000'): - if mult != str(val): - getattr(self, 'aggBBmultItem'+mult).set_active(False) + if self.hud_params['h_agg_bb_mult'] != num \ + and getattr(self, 'h_aggBBmultItem'+str(num)).get_active(): + print 'set_player_aggregation', num + self.hud_params['h_agg_bb_mult'] = num + for mult in ('1', '2', '3', '10', '10000'): + if mult != str(num): + getattr(self, 'h_aggBBmultItem'+mult).set_active(False) + else: + self.hud_params['aggregate_ring'] = True + self.hud_params['aggregate_tour'] = True + + if self.hud_params['agg_bb_mult'] != num \ + and getattr(self, 'aggBBmultItem'+str(num)).get_active(): + print 'set_opponent_aggregation', num + self.hud_params['agg_bb_mult'] = num + for mult in ('1', '2', '3', '10', '10000'): + if mult != str(num): + getattr(self, 'aggBBmultItem'+mult).set_active(False) def set_hud_style(self, widget, val): - # try setting these to true all the time, and set the multiplier to 1 to turn agg off: - if val[0] == 'H': + (player_opp, style) = val + if player_opp == 'P': param = 'h_hud_style' + prefix = 'h_' else: param = 'hud_style' + prefix = '' - if val[1] == 'A' and getattr(self, 'HAStyleOption').get_active(): + if style == 'A' and getattr(self, prefix+'hudStyleOptionA').get_active(): self.hud_params[param] = 'A' - getattr(self, 'HSStyleOption').set_active(False) - getattr(self, 'HTStyleOption').set_active(False) - elif val[1] == 'S' and getattr(self, 'HSStyleOption').get_active(): + getattr(self, prefix+'hudStyleOptionS').set_active(False) + getattr(self, prefix+'hudStyleOptionT').set_active(False) + elif style == 'S' and getattr(self, prefix+'hudStyleOptionS').get_active(): self.hud_params[param] = 'S' - getattr(self, 'HAStyleOption').set_active(False) - getattr(self, 'HTStyleOption').set_active(False) - elif val[1] == 'T' and self.HTStyleOption.get_active(): + getattr(self, prefix+'hudStyleOptionA').set_active(False) + getattr(self, prefix+'hudStyleOptionT').set_active(False) + elif style == 'T' and getattr(self, prefix+'hudStyleOptionT').get_active(): self.hud_params[param] = 'T' - getattr(self, 'HAStyleOption').set_active(False) - getattr(self, 'HSStyleOption').set_active(False) - print "setting self.hud_params[%s] = %s" % (param, val[1]) + getattr(self, prefix+'hudStyleOptionA').set_active(False) + getattr(self, prefix+'hudStyleOptionS').set_active(False) + print "setting self.hud_params[%s] = %s" % (param, style) def update_table_position(self): if os.name == 'nt': From 7900ebcebe429fe43a69c929ed6ea32222c797f8 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 4 Oct 2009 17:46:04 +0100 Subject: [PATCH 10/52] Tell user what is happening on startup --- pyfpdb/Configuration.py | 24 +++++++++++++++++++----- pyfpdb/fpdb.py | 9 ++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index b8022a45..a643696a 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -311,13 +311,21 @@ class Config: pass if file == None: # that didn't work either, just die - print "No HUD_config_xml found. Exiting" - sys.stderr.write("No HUD_config_xml found. Exiting") + print "No HUD_config_xml found after looking in current directory and "+self.default_config_path+"\nExiting" + sys.stderr.write("No HUD_config_xml found after looking in current directory and "+self.default_config_path+"\nExiting") + print "press enter to continue" + sys.stdin.readline() sys.exit() # Parse even if there was no real config file found and we are using the example # If using the example, we'll edit it later +# sc 2009/10/04 Example already copied to main filename, is this ok? log.info("Reading configuration file %s" % file) + if os.sep in file: + print "\nReading configuration file %s\n" % file + else: + print "\nReading configuration file %s" % file + print "in %s\n" % os.getcwd() try: doc = xml.dom.minidom.parse(file) except: @@ -405,6 +413,8 @@ class Config: db_pass = df_parms['db-password']) self.save(file=os.path.join(self.default_config_path, "HUD_config.xml")) + print "" + def set_hhArchiveBase(self, path): self.imp.node.setAttribute("hhArchiveBase", path) @@ -454,11 +464,15 @@ class Config: def find_example_config(self): if os.path.exists('HUD_config.xml.example'): # there is a HUD_config in the cwd - file = 'HUD_config.xml.example' # so we use it + file = 'HUD_config.xml' # so we use it + try: + shutil.copyfile(file+'.example', file) + except: + file = '' print "No HUD_config.xml found, using HUD_config.xml.example.\n", \ - "A HUD_config.xml will be written. You will probably have to edit it." + "A HUD_config.xml has been created. You will probably have to edit it." sys.stderr.write("No HUD_config.xml found, using HUD_config.xml.example.\n" + \ - "A HUD_config.xml will be written. You will probably have to edit it.") + "A HUD_config.xml has been created. You will probably have to edit it.") else: file = None return file diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 4703d96d..4065c243 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -453,7 +453,14 @@ class fpdb: self.db.disconnect() self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) - self.db = Database.Database(self.config, sql = self.sql) + try: + self.db = Database.Database(self.config, sql = self.sql) + except FpdbError: + print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']) + sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])) + except: + print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']) + sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])) if self.db.fdb.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) From 8851b141a2caea1780514ac90e3329b1490a07c1 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 5 Oct 2009 22:12:35 +0100 Subject: [PATCH 11/52] add dropdown to player name in filter --- pyfpdb/Database.py | 10 ++++++++++ pyfpdb/Filters.py | 12 +++++++++++- pyfpdb/SQL.py | 7 +++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index c923517e..c5421684 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -537,6 +537,16 @@ class Database: else: return None + def get_player_names(self, config, site_id=None, like_player_name="%"): + """Fetch player names from players. Use site_id and like_player_name if provided""" + + if site_id == None: + site_id = -1 + c = self.get_cursor() + c.execute(self.sql.query['get_player_names'], (like_player_name, site_id, site_id)) + rows = c.fetchall() + return rows + #returns the SQL ids of the names given in an array # TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict # { playername: id } instead of depending on it's relation to the positions list diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 9ded56b4..d4563059 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -23,6 +23,7 @@ import os import sys from optparse import OptionParser from time import * +import gobject #import pokereval import Configuration @@ -228,7 +229,16 @@ class Filters(threading.Thread): pname.set_width_chars(20) hbox.pack_start(pname, False, True, 0) pname.connect("changed", self.__set_hero_name, site) - #TODO: Look at GtkCompletion - to fill out usernames + + # Added EntryCompletion but maybe comboBoxEntry is more flexible? (e.g. multiple choices) + completion = gtk.EntryCompletion() + pname.set_completion(completion) + liststore = gtk.ListStore(gobject.TYPE_STRING) + completion.set_model(liststore) + completion.set_text_column(0) + names = self.db.get_player_names(self.conf) # (config=self.conf, site_id=None, like_player_name="%") + for n in names: + liststore.append(n) self.__set_hero_name(pname, site) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 0c551634..1145afec 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1235,6 +1235,13 @@ class Sql: and Players.siteId = Sites.id """ + self.query['get_player_names'] = """ + select p.name + from Players p + where lower(p.name) like lower(%s) + and (p.siteId = %s or %s = -1) + """ + self.query['getSiteId'] = """SELECT id from Sites where name = %s""" self.query['get_stats_from_hand'] = """ From 94af5b1ea82d707f689a70cfc5cf1b1c48d930c4 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 6 Oct 2009 12:08:20 +0800 Subject: [PATCH 12/52] Fix order bug for seats in NEWIMPORT --- pyfpdb/Database.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f5e947e1..3c8c21c4 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1419,9 +1419,8 @@ class Database: p['siteHandNo'], p['handStart'], datetime.today(), #importtime -# len(p['names']), #seats - p['maxSeats'], p['seats'], + p['maxSeats'], p['boardcard1'], p['boardcard2'], p['boardcard3'], From fdef5b12d9a2ea64b3e44617f2fb2f1112f6f3cb Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 6 Oct 2009 18:30:52 +0800 Subject: [PATCH 13/52] Add playersVpi to NEWIMPORT code Untested at the moment, moved the code from Hand.py into DerivedStats. --- pyfpdb/Database.py | 4 +-- pyfpdb/DerivedStats.py | 61 ++++++++++++++++++++++++++++++++++-------- pyfpdb/Hand.py | 58 +++++++++------------------------------ 3 files changed, 65 insertions(+), 58 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 3c8c21c4..22aeb677 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1382,6 +1382,7 @@ class Database: importtime, seats, maxseats, + playersVpi, boardcard1, boardcard2, boardcard3, @@ -1395,9 +1396,8 @@ class Database: ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s)""" + %s, %s, %s, %s, %s, %s, %s, %s)""" #--- texture, -#-- playersVpi, #-- playersAtStreet1, #-- playersAtStreet2, #-- playersAtStreet3, diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 3de15ee5..9f900ce0 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -106,6 +106,9 @@ class DerivedStats(): print "hands =", self.hands print "handsplayers =", self.handsplayers + def getHands(self): + return self.hands + def assembleHands(self, hand): self.hands['tableName'] = hand.tablename self.hands['siteHandNo'] = hand.handid @@ -114,17 +117,53 @@ class DerivedStats(): self.hands['importTime'] = None self.hands['seats'] = self.countPlayers(hand) self.hands['maxSeats'] = hand.maxseats - self.hands['boardcard1'] = None - self.hands['boardcard2'] = None - self.hands['boardcard3'] = None - self.hands['boardcard4'] = None - self.hands['boardcard5'] = None - boardCard = 1 - for street in hand.communityStreets: - for card in hand.board[street]: - self.hands['boardcard%s' % str(boardCard)] = Card.encodeCard(card) - boardCard += 1 + # This (i think...) is correct for both stud and flop games, as hand.board['street'] disappears, and + # those values remain default in stud. + boardcards = hand.board['FLOP'] + hand.board['TURN'] + hand.board['RIVER'] + [u'0x', u'0x', u'0x', u'0x', u'0x'] + cards = [Card.encodeCard(c) for c in boardcards[0:5]] + self.hands['boardcard1'] = cards[0] + self.hands['boardcard2'] = cards[1] + self.hands['boardcard3'] = cards[2] + self.hands['boardcard4'] = cards[3] + self.hands['boardcard5'] = cards[4] + + #print "DEBUG: self.getStreetTotals = (%s, %s, %s, %s, %s)" % hand.getStreetTotals() + #FIXME: Pot size still in decimal, needs to be converted to cents + (self.hands['street1Pot'], + self.hands['street2Pot'], + self.hands['street3Pot'], + self.hands['street4Pot'], + self.hands['showdownPot']) = hand.getStreetTotals() + + + self.vpip(hand) # Gives playersVpi (num of players vpip) + # texture smallint, + # playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */ + # Needs to be recorded + # playersAtStreet2 SMALLINT NOT NULL, + # Needs to be recorded + # playersAtStreet3 SMALLINT NOT NULL, + # Needs to be recorded + # playersAtStreet4 SMALLINT NOT NULL, + # Needs to be recorded + # playersAtShowdown SMALLINT NOT NULL, + # Needs to be recorded + # street0Raises TINYINT NOT NULL, /* num small bets paid to see flop/street4, including blind */ + # Needs to be recorded + # street1Raises TINYINT NOT NULL, /* num small bets paid to see turn/street5 */ + # Needs to be recorded + # street2Raises TINYINT NOT NULL, /* num big bets paid to see river/street6 */ + # Needs to be recorded + # street3Raises TINYINT NOT NULL, /* num big bets paid to see sd/street7 */ + # Needs to be recorded + # street4Raises TINYINT NOT NULL, /* num big bets paid to see showdown */ + # Needs to be recorded + + # comment TEXT, + # commentTs DATETIME + + def assembleHandsPlayers(self, hand): self.vpip(self.hand) @@ -157,4 +196,4 @@ class DerivedStats(): self.handsplayers[player[1]]['street%sAggr' % i] = False def countPlayers(self, hand): - pass \ No newline at end of file + pass diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 05ec3541..2527f636 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -194,64 +194,32 @@ dealt whether they were seen in a 'dealt to' line """ Function to insert Hand into database Should not commit, and do minimal selects. Callers may want to cache commits db: a connected fpdb_db object""" - # TODO: + + ##### + # Players, Gametypes, TourneyTypes are all shared functions that are needed for additional tables + # These functions are intended for prep insert eventually + ##### # Players - base playerid and siteid tuple sqlids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId) #Gametypes gtid = db.getGameTypeId(self.siteId, self.gametype) + self.stats.assembleHands(self) + + ##### + # End prep functions + ##### + # HudCache data to come from DerivedStats class # HandsActions - all actions for all players for all streets - self.actions + # Hands - Summary information of hand indexed by handId - gameinfo - #This should be moved to prepInsert - hh = {} - hh['siteHandNo'] = self.handid - hh['handStart'] = self.starttime + hh = self.stats.getHands() hh['gameTypeId'] = gtid # seats TINYINT NOT NULL, - hh['tableName'] = self.tablename - hh['maxSeats'] = self.maxseats hh['seats'] = len(sqlids) - # Flop turn and river may all be empty - add (likely) too many elements and trim with range - boardcards = self.board['FLOP'] + self.board['TURN'] + self.board['RIVER'] + [u'0x', u'0x', u'0x', u'0x', u'0x'] - cards = [Card.encodeCard(c) for c in boardcards[0:5]] - hh['boardcard1'] = cards[0] - hh['boardcard2'] = cards[1] - hh['boardcard3'] = cards[2] - hh['boardcard4'] = cards[3] - hh['boardcard5'] = cards[4] - # texture smallint, - # playersVpi SMALLINT NOT NULL, /* num of players vpi */ - # Needs to be recorded - # playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */ - # Needs to be recorded - # playersAtStreet2 SMALLINT NOT NULL, - # Needs to be recorded - # playersAtStreet3 SMALLINT NOT NULL, - # Needs to be recorded - # playersAtStreet4 SMALLINT NOT NULL, - # Needs to be recorded - # playersAtShowdown SMALLINT NOT NULL, - # Needs to be recorded - # street0Raises TINYINT NOT NULL, /* num small bets paid to see flop/street4, including blind */ - # Needs to be recorded - # street1Raises TINYINT NOT NULL, /* num small bets paid to see turn/street5 */ - # Needs to be recorded - # street2Raises TINYINT NOT NULL, /* num big bets paid to see river/street6 */ - # Needs to be recorded - # street3Raises TINYINT NOT NULL, /* num big bets paid to see sd/street7 */ - # Needs to be recorded - # street4Raises TINYINT NOT NULL, /* num big bets paid to see showdown */ - # Needs to be recorded - - #print "DEBUG: self.getStreetTotals = (%s, %s, %s, %s, %s)" % self.getStreetTotals() - #FIXME: Pot size still in decimal, needs to be converted to cents - (hh['street1Pot'], hh['street2Pot'], hh['street3Pot'], hh['street4Pot'], hh['showdownPot']) = self.getStreetTotals() - - # comment TEXT, - # commentTs DATETIME #print hh handid = db.storeHand(hh) # HandsPlayers - ? ... Do we fix winnings? From 024618235f68ab29ca9d2e4379332bcd76260b6a Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 7 Oct 2009 14:15:12 +0800 Subject: [PATCH 14/52] Clean up variables in DerivedStats Doesn't look like they are going to be used like that --- pyfpdb/DerivedStats.py | 70 ------------------------------------------ 1 file changed, 70 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 9f900ce0..ffc673b1 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -22,76 +22,6 @@ class DerivedStats(): def __init__(self, hand): self.hand = hand - self.activeSeats = 0 - self.position = 0 - self.tourneyTypeId = 0 - - self.HDs = 0 - self.street0VPI = 0 - self.street0Aggr = 0 - self.street0_3BChance = 0 - self.street0_3BDone = 0 - self.street0_4BChance = 0 - self.street0_4BDone = 0 - - self.street1Seen = 0 - self.street2Seen = 0 - self.street3Seen = 0 - self.street4Seen = 0 - self.sawShowdown = 0 - - self.street1Aggr = 0 - self.street2Aggr = 0 - self.street3Aggr = 0 - self.street4Aggr = 0 - - self.otherRaisedStreet1 = 0 - self.otherRaisedStreet2 = 0 - self.otherRaisedStreet3 = 0 - self.otherRaisedStreet4 = 0 - self.foldToOtherRaisedStreet1 = 0 - self.foldToOtherRaisedStreet2 = 0 - self.foldToOtherRaisedStreet3 = 0 - self.foldToOtherRaisedStreet4 = 0 - self.wonWhenSeenStreet1 = 0 - self.wonAtSD = 0 - - self.stealAttemptChance = 0 - self.stealAttempted = 0 - self.foldBbToStealChance = 0 - self.foldedBbToSteal = 0 - self.foldSbToStealChance = 0 - self.foldedSbToSteal = 0 - - self.street1CBChance = 0 - self.street1CBDone = 0 - self.street2CBChance = 0 - self.street2CBDone = 0 - self.street3CBChance = 0 - self.street3CBDone = 0 - self.street4CBChance = 0 - self.street4CBDone = 0 - - self.foldToStreet1CBChance = 0 - self.foldToStreet1CBDone = 0 - self.foldToStreet2CBChance = 0 - self.foldToStreet2CBDone = 0 - self.foldToStreet3CBChance = 0 - self.foldToStreet3CBDone = 0 - self.foldToStreet4CBChance = 0 - self.foldToStreet4CBDone = 0 - - self.totalProfit = 0 - - self.street1CheckCallRaiseChance = 0 - self.street1CheckCallRaiseDone = 0 - self.street2CheckCallRaiseChance = 0 - self.street2CheckCallRaiseDone = 0 - self.street3CheckCallRaiseChance = 0 - self.street3CheckCallRaiseDone = 0 - self.street4CheckCallRaiseChance = 0 - self.street4CheckCallRaiseDone = 0 - self.hands = {} self.handsplayers = {} From 7d708a327c958fcdc6cd5511eaffc0026d6cb57b Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 7 Oct 2009 23:45:59 +0100 Subject: [PATCH 15/52] try to fix aggBBmultItemAll error --- pyfpdb/Hud.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index ad42bb59..09f60700 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -258,7 +258,7 @@ class Hud: elif self.hud_params['h_agg_bb_mult'] == 10: getattr(self, 'h_aggBBmultItem10').set_active(True) elif self.hud_params['h_agg_bb_mult'] > 9000: - getattr(self, 'h_aggBBmultItemAll').set_active(True) + getattr(self, 'h_aggBBmultItem10000').set_active(True) # if self.hud_params['agg_bb_mult'] == 1: getattr(self, 'aggBBmultItem1').set_active(True) @@ -269,7 +269,7 @@ class Hud: elif self.hud_params['agg_bb_mult'] == 10: getattr(self, 'aggBBmultItem10').set_active(True) elif self.hud_params['agg_bb_mult'] > 9000: - getattr(self, 'aggBBmultItemAll').set_active(True) + getattr(self, 'aggBBmultItem10000').set_active(True) # if self.hud_params['h_hud_style'] == 'A': getattr(self, 'h_hudStyleOptionA').set_active(True) From 31f48c493279c0d8863a904c1f0e775882efcbf0 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 8 Oct 2009 18:01:49 +0800 Subject: [PATCH 16/52] [NEWIMPORT] Calculate playersAtStreetX Untested code. Still missing playersAtShowdown, haven't looked to see if hand.actionStreets contains showdown. --- pyfpdb/DerivedStats.py | 54 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index ffc673b1..a4fb630b 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -68,17 +68,10 @@ class DerivedStats(): self.vpip(hand) # Gives playersVpi (num of players vpip) + self.playersAtStreetX(hand) # Gives playersAtStreet1..4 and Showdown + # texture smallint, - # playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */ - # Needs to be recorded - # playersAtStreet2 SMALLINT NOT NULL, - # Needs to be recorded - # playersAtStreet3 SMALLINT NOT NULL, - # Needs to be recorded - # playersAtStreet4 SMALLINT NOT NULL, - # Needs to be recorded - # playersAtShowdown SMALLINT NOT NULL, - # Needs to be recorded + # street0Raises TINYINT NOT NULL, /* num small bets paid to see flop/street4, including blind */ # Needs to be recorded # street1Raises TINYINT NOT NULL, /* num small bets paid to see turn/street5 */ @@ -113,6 +106,47 @@ class DerivedStats(): self.handsplayers[player[1]]['vpip'] = False self.hands['playersVpi'] = len(vpipers) + def playersAtStreetX(self, hand): + """playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4/draw1 */""" + # self.actions[street] is a list of all actions in a tuple, contining the player name first + # [ (player, action, ....), (player2, action, ...) ] + # The number of unique players in the list per street gives the value for playersAtStreetXXX + + self.hands['playersAtStreet1'] = 0 + self.hands['playersAtStreet2'] = 0 + self.hands['playersAtStreet3'] = 0 + self.hands['playersAtStreet4'] = 0 + self.hands['playersAtShowdown'] = 0 + + for street in hand.actionStreets: + actors = {} + for act in a[street]: + actors[act[0]] = 1 + #print "len(actors.keys(%s)): %s" % ( street, len(actors.keys())) + if hand.gametype['base'] in ("hold"): + if street in "FLOP": self.hands['playersAtStreet1'] = len(actors.keys()) + elif street in "TURN": self.hands['playersAtStreet2'] = len(actors.keys()) + elif street in "RIVER": self.hands['playersAtStreet3'] = len(actors.keys()) + elif hand.gametype['base'] in ("stud"): + if street in "FOURTH": self.hands['playersAtStreet1'] = len(actors.keys()) + elif street in "FIFTH": self.hands['playersAtStreet2'] = len(actors.keys()) + elif street in "SIXTH": self.hands['playersAtStreet3'] = len(actors.keys()) + elif street in "SEVENTH": self.hands['playersAtStreet4'] = len(actors.keys()) + elif hand.gametype['base'] in ("draw"): + if street in "DRAWONE": self.hands['playersAtStreet1'] = len(actors.keys()) + elif street in "DRAWTWO": self.hands['playersAtStreet2'] = len(actors.keys()) + elif street in "DRAWTHREE": self.hands['playersAtStreet3'] = len(actors.keys()) + + #Need playersAtShowdown + + + def streetXRaises(self, hand): + # self.actions[street] is a list of all actions in a tuple, contining the action as the second element + # [ (player, action, ....), (player2, action, ...) ] + # No idea what this value is actually supposed to be + # In theory its "num small bets paid to see flop/street4, including blind" which makes sense for limit. Not so useful for nl + + def aggr(self, hand, i): aggrers = set() for act in hand.actions[hand.actionStreets[i]]: From cf6c3c8ad00075d166abb815d256130eaae63114 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 8 Oct 2009 18:07:54 +0800 Subject: [PATCH 17/52] [NEWIMPOR] Fix playersVpi from last patch Oops - forgot to add the argument --- pyfpdb/Database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 22aeb677..c798e72d 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1382,7 +1382,7 @@ class Database: importtime, seats, maxseats, - playersVpi, + playersVpi, boardcard1, boardcard2, boardcard3, @@ -1421,12 +1421,12 @@ class Database: datetime.today(), #importtime p['seats'], p['maxSeats'], + p['playersVpi'], p['boardcard1'], p['boardcard2'], p['boardcard3'], p['boardcard4'], p['boardcard5'], -# hudCache['playersVpi'], # hudCache['playersAtStreet1'], # hudCache['playersAtStreet2'], # hudCache['playersAtStreet3'], From 6d0ec5d8316682aea4069f7b925b0d1f791a57be Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 8 Oct 2009 18:13:13 +0800 Subject: [PATCH 18/52] [NEWIMPORT] Add playersAtStreetX to insert --- pyfpdb/Database.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index c798e72d..38c475d9 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1388,6 +1388,11 @@ class Database: boardcard3, boardcard4, boardcard5, + playersAtStreet1, + playersAtStreet2, + playersAtStreet3, + playersAtStreet4, + playersAtShowdown, street1Pot, street2Pot, street3Pot, @@ -1396,19 +1401,14 @@ class Database: ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s)""" + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s)""" #--- texture, -#-- playersAtStreet1, -#-- playersAtStreet2, -#-- playersAtStreet3, -#-- playersAtStreet4, -#-- playersAtShowdown, #-- street0Raises, #-- street1Raises, #-- street2Raises, #-- street3Raises, #-- street4Raises, -#-- seats, q = q.replace('%s', self.sql.query['placeholder']) print "DEBUG: p: %s" %p @@ -1427,11 +1427,11 @@ class Database: p['boardcard3'], p['boardcard4'], p['boardcard5'], -# hudCache['playersAtStreet1'], -# hudCache['playersAtStreet2'], -# hudCache['playersAtStreet3'], -# hudCache['playersAtStreet4'], -# hudCache['playersAtShowdown'], + p['playersAtStreet1'], + p['playersAtStreet2'], + p['playersAtStreet3'], + p['playersAtStreet4'], + p['playersAtShowdown'], # hudCache['street0Raises'], # hudCache['street1Raises'], # hudCache['street2Raises'], From ee864033ee09dfeda69c9ffe7256116f9650bca8 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Fri, 9 Oct 2009 07:31:25 -0400 Subject: [PATCH 19/52] Add exception for not being able to connect to MySQL, make use of it to pop up an error box --- pyfpdb/Exceptions.py | 3 +++ pyfpdb/fpdb.py | 9 +++++++-- pyfpdb/fpdb_db.py | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Exceptions.py b/pyfpdb/Exceptions.py index f3d75e89..eaf5d798 100644 --- a/pyfpdb/Exceptions.py +++ b/pyfpdb/Exceptions.py @@ -17,5 +17,8 @@ class FpdbParseError(FpdbError): class FpdbDatabaseError(FpdbError): pass +class FpdbMySQLFailedError(FpdbDatabaseError): + pass + class DuplicateError(FpdbError): pass diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 4703d96d..5d8d7191 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -76,7 +76,7 @@ import SQL import Database import FpdbSQLQueries import Configuration -from Exceptions import * +import Exceptions VERSION = "0.11" @@ -453,7 +453,12 @@ class fpdb: self.db.disconnect() self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) - self.db = Database.Database(self.config, sql = self.sql) + try: + self.db = Database.Database(self.config, sql = self.sql) + except Exceptions.FpdbMySQLFailedError: + self.warning_box("Unable to connect to MySQL! Is the MySQL server running?!", "FPDB ERROR") + exit() + if self.db.fdb.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 428aa173..17fecc2c 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -80,7 +80,7 @@ class fpdb_db: try: self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) except: - raise FpdbError("MySQL connection failed") + raise FpdbMySQLFailedError("MySQL connection failed") elif backend==fpdb_db.PGSQL: import psycopg2 import psycopg2.extensions From d4cbed121ddc135538615f24b4613701855fd197 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Fri, 9 Oct 2009 07:39:05 -0400 Subject: [PATCH 20/52] fix indentation errors --- pyfpdb/DerivedStats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index a4fb630b..7d428be9 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -107,7 +107,7 @@ class DerivedStats(): self.hands['playersVpi'] = len(vpipers) def playersAtStreetX(self, hand): - """playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4/draw1 */""" + """ playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4/draw1 */""" # self.actions[street] is a list of all actions in a tuple, contining the player name first # [ (player, action, ....), (player2, action, ...) ] # The number of unique players in the list per street gives the value for playersAtStreetXXX @@ -145,7 +145,7 @@ class DerivedStats(): # [ (player, action, ....), (player2, action, ...) ] # No idea what this value is actually supposed to be # In theory its "num small bets paid to see flop/street4, including blind" which makes sense for limit. Not so useful for nl - + pass def aggr(self, hand, i): aggrers = set() From b8be20f5513d43941d74a6616972b9ffbd24cbce Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 11 Oct 2009 22:44:52 +0100 Subject: [PATCH 21/52] show nl and fl limits separately in filter --- pyfpdb/Filters.py | 65 +++++++++++++++++++++++----- pyfpdb/GuiPlayerStats.py | 44 ++++++++++++------- pyfpdb/SQL.py | 92 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 171 insertions(+), 30 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index d4563059..cb5ad6f2 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -54,6 +54,7 @@ class Filters(threading.Thread): ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' + ,'limitsFL':'FL', 'limitsNL':'NL' } # For use in date ranges. @@ -98,6 +99,8 @@ class Filters(threading.Thread): self.cbLimits = {} self.cbNoLimits = None self.cbAllLimits = None + self.cbFL = None + self.cbNL = None self.fillLimitsFrame(vbox, self.display) limitsFrame.add(vbox) @@ -288,12 +291,29 @@ class Filters(threading.Thread): self.cbAllLimits.set_active(False) elif limit == "all": if self.limits[limit]: - for cb in self.cbLimits.values(): - cb.set_active(True) + #for cb in self.cbLimits.values(): + # cb.set_active(True) + if self.cbFL != None: + self.cbFL.set_active(True) + if self.cbNL != None: + self.cbNL.set_active(True) elif limit == "none": if self.limits[limit]: for cb in self.cbLimits.values(): cb.set_active(False) + self.cbNL.set_active(False) + self.cbFL.set_active(False) + elif limit == "fl": + for cb in self.cbLimits.values(): + #print "cb label: ", cb.children()[0].get_text() + if cb.get_children()[0].get_text().isdigit(): + cb.set_active(self.limits[limit]) + + elif limit == "nl": + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "nl" in t and len(t) > 2: + cb.set_active(self.limits[limit]) def __set_seat_select(self, w, seat): #print "__set_seat_select: seat =", seat, "active =", w.get_active() @@ -352,8 +372,10 @@ class Filters(threading.Thread): vbox.pack_start(vbox1, False, False, 0) self.boxes['limits'] = vbox1 - self.cursor.execute(self.sql.query['getLimits']) + self.cursor.execute(self.sql.query['getLimits2']) + # selects limitType, bigBlind result = self.db.cursor.fetchall() + fl, nl = False, False if len(result) >= 1: hbox = gtk.HBox(True, 0) vbox1.pack_start(hbox, False, False, 0) @@ -367,17 +389,37 @@ class Filters(threading.Thread): vbox2.pack_start(hbox, False, False, 0) else: vbox3.pack_start(hbox, False, False, 0) - self.cbLimits[line[0]] = self.createLimitLine(hbox, line[0], line[0]) + if line[0] == 'fl': + self.cbLimits[line[1]] = self.createLimitLine(hbox, str(line[1]), str(line[1])) + fl = True + else: + self.cbLimits[str(line[1])+line[0]] = self.createLimitLine(hbox, str(line[1])+line[0], str(line[1])+line[0]) + nl = True if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: + hbox = gtk.HBox(True, 0) + vbox1.pack_start(hbox, False, False, 0) + vbox2 = gtk.VBox(False, 0) + hbox.pack_start(vbox2, False, False, 0) + vbox3 = gtk.VBox(False, 0) + hbox.pack_start(vbox3, False, False, 0) + hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) + vbox2.pack_start(hbox, False, False, 0) self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall']) hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) + vbox2.pack_start(hbox, False, False, 0) self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow']) + + if "LimitType" in display and display["LimitType"] == True and len(result) >= 2: + if fl: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL']) + if nl: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL']) + else: print "INFO: No games returned from database" @@ -439,8 +481,11 @@ class Filters(threading.Thread): self.boxes['groups'] = vbox1 hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) + vbox1.pack_start(hbox, False, False, 0) + cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow']) + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) cb = gtk.CheckButton(self.filterText['posnshow']) cb.connect('clicked', self.__set_group_select, 'posn') hbox.pack_start(cb, False, False, 0) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index add46bef..007ab4dd 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -54,17 +54,18 @@ class GuiPlayerStats (threading.Thread): self.filterText = {'handhead':'Hand Breakdown for all levels listed above' } - filters_display = { "Heroes" : True, - "Sites" : True, - "Games" : False, - "Limits" : True, - "LimitSep" : True, - "Seats" : True, - "SeatSep" : True, - "Dates" : True, - "Groups" : True, - "Button1" : True, - "Button2" : True + filters_display = { "Heroes" : True, + "Sites" : True, + "Games" : False, + "Limits" : True, + "LimitSep" : True, + "LimitType" : True, + "Seats" : True, + "SeatSep" : True, + "Dates" : True, + "Groups" : True, + "Button1" : True, + "Button2" : True } self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) @@ -344,13 +345,26 @@ class GuiPlayerStats (threading.Thread): query = query.replace('', '') query = query.replace('', '') - if [x for x in limits if str(x).isdigit()]: - blindtest = str(tuple([x for x in limits if str(x).isdigit()])) + lims = [int(x) for x in limits if x.isdigit()] + nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl'] + bbtest = "and ( (gt.limitType = 'fl' and gt.bigBlind in " + # and ( (limit and bb in()) or (nolimit and bb in ()) ) + if lims: + blindtest = str(tuple(lims)) blindtest = blindtest.replace("L", "") blindtest = blindtest.replace(",)",")") - query = query.replace("", " and gt.bigBlind in " + blindtest + " ") + bbtest = bbtest + blindtest + ' ) ' else: - query = query.replace("", "") + bbtest = bbtest + '(-1) ) ' + bbtest = bbtest + " or (gt.limitType = 'nl' and gt.bigBlind in " + if nolims: + blindtest = str(tuple(nolims)) + blindtest = blindtest.replace("L", "") + blindtest = blindtest.replace(",)",")") + bbtest = bbtest + blindtest + ' ) )' + else: + bbtest = bbtest + '(-1) ) )' + query = query.replace("", bbtest) if holecards: # pinch level variables for hole card query query = query.replace("", "hp.startcards") diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 1145afec..51ae1a1e 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1720,6 +1720,9 @@ class Sql: self.query['getSiteId'] = """SELECT id from Sites where name = %s""" self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC""" + self.query['getLimits2'] = """SELECT DISTINCT limitType, bigBlind + from Gametypes + ORDER by bigBlind DESC""" if db_server == 'mysql': self.query['playerDetailedStats'] = """ @@ -1775,7 +1778,7 @@ class Sql: inner join Gametypes gt on (gt.Id = h.gameTypeId) inner join Sites s on (s.Id = gt.siteId) where hp.playerId in - and hp.tourneysPlayersId IS NULL + /*and hp.tourneysPlayersId IS NULL*/ and h.seats @@ -1801,7 +1804,7 @@ class Sql: ,upper(gt.limitType) ,s.name """ - else: # assume postgresql + elif db_server == 'postgresql': self.query['playerDetailedStats'] = """ select AS hgametypeid ,gt.base @@ -1855,7 +1858,88 @@ class Sql: inner join Gametypes gt on (gt.Id = h.gameTypeId) inner join Sites s on (s.Id = gt.siteId) where hp.playerId in - and hp.tourneysPlayersId IS NULL + /*and hp.tourneysPlayersId IS NULL*/ + and h.seats + + + and to_char(h.handStart, 'YYYY-MM-DD') + group by hgameTypeId + ,hp.playerId + ,gt.base + ,gt.category + + ,plposition + ,upper(gt.limitType) + ,s.name + order by hp.playerId + ,gt.base + ,gt.category + + ,case when 'B' then 'B' + when 'S' then 'S' + when '0' then 'Y' + else 'Z'|| + end + + ,maxbigblind desc + ,upper(gt.limitType) + ,s.name + """ + elif db_server == 'sqlite': + self.query['playerDetailedStats'] = """ + select AS hgametypeid + ,gt.base + ,gt.category + ,upper(gt.limitType) AS limittype + ,s.name + ,min(gt.bigBlind) AS minbigblind + ,max(gt.bigBlind) AS maxbigblind + /*, AS gtid*/ + , AS plposition + ,count(1) AS n + ,100.0*sum(cast(hp.street0VPI as integer))/count(1) AS vpip + ,100.0*sum(cast(hp.street0Aggr as integer))/count(1) AS pfr + ,case when sum(cast(hp.street0_3Bchance as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street0_3Bdone as integer))/sum(cast(hp.street0_3Bchance as integer)) + end AS pf3 + ,case when sum(cast(hp.stealattemptchance as integer)) = 0 then -999 + else 100.0*sum(cast(hp.stealattempted as integer))/sum(cast(hp.stealattemptchance as integer)) + end AS steals + ,100.0*sum(cast(hp.street1Seen as integer))/count(1) AS saw_f + ,100.0*sum(cast(hp.sawShowdown as integer))/count(1) AS sawsd + ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.sawShowdown as integer))/sum(cast(hp.street1Seen as integer)) + end AS wtsdwsf + ,case when sum(cast(hp.sawShowdown as integer)) = 0 then -999 + else 100.0*sum(cast(hp.wonAtSD as integer))/sum(cast(hp.sawShowdown as integer)) + end AS wmsd + ,case when sum(cast(hp.street1Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street1Aggr as integer))/sum(cast(hp.street1Seen as integer)) + end AS flafq + ,case when sum(cast(hp.street2Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street2Aggr as integer))/sum(cast(hp.street2Seen as integer)) + end AS tuafq + ,case when sum(cast(hp.street3Seen as integer)) = 0 then -999 + else 100.0*sum(cast(hp.street3Aggr as integer))/sum(cast(hp.street3Seen as integer)) + end AS rvafq + ,case when sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer)) = 0 then -999 + else 100.0*(sum(cast(hp.street1Aggr as integer))+sum(cast(hp.street2Aggr as integer))+sum(cast(hp.street3Aggr as integer))) + /(sum(cast(hp.street1Seen as integer))+sum(cast(hp.street2Seen as integer))+sum(cast(hp.street3Seen as integer))) + end AS pofafq + ,sum(hp.totalProfit)/100.0 AS net + ,sum(hp.rake)/100.0 AS rake + ,100.0*avg(hp.totalProfit/(gt.bigBlind+0.0)) AS bbper100 + ,avg(hp.totalProfit)/100.0 AS profitperhand + ,100.0*avg((hp.totalProfit+hp.rake)/(gt.bigBlind+0.0)) AS bb100xr + ,avg((hp.totalProfit+hp.rake)/100.0) AS profhndxr + ,avg(h.seats+0.0) AS avgseats + ,variance(hp.totalProfit/100.0) AS variance + from HandsPlayers hp + inner join Hands h on (h.id = hp.handId) + inner join Gametypes gt on (gt.Id = h.gameTypeId) + inner join Sites s on (s.Id = gt.siteId) + where hp.playerId in + /*and hp.tourneysPlayersId IS NULL*/ and h.seats @@ -1882,8 +1966,6 @@ class Sql: ,upper(gt.limitType) ,s.name """ - #elif db_server == 'sqlite': - # self.query['playerDetailedStats'] = """ """ if db_server == 'mysql': self.query['playerStats'] = """ From b14fd2553c9e19a160341aae206d5fac380f86d2 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 11 Oct 2009 23:34:05 +0100 Subject: [PATCH 22/52] add some debug for session stats - I think there is a bug in here somewhere that makes it include too many hands sometimes ... --- pyfpdb/Database.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index c5421684..36e52d83 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -431,6 +431,11 @@ class Database: 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) + try: + print "Session: hero_id =", hero_id, "hds =", stat_dict[hero_id]['n'] + except: + pass + if hud_style == 'S' and h_hud_style == 'S': return stat_dict @@ -452,7 +457,7 @@ class Database: #elif h_hud_style == 'H': # h_stylekey = date_nhands_ago needs array by player here ... - #if aggregate: always use aggreagte query now: use agg_bb_mult of 1 for no aggregation: + #if aggregate: always use aggregate 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 @@ -474,6 +479,10 @@ class Database: t_dict[name.lower()] = val # print t_dict stat_dict[t_dict['player_id']] = t_dict + try: + print "get_stats end: hero_id =", hero_id, "hds =", stat_dict[hero_id]['n'] + except: + pass return stat_dict From 181294ddf4507f791f54431002165864bb4cfb1e Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 11 Oct 2009 23:36:26 +0100 Subject: [PATCH 23/52] tidy up Filters and PlayerStats layout a bit --- pyfpdb/Filters.py | 18 +++++++++--------- pyfpdb/SQL.py | 10 +++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index cb5ad6f2..2a02aedf 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -453,15 +453,6 @@ class Filters(threading.Thread): hbox.pack_start(lbl_to, expand=False, padding=3) hbox.pack_start(sb2, False, False, 0) - if "SeatSep" in display and display["SeatSep"] == True: - hbox = gtk.HBox(False, 0) - vbox1.pack_start(hbox, False, True, 0) - cb = gtk.CheckButton(self.filterText['seatsshow']) - cb.connect('clicked', self.__set_seat_select, 'show') - hbox.pack_start(cb, False, False, 0) - self.sbSeats['show'] = cb - self.seats['show'] = False - self.sbSeats['from'] = sb1 self.sbSeats['to'] = sb2 @@ -492,6 +483,15 @@ class Filters(threading.Thread): self.sbGroups['posn'] = cb self.groups['posn'] = False + if "SeatSep" in display and display["SeatSep"] == True: + hbox = gtk.HBox(False, 0) + vbox1.pack_start(hbox, False, True, 0) + cb = gtk.CheckButton(self.filterText['seatsshow']) + cb.connect('clicked', self.__set_seat_select, 'show') + hbox.pack_start(cb, False, False, 0) + self.sbSeats['show'] = cb + self.seats['show'] = False + def fillCardsFrame(self, vbox): hbox1 = gtk.HBox(True,0) hbox1.show() diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 51ae1a1e..9279126e 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1721,8 +1721,8 @@ class Sql: self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC""" self.query['getLimits2'] = """SELECT DISTINCT limitType, bigBlind - from Gametypes - ORDER by bigBlind DESC""" + from Gametypes + ORDER by limitType DESC, bigBlind DESC""" if db_server == 'mysql': self.query['playerDetailedStats'] = """ @@ -1800,8 +1800,8 @@ class Sql: else concat('Z', ) end + ,upper(gt.limitType) desc ,maxbigblind desc - ,upper(gt.limitType) ,s.name """ elif db_server == 'postgresql': @@ -1881,8 +1881,8 @@ class Sql: else 'Z'|| end + ,upper(gt.limitType) desc ,maxbigblind desc - ,upper(gt.limitType) ,s.name """ elif db_server == 'sqlite': @@ -1962,8 +1962,8 @@ class Sql: else 'Z'|| end + ,upper(gt.limitType) desc ,maxbigblind desc - ,upper(gt.limitType) ,s.name """ From aaba84de191e8a6904d3a15e95797d3d955c2c94 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 12 Oct 2009 23:02:20 +0100 Subject: [PATCH 24/52] Add ring/tourney radio button to filter --- pyfpdb/Filters.py | 139 ++++++++++++++++++++++++++++++++------- pyfpdb/GuiPlayerStats.py | 22 ++++--- pyfpdb/SQL.py | 4 +- 3 files changed, 130 insertions(+), 35 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 2a02aedf..ac036cbf 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -54,7 +54,7 @@ class Filters(threading.Thread): ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' - ,'limitsFL':'FL', 'limitsNL':'NL' + ,'limitsFL':'FL', 'limitsNL':'NL', 'ring':'Ring', 'tour':'Tourney' } # For use in date ranges. @@ -101,6 +101,9 @@ class Filters(threading.Thread): self.cbAllLimits = None self.cbFL = None self.cbNL = None + self.rb = {} # radio buttons for ring/tour + self.type = None # ring/tour + self.types = {} # list of all ring/tour values self.fillLimitsFrame(vbox, self.display) limitsFrame.add(vbox) @@ -193,6 +196,9 @@ class Filters(threading.Thread): ltuple.append(l) return ltuple + def getType(self): + return(self.type) + def getSeats(self): if 'from' in self.sbSeats: self.seats['from'] = self.sbSeats['from'].get_value_as_int() @@ -282,13 +288,18 @@ class Filters(threading.Thread): #print w.get_active() self.limits[limit] = w.get_active() print "self.limit[%s] set to %s" %(limit, self.limits[limit]) - if str(limit).isdigit(): + if limit.isdigit() or (len(limit) > 2 and limit[-2:] == 'nl'): if self.limits[limit]: if self.cbNoLimits != None: self.cbNoLimits.set_active(False) else: if self.cbAllLimits != None: self.cbAllLimits.set_active(False) + if not self.limits[limit]: + if limit.isdigit(): + self.cbFL.set_active(False) + else: + self.cbNL.set_active(False) elif limit == "all": if self.limits[limit]: #for cb in self.cbLimits.values(): @@ -304,16 +315,72 @@ class Filters(threading.Thread): self.cbNL.set_active(False) self.cbFL.set_active(False) elif limit == "fl": + if not self.limits[limit]: + # only toggle all fl limits off if they are all currently on + # this stops turning one off from cascading into 'fl' box off + # and then all fl limits being turned off + all_fl_on = True + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if t.isdigit(): + if not cb.get_active(): + all_fl_on = False + found = {'ring':False, 'tour':False} for cb in self.cbLimits.values(): #print "cb label: ", cb.children()[0].get_text() - if cb.get_children()[0].get_text().isdigit(): - cb.set_active(self.limits[limit]) - + t = cb.get_children()[0].get_text() + if t.isdigit(): + if self.limits[limit] or all_fl_on: + cb.set_active(self.limits[limit]) + found[self.types[t]] = True + if self.limits[limit]: + if not found[self.type]: + if self.type == 'ring': + if 'tour' in self.rb: + self.rb['tour'].set_active(True) + elif self.type == 'tour': + if 'ring' in self.rb: + self.rb['ring'].set_active(True) elif limit == "nl": + if not self.limits[limit]: + # only toggle all nl limits off if they are all currently on + # this stops turning one off from cascading into 'nl' box off + # and then all nl limits being turned off + all_nl_on = True + for cb in self.cbLimits.values(): + t = cb.get_children()[0].get_text() + if "nl" in t and len(t) > 2: + if not cb.get_active(): + all_nl_on = False + found = {'ring':False, 'tour':False} for cb in self.cbLimits.values(): t = cb.get_children()[0].get_text() if "nl" in t and len(t) > 2: - cb.set_active(self.limits[limit]) + if self.limits[limit] or all_nl_on: + cb.set_active(self.limits[limit]) + found[self.types[t]] = True + if self.limits[limit]: + if not found[self.type]: + if self.type == 'ring': + self.rb['tour'].set_active(True) + elif self.type == 'tour': + self.rb['ring'].set_active(True) + elif limit == "ring": + print "set", limit, "to", self.limits[limit] + if self.limits[limit]: + self.type = "ring" + for cb in self.cbLimits.values(): + #print "cb label: ", cb.children()[0].get_text() + if self.types[cb.get_children()[0].get_text()] == 'tour': + cb.set_active(False) + elif limit == "tour": + print "set", limit, "to", self.limits[limit] + if self.limits[limit]: + self.type = "tour" + for cb in self.cbLimits.values(): + #print "cb label: ", cb.children()[0].get_text() + if self.types[cb.get_children()[0].get_text()] == 'ring': + cb.set_active(False) def __set_seat_select(self, w, seat): #print "__set_seat_select: seat =", seat, "active =", w.get_active() @@ -358,15 +425,14 @@ class Filters(threading.Thread): print "INFO: No games returned from database" def fillLimitsFrame(self, vbox, display): - hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, False, 0) + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) lbl_title = gtk.Label(self.filterText['limitstitle']) lbl_title.set_alignment(xalign=0.0, yalign=0.5) - hbox.pack_start(lbl_title, expand=True, padding=3) + top_hbox.pack_start(lbl_title, expand=True, padding=3) showb = gtk.Button(label="hide", stock=None, use_underline=True) showb.set_alignment(xalign=1.0, yalign=0.5) showb.connect('clicked', self.__toggle_box, 'limits') - hbox.pack_start(showb, expand=False, padding=1) vbox1 = gtk.VBox(False, 0) vbox.pack_start(vbox1, False, False, 0) @@ -383,18 +449,23 @@ class Filters(threading.Thread): hbox.pack_start(vbox2, False, False, 0) vbox3 = gtk.VBox(False, 0) hbox.pack_start(vbox3, False, False, 0) + found = {'nl':False, 'fl':False, 'ring':False, 'tour':False} for i, line in enumerate(result): hbox = gtk.HBox(False, 0) if i <= len(result)/2: vbox2.pack_start(hbox, False, False, 0) else: vbox3.pack_start(hbox, False, False, 0) - if line[0] == 'fl': - self.cbLimits[line[1]] = self.createLimitLine(hbox, str(line[1]), str(line[1])) - fl = True + if line[1] == 'fl': + name = str(line[2]) + found['fl'] = True else: - self.cbLimits[str(line[1])+line[0]] = self.createLimitLine(hbox, str(line[1])+line[0], str(line[1])+line[0]) - nl = True + name = str(line[2])+line[1] + found['nl'] = True + self.cbLimits[name] = self.createLimitLine(hbox, name, name) + self.types[name] = line[0] + found[line[0]] = True # type is ring/tour + self.type = line[0] # if only one type, set it now if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2: hbox = gtk.HBox(True, 0) vbox1.pack_start(hbox, False, False, 0) @@ -410,19 +481,37 @@ class Filters(threading.Thread): vbox2.pack_start(hbox, False, False, 0) self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone']) - if "LimitType" in display and display["LimitType"] == True and len(result) >= 2: - if fl: - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL']) - if nl: - hbox = gtk.HBox(False, 0) - vbox3.pack_start(hbox, False, False, 0) - self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL']) - + dest = vbox3 # for ring/tour buttons + if "LimitType" in display and display["LimitType"] == True and found['nl'] and found['fl']: + #if found['fl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbFL = self.createLimitLine(hbox, 'fl', self.filterText['limitsFL']) + #if found['nl']: + hbox = gtk.HBox(False, 0) + vbox3.pack_start(hbox, False, False, 0) + self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL']) + dest = vbox2 # for ring/tour buttons else: print "INFO: No games returned from database" + if "Type" in display and display["Type"] == True and found['ring'] and found['tour']: + rb1 = gtk.RadioButton(None, self.filterText['ring']) + rb1.connect('clicked', self.__set_limit_select, 'ring') + rb2 = gtk.RadioButton(rb1, self.filterText['tour']) + rb2.connect('clicked', self.__set_limit_select, 'tour') + top_hbox.pack_start(rb1, False, False, 0) # (child, expand, fill, padding) + top_hbox.pack_start(rb2, True, True, 0) # child uses expand space if fill is true + + self.rb['ring'] = rb1 + self.rb['tour'] = rb2 + #print "about to set ring to true" + rb1.set_active(True) + # set_active doesn't seem to call this for some reason so call manually: + self.__set_limit_select(rb1, 'ring') + self.type = 'ring' + top_hbox.pack_start(showb, expand=False, padding=1) + def fillSeatsFrame(self, vbox, display): hbox = gtk.HBox(False, 0) vbox.pack_start(hbox, False, False, 0) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 007ab4dd..4b82c861 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -60,6 +60,7 @@ class GuiPlayerStats (threading.Thread): "Limits" : True, "LimitSep" : True, "LimitType" : True, + "Type" : True, "Seats" : True, "SeatSep" : True, "Dates" : True, @@ -158,6 +159,7 @@ class GuiPlayerStats (threading.Thread): heroes = self.filters.getHeroes() siteids = self.filters.getSiteIds() limits = self.filters.getLimits() + type = self.filters.getType() seats = self.filters.getSeats() groups = self.filters.getGroups() dates = self.filters.getDates() @@ -186,16 +188,16 @@ class GuiPlayerStats (threading.Thread): print "No limits found" return - self.createStatsTable(vbox, playerids, sitenos, limits, seats, groups, dates) + self.createStatsTable(vbox, playerids, sitenos, limits, type, seats, groups, dates) - def createStatsTable(self, vbox, playerids, sitenos, limits, seats, groups, dates): + def createStatsTable(self, vbox, playerids, sitenos, limits, type, seats, groups, dates): starttime = time() # Display summary table at top of page # 3rd parameter passes extra flags, currently includes: # holecards - whether to display card breakdown (True/False) flags = [False] - self.addTable(vbox, 'playerDetailedStats', flags, playerids, sitenos, limits, seats, groups, dates) + self.addTable(vbox, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) # Separator sep = gtk.HSeparator() @@ -218,13 +220,13 @@ class GuiPlayerStats (threading.Thread): # Detailed table flags = [True] - self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, seats, groups, dates) + self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) self.db.rollback() print "Stats page displayed in %4.2f seconds" % (time() - starttime) #end def fillStatsFrame(self, vbox): - def addTable(self, vbox, query, flags, playerids, sitenos, limits, seats, groups, dates): + def addTable(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates): row = 0 sqlrow = 0 colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 @@ -232,7 +234,7 @@ class GuiPlayerStats (threading.Thread): else: holecards = flags[0] tmp = self.sql.query[query] - tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats, groups, dates) + tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates) self.cursor.execute(tmp) result = self.cursor.fetchall() colnames = [desc[0].lower() for desc in self.cursor.description] @@ -318,9 +320,9 @@ class GuiPlayerStats (threading.Thread): row += 1 vbox.show_all() - #end def addTable(self, query, vars, playerids, sitenos, limits, seats): + #end def addTable(self, query, vars, playerids, sitenos, limits, type, seats, groups, dates): - def refineQuery(self, query, flags, playerids, sitenos, limits, seats, groups, dates): + def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates): if not flags: holecards = False else: holecards = flags[0] @@ -364,6 +366,10 @@ class GuiPlayerStats (threading.Thread): bbtest = bbtest + blindtest + ' ) )' else: bbtest = bbtest + '(-1) ) )' + if type == 'ring': + bbtest = bbtest + " and gt.type = 'ring' " + elif type == 'tour': + bbtest = bbtest + " and gt.type = 'tour' " query = query.replace("", bbtest) if holecards: # pinch level variables for hole card query diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 9279126e..0f414e41 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1720,9 +1720,9 @@ class Sql: self.query['getSiteId'] = """SELECT id from Sites where name = %s""" self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC""" - self.query['getLimits2'] = """SELECT DISTINCT limitType, bigBlind + self.query['getLimits2'] = """SELECT DISTINCT type, limitType, bigBlind from Gametypes - ORDER by limitType DESC, bigBlind DESC""" + ORDER by type, limitType DESC, bigBlind DESC""" if db_server == 'mysql': self.query['playerDetailedStats'] = """ From 1d0177f6d47a93666f642334aa9438960c2475b8 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 13 Oct 2009 14:04:19 +0800 Subject: [PATCH 25/52] [NEWIMPORT] Finish up Hand import Decided to leave streetXRaisesN alone for the moment --- pyfpdb/Database.py | 25 +++++++++++++------------ pyfpdb/DerivedStats.py | 28 +++++++++------------------- pyfpdb/fpdb.py | 0 3 files changed, 22 insertions(+), 31 deletions(-) mode change 100644 => 100755 pyfpdb/fpdb.py diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index e05a38b8..60ce39aa 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1391,6 +1391,7 @@ class Database: importtime, seats, maxseats, + texture, playersVpi, boardcard1, boardcard2, @@ -1402,6 +1403,11 @@ class Database: playersAtStreet3, playersAtStreet4, playersAtShowdown, + street0Raises, + street1Raises, + street2Raises, + street3Raises, + street4Raises, street1Pot, street2Pot, street3Pot, @@ -1411,13 +1417,7 @@ class Database: VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s)""" -#--- texture, -#-- street0Raises, -#-- street1Raises, -#-- street2Raises, -#-- street3Raises, -#-- street4Raises, + %s, %s, %s, %s, %s, %s, %s, %s, %s)""" q = q.replace('%s', self.sql.query['placeholder']) print "DEBUG: p: %s" %p @@ -1430,6 +1430,7 @@ class Database: datetime.today(), #importtime p['seats'], p['maxSeats'], + p['texture'], p['playersVpi'], p['boardcard1'], p['boardcard2'], @@ -1441,11 +1442,11 @@ class Database: p['playersAtStreet3'], p['playersAtStreet4'], p['playersAtShowdown'], -# hudCache['street0Raises'], -# hudCache['street1Raises'], -# hudCache['street2Raises'], -# hudCache['street3Raises'], -# hudCache['street4Raises'], + p['street0Raises'], + p['street1Raises'], + p['street2Raises'], + p['street3Raises'], + p['street4Raises'], p['street1Pot'], p['street2Pot'], p['street3Pot'], diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 7d428be9..fa85df14 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -47,6 +47,7 @@ class DerivedStats(): self.hands['importTime'] = None self.hands['seats'] = self.countPlayers(hand) self.hands['maxSeats'] = hand.maxseats + self.hands['texture'] = None # No calculation done for this yet. # This (i think...) is correct for both stud and flop games, as hand.board['street'] disappears, and # those values remain default in stud. @@ -66,27 +67,11 @@ class DerivedStats(): self.hands['street4Pot'], self.hands['showdownPot']) = hand.getStreetTotals() - self.vpip(hand) # Gives playersVpi (num of players vpip) self.playersAtStreetX(hand) # Gives playersAtStreet1..4 and Showdown - # texture smallint, - - # street0Raises TINYINT NOT NULL, /* num small bets paid to see flop/street4, including blind */ - # Needs to be recorded - # street1Raises TINYINT NOT NULL, /* num small bets paid to see turn/street5 */ - # Needs to be recorded - # street2Raises TINYINT NOT NULL, /* num big bets paid to see river/street6 */ - # Needs to be recorded - # street3Raises TINYINT NOT NULL, /* num big bets paid to see sd/street7 */ - # Needs to be recorded - # street4Raises TINYINT NOT NULL, /* num big bets paid to see showdown */ - # Needs to be recorded - - # comment TEXT, - # commentTs DATETIME - - + # comment TEXT, + # commentTs DATETIME def assembleHandsPlayers(self, hand): self.vpip(self.hand) @@ -145,7 +130,12 @@ class DerivedStats(): # [ (player, action, ....), (player2, action, ...) ] # No idea what this value is actually supposed to be # In theory its "num small bets paid to see flop/street4, including blind" which makes sense for limit. Not so useful for nl - pass + # Leaving empty for the moment, + self.hands['street0Raises'] = 0 # /* num small bets paid to see flop/street4, including blind */ + self.hands['street1Raises'] = 0 # /* num small bets paid to see turn/street5 */ + self.hands['street2Raises'] = 0 # /* num big bets paid to see river/street6 */ + self.hands['street3Raises'] = 0 # /* num big bets paid to see sd/street7 */ + self.hands['street4Raises'] = 0 # /* num big bets paid to see showdown */ def aggr(self, hand, i): aggrers = set() diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py old mode 100644 new mode 100755 From 00a85936316259b9cde846aa40fc5a0ac2ffbe5f Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 13 Oct 2009 14:12:25 +0800 Subject: [PATCH 26/52] Fix table re-create bug in fillDefaultData --- pyfpdb/Database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 60ce39aa..b283a716 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1152,7 +1152,7 @@ class Database: elif self.backend == self.MYSQL_INNODB: c.execute("""insert into TourneyTypes(id, siteId, buyin, fee, maxSeats, knockout ,rebuyOrAddon, speed, headsUp, shootout, matrix) - values (1, 0, 0, 0, False, False, null, False, False, False);""") + values (DEFAULT, 1, 0, 0, 0, False, False, null, False, False, False);""") #end def fillDefaultData From f4887235a071c66c1f5f1ccc5d322dfe72afd15d Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 13 Oct 2009 15:58:05 +0800 Subject: [PATCH 27/52] [NEWIMPORT] Fix Hand import so it runs Also comment out some debug --- pyfpdb/DerivedStats.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index fa85df14..0140f49f 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -68,7 +68,10 @@ class DerivedStats(): self.hands['showdownPot']) = hand.getStreetTotals() self.vpip(hand) # Gives playersVpi (num of players vpip) + #print "DEBUG: vpip: %s" %(self.hands['playersVpi']) self.playersAtStreetX(hand) # Gives playersAtStreet1..4 and Showdown + #print "DEBUG: playersAtStreet 1:'%s' 2:'%s' 3:'%s' 4:'%s'" %(self.hands['playersAtStreet1'],self.hands['playersAtStreet2'],self.hands['playersAtStreet3'],self.hands['playersAtStreet4']) + self.streetXRaises(hand) # Empty function currently # comment TEXT, # commentTs DATETIME @@ -84,11 +87,12 @@ class DerivedStats(): if act[1] in ('calls','bets', 'raises'): vpipers.add(act[0]) - for player in hand.players: - if player[1] in vpipers: - self.handsplayers[player[1]]['vpip'] = True - else: - self.handsplayers[player[1]]['vpip'] = False + #for player in hand.players: + # print "DEBUG: '%s' '%s' '%s'" %(player, player[1], vpipers) + # if player[1] in vpipers: + # self.handsplayers[player[1]]['vpip'] = True + # else: + # self.handsplayers[player[1]]['vpip'] = False self.hands['playersVpi'] = len(vpipers) def playersAtStreetX(self, hand): @@ -105,7 +109,7 @@ class DerivedStats(): for street in hand.actionStreets: actors = {} - for act in a[street]: + for act in hand.actions[street]: actors[act[0]] = 1 #print "len(actors.keys(%s)): %s" % ( street, len(actors.keys())) if hand.gametype['base'] in ("hold"): From 4d04a4b1dbe54b14ed28148916ca49d932f4ab21 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 13 Oct 2009 17:30:49 +0800 Subject: [PATCH 28/52] [NEWIMPORT] Take a copy of generateHudCache for DerivedStats Commented out, should give a good basis for generating the stats from Hand class --- pyfpdb/DerivedStats.py | 690 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 690 insertions(+) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 0140f49f..315ae707 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -81,6 +81,696 @@ class DerivedStats(): for i, street in enumerate(hand.actionStreets[1:]): self.aggr(self.hand, i) + def assembleHudCache(self, hand): +# # def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo +# # ,winnings, totalWinnings, positions, actionTypes, actionAmounts, antes): +# #"""calculates data for the HUD during import. IMPORTANT: if you change this method make +# # sure to also change the following storage method and table_viewer.prepare_data if necessary +# #""" +# #print "generateHudCacheData, len(player_ids)=", len(player_ids) +# #setup subarrays of the result dictionary. +# street0VPI=[] +# street0Aggr=[] +# street0_3BChance=[] +# street0_3BDone=[] +# street1Seen=[] +# street2Seen=[] +# street3Seen=[] +# street4Seen=[] +# sawShowdown=[] +# street1Aggr=[] +# street2Aggr=[] +# street3Aggr=[] +# street4Aggr=[] +# otherRaisedStreet1=[] +# otherRaisedStreet2=[] +# otherRaisedStreet3=[] +# otherRaisedStreet4=[] +# foldToOtherRaisedStreet1=[] +# foldToOtherRaisedStreet2=[] +# foldToOtherRaisedStreet3=[] +# foldToOtherRaisedStreet4=[] +# wonWhenSeenStreet1=[] +# +# wonAtSD=[] +# stealAttemptChance=[] +# stealAttempted=[] +# hudDataPositions=[] +# +# street0Calls=[] +# street1Calls=[] +# street2Calls=[] +# street3Calls=[] +# street4Calls=[] +# street0Bets=[] +# street1Bets=[] +# street2Bets=[] +# street3Bets=[] +# street4Bets=[] +# #street0Raises=[] +# #street1Raises=[] +# #street2Raises=[] +# #street3Raises=[] +# #street4Raises=[] +# +# # Summary figures for hand table: +# result={} +# result['playersVpi']=0 +# result['playersAtStreet1']=0 +# result['playersAtStreet2']=0 +# result['playersAtStreet3']=0 +# result['playersAtStreet4']=0 +# result['playersAtShowdown']=0 +# result['street0Raises']=0 +# result['street1Raises']=0 +# result['street2Raises']=0 +# result['street3Raises']=0 +# result['street4Raises']=0 +# result['street1Pot']=0 +# result['street2Pot']=0 +# result['street3Pot']=0 +# result['street4Pot']=0 +# result['showdownPot']=0 +# +# firstPfRaiseByNo=-1 +# firstPfRaiserId=-1 +# firstPfRaiserNo=-1 +# firstPfCallByNo=-1 +# firstPfCallerId=-1 +# +# for i, action in enumerate(actionTypeByNo[0]): +# if action[1] == "bet": +# firstPfRaiseByNo = i +# firstPfRaiserId = action[0] +# for j, pid in enumerate(player_ids): +# if pid == firstPfRaiserId: +# firstPfRaiserNo = j +# break +# break +# for i, action in enumerate(actionTypeByNo[0]): +# if action[1] == "call": +# firstPfCallByNo = i +# firstPfCallerId = action[0] +# break +# firstPlayId = firstPfCallerId +# if firstPfRaiseByNo <> -1: +# if firstPfRaiseByNo < firstPfCallByNo or firstPfCallByNo == -1: +# firstPlayId = firstPfRaiserId +# +# +# cutoffId=-1 +# buttonId=-1 +# sbId=-1 +# bbId=-1 +# if base=="hold": +# for player, pos in enumerate(positions): +# if pos == 1: +# cutoffId = player_ids[player] +# if pos == 0: +# buttonId = player_ids[player] +# if pos == 'S': +# sbId = player_ids[player] +# if pos == 'B': +# bbId = player_ids[player] +# +# someoneStole=False +# +# #run a loop for each player preparing the actual values that will be commited to SQL +# for player in xrange(len(player_ids)): +# #set default values +# myStreet0VPI=False +# myStreet0Aggr=False +# myStreet0_3BChance=False +# myStreet0_3BDone=False +# myStreet1Seen=False +# myStreet2Seen=False +# myStreet3Seen=False +# myStreet4Seen=False +# mySawShowdown=False +# myStreet1Aggr=False +# myStreet2Aggr=False +# myStreet3Aggr=False +# myStreet4Aggr=False +# myOtherRaisedStreet1=False +# myOtherRaisedStreet2=False +# myOtherRaisedStreet3=False +# myOtherRaisedStreet4=False +# myFoldToOtherRaisedStreet1=False +# myFoldToOtherRaisedStreet2=False +# myFoldToOtherRaisedStreet3=False +# myFoldToOtherRaisedStreet4=False +# myWonWhenSeenStreet1=0.0 +# myWonAtSD=0.0 +# myStealAttemptChance=False +# myStealAttempted=False +# myStreet0Calls=0 +# myStreet1Calls=0 +# myStreet2Calls=0 +# myStreet3Calls=0 +# myStreet4Calls=0 +# myStreet0Bets=0 +# myStreet1Bets=0 +# myStreet2Bets=0 +# myStreet3Bets=0 +# myStreet4Bets=0 +# #myStreet0Raises=0 +# #myStreet1Raises=0 +# #myStreet2Raises=0 +# #myStreet3Raises=0 +# #myStreet4Raises=0 +# +# #calculate VPIP and PFR +# street=0 +# heroPfRaiseCount=0 +# for currentAction in action_types[street][player]: # finally individual actions +# if currentAction == "bet": +# myStreet0Aggr = True +# if currentAction == "bet" or currentAction == "call": +# myStreet0VPI = True +# +# if myStreet0VPI: +# result['playersVpi'] += 1 +# myStreet0Calls = action_types[street][player].count('call') +# myStreet0Bets = action_types[street][player].count('bet') +# # street0Raises = action_types[street][player].count('raise') bet count includes raises for now +# result['street0Raises'] += myStreet0Bets +# +# #PF3BChance and PF3B +# pfFold=-1 +# pfRaise=-1 +# if firstPfRaiseByNo != -1: +# for i, actionType in enumerate(actionTypeByNo[0]): +# if actionType[0] == player_ids[player]: +# if actionType[1] == "bet" and pfRaise == -1 and i > firstPfRaiseByNo: +# pfRaise = i +# if actionType[1] == "fold" and pfFold == -1: +# pfFold = i +# if pfFold == -1 or pfFold > firstPfRaiseByNo: +# myStreet0_3BChance = True +# if pfRaise > firstPfRaiseByNo: +# myStreet0_3BDone = True +# +# #steal calculations +# if base=="hold": +# if len(player_ids)>=3: # no point otherwise # was 5, use 3 to match pokertracker definition +# if positions[player]==1: +# if firstPfRaiserId==player_ids[player] \ +# and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): +# myStealAttempted=True +# myStealAttemptChance=True +# if firstPlayId==cutoffId or firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: +# myStealAttemptChance=True +# if positions[player]==0: +# if firstPfRaiserId==player_ids[player] \ +# and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): +# myStealAttempted=True +# myStealAttemptChance=True +# if firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: +# myStealAttemptChance=True +# if positions[player]=='S': +# if firstPfRaiserId==player_ids[player] \ +# and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): +# myStealAttempted=True +# myStealAttemptChance=True +# if firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: +# myStealAttemptChance=True +# if positions[player]=='B': +# pass +# +# if myStealAttempted: +# someoneStole=True +# +# +# #calculate saw* values +# isAllIn = False +# if any(i for i in allIns[0][player]): +# isAllIn = True +# if (len(action_types[1][player])>0 or isAllIn): +# myStreet1Seen = True +# +# if any(i for i in allIns[1][player]): +# isAllIn = True +# if (len(action_types[2][player])>0 or isAllIn): +# myStreet2Seen = True +# +# if any(i for i in allIns[2][player]): +# isAllIn = True +# if (len(action_types[3][player])>0 or isAllIn): +# myStreet3Seen = True +# +# #print "base:", base +# if base=="hold": +# mySawShowdown = True +# if any(actiontype == "fold" for actiontype in action_types[3][player]): +# mySawShowdown = False +# else: +# #print "in else" +# if any(i for i in allIns[3][player]): +# isAllIn = True +# if (len(action_types[4][player])>0 or isAllIn): +# #print "in if" +# myStreet4Seen = True +# +# mySawShowdown = True +# if any(actiontype == "fold" for actiontype in action_types[4][player]): +# mySawShowdown = False +# +# if myStreet1Seen: +# result['playersAtStreet1'] += 1 +# if myStreet2Seen: +# result['playersAtStreet2'] += 1 +# if myStreet3Seen: +# result['playersAtStreet3'] += 1 +# if myStreet4Seen: +# result['playersAtStreet4'] += 1 +# if mySawShowdown: +# result['playersAtShowdown'] += 1 +# +# #flop stuff +# street=1 +# if myStreet1Seen: +# if any(actiontype == "bet" for actiontype in action_types[street][player]): +# myStreet1Aggr = True +# +# myStreet1Calls = action_types[street][player].count('call') +# myStreet1Bets = action_types[street][player].count('bet') +# # street1Raises = action_types[street][player].count('raise') bet count includes raises for now +# result['street1Raises'] += myStreet1Bets +# +# for otherPlayer in xrange(len(player_ids)): +# if player==otherPlayer: +# pass +# else: +# for countOther in xrange(len(action_types[street][otherPlayer])): +# if action_types[street][otherPlayer][countOther]=="bet": +# myOtherRaisedStreet1=True +# for countOtherFold in xrange(len(action_types[street][player])): +# if action_types[street][player][countOtherFold]=="fold": +# myFoldToOtherRaisedStreet1=True +# +# #turn stuff - copy of flop with different vars +# street=2 +# if myStreet2Seen: +# if any(actiontype == "bet" for actiontype in action_types[street][player]): +# myStreet2Aggr = True +# +# myStreet2Calls = action_types[street][player].count('call') +# myStreet2Bets = action_types[street][player].count('bet') +# # street2Raises = action_types[street][player].count('raise') bet count includes raises for now +# result['street2Raises'] += myStreet2Bets +# +# for otherPlayer in xrange(len(player_ids)): +# if player==otherPlayer: +# pass +# else: +# for countOther in xrange(len(action_types[street][otherPlayer])): +# if action_types[street][otherPlayer][countOther]=="bet": +# myOtherRaisedStreet2=True +# for countOtherFold in xrange(len(action_types[street][player])): +# if action_types[street][player][countOtherFold]=="fold": +# myFoldToOtherRaisedStreet2=True +# +# #river stuff - copy of flop with different vars +# street=3 +# if myStreet3Seen: +# if any(actiontype == "bet" for actiontype in action_types[street][player]): +# myStreet3Aggr = True +# +# myStreet3Calls = action_types[street][player].count('call') +# myStreet3Bets = action_types[street][player].count('bet') +# # street3Raises = action_types[street][player].count('raise') bet count includes raises for now +# result['street3Raises'] += myStreet3Bets +# +# for otherPlayer in xrange(len(player_ids)): +# if player==otherPlayer: +# pass +# else: +# for countOther in xrange(len(action_types[street][otherPlayer])): +# if action_types[street][otherPlayer][countOther]=="bet": +# myOtherRaisedStreet3=True +# for countOtherFold in xrange(len(action_types[street][player])): +# if action_types[street][player][countOtherFold]=="fold": +# myFoldToOtherRaisedStreet3=True +# +# #stud river stuff - copy of flop with different vars +# street=4 +# if myStreet4Seen: +# if any(actiontype == "bet" for actiontype in action_types[street][player]): +# myStreet4Aggr=True +# +# myStreet4Calls = action_types[street][player].count('call') +# myStreet4Bets = action_types[street][player].count('bet') +# # street4Raises = action_types[street][player].count('raise') bet count includes raises for now +# result['street4Raises'] += myStreet4Bets +# +# for otherPlayer in xrange(len(player_ids)): +# if player==otherPlayer: +# pass +# else: +# for countOther in xrange(len(action_types[street][otherPlayer])): +# if action_types[street][otherPlayer][countOther]=="bet": +# myOtherRaisedStreet4=True +# for countOtherFold in xrange(len(action_types[street][player])): +# if action_types[street][player][countOtherFold]=="fold": +# myFoldToOtherRaisedStreet4=True +# +# if winnings[player] != 0: +# if myStreet1Seen: +# myWonWhenSeenStreet1 = winnings[player] / float(totalWinnings) +# if mySawShowdown: +# myWonAtSD=myWonWhenSeenStreet1 +# +# #add each value to the appropriate array +# street0VPI.append(myStreet0VPI) +# street0Aggr.append(myStreet0Aggr) +# street0_3BChance.append(myStreet0_3BChance) +# street0_3BDone.append(myStreet0_3BDone) +# street1Seen.append(myStreet1Seen) +# street2Seen.append(myStreet2Seen) +# street3Seen.append(myStreet3Seen) +# street4Seen.append(myStreet4Seen) +# sawShowdown.append(mySawShowdown) +# street1Aggr.append(myStreet1Aggr) +# street2Aggr.append(myStreet2Aggr) +# street3Aggr.append(myStreet3Aggr) +# street4Aggr.append(myStreet4Aggr) +# otherRaisedStreet1.append(myOtherRaisedStreet1) +# otherRaisedStreet2.append(myOtherRaisedStreet2) +# otherRaisedStreet3.append(myOtherRaisedStreet3) +# otherRaisedStreet4.append(myOtherRaisedStreet4) +# foldToOtherRaisedStreet1.append(myFoldToOtherRaisedStreet1) +# foldToOtherRaisedStreet2.append(myFoldToOtherRaisedStreet2) +# foldToOtherRaisedStreet3.append(myFoldToOtherRaisedStreet3) +# foldToOtherRaisedStreet4.append(myFoldToOtherRaisedStreet4) +# wonWhenSeenStreet1.append(myWonWhenSeenStreet1) +# wonAtSD.append(myWonAtSD) +# stealAttemptChance.append(myStealAttemptChance) +# stealAttempted.append(myStealAttempted) +# if base=="hold": +# pos=positions[player] +# if pos=='B': +# hudDataPositions.append('B') +# elif pos=='S': +# hudDataPositions.append('S') +# elif pos==0: +# hudDataPositions.append('D') +# elif pos==1: +# hudDataPositions.append('C') +# elif pos>=2 and pos<=4: +# hudDataPositions.append('M') +# elif pos>=5 and pos<=8: +# hudDataPositions.append('E') +# ### RHH Added this elif to handle being a dead hand before the BB (pos==9) +# elif pos==9: +# hudDataPositions.append('X') +# else: +# raise FpdbError("invalid position") +# elif base=="stud": +# #todo: stud positions and steals +# pass +# +# street0Calls.append(myStreet0Calls) +# street1Calls.append(myStreet1Calls) +# street2Calls.append(myStreet2Calls) +# street3Calls.append(myStreet3Calls) +# street4Calls.append(myStreet4Calls) +# street0Bets.append(myStreet0Bets) +# street1Bets.append(myStreet1Bets) +# street2Bets.append(myStreet2Bets) +# street3Bets.append(myStreet3Bets) +# street4Bets.append(myStreet4Bets) +# #street0Raises.append(myStreet0Raises) +# #street1Raises.append(myStreet1Raises) +# #street2Raises.append(myStreet2Raises) +# #street3Raises.append(myStreet3Raises) +# #street4Raises.append(myStreet4Raises) +# +# #add each array to the to-be-returned dictionary +# result['street0VPI']=street0VPI +# result['street0Aggr']=street0Aggr +# result['street0_3BChance']=street0_3BChance +# result['street0_3BDone']=street0_3BDone +# result['street1Seen']=street1Seen +# result['street2Seen']=street2Seen +# result['street3Seen']=street3Seen +# result['street4Seen']=street4Seen +# result['sawShowdown']=sawShowdown +# +# result['street1Aggr']=street1Aggr +# result['otherRaisedStreet1']=otherRaisedStreet1 +# result['foldToOtherRaisedStreet1']=foldToOtherRaisedStreet1 +# result['street2Aggr']=street2Aggr +# result['otherRaisedStreet2']=otherRaisedStreet2 +# result['foldToOtherRaisedStreet2']=foldToOtherRaisedStreet2 +# result['street3Aggr']=street3Aggr +# result['otherRaisedStreet3']=otherRaisedStreet3 +# result['foldToOtherRaisedStreet3']=foldToOtherRaisedStreet3 +# result['street4Aggr']=street4Aggr +# result['otherRaisedStreet4']=otherRaisedStreet4 +# result['foldToOtherRaisedStreet4']=foldToOtherRaisedStreet4 +# result['wonWhenSeenStreet1']=wonWhenSeenStreet1 +# result['wonAtSD']=wonAtSD +# result['stealAttemptChance']=stealAttemptChance +# result['stealAttempted']=stealAttempted +# result['street0Calls']=street0Calls +# result['street1Calls']=street1Calls +# result['street2Calls']=street2Calls +# result['street3Calls']=street3Calls +# result['street4Calls']=street4Calls +# result['street0Bets']=street0Bets +# result['street1Bets']=street1Bets +# result['street2Bets']=street2Bets +# result['street3Bets']=street3Bets +# result['street4Bets']=street4Bets +# #result['street0Raises']=street0Raises +# #result['street1Raises']=street1Raises +# #result['street2Raises']=street2Raises +# #result['street3Raises']=street3Raises +# #result['street4Raises']=street4Raises +# +# #now the various steal values +# foldBbToStealChance=[] +# foldedBbToSteal=[] +# foldSbToStealChance=[] +# foldedSbToSteal=[] +# for player in xrange(len(player_ids)): +# myFoldBbToStealChance=False +# myFoldedBbToSteal=False +# myFoldSbToStealChance=False +# myFoldedSbToSteal=False +# +# if base=="hold": +# if someoneStole and (positions[player]=='B' or positions[player]=='S') and firstPfRaiserId!=player_ids[player]: +# street=0 +# for count in xrange(len(action_types[street][player])):#individual actions +# if positions[player]=='B': +# myFoldBbToStealChance=True +# if action_types[street][player][count]=="fold": +# myFoldedBbToSteal=True +# if positions[player]=='S': +# myFoldSbToStealChance=True +# if action_types[street][player][count]=="fold": +# myFoldedSbToSteal=True +# +# +# foldBbToStealChance.append(myFoldBbToStealChance) +# foldedBbToSteal.append(myFoldedBbToSteal) +# foldSbToStealChance.append(myFoldSbToStealChance) +# foldedSbToSteal.append(myFoldedSbToSteal) +# result['foldBbToStealChance']=foldBbToStealChance +# result['foldedBbToSteal']=foldedBbToSteal +# result['foldSbToStealChance']=foldSbToStealChance +# result['foldedSbToSteal']=foldedSbToSteal +# +# #now CB +# street1CBChance=[] +# street1CBDone=[] +# didStreet1CB=[] +# for player in xrange(len(player_ids)): +# myStreet1CBChance=False +# myStreet1CBDone=False +# +# if street0VPI[player]: +# myStreet1CBChance=True +# if street1Aggr[player]: +# myStreet1CBDone=True +# didStreet1CB.append(player_ids[player]) +# +# street1CBChance.append(myStreet1CBChance) +# street1CBDone.append(myStreet1CBDone) +# result['street1CBChance']=street1CBChance +# result['street1CBDone']=street1CBDone +# +# #now 2B +# street2CBChance=[] +# street2CBDone=[] +# didStreet2CB=[] +# for player in xrange(len(player_ids)): +# myStreet2CBChance=False +# myStreet2CBDone=False +# +# if street1CBDone[player]: +# myStreet2CBChance=True +# if street2Aggr[player]: +# myStreet2CBDone=True +# didStreet2CB.append(player_ids[player]) +# +# street2CBChance.append(myStreet2CBChance) +# street2CBDone.append(myStreet2CBDone) +# result['street2CBChance']=street2CBChance +# result['street2CBDone']=street2CBDone +# +# #now 3B +# street3CBChance=[] +# street3CBDone=[] +# didStreet3CB=[] +# for player in xrange(len(player_ids)): +# myStreet3CBChance=False +# myStreet3CBDone=False +# +# if street2CBDone[player]: +# myStreet3CBChance=True +# if street3Aggr[player]: +# myStreet3CBDone=True +# didStreet3CB.append(player_ids[player]) +# +# street3CBChance.append(myStreet3CBChance) +# street3CBDone.append(myStreet3CBDone) +# result['street3CBChance']=street3CBChance +# result['street3CBDone']=street3CBDone +# +# #and 4B +# street4CBChance=[] +# street4CBDone=[] +# didStreet4CB=[] +# for player in xrange(len(player_ids)): +# myStreet4CBChance=False +# myStreet4CBDone=False +# +# if street3CBDone[player]: +# myStreet4CBChance=True +# if street4Aggr[player]: +# myStreet4CBDone=True +# didStreet4CB.append(player_ids[player]) +# +# street4CBChance.append(myStreet4CBChance) +# street4CBDone.append(myStreet4CBDone) +# result['street4CBChance']=street4CBChance +# result['street4CBDone']=street4CBDone +# +# +# result['position']=hudDataPositions +# +# foldToStreet1CBChance=[] +# foldToStreet1CBDone=[] +# foldToStreet2CBChance=[] +# foldToStreet2CBDone=[] +# foldToStreet3CBChance=[] +# foldToStreet3CBDone=[] +# foldToStreet4CBChance=[] +# foldToStreet4CBDone=[] +# +# for player in xrange(len(player_ids)): +# myFoldToStreet1CBChance=False +# myFoldToStreet1CBDone=False +# foldToStreet1CBChance.append(myFoldToStreet1CBChance) +# foldToStreet1CBDone.append(myFoldToStreet1CBDone) +# +# myFoldToStreet2CBChance=False +# myFoldToStreet2CBDone=False +# foldToStreet2CBChance.append(myFoldToStreet2CBChance) +# foldToStreet2CBDone.append(myFoldToStreet2CBDone) +# +# myFoldToStreet3CBChance=False +# myFoldToStreet3CBDone=False +# foldToStreet3CBChance.append(myFoldToStreet3CBChance) +# foldToStreet3CBDone.append(myFoldToStreet3CBDone) +# +# myFoldToStreet4CBChance=False +# myFoldToStreet4CBDone=False +# foldToStreet4CBChance.append(myFoldToStreet4CBChance) +# foldToStreet4CBDone.append(myFoldToStreet4CBDone) +# +# if len(didStreet1CB)>=1: +# generateFoldToCB(1, player_ids, didStreet1CB, street1CBDone, foldToStreet1CBChance, foldToStreet1CBDone, actionTypeByNo) +# +# if len(didStreet2CB)>=1: +# generateFoldToCB(2, player_ids, didStreet2CB, street2CBDone, foldToStreet2CBChance, foldToStreet2CBDone, actionTypeByNo) +# +# if len(didStreet3CB)>=1: +# generateFoldToCB(3, player_ids, didStreet3CB, street3CBDone, foldToStreet3CBChance, foldToStreet3CBDone, actionTypeByNo) +# +# if len(didStreet4CB)>=1: +# generateFoldToCB(4, player_ids, didStreet4CB, street4CBDone, foldToStreet4CBChance, foldToStreet4CBDone, actionTypeByNo) +# +# result['foldToStreet1CBChance']=foldToStreet1CBChance +# result['foldToStreet1CBDone']=foldToStreet1CBDone +# result['foldToStreet2CBChance']=foldToStreet2CBChance +# result['foldToStreet2CBDone']=foldToStreet2CBDone +# result['foldToStreet3CBChance']=foldToStreet3CBChance +# result['foldToStreet3CBDone']=foldToStreet3CBDone +# result['foldToStreet4CBChance']=foldToStreet4CBChance +# result['foldToStreet4CBDone']=foldToStreet4CBDone +# +# +# totalProfit=[] +# +# street1CheckCallRaiseChance=[] +# street1CheckCallRaiseDone=[] +# street2CheckCallRaiseChance=[] +# street2CheckCallRaiseDone=[] +# street3CheckCallRaiseChance=[] +# street3CheckCallRaiseDone=[] +# street4CheckCallRaiseChance=[] +# street4CheckCallRaiseDone=[] +# #print "b4 totprof calc, len(playerIds)=", len(player_ids) +# for pl in xrange(len(player_ids)): +# #print "pl=", pl +# myTotalProfit=winnings[pl] # still need to deduct other costs +# if antes: +# myTotalProfit=winnings[pl] - antes[pl] +# for i in xrange(len(actionTypes)): #iterate through streets +# #for j in xrange(len(actionTypes[i])): #iterate through names (using pl loop above) +# for k in xrange(len(actionTypes[i][pl])): #iterate through individual actions of that player on that street +# myTotalProfit -= actionAmounts[i][pl][k] +# +# myStreet1CheckCallRaiseChance=False +# myStreet1CheckCallRaiseDone=False +# myStreet2CheckCallRaiseChance=False +# myStreet2CheckCallRaiseDone=False +# myStreet3CheckCallRaiseChance=False +# myStreet3CheckCallRaiseDone=False +# myStreet4CheckCallRaiseChance=False +# myStreet4CheckCallRaiseDone=False +# +# #print "myTotalProfit=", myTotalProfit +# totalProfit.append(myTotalProfit) +# #print "totalProfit[]=", totalProfit +# +# street1CheckCallRaiseChance.append(myStreet1CheckCallRaiseChance) +# street1CheckCallRaiseDone.append(myStreet1CheckCallRaiseDone) +# street2CheckCallRaiseChance.append(myStreet2CheckCallRaiseChance) +# street2CheckCallRaiseDone.append(myStreet2CheckCallRaiseDone) +# street3CheckCallRaiseChance.append(myStreet3CheckCallRaiseChance) +# street3CheckCallRaiseDone.append(myStreet3CheckCallRaiseDone) +# street4CheckCallRaiseChance.append(myStreet4CheckCallRaiseChance) +# street4CheckCallRaiseDone.append(myStreet4CheckCallRaiseDone) +# +# result['totalProfit']=totalProfit +# #print "res[totalProfit]=", result['totalProfit'] +# +# result['street1CheckCallRaiseChance']=street1CheckCallRaiseChance +# result['street1CheckCallRaiseDone']=street1CheckCallRaiseDone +# result['street2CheckCallRaiseChance']=street2CheckCallRaiseChance +# result['street2CheckCallRaiseDone']=street2CheckCallRaiseDone +# result['street3CheckCallRaiseChance']=street3CheckCallRaiseChance +# result['street3CheckCallRaiseDone']=street3CheckCallRaiseDone +# result['street4CheckCallRaiseChance']=street4CheckCallRaiseChance +# result['street4CheckCallRaiseDone']=street4CheckCallRaiseDone +# return result +# #end def generateHudCacheData + pass + def vpip(self, hand): vpipers = set() for act in hand.actions[hand.actionStreets[1]]: From 843bd754f6e9e259a81050c0da4f2704eee78d0d Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 13 Oct 2009 17:42:02 +0800 Subject: [PATCH 29/52] [NEWIMPORT] Prep insert functions Cleaned up storeHandsPlayers and added storeHudCacheNew Haven't decided on the data structures to be passed in as yet so the functions only insert the bare minimum and have a list of commented out variables --- pyfpdb/Database.py | 402 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 306 insertions(+), 96 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index b283a716..f0146c7f 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1420,8 +1420,7 @@ class Database: %s, %s, %s, %s, %s, %s, %s, %s, %s)""" q = q.replace('%s', self.sql.query['placeholder']) - print "DEBUG: p: %s" %p - print "DEBUG: gtid: %s" % p['gameTypeId'] + self.cursor.execute(q, ( p['tableName'], p['gameTypeId'], @@ -1456,101 +1455,312 @@ class Database: #return getLastInsertId(backend, conn, cursor) # def storeHand - def storeHandsPlayers(self, p): - #def store_hands_players_holdem_omaha(self, backend, category, hands_id, player_ids, start_cashes - # ,positions, card_values, card_suits, winnings, rakes, seatNos, hudCache): - # result=[] - # - # # postgres (and others?) needs the booleans converted to ints before saving: - # # (or we could just save them as boolean ... but then we can't sum them so easily in sql ???) - # # NO - storing booleans for now so don't need this - # #hudCacheInt = {} - # #for k,v in hudCache.iteritems(): - # # if k in ('wonWhenSeenStreet1', 'wonAtSD', 'totalProfit'): - # # hudCacheInt[k] = v - # # else: - # # hudCacheInt[k] = map(lambda x: 1 if x else 0, v) - # - # try: - # inserts = [] - # for i in xrange(len(player_ids)): - # card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - # card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - # - # if (category=="holdem"): - # startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1]) - # card3 = None - # card4 = None - # elif (category=="omahahi" or category=="omahahilo"): - # startCards = Card.fourStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1] - # ,card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3]) - # card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - # card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - # else: - # raise FpdbError("invalid category") - # - # inserts.append( ( - # hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid - needed for hudcache - # card1, card2, card3, card4, startCards, - # winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], - # hudCache['street0VPI'][i], hudCache['street0Aggr'][i], - # hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], - # hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], - # hudCache['street4Seen'][i], hudCache['sawShowdown'][i], - # hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], - # hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i], - # hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i], - # hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i], - # hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i], - # hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i], - # hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i], - # hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i], - # hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i], - # hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i], - # hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i], - # hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i], - # hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i], - # hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i], - # hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], - # hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], - # hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], - # hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i], - # hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], hudCache['street3Calls'][i], hudCache['street4Calls'][i], - # hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], hudCache['street3Bets'][i], hudCache['street4Bets'][i] - # ) ) - # c = self.get_cursor() - # c.executemany (""" - # INSERT INTO HandsPlayers - # (handId, playerId, startCash, position, tourneyTypeId, - # card1, card2, card3, card4, startCards, winnings, rake, seatNo, totalProfit, - # street0VPI, street0Aggr, street0_3BChance, street0_3BDone, - # street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, - # street1Aggr, street2Aggr, street3Aggr, street4Aggr, - # otherRaisedStreet1, otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, - # foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, - # wonWhenSeenStreet1, wonAtSD, - # stealAttemptChance, stealAttempted, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal, - # street1CBChance, street1CBDone, street2CBChance, street2CBDone, - # street3CBChance, street3CBDone, street4CBChance, street4CBDone, - # foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone, - # foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone, - # street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, - # street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone, - # street0Calls, street1Calls, street2Calls, street3Calls, street4Calls, - # street0Bets, street1Bets, street2Bets, street3Bets, street4Bets - # ) - # VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - # %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - # %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - # %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - # ,inserts ) - # result.append( self.get_last_insert_id(c) ) # wrong? not used currently - # except: - # raise FpdbError( "store_hands_players_holdem_omaha error: " + str(sys.exc_value) ) - # - # return result + def storeHandsPlayers(self, hid, pid, p): + q = """INSERT INTO HandsPlayers ( + handId, + playerId + ) + VALUES ( + %s, %s + )""" - pass +# startCash, +# position, +# tourneyTypeId, +# card1, +# card2, +# card3, +# card4, +# startCards, +# winnings, +# rake, +# seatNo, +# totalProfit, +# street0VPI, +# street0Aggr, +# street0_3BChance, +# street0_3BDone, +# street1Seen, +# street2Seen, +# street3Seen, +# street4Seen, +# sawShowdown, +# street1Aggr, +# street2Aggr, +# street3Aggr, +# street4Aggr, +# otherRaisedStreet1, +# otherRaisedStreet2, +# otherRaisedStreet3, +# otherRaisedStreet4, +# foldToOtherRaisedStreet1, +# foldToOtherRaisedStreet2, +# foldToOtherRaisedStreet3, +# foldToOtherRaisedStreet4, +# wonWhenSeenStreet1, +# wonAtSD, +# stealAttemptChance, +# stealAttempted, +# foldBbToStealChance, +# foldedBbToSteal, +# foldSbToStealChance, +# foldedSbToSteal, +# street1CBChance, +# street1CBDone, +# street2CBChance, +# street2CBDone, +# street3CBChance, +# street3CBDone, +# street4CBChance, +# street4CBDone, +# foldToStreet1CBChance, +# foldToStreet1CBDone, +# foldToStreet2CBChance, +# foldToStreet2CBDone, +# foldToStreet3CBChance, +# foldToStreet3CBDone, +# foldToStreet4CBChance, +# foldToStreet4CBDone, +# street1CheckCallRaiseChance, +# street1CheckCallRaiseDone, +# street2CheckCallRaiseChance, +# street2CheckCallRaiseDone, +# street3CheckCallRaiseChance, +# street3CheckCallRaiseDone, +# street4CheckCallRaiseChance, +# street4CheckCallRaiseDone, +# street0Calls, +# street1Calls, +# street2Calls, +# street3Calls, +# street4Calls, +# street0Bets, +# street1Bets, +# street2Bets, +# street3Bets, +# street4Bets + + q = q.replace('%s', self.sql.query['placeholder']) + + self.cursor.execute(q, ( + hid, + pid + )) +# startCash, +# position, +# tourneyTypeId, +# card1, +# card2, +# card3, +# card4, +# startCards, +# winnings, +# rake, +# seatNo, +# totalProfit, +# street0VPI, +# street0Aggr, +# street0_3BChance, +# street0_3BDone, +# street1Seen, +# street2Seen, +# street3Seen, +# street4Seen, +# sawShowdown, +# street1Aggr, +# street2Aggr, +# street3Aggr, +# street4Aggr, +# otherRaisedStreet1, +# otherRaisedStreet2, +# otherRaisedStreet3, +# otherRaisedStreet4, +# foldToOtherRaisedStreet1, +# foldToOtherRaisedStreet2, +# foldToOtherRaisedStreet3, +# foldToOtherRaisedStreet4, +# wonWhenSeenStreet1, +# wonAtSD, +# stealAttemptChance, +# stealAttempted, +# foldBbToStealChance, +# foldedBbToSteal, +# foldSbToStealChance, +# foldedSbToSteal, +# street1CBChance, +# street1CBDone, +# street2CBChance, +# street2CBDone, +# street3CBChance, +# street3CBDone, +# street4CBChance, +# street4CBDone, +# foldToStreet1CBChance, +# foldToStreet1CBDone, +# foldToStreet2CBChance, +# foldToStreet2CBDone, +# foldToStreet3CBChance, +# foldToStreet3CBDone, +# foldToStreet4CBChance, +# foldToStreet4CBDone, +# street1CheckCallRaiseChance, +# street1CheckCallRaiseDone, +# street2CheckCallRaiseChance, +# street2CheckCallRaiseDone, +# street3CheckCallRaiseChance, +# street3CheckCallRaiseDone, +# street4CheckCallRaiseChance, +# street4CheckCallRaiseDone, +# street0Calls, +# street1Calls, +# street2Calls, +# street3Calls, +# street4Calls, +# street0Bets, +# street1Bets, +# street2Bets, +# street3Bets, +# street4Bets + + def storeHudCacheNew(self, gid, pid, hc): + q = """INSERT INTO HudCache ( + gametypeId, + playerId + ) + VALUES ( + %s, %s + )""" + +# gametypeId, +# playerId, +# activeSeats, +# position, +# tourneyTypeId, +# styleKey, +# HDs, +# street0VPI, +# street0Aggr, +# street0_3BChance, +# street0_3BDone, +# street1Seen, +# street2Seen, +# street3Seen, +# street4Seen, +# sawShowdown, +# street1Aggr, +# street2Aggr, +# street3Aggr, +# street4Aggr, +# otherRaisedStreet1, +# otherRaisedStreet2, +# otherRaisedStreet3, +# otherRaisedStreet4, +# foldToOtherRaisedStreet1, +# foldToOtherRaisedStreet2, +# foldToOtherRaisedStreet3, +# foldToOtherRaisedStreet4, +# wonWhenSeenStreet1, +# wonAtSD, +# stealAttemptChance, +# stealAttempted, +# foldBbToStealChance, +# foldedBbToSteal, +# foldSbToStealChance, +# foldedSbToSteal, +# street1CBChance, +# street1CBDone, +# street2CBChance, +# street2CBDone, +# street3CBChance, +# street3CBDone, +# street4CBChance, +# street4CBDone, +# foldToStreet1CBChance, +# foldToStreet1CBDone, +# foldToStreet2CBChance, +# foldToStreet2CBDone, +# foldToStreet3CBChance, +# foldToStreet3CBDone, +# foldToStreet4CBChance, +# foldToStreet4CBDone, +# totalProfit, +# street1CheckCallRaiseChance, +# street1CheckCallRaiseDone, +# street2CheckCallRaiseChance, +# street2CheckCallRaiseDone, +# street3CheckCallRaiseChance, +# street3CheckCallRaiseDone, +# street4CheckCallRaiseChance, +# street4CheckCallRaiseDone) + + q = q.replace('%s', self.sql.query['placeholder']) + + self.cursor.execute(q, ( + gid, + pid + )) + +# gametypeId, +# playerId, +# activeSeats, +# position, +# tourneyTypeId, +# styleKey, +# HDs, +# street0VPI, +# street0Aggr, +# street0_3BChance, +# street0_3BDone, +# street1Seen, +# street2Seen, +# street3Seen, +# street4Seen, +# sawShowdown, +# street1Aggr, +# street2Aggr, +# street3Aggr, +# street4Aggr, +# otherRaisedStreet1, +# otherRaisedStreet2, +# otherRaisedStreet3, +# otherRaisedStreet4, +# foldToOtherRaisedStreet1, +# foldToOtherRaisedStreet2, +# foldToOtherRaisedStreet3, +# foldToOtherRaisedStreet4, +# wonWhenSeenStreet1, +# wonAtSD, +# stealAttemptChance, +# stealAttempted, +# foldBbToStealChance, +# foldedBbToSteal, +# foldSbToStealChance, +# foldedSbToSteal, +# street1CBChance, +# street1CBDone, +# street2CBChance, +# street2CBDone, +# street3CBChance, +# street3CBDone, +# street4CBChance, +# street4CBDone, +# foldToStreet1CBChance, +# foldToStreet1CBDone, +# foldToStreet2CBChance, +# foldToStreet2CBDone, +# foldToStreet3CBChance, +# foldToStreet3CBDone, +# foldToStreet4CBChance, +# foldToStreet4CBDone, +# totalProfit, +# street1CheckCallRaiseChance, +# street1CheckCallRaiseDone, +# street2CheckCallRaiseChance, +# street2CheckCallRaiseDone, +# street3CheckCallRaiseChance, +# street3CheckCallRaiseDone, +# street4CheckCallRaiseChance, +# street4CheckCallRaiseDone) ################################# From 785e3d63a23beb143f85a951ea8a2b0450c8f8db Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 13 Oct 2009 21:52:13 +0100 Subject: [PATCH 30/52] add 'is db running' printed message when pg db connect fails --- pyfpdb/fpdb_db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 17fecc2c..986c747f 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -111,7 +111,7 @@ class fpdb_db: password = password, database = database) except: - msg = "PostgreSQL connection to database (%s) user (%s) failed." % (database, user) + msg = "PostgreSQL connection to database (%s) user (%s) failed. Are you sure the DB is running?" % (database, user) print msg raise FpdbError(msg) elif backend == fpdb_db.SQLITE: From 4b0a399ffd273b016f4ba36b272cb814f8dda9b1 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 13 Oct 2009 21:53:51 +0100 Subject: [PATCH 31/52] stop fpdb.py accessing fpdb_db directly --- pyfpdb/Database.py | 25 ++++++++++++++----------- pyfpdb/fpdb.py | 28 +++++++++++++++++----------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f0146c7f..4a0f2e17 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -188,14 +188,7 @@ class Database: log.info("Creating Database instance, sql = %s" % sql) self.config = c self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql - self.fdb.do_connect(c) - self.connection = self.fdb.db - - db_params = c.get_db_parameters() - self.import_options = c.get_import_parameters() - self.type = db_params['db-type'] - self.backend = db_params['db-backend'] - self.db_server = db_params['db-server'] + self.do_connect(c) if self.backend == self.PGSQL: from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE @@ -206,14 +199,14 @@ class Database: # where possible avoid creating new SQL instance by using the global one passed in if sql is None: - self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) + self.sql = SQL.Sql(type = self.type, db_server = self.db_server) else: self.sql = sql - if self.backend == self.SQLITE and db_params['db-databaseName'] == ':memory:' and self.fdb.wrongDbVersion: + if self.backend == self.SQLITE and self.database == ':memory:' and self.wrongDbVersion: log.info("sqlite/:memory: - creating") self.recreate_tables() - self.fdb.wrongDbVersion = False + self.wrongDbVersion = False self.pcache = None # PlayerId cache self.cachemiss = 0 # Delete me later - using to count player cache misses @@ -245,6 +238,16 @@ class Database: def do_connect(self, c): self.fdb.do_connect(c) + self.connection = self.fdb.db + self.wrongDbVersion = self.fdb.wrongDbVersion + + db_params = c.get_db_parameters() + self.import_options = c.get_import_parameters() + self.type = db_params['db-type'] + self.backend = db_params['db-backend'] + self.db_server = db_params['db-server'] + self.database = db_params['db-databaseName'] + self.host = db_params['db-host'] def commit(self): self.fdb.db.commit() diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 6d58f733..18bc65d9 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -44,6 +44,7 @@ else: print "Python " + sys.version[0:3] + '...\n' +import traceback import threading import Options import string @@ -64,7 +65,6 @@ import gtk import interlocks -import fpdb_simple import GuiBulkImport import GuiPlayerStats import GuiPositionalStats @@ -76,7 +76,7 @@ import SQL import Database import FpdbSQLQueries import Configuration -import Exceptions +from Exceptions import * VERSION = "0.11" @@ -234,13 +234,13 @@ class fpdb: dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database " \ - +self.db.fdb.database+" on "+self.db.fdb.host+" they will be deleted." + +self.db.database+" on "+self.db.host+" they will be deleted." dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted response = dia_confirm.run() dia_confirm.destroy() if response == gtk.RESPONSE_YES: - #if self.db.fdb.backend == self.fdb_lock.fdb.MYSQL_INNODB: + #if self.db.backend == self.fdb_lock.fdb.MYSQL_INNODB: # mysql requires locks on all tables or none - easier to release this lock # than lock all the other tables # ToDo: lock all other tables so that lock doesn't have to be released @@ -455,17 +455,23 @@ class fpdb: self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) try: self.db = Database.Database(self.config, sql = self.sql) - except Exceptions.FpdbMySQLFailedError: + except FpdbMySQLFailedError: self.warning_box("Unable to connect to MySQL! Is the MySQL server running?!", "FPDB ERROR") exit() except FpdbError: - print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']) + #print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']) + self.warning_box("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']), "FPDB ERROR") + err = traceback.extract_tb(sys.exc_info()[2])[-1] + print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])) except: - print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']) + #print "Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']) + self.warning_box("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']), "FPDB ERROR") + err = traceback.extract_tb(sys.exc_info()[2])[-1] + print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])) - if self.db.fdb.wrongDbVersion: + if self.db.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) label = gtk.Label("An invalid DB version or missing tables have been detected.") @@ -484,14 +490,14 @@ class fpdb: diaDbVersionWarning.destroy() if self.status_bar == None: - self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) + self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host)) self.main_vbox.pack_end(self.status_bar, False, True, 0) self.status_bar.show() else: - self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) + self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.database, self.db.host)) # Database connected to successfully, load queries to pass on to other classes - self.db.connection.rollback() + self.db.rollback() self.validate_config() From 4d92e3d2a0275c8339062e9425f49dab9d605a0a Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 13 Oct 2009 23:06:09 +0100 Subject: [PATCH 32/52] update graph viewer to work with enhanced filter --- pyfpdb/Filters.py | 16 +++++---- pyfpdb/GuiGraphViewer.py | 77 ++++++++++++++++++++++++++-------------- pyfpdb/SQL.py | 12 +++---- 3 files changed, 67 insertions(+), 38 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index ac036cbf..6ad242bb 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -32,19 +32,20 @@ import FpdbSQLQueries class Filters(threading.Thread): def __init__(self, db, config, qdict, display = {}, debug=True): - self.debug=debug + # config and qdict are now redundant + self.debug = debug #print "start of GraphViewer constructor" - self.db=db - self.cursor=db.cursor - self.sql=qdict - self.conf = config + self.db = db + self.cursor = db.cursor + self.sql = db.sql + self.conf = db.config self.display = display self.sites = {} self.games = {} self.limits = {} self.seats = {} - self.groups = {} + self.groups = {} self.siteid = {} self.heroes = {} self.boxes = {} @@ -451,6 +452,9 @@ class Filters(threading.Thread): hbox.pack_start(vbox3, False, False, 0) found = {'nl':False, 'fl':False, 'ring':False, 'tour':False} for i, line in enumerate(result): + if "UseType" in self.display: + if line[0] != self.display["UseType"]: + continue hbox = gtk.HBox(False, 0) if i <= len(result)/2: vbox2.pack_start(hbox, False, False, 0) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index f5beadcf..f91c9870 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -53,20 +53,26 @@ class GuiGraphViewer (threading.Thread): self.db = Database.Database(self.conf, sql=self.sql) - filters_display = { "Heroes" : True, - "Sites" : True, - "Games" : True, - "Limits" : True, - "Seats" : False, - "Dates" : True, - "Button1" : True, - "Button2" : True + filters_display = { "Heroes" : True, + "Sites" : True, + "Games" : True, + "Limits" : True, + "LimitSep" : True, + "LimitType" : True, + "Type" : False, + "UseType" : 'ring', + "Seats" : False, + "SeatSep" : False, + "Dates" : True, + "Groups" : False, + "Button1" : True, + "Button2" : True } self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display) - self.filters.registerButton1Name("Refresh Graph") + self.filters.registerButton1Name("Refresh _Graph") self.filters.registerButton1Callback(self.generateGraph) - self.filters.registerButton2Name("Export to File") + self.filters.registerButton2Name("_Export to File") self.filters.registerButton2Callback(self.exportGraph) self.mainHBox = gtk.HBox(False, 0) @@ -146,10 +152,8 @@ class GuiGraphViewer (threading.Thread): raise def generateGraph(self, widget, data): - print "generateGraph: start" try: self.clearGraphData() - print "after cleardata" sitenos = [] playerids = [] @@ -158,15 +162,18 @@ class GuiGraphViewer (threading.Thread): heroes = self.filters.getHeroes() siteids = self.filters.getSiteIds() limits = self.filters.getLimits() - print "got filter data" + for i in ('show', 'none'): + if i in limits: + limits.remove(i) # Which sites are selected? for site in sites: if sites[site] == True: sitenos.append(siteids[site]) - self.db.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) - result = self.db.cursor.fetchall() + c = self.db.get_cursor() + c.execute(self.sql.query['getPlayerId'], (heroes[site],)) + result = c.fetchall() if len(result) == 1: - playerids.append(result[0][0]) + playerids.append( int(result[0][0]) ) if not sitenos: #Should probably pop up here. @@ -182,12 +189,10 @@ class GuiGraphViewer (threading.Thread): return #Set graph properties - print "add_subplot" self.ax = self.fig.add_subplot(111) #Get graph data from DB starttime = time() - print "get line: playerids =", playerids, "sitenos =", sitenos, "limits =", limits line = self.getRingProfitGraph(playerids, sitenos, limits) print "Graph generated in: %s" %(time() - starttime) @@ -234,12 +239,31 @@ class GuiGraphViewer (threading.Thread): # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829) nametest = str(tuple(names)) sitetest = str(tuple(sites)) - limittest = str(tuple(limits)) - nametest = nametest.replace("L", "") - nametest = nametest.replace(",)",")") - sitetest = sitetest.replace(",)",")") - limittest = limittest.replace("L", "") - limittest = limittest.replace(",)",")") + #nametest = nametest.replace("L", "") + + lims = [int(x) for x in limits if x.isdigit()] + nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl'] + limittest = "and ( (gt.limitType = 'fl' and gt.bigBlind in " + # and ( (limit and bb in()) or (nolimit and bb in ()) ) + if lims: + blindtest = str(tuple(lims)) + blindtest = blindtest.replace("L", "") + blindtest = blindtest.replace(",)",")") + limittest = limittest + blindtest + ' ) ' + else: + limittest = limittest + '(-1) ) ' + limittest = limittest + " or (gt.limitType = 'nl' and gt.bigBlind in " + if nolims: + blindtest = str(tuple(nolims)) + blindtest = blindtest.replace("L", "") + blindtest = blindtest.replace(",)",")") + limittest = limittest + blindtest + ' ) )' + else: + limittest = limittest + '(-1) ) )' + if type == 'ring': + limittest = limittest + " and gt.type = 'ring' " + elif type == 'tour': + limittest = limittest + " and gt.type = 'tour' " #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf tmp = tmp.replace("", nametest) @@ -247,6 +271,7 @@ class GuiGraphViewer (threading.Thread): tmp = tmp.replace("", start_date) tmp = tmp.replace("", end_date) tmp = tmp.replace("", limittest) + tmp = tmp.replace(",)", ")") #print "DEBUG: sql query:" #print tmp @@ -255,10 +280,10 @@ class GuiGraphViewer (threading.Thread): winnings = self.db.cursor.fetchall() self.db.rollback() - if(winnings == ()): + if winnings == (): return None - y=map(lambda x:float(x[3]), winnings) + y = map(lambda x:float(x[1]), winnings) line = cumsum(y) return line/100 #end of def getRingProfitGraph diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 0f414e41..bb918d97 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -2455,16 +2455,16 @@ class Sql: # self.query['playerStatsByPosition'] = """ """ self.query['getRingProfitAllHandsPlayerIdSite'] = """ - SELECT hp.handId, hp.totalProfit, hp.totalProfit, hp.totalProfit + SELECT hp.handId, hp.totalProfit FROM HandsPlayers hp - INNER JOIN Players pl ON (hp.playerId = pl.id) - INNER JOIN Hands h ON (h.id = hp.handId) - INNER JOIN Gametypes g ON (h.gametypeId = g.id) - where pl.id in + INNER JOIN Players pl ON (pl.id = hp.playerId) + INNER JOIN Hands h ON (h.id = hp.handId) + INNER JOIN Gametypes gt ON (gt.id = h.gametypeId) + WHERE pl.id in AND pl.siteId in AND h.handStart > '' AND h.handStart < '' - AND g.bigBlind in + AND hp.tourneysPlayersId IS NULL GROUP BY h.handStart, hp.handId, hp.totalProfit ORDER BY h.handStart""" From 1fc015b09fe4fbc3c1a8b5c3e5108e2f401a2621 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 14 Oct 2009 12:05:17 +0800 Subject: [PATCH 33/52] [NEWIMPORT] Move db insert into SQL.py (store_hand) --- pyfpdb/Database.py | 36 +----------------------------------- pyfpdb/SQL.py | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f0146c7f..72083819 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1383,41 +1383,7 @@ class Database: def storeHand(self, p): #stores into table hands: - q = """INSERT INTO Hands ( - tablename, - gametypeid, - sitehandno, - handstart, - importtime, - seats, - maxseats, - texture, - playersVpi, - boardcard1, - boardcard2, - boardcard3, - boardcard4, - boardcard5, - playersAtStreet1, - playersAtStreet2, - playersAtStreet3, - playersAtStreet4, - playersAtShowdown, - street0Raises, - street1Raises, - street2Raises, - street3Raises, - street4Raises, - street1Pot, - street2Pot, - street3Pot, - street4Pot, - showdownPot - ) - VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s)""" + q = self.sql.query['store_hand'] q = q.replace('%s', self.sql.query['placeholder']) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 0f414e41..12df7aa4 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3110,6 +3110,44 @@ class Sql: self.query['handsPlayersTTypeId_joiner'] = " OR TourneysPlayersId+0=" self.query['handsPlayersTTypeId_joiner_id'] = " OR id=" + self.query['store_hand'] = """INSERT INTO Hands ( + tablename, + gametypeid, + sitehandno, + handstart, + importtime, + seats, + maxseats, + texture, + playersVpi, + boardcard1, + boardcard2, + boardcard3, + boardcard4, + boardcard5, + playersAtStreet1, + playersAtStreet2, + playersAtStreet3, + playersAtStreet4, + playersAtShowdown, + street0Raises, + street1Raises, + street2Raises, + street3Raises, + street4Raises, + street1Pot, + street2Pot, + street3Pot, + street4Pot, + showdownPot + ) + VALUES + (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s)""" + + + if db_server == 'mysql': From 2350474d38257efdf4111e96d1ee3084611555e6 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 14 Oct 2009 20:20:17 +0800 Subject: [PATCH 34/52] [NEWIMPORT] Start of HandsPlayers insert --- pyfpdb/Database.py | 102 +++++++---------------------------------- pyfpdb/DerivedStats.py | 13 +++++- pyfpdb/Hand.py | 4 +- 3 files changed, 32 insertions(+), 87 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index ac2ea49e..e80c4694 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1421,19 +1421,29 @@ class Database: p['street4Pot'], p['showdownPot'] )) - #return getLastInsertId(backend, conn, cursor) + return self.get_last_insert_id(self.cursor) # def storeHand - def storeHandsPlayers(self, hid, pid, p): + def storeHandsPlayers(self, hid, pids, pdata): + #print "DEBUG: %s %s %s" %(hid, pids, pdata) + inserts = [] + for p in pdata: + inserts.append( (hid, + pids[p], + pdata[p]['startCash'], + pdata[p]['seatNo'] + ) ) + q = """INSERT INTO HandsPlayers ( handId, - playerId + playerId, + startCash, + seatNo ) VALUES ( - %s, %s + %s, %s, %s, %s )""" -# startCash, # position, # tourneyTypeId, # card1, @@ -1443,7 +1453,6 @@ class Database: # startCards, # winnings, # rake, -# seatNo, # totalProfit, # street0VPI, # street0Aggr, @@ -1511,85 +1520,8 @@ class Database: q = q.replace('%s', self.sql.query['placeholder']) - self.cursor.execute(q, ( - hid, - pid - )) -# startCash, -# position, -# tourneyTypeId, -# card1, -# card2, -# card3, -# card4, -# startCards, -# winnings, -# rake, -# seatNo, -# totalProfit, -# street0VPI, -# street0Aggr, -# street0_3BChance, -# street0_3BDone, -# street1Seen, -# street2Seen, -# street3Seen, -# street4Seen, -# sawShowdown, -# street1Aggr, -# street2Aggr, -# street3Aggr, -# street4Aggr, -# otherRaisedStreet1, -# otherRaisedStreet2, -# otherRaisedStreet3, -# otherRaisedStreet4, -# foldToOtherRaisedStreet1, -# foldToOtherRaisedStreet2, -# foldToOtherRaisedStreet3, -# foldToOtherRaisedStreet4, -# wonWhenSeenStreet1, -# wonAtSD, -# stealAttemptChance, -# stealAttempted, -# foldBbToStealChance, -# foldedBbToSteal, -# foldSbToStealChance, -# foldedSbToSteal, -# street1CBChance, -# street1CBDone, -# street2CBChance, -# street2CBDone, -# street3CBChance, -# street3CBDone, -# street4CBChance, -# street4CBDone, -# foldToStreet1CBChance, -# foldToStreet1CBDone, -# foldToStreet2CBChance, -# foldToStreet2CBDone, -# foldToStreet3CBChance, -# foldToStreet3CBDone, -# foldToStreet4CBChance, -# foldToStreet4CBDone, -# street1CheckCallRaiseChance, -# street1CheckCallRaiseDone, -# street2CheckCallRaiseChance, -# street2CheckCallRaiseDone, -# street3CheckCallRaiseChance, -# street3CheckCallRaiseDone, -# street4CheckCallRaiseChance, -# street4CheckCallRaiseDone, -# street0Calls, -# street1Calls, -# street2Calls, -# street3Calls, -# street4Calls, -# street0Bets, -# street1Bets, -# street2Bets, -# street3Bets, -# street4Bets + #print "DEBUG: inserts: %s" %inserts + self.cursor.executemany(q, inserts) def storeHudCacheNew(self, gid, pid, hc): q = """INSERT INTO HudCache ( diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 315ae707..fd4ffd0e 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -39,6 +39,9 @@ class DerivedStats(): def getHands(self): return self.hands + def getHandsPlayers(self): + return self.handsplayers + def assembleHands(self, hand): self.hands['tableName'] = hand.tablename self.hands['siteHandNo'] = hand.handid @@ -77,10 +80,18 @@ class DerivedStats(): # commentTs DATETIME def assembleHandsPlayers(self, hand): - self.vpip(self.hand) + #self.vpip(self.hand) + + #hand.players = [[seat, name, chips],[seat, name, chips]] + for player in hand.players: + self.handsplayers[player[1]] = {} + self.handsplayers[player[1]]['seatNo'] = player[0] + self.handsplayers[player[1]]['startCash'] = player[2] + for i, street in enumerate(hand.actionStreets[1:]): self.aggr(self.hand, i) + def assembleHudCache(self, hand): # # def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo # # ,winnings, totalWinnings, positions, actionTypes, actionAmounts, antes): diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 2527f636..d8dc1889 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -206,13 +206,14 @@ db: a connected fpdb_db object""" gtid = db.getGameTypeId(self.siteId, self.gametype) self.stats.assembleHands(self) + self.stats.assembleHandsPlayers(self) ##### # End prep functions ##### - # HudCache data to come from DerivedStats class # HandsActions - all actions for all players for all streets - self.actions + # HudCache data can be generated from HandsActions (HandsPlayers?) # Hands - Summary information of hand indexed by handId - gameinfo hh = self.stats.getHands() @@ -223,6 +224,7 @@ db: a connected fpdb_db object""" #print hh handid = db.storeHand(hh) # HandsPlayers - ? ... Do we fix winnings? + db.storeHandsPlayers(handid, sqlids, self.stats.getHandsPlayers()) # Tourneys ? # TourneysPlayers From 7b2c1fa24300661e8b82fd9c40f016749a63d8a2 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 14 Oct 2009 20:28:07 +0800 Subject: [PATCH 35/52] [NEWIMPORT] Minor update, use DerivedStats.getStats() --- pyfpdb/DerivedStats.py | 15 ++++++--------- pyfpdb/Hand.py | 3 +-- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index fd4ffd0e..5f0d2aff 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -80,11 +80,8 @@ class DerivedStats(): # commentTs DATETIME def assembleHandsPlayers(self, hand): - #self.vpip(self.hand) - #hand.players = [[seat, name, chips],[seat, name, chips]] for player in hand.players: - self.handsplayers[player[1]] = {} self.handsplayers[player[1]]['seatNo'] = player[0] self.handsplayers[player[1]]['startCash'] = player[2] @@ -788,14 +785,14 @@ class DerivedStats(): if act[1] in ('calls','bets', 'raises'): vpipers.add(act[0]) - #for player in hand.players: - # print "DEBUG: '%s' '%s' '%s'" %(player, player[1], vpipers) - # if player[1] in vpipers: - # self.handsplayers[player[1]]['vpip'] = True - # else: - # self.handsplayers[player[1]]['vpip'] = False self.hands['playersVpi'] = len(vpipers) + for player in hand.players: + if player[1] in vpipers: + self.handsplayers[player[1]]['vpip'] = True + else: + self.handsplayers[player[1]]['vpip'] = False + def playersAtStreetX(self, hand): """ playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4/draw1 */""" # self.actions[street] is a list of all actions in a tuple, contining the player name first diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index d8dc1889..602a6a1a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -205,8 +205,7 @@ db: a connected fpdb_db object""" #Gametypes gtid = db.getGameTypeId(self.siteId, self.gametype) - self.stats.assembleHands(self) - self.stats.assembleHandsPlayers(self) + self.stats.getStats(self) ##### # End prep functions From a232a94eb1d36f59b79c8b67682b1572633661f3 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Wed, 14 Oct 2009 16:04:09 +0300 Subject: [PATCH 36/52] Try to make hud more configurable Modified files: * Configuration.py * HUD_config.xml.example * HUD_main.py Instead of tweaking aggregation settings directly in code, make the values configurable through HUD_config.xml; use the newly created element for this. Retain coding convention and key-value names as they are. --- pyfpdb/Configuration.py | 47 ++++++++++++++++++ pyfpdb/HUD_config.xml.example | 93 ++++++++++++++++++++++++++++++++++- pyfpdb/HUD_main.py | 2 +- 3 files changed, 139 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 89f4fb29..7f0f937e 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -282,6 +282,19 @@ class HudUI: def __init__(self, node): self.node = node self.label = node.getAttribute('label') + # + self.aggregate_ring = fix_tf(node.getAttribute('aggregate_ring_game_stats')) + self.aggregate_tour = fix_tf(node.getAttribute('aggregate_tourney_stats')) + self.hud_style = node.getAttribute('stat_aggregation_range') + self.hud_days = node.getAttribute('aggregation_days') + self.agg_bb_mult = node.getAttribute('aggregation_level_multiplier') + # + self.h_aggregate_ring = fix_tf(node.getAttribute('aggregate_hero_ring_game_stats')) + self.h_aggregate_tour = fix_tf(node.getAttribute('aggregate_hero_tourney_stats')) + self.h_hud_style = node.getAttribute('hero_stat_aggregation_range') + self.h_hud_days = node.getAttribute('hero_aggregation_days') + self.h_agg_bb_mult = node.getAttribute('hero_aggregation_level_multiplier') + def __str__(self): return " label = %s\n" % self.label @@ -629,6 +642,7 @@ class Config: # Allow to change the menu appearance def get_hud_ui_parameters(self): hui = {} + default_text = 'FPDB Menu - Right click\nLeft-Drag to Move' try: hui['label'] = self.ui.label @@ -636,6 +650,39 @@ class Config: hui['label'] = default_text except: hui['label'] = default_text + + try: hui['aggregate_ring'] = self.ui.aggregate_ring + except: hui['aggregate_ring'] = False + + try: hui['aggregate_tour'] = self.ui.aggregate_tour + except: hui['aggregate_tour'] = True + + try: hui['hud_style'] = self.ui.hud_style + except: hui['hud_style'] = 'A' + + try: hui['hud_days'] = self.ui.hud_days + except: hui['hud_days'] = 90 + + try: hui['agg_bb_mult'] = self.ui.agg_bb_mult + except: hui['agg_bb_mult'] = 1 + + # Hero specific + + try: hui['h_aggregate_ring'] = self.ui.h_aggregate_ring + except: hui['h_aggregate_ring'] = False + + try: hui['h_aggregate_tour'] = self.ui.h_aggregate_tour + except: hui['h_aggregate_tour'] = True + + try: hui['h_hud_style'] = self.ui.h_hud_style + except: hui['h_hud_style'] = 'S' + + try: hui['h_hud_days'] = self.ui.h_hud_days + except: hui['h_hud_days'] = 30 + + try: hui['h_agg_bb_mult'] = self.ui.h_agg_bb_mult + except: hui['h_agg_bb_mult'] = 1 + return hui diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index de2f1bba..1fe19c5a 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -4,8 +4,97 @@ - + + + diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 23c1ef03..95a25a29 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -91,7 +91,7 @@ class HUD_main(object): self.db_name = db_name self.config = Configuration.Config(file=options.config, dbname=options.dbname) self.hud_dict = {} - self.hud_params = def_hud_params + self.hud_params = self.config.get_hud_ui_parameters() # a thread to read stdin gobject.threads_init() # this is required From 16d1f43c7e34c7be3e0452a8ae82b36ddd728ce3 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 14 Oct 2009 23:55:51 +0800 Subject: [PATCH 37/52] [NEWIMPORT] HandsPlayers.streetXAggr insert. --- pyfpdb/Database.py | 20 +++++++++++++------- pyfpdb/DerivedStats.py | 2 ++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index e80c4694..d25b309c 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1431,16 +1431,27 @@ class Database: inserts.append( (hid, pids[p], pdata[p]['startCash'], - pdata[p]['seatNo'] + pdata[p]['seatNo'], + pdata[p]['street0Aggr'], + pdata[p]['street1Aggr'], + pdata[p]['street2Aggr'], + pdata[p]['street3Aggr'], + pdata[p]['street4Aggr'] ) ) q = """INSERT INTO HandsPlayers ( handId, playerId, startCash, - seatNo + seatNo, + street0Aggr, + street1Aggr, + street2Aggr, + street3Aggr, + street4Aggr ) VALUES ( + %s, %s, %s, %s, %s, %s, %s, %s, %s )""" @@ -1455,7 +1466,6 @@ class Database: # rake, # totalProfit, # street0VPI, -# street0Aggr, # street0_3BChance, # street0_3BDone, # street1Seen, @@ -1463,10 +1473,6 @@ class Database: # street3Seen, # street4Seen, # sawShowdown, -# street1Aggr, -# street2Aggr, -# street3Aggr, -# street4Aggr, # otherRaisedStreet1, # otherRaisedStreet2, # otherRaisedStreet3, diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 5f0d2aff..5b69bbfb 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -29,6 +29,8 @@ class DerivedStats(): for player in hand.players: self.handsplayers[player[1]] = {} + #Init vars that may not be used, but still need to be inserted. + self.handsplayers[player[1]]['street4Aggr'] = False self.assembleHands(self.hand) self.assembleHandsPlayers(self.hand) From 54d309f797d68a6b629ecbb278431fd25e50865e Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Wed, 14 Oct 2009 19:33:19 +0300 Subject: [PATCH 38/52] Minor fixes to hud setup code --- pyfpdb/Configuration.py | 4 ++-- pyfpdb/HUD_config.xml.example | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 7f0f937e..924d6584 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -660,7 +660,7 @@ class Config: try: hui['hud_style'] = self.ui.hud_style except: hui['hud_style'] = 'A' - try: hui['hud_days'] = self.ui.hud_days + try: hui['hud_days'] = int(self.ui.hud_days) except: hui['hud_days'] = 90 try: hui['agg_bb_mult'] = self.ui.agg_bb_mult @@ -677,7 +677,7 @@ class Config: try: hui['h_hud_style'] = self.ui.h_hud_style except: hui['h_hud_style'] = 'S' - try: hui['h_hud_days'] = self.ui.h_hud_days + try: hui['h_hud_days'] = int(self.ui.h_hud_days) except: hui['h_hud_days'] = 30 try: hui['h_agg_bb_mult'] = self.ui.h_agg_bb_mult diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index 1fe19c5a..bfeafd8d 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -82,7 +82,7 @@ Date: Thu, 15 Oct 2009 11:57:42 +0800 Subject: [PATCH 39/52] Make GuiBulkImport allow multi-file select --- pyfpdb/GuiBulkImport.py | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 21f9e050..de8580df 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -40,21 +40,6 @@ class GuiBulkImport(): # CONFIGURATION - update these as preferred: allowThreads = True # set to True to try out the threads field - # not used - def import_dir(self): - """imports a directory, non-recursive. todo: move this to fpdb_import so CLI can use it""" - - self.path = self.inputFile - self.importer.addImportDirectory(self.path) - self.importer.setCallHud(False) - starttime = time() - if not self.importer.settings['threads'] > 1: - (stored, dups, partial, errs, ttime) = self.importer.runImport() - print 'GuiBulkImport.import_dir done: Stored: %d Duplicates: %d Partial: %d Errors: %d in %s seconds - %d/sec'\ - % (stored, dups, partial, errs, ttime, stored / ttime) - else: - self.importer.RunImportThreaded() - def dopulse(self): self.progressbar.pulse() return True @@ -77,7 +62,7 @@ class GuiBulkImport(): self.timer = gobject.timeout_add(100, self.dopulse) # get the dir to import from the chooser - self.inputFile = self.chooser.get_filename() + selected = self.chooser.get_filenames() # get the import settings from the gui and save in the importer self.importer.setHandCount(int(self.spin_hands.get_text())) @@ -103,7 +88,8 @@ class GuiBulkImport(): self.importer.setDropHudCache("auto") sitename = self.cbfilter.get_model()[self.cbfilter.get_active()][0] - self.importer.addBulkImportImportFileOrDir(self.inputFile, site = sitename) + for selection in selected: + self.importer.addBulkImportImportFileOrDir(selection, site = sitename) self.importer.setCallHud(False) starttime = time() # try: @@ -151,6 +137,7 @@ class GuiBulkImport(): self.chooser = gtk.FileChooserWidget() self.chooser.set_filename(self.settings['bulkImport-defaultPath']) + self.chooser.set_select_multiple(True) self.vbox.add(self.chooser) self.chooser.show() From 7a9237b70773ffb0a50ffd4c9a12991ea83a0d91 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 15 Oct 2009 15:12:08 +0800 Subject: [PATCH 40/52] GuiBulkImport - make cli version print out import stats --- pyfpdb/GuiBulkImport.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index de8580df..667e4d6c 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -337,8 +337,10 @@ def main(argv=None): importer.setThreads(-1) importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername) importer.setCallHud(False) - importer.runImport() + (stored, dups, partial, errs, ttime) = importer.runImport() importer.clearFileList() + print 'GuiBulkImport done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec'\ + % (stored, dups, partial, errs, ttime, (stored+0.0) / ttime) if __name__ == '__main__': From c3bc165a902e13321f834cfc554d749523a8a5ca Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 15 Oct 2009 15:13:09 +0800 Subject: [PATCH 41/52] Add comment to DerivedStats --- pyfpdb/DerivedStats.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 5b69bbfb..106bd038 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -801,6 +801,8 @@ class DerivedStats(): # [ (player, action, ....), (player2, action, ...) ] # The number of unique players in the list per street gives the value for playersAtStreetXXX + # FIXME?? - This isn't couting people that are all in - at least showdown needs to reflect this + self.hands['playersAtStreet1'] = 0 self.hands['playersAtStreet2'] = 0 self.hands['playersAtStreet3'] = 0 From ceaa78bdc80677adff393f6abb263c61e99ca765 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 15 Oct 2009 15:23:47 +0800 Subject: [PATCH 42/52] Add usage message to GuiBulkImport cli I keep forgetting the format for Full Tilt cli import --- pyfpdb/GuiBulkImport.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 667e4d6c..9cb54d50 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -304,8 +304,20 @@ def main(argv=None): help="If this option is passed it quits when it encounters any error") parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int", help="How often to print a one-line status report (0 (default) means never)") + parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False, + help="Print some useful one liners") (options, sys.argv) = parser.parse_args(args = argv) + if options.usage == True: + #Print usage examples and exit + print "USAGE:" + print 'PokerStars converter: ./GuiBulkImport -c PokerStars -f filename' + print 'Full Tilt converter: ./GuiBulkImport -c "Full Tilt Poker" -f filename' + print "Everleaf converter: ./GuiBulkImport -c Everleaf -f filename" + print "Absolute converter: ./GuiBulkImport -c Absolute -f filename" + print "PartyPoker converter: ./GuiBulkImport -c PartyPoker -f filename" + sys.exit(0) + config = Configuration.Config() settings = {} From ac50cf85ca475da3cf0251ba0ed4bfd6e1a9fdc7 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 15 Oct 2009 23:02:50 +0100 Subject: [PATCH 43/52] update comments on aggregation --- pyfpdb/HUD_main.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 23c1ef03..e71c3ee9 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -59,9 +59,11 @@ import Hud # 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 aggregation is used, the value of agg_bb_mult determines what levels are included. If +# agg_bb_mult is M and current blind level is L, blinds between L/M and L*M are included. e.g. # if agg_bb_mult is 100, almost all levels are included in all HUD displays -# if agg_bb_mult is 2.1, levels from half to double the current blind level are included in the HUD +# if agg_bb_mult is 2, levels from half to double the current blind level are included in the HUD +# if agg_bb_mult is 1 only the current level is included # - Set hud_style to A to see stats for all-time # Set hud_style to S to only see stats for current session (currently this shows stats for the last 24 hours) # Set hud_style to T to only see stats for the last N days (uses value in hud_days) @@ -71,14 +73,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' : 10000 # 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' : 'S' # A(ll) / S(ession) / T(ime in days) - , 'h_hud_days' : 30 - , 'h_agg_bb_mult' : 1 # 1 means no aggregation + , 'h_hud_days' : 60 + , 'h_agg_bb_mult' : 10000 # 1 means no aggregation # , 'h_hud_session_gap' : 30 not currently used } From 639036871b6e6859dcb388be100d07d8aeeef7b6 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 18 Oct 2009 07:54:41 +0800 Subject: [PATCH 44/52] HUD_config.xml.example update Added Betfair to default config - copied Party. Also went through and cleaned up whitespace in that file at the same time - tabs to spaces, cleaned trailing spaces. --- pyfpdb/HUD_config.xml.example | 778 ++++++++++++++++++---------------- 1 file changed, 412 insertions(+), 366 deletions(-) diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index bfeafd8d..34a8f16d 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -96,359 +96,404 @@ Left-Drag to Move" /> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + bgcolor="#000000" + fgcolor="#FFFFFF" + hudopacity="1.0" + font="Sans" + font_size="8" + supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + bgcolor="#000000" + fgcolor="#FFFFFF" + hudopacity="1.0" + font="Sans" + font_size="8" + supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + supported_games="holdem"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + supported_games="holdem"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + supported_games="holdem"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + supported_games="holdem"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - + - + @@ -468,50 +513,50 @@ Left-Drag to Move" - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -521,6 +566,7 @@ Left-Drag to Move" + From cfc854ab50e3e0771a7326ac0ffc058b94c1ac5c Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 18 Oct 2009 07:56:34 +0800 Subject: [PATCH 45/52] Fix some bugs in BetfairToFpdb. As reported by tchaz on 2+2: http://forumserver.twoplustwo.com/showpost.php?p=13870274&postcount=1960 Using the only sample file I have for Betfair, it appears there is still and accounting error --- pyfpdb/BetfairToFpdb.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pyfpdb/BetfairToFpdb.py b/pyfpdb/BetfairToFpdb.py index 59344991..f4d8bf9b 100755 --- a/pyfpdb/BetfairToFpdb.py +++ b/pyfpdb/BetfairToFpdb.py @@ -105,7 +105,7 @@ class Betfair(HandHistoryConverter): logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE'))) hand.handid = m.group('HID') hand.tablename = m.group('TABLE') - hand.starttime = time.strptime(m.group('DATETIME'), "%A, %B %d, %H:%M:%S GMT %Y") + hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%A, %B %d, %H:%M:%S GMT %Y") #hand.buttonpos = int(m.group('BUTTON')) def readPlayerStacks(self, hand): @@ -144,6 +144,7 @@ class Betfair(HandHistoryConverter): def readAntes(self, hand): logging.debug("reading antes") + m = self.re_Antes.finditer(hand.handText) for player in m: logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))) hand.addAnte(player.group('PNAME'), player.group('ANTE')) @@ -160,17 +161,15 @@ class Betfair(HandHistoryConverter): hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON')) def readHeroCards(self, hand): - m = self.re_HeroCards.search(hand.handText) - if(m == None): - #Not involved in hand - hand.involved = False - else: - hand.hero = m.group('PNAME') - # "2c, qh" -> set(["2c","qc"]) - # Also works with Omaha hands. - cards = m.group('CARDS') - cards = [c.strip() for c in cards.split(',')] - hand.addHoleCards(cards, m.group('PNAME')) + # streets PREFLOP, PREDRAW, and THIRD are special cases beacause + # we need to grab hero's cards + for street in ('PREFLOP', 'DEAL'): + if street in hand.streets.keys(): + m = self.re_HeroCards.finditer(hand.streets[street]) + for found in m: + hand.hero = found.group('PNAME') + newcards = [c.strip() for c in found.group('CARDS').split(',')] + hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True) def readStudPlayerCards(self, hand, street): # balh blah blah From 5beb0335476bc34c642fdc5fd4eb39b99a1eff7f Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 18 Oct 2009 12:19:22 +0100 Subject: [PATCH 46/52] debug session stats --- pyfpdb/Database.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index d25b309c..828efba0 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -392,7 +392,7 @@ class Database: print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) else: if row and row[0]: - self.hand_1_day_ago = row[0] + self.hand_1day_ago = int(row[0]) d = timedelta(days=hud_days) now = datetime.utcnow() - d @@ -434,10 +434,6 @@ class Database: 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) - try: - print "Session: hero_id =", hero_id, "hds =", stat_dict[hero_id]['n'] - except: - pass if hud_style == 'S' and h_hud_style == 'S': return stat_dict @@ -463,7 +459,7 @@ class Database: #if aggregate: always use aggregate 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 + #print "agg query subs:", subs #else: # query = 'get_stats_from_hand' # subs = (hand, stylekey) @@ -482,10 +478,6 @@ class Database: t_dict[name.lower()] = val # print t_dict stat_dict[t_dict['player_id']] = t_dict - try: - print "get_stats end: hero_id =", hero_id, "hds =", stat_dict[hero_id]['n'] - except: - pass return stat_dict From 6453154ef6aec454419c2ac46c41d507fa1478bd Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 18 Oct 2009 17:18:07 +0100 Subject: [PATCH 47/52] prepare for all players display --- pyfpdb/GuiPlayerStats.py | 68 ++++++++++++++++++++++++++++------------ pyfpdb/SQL.py | 6 +++- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 4b82c861..9d90974c 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -82,6 +82,7 @@ class GuiPlayerStats (threading.Thread): self.columns = [ ["game", True, "Game", 0.0, "%s"] , ["hand", False, "Hand", 0.0, "%s"] # true not allowed for this line , ["plposition", False, "Posn", 1.0, "%s"] # true not allowed for this line (set in code) + , ["pname", False, "Name", 0.0, "%s"] # true not allowed for this line (set in code) , ["n", True, "Hds", 1.0, "%d"] , ["avgseats", False, "Seats", 1.0, "%3.1f"] , ["vpip", True, "VPIP", 1.0, "%3.1f"] @@ -125,8 +126,9 @@ class GuiPlayerStats (threading.Thread): self.stats_vbox = None self.detailFilters = [] # the data used to enhance the sql select - self.main_hbox = gtk.HBox(False, 0) - self.main_hbox.show() + #self.main_hbox = gtk.HBox(False, 0) + #self.main_hbox.show() + self.main_hbox = gtk.HPaned() self.stats_frame = gtk.Frame() self.stats_frame.show() @@ -136,8 +138,11 @@ class GuiPlayerStats (threading.Thread): self.stats_frame.add(self.stats_vbox) # self.fillStatsFrame(self.stats_vbox) - self.main_hbox.pack_start(self.filters.get_vbox()) - self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True) + #self.main_hbox.pack_start(self.filters.get_vbox()) + #self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True) + self.main_hbox.pack1(self.filters.get_vbox()) + self.main_hbox.pack2(self.stats_frame) + self.main_hbox.show() # make sure Hand column is not displayed [x for x in self.columns if x[0] == 'hand'][0][1] = False @@ -149,7 +154,8 @@ class GuiPlayerStats (threading.Thread): def refreshStats(self, widget, data): try: self.stats_vbox.destroy() except AttributeError: pass - self.stats_vbox = gtk.VBox(False, 0) + #self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox = gtk.VPaned() self.stats_vbox.show() self.stats_frame.add(self.stats_vbox) self.fillStatsFrame(self.stats_vbox) @@ -192,27 +198,44 @@ class GuiPlayerStats (threading.Thread): def createStatsTable(self, vbox, playerids, sitenos, limits, type, seats, groups, dates): starttime = time() + #groups['allplayers'] = True # testing + + # Scrolled window for summary table + swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) + swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + swin.show() + #vbox.pack_start(swin, expand=True, padding=3) + vbox.pack1(swin) + + vbox1 = gtk.VBox(False, 0) + vbox1.show() + swin.add_with_viewport(vbox1) # Display summary table at top of page # 3rd parameter passes extra flags, currently includes: # holecards - whether to display card breakdown (True/False) flags = [False] - self.addTable(vbox, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) + self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) + + # Only display one section if all players being shown (query currently too slow for startcards) + if 'allplayers' in groups and groups['allplayers']: + return # Separator - sep = gtk.HSeparator() - vbox.pack_start(sep, expand=False, padding=3) - sep.show_now() - vbox.show_now() - heading = gtk.Label(self.filterText['handhead']) - heading.show() - vbox.pack_start(heading, expand=False, padding=3) + #sep = gtk.HSeparator() + #vbox.pack_start(sep, expand=False, padding=3) + #sep.show_now() + #vbox.show_now() + #heading = gtk.Label(self.filterText['handhead']) + #heading.show() + #vbox.pack_start(heading, expand=False, padding=3) # Scrolled window for detailed table (display by hand) swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) swin.show() - vbox.pack_start(swin, expand=True, padding=3) + #vbox.pack_start(swin, expand=True, padding=3) + vbox.pack2(swin) vbox1 = gtk.VBox(False, 0) vbox1.show() @@ -326,13 +349,18 @@ class GuiPlayerStats (threading.Thread): if not flags: holecards = False else: holecards = flags[0] - if playerids: - nametest = str(tuple(playerids)) - nametest = nametest.replace("L", "") - nametest = nametest.replace(",)",")") - query = query.replace("", nametest) + if 'allplayers' in groups and groups['allplayers']: + nametest = "(select id from players)" + # set flag in self.columns to show player name column + [x for x in self.columns if x[0] == 'pname'][0][1] = True else: - query = query.replace("", "1 = 2") + if playerids: + nametest = str(tuple(playerids)) + nametest = nametest.replace("L", "") + nametest = nametest.replace(",)",")") + else: + nametest = "1 = 2" + query = query.replace("", nametest) if seats: query = query.replace('', 'between ' + str(seats['from']) + ' and ' + str(seats['to'])) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 629f682e..a226825f 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1807,6 +1807,7 @@ class Sql: elif db_server == 'postgresql': self.query['playerDetailedStats'] = """ select AS hgametypeid + ,p.name AS pname ,gt.base ,gt.category ,upper(gt.limitType) AS limittype @@ -1857,6 +1858,7 @@ class Sql: inner join Hands h on (h.id = hp.handId) inner join Gametypes gt on (gt.Id = h.gameTypeId) inner join Sites s on (s.Id = gt.siteId) + inner join Players p on (p.Id = hp.playerId) where hp.playerId in /*and hp.tourneysPlayersId IS NULL*/ and h.seats @@ -1864,6 +1866,7 @@ class Sql: and to_char(h.handStart, 'YYYY-MM-DD') group by hgameTypeId + ,pname ,hp.playerId ,gt.base ,gt.category @@ -1871,7 +1874,8 @@ class Sql: ,plposition ,upper(gt.limitType) ,s.name - order by hp.playerId + order by pname + ,hp.playerId ,gt.base ,gt.category From c1a998b7d87b9de7ddb0a206613566c84b76eafb Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 18 Oct 2009 22:56:10 +0100 Subject: [PATCH 48/52] add all player (and min hands) ability to stats window --- pyfpdb/Filters.py | 45 ++++++++++++++++++++++++++++----- pyfpdb/GuiPlayerStats.py | 54 +++++++++++++++++++++++++++++----------- pyfpdb/SQL.py | 5 ++-- 3 files changed, 80 insertions(+), 24 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 6ad242bb..e67df502 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -55,6 +55,7 @@ class Filters(threading.Thread): ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' + ,'groupsall':'All Players' ,'limitsFL':'FL', 'limitsNL':'NL', 'ring':'Ring', 'tour':'Tourney' } @@ -64,6 +65,10 @@ class Filters(threading.Thread): self.start_date.set_property('editable', False) self.end_date.set_property('editable', False) + # For use in groups etc + self.sbGroups = {} + self.numHands = 0 + # Outer Packing box self.mainVBox = gtk.VBox(False, 0) @@ -71,7 +76,7 @@ class Filters(threading.Thread): playerFrame.set_label_align(0.0, 0.0) vbox = gtk.VBox(False, 0) - self.fillPlayerFrame(vbox) + self.fillPlayerFrame(vbox, self.display) playerFrame.add(vbox) self.boxes['player'] = vbox @@ -122,7 +127,6 @@ class Filters(threading.Thread): groupsFrame = gtk.Frame() groupsFrame.show() vbox = gtk.VBox(False, 0) - self.sbGroups = {} self.fillGroupsFrame(vbox, self.display) groupsFrame.add(vbox) @@ -181,6 +185,9 @@ class Filters(threading.Thread): return self.mainVBox #end def get_vbox + def getNumHands(self): + return self.numHands + def getSites(self): return self.sites @@ -256,6 +263,13 @@ class Filters(threading.Thread): self.heroes[site] = w.get_text() # print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site]) + def __set_num_hands(self, w, val): + try: + self.numHands = int(w.get_text()) + except: + self.numHands = 0 + print "DEBUG: setting numHands:", self.numHands + def createSiteLine(self, hbox, site): cb = gtk.CheckButton(site) cb.connect('clicked', self.__set_site_select, site) @@ -393,13 +407,32 @@ class Filters(threading.Thread): self.groups[group] = w.get_active() print "self.groups[%s] set to %s" %(group, self.groups[group]) - def fillPlayerFrame(self, vbox): + def fillPlayerFrame(self, vbox, display): for site in self.conf.get_supported_sites(): - pathHBox = gtk.HBox(False, 0) - vbox.pack_start(pathHBox, False, True, 0) + hBox = gtk.HBox(False, 0) + vbox.pack_start(hBox, False, True, 0) player = self.conf.supported_sites[site].screen_name - self.createPlayerLine(pathHBox, site, player) + self.createPlayerLine(hBox, site, player) + + if "GroupsAll" in display and display["GroupsAll"] == True: + hbox = gtk.HBox(False, 0) + vbox.pack_start(hbox, False, False, 0) + cb = gtk.CheckButton(self.filterText['groupsall']) + cb.connect('clicked', self.__set_group_select, 'allplayers') + hbox.pack_start(cb, False, False, 0) + self.sbGroups['allplayers'] = cb + self.groups['allplayers'] = False + + lbl = gtk.Label('Min # Hands:') + lbl.set_alignment(xalign=1.0, yalign=0.5) + hbox.pack_start(lbl, expand=True, padding=3) + + phands = gtk.Entry() + phands.set_text('0') + phands.set_width_chars(8) + hbox.pack_start(phands, False, False, 0) + phands.connect("changed", self.__set_num_hands, site) def fillSitesFrame(self, vbox): for site in self.conf.get_supported_sites(): diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 9d90974c..cb5f2936 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -65,6 +65,7 @@ class GuiPlayerStats (threading.Thread): "SeatSep" : True, "Dates" : True, "Groups" : True, + "GroupsAll" : True, "Button1" : True, "Button2" : True } @@ -198,7 +199,6 @@ class GuiPlayerStats (threading.Thread): def createStatsTable(self, vbox, playerids, sitenos, limits, type, seats, groups, dates): starttime = time() - #groups['allplayers'] = True # testing # Scrolled window for summary table swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) @@ -214,35 +214,38 @@ class GuiPlayerStats (threading.Thread): # Display summary table at top of page # 3rd parameter passes extra flags, currently includes: # holecards - whether to display card breakdown (True/False) - flags = [False] + # numhands - min number hands required when displaying all players + flags = [False, self.filters.getNumHands()] self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) # Only display one section if all players being shown (query currently too slow for startcards) - if 'allplayers' in groups and groups['allplayers']: - return + #if 'allplayers' in groups and groups['allplayers'] and 1==2: + # return # Separator #sep = gtk.HSeparator() #vbox.pack_start(sep, expand=False, padding=3) #sep.show_now() #vbox.show_now() - #heading = gtk.Label(self.filterText['handhead']) - #heading.show() - #vbox.pack_start(heading, expand=False, padding=3) + vbox2 = gtk.VBox(False, 0) + heading = gtk.Label(self.filterText['handhead']) + heading.show() + vbox2.pack_start(heading, expand=False, padding=3) # Scrolled window for detailed table (display by hand) swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) swin.show() - #vbox.pack_start(swin, expand=True, padding=3) - vbox.pack2(swin) + vbox2.pack_start(swin, expand=True, padding=3) + vbox.pack2(vbox2) + vbox2.show() vbox1 = gtk.VBox(False, 0) vbox1.show() swin.add_with_viewport(vbox1) # Detailed table - flags = [True] + flags[0] = True self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) self.db.rollback() @@ -346,13 +349,29 @@ class GuiPlayerStats (threading.Thread): #end def addTable(self, query, vars, playerids, sitenos, limits, type, seats, groups, dates): def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates): - if not flags: holecards = False - else: holecards = flags[0] + having = '' + if not flags: + holecards = False + numhands = 0 + else: + holecards = flags[0] + numhands = flags[1] if 'allplayers' in groups and groups['allplayers']: - nametest = "(select id from players)" - # set flag in self.columns to show player name column - [x for x in self.columns if x[0] == 'pname'][0][1] = True + nametest = "(hp.playerId)" + if holecards or groups['posn']: + pname = "'all players'" + # set flag in self.columns to not show player name column + [x for x in self.columns if x[0] == 'pname'][0][1] = False + # can't do this yet (re-write doing more maths in python instead of sql?) + if numhands: + nametest = "(-1)" + else: + pname = "p.name" + # set flag in self.columns to show player name column + [x for x in self.columns if x[0] == 'pname'][0][1] = True + if numhands: + having = ' and count(1) > %d ' % (numhands,) else: if playerids: nametest = str(tuple(playerids)) @@ -360,7 +379,12 @@ class GuiPlayerStats (threading.Thread): nametest = nametest.replace(",)",")") else: nametest = "1 = 2" + pname = "p.name" + # set flag in self.columns to not show player name column + [x for x in self.columns if x[0] == 'pname'][0][1] = False query = query.replace("", nametest) + query = query.replace("", pname) + query = query.replace("", having) if seats: query = query.replace('', 'between ' + str(seats['from']) + ' and ' + str(seats['to'])) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index a226825f..4b137e0c 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1807,7 +1807,7 @@ class Sql: elif db_server == 'postgresql': self.query['playerDetailedStats'] = """ select AS hgametypeid - ,p.name AS pname + , AS pname ,gt.base ,gt.category ,upper(gt.limitType) AS limittype @@ -1867,15 +1867,14 @@ class Sql: and to_char(h.handStart, 'YYYY-MM-DD') group by hgameTypeId ,pname - ,hp.playerId ,gt.base ,gt.category ,plposition ,upper(gt.limitType) ,s.name + having 1 = 1 order by pname - ,hp.playerId ,gt.base ,gt.category From 4b7aadd32559c2364060586f4bfb0a8ffe3634ad Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 18 Oct 2009 23:19:26 +0100 Subject: [PATCH 49/52] fix starting hand order --- pyfpdb/GuiPlayerStats.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index cb5f2936..3946e629 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -424,9 +424,12 @@ class GuiPlayerStats (threading.Thread): bbtest = bbtest + " and gt.type = 'tour' " query = query.replace("", bbtest) - if holecards: # pinch level variables for hole card query + if holecards: # re-use level variables for hole card query query = query.replace("", "hp.startcards") - query = query.replace("", ",hgameTypeId desc") + query = query.replace("" + , ",case when hp.startcards/13 >= mod(hp.startcards,13) then hp.startcards + 0.1 " + + " else 13*mod(hp.startcards,13) + hp.startcards/13 " + + " end desc ") else: query = query.replace("", "") groupLevels = "show" not in str(limits) From 35cc1b1314b9546c3cbc575c8f54198020398540 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 19 Oct 2009 00:15:11 +0100 Subject: [PATCH 50/52] fix mysql code for new stats options --- pyfpdb/GuiPlayerStats.py | 4 ++-- pyfpdb/SQL.py | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 3946e629..7a474686 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -427,8 +427,8 @@ class GuiPlayerStats (threading.Thread): if holecards: # re-use level variables for hole card query query = query.replace("", "hp.startcards") query = query.replace("" - , ",case when hp.startcards/13 >= mod(hp.startcards,13) then hp.startcards + 0.1 " - + " else 13*mod(hp.startcards,13) + hp.startcards/13 " + , ",case when floor(hp.startcards/13) >= mod(hp.startcards,13) then hp.startcards + 0.1 " + + " else 13*mod(hp.startcards,13) + floor(hp.startcards/13) " + " end desc ") else: query = query.replace("", "") diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 4b137e0c..251a56fa 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1727,6 +1727,7 @@ class Sql: if db_server == 'mysql': self.query['playerDetailedStats'] = """ select AS hgametypeid + , AS pname ,gt.base ,gt.category ,upper(gt.limitType) AS limittype @@ -1777,6 +1778,7 @@ class Sql: inner join Hands h on (h.id = hp.handId) inner join Gametypes gt on (gt.Id = h.gameTypeId) inner join Sites s on (s.Id = gt.siteId) + inner join Players p on (p.Id = hp.playerId) where hp.playerId in /*and hp.tourneysPlayersId IS NULL*/ and h.seats @@ -1784,14 +1786,15 @@ class Sql: and date_format(h.handStart, '%Y-%m-%d') group by hgameTypeId - ,hp.playerId + ,pname ,gt.base ,gt.category ,plposition ,upper(gt.limitType) ,s.name - order by hp.playerId + having 1 = 1 + order by pname ,gt.base ,gt.category From 2c7a853b3f6bc5c2942d33b4bca5697902cb75c6 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 19 Oct 2009 00:36:08 +0100 Subject: [PATCH 51/52] keep heading on screen when scrolling stats windows --- pyfpdb/GuiPlayerStats.py | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 7a474686..e51ff4a3 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -204,29 +204,16 @@ class GuiPlayerStats (threading.Thread): swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None) swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) swin.show() - #vbox.pack_start(swin, expand=True, padding=3) vbox.pack1(swin) - vbox1 = gtk.VBox(False, 0) - vbox1.show() - swin.add_with_viewport(vbox1) - # Display summary table at top of page # 3rd parameter passes extra flags, currently includes: # holecards - whether to display card breakdown (True/False) # numhands - min number hands required when displaying all players flags = [False, self.filters.getNumHands()] - self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) - - # Only display one section if all players being shown (query currently too slow for startcards) - #if 'allplayers' in groups and groups['allplayers'] and 1==2: - # return + self.addTable(swin, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) # Separator - #sep = gtk.HSeparator() - #vbox.pack_start(sep, expand=False, padding=3) - #sep.show_now() - #vbox.show_now() vbox2 = gtk.VBox(False, 0) heading = gtk.Label(self.filterText['handhead']) heading.show() @@ -240,13 +227,9 @@ class GuiPlayerStats (threading.Thread): vbox.pack2(vbox2) vbox2.show() - vbox1 = gtk.VBox(False, 0) - vbox1.show() - swin.add_with_viewport(vbox1) - # Detailed table flags[0] = True - self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) + self.addTable(swin, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) self.db.rollback() print "Stats page displayed in %4.2f seconds" % (time() - starttime) @@ -272,7 +255,8 @@ class GuiPlayerStats (threading.Thread): liststore = gtk.ListStore(*([str] * len(cols_to_show))) view = gtk.TreeView(model=liststore) view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) - vbox.pack_start(view, expand=False, padding=3) + #vbox.pack_start(view, expand=False, padding=3) + vbox.add(view) textcell = gtk.CellRendererText() textcell50 = gtk.CellRendererText() textcell50.set_property('xalign', 0.5) From 6a029ccfa7850324950c65c0f0f9a331e40c50bc Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 19 Oct 2009 00:36:31 +0100 Subject: [PATCH 52/52] comment out debug statement --- pyfpdb/Filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index e67df502..08581c83 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -268,7 +268,7 @@ class Filters(threading.Thread): self.numHands = int(w.get_text()) except: self.numHands = 0 - print "DEBUG: setting numHands:", self.numHands +# print "DEBUG: setting numHands:", self.numHands def createSiteLine(self, hbox, site): cb = gtk.CheckButton(site)