From e880fb89546f9cbb2f36e519ee445fc843fedeb8 Mon Sep 17 00:00:00 2001 From: eblade Date: Thu, 2 Apr 2009 05:02:24 -0400 Subject: [PATCH 01/34] add a giant tooltip temporarily to the popup stats window --- pyfpdb/Hud.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index cf96893f..122e94a9 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -529,11 +529,15 @@ class Popup_window: # db_connection.close_connection() stat_dict = stat_window.parent.stat_dict pu_text = "" + mo_text = "" for s in stat_list: number = Stats.do_stat(stat_dict, player = int(stat_window.player_id), stat = s) + mo_text += number[5] + " " + number[4] + "\n" pu_text += number[3] + "\n" + - self.lab.set_text(pu_text) + self.lab.set_text(pu_text) + Stats.do_tip(self.lab, mo_text) self.window.show_all() self.window.set_transient_for(stat_window.window) From f1230c459c77aeed94442e5c5b88d692774b151a Mon Sep 17 00:00:00 2001 From: eblade Date: Sat, 30 May 2009 12:02:31 -0400 Subject: [PATCH 02/34] Apparently I made a comment and a change that I didn't realise before 0.11, and forgot to commit. oopsie. --- pyfpdb/Hud.py | 1 + pyfpdb/Tables.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 87cf9f14..8360dc20 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -473,6 +473,7 @@ class Popup_window: def __init__(self, parent, stat_window): self.sb_click = 0 self.stat_window = stat_window + self.parent = parent # create the popup window self.window = gtk.Window() diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index ffc50b01..7bc22710 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -309,6 +309,10 @@ def get_site_from_exe(c, exe): return params['site_name'] return None +def everleaf_decode_table(tw): +# 2 - Tournament ID: 573256 - NL Hold'em - 150/300 blinds - Good luck ! - [Connection is ...] + pass + def pokerstars_decode_table(tw): # Extract poker information from the window title. This is not needed for # fpdb, since all that information is available in the db via new_hand_number. From 6e63e2a5e945db4f2f49c2a8ac85840813d5bdac Mon Sep 17 00:00:00 2001 From: eblade Date: Wed, 10 Jun 2009 12:58:14 -0400 Subject: [PATCH 03/34] fix some junk related to determining window height/width, b_width and tb_height, comment out the window_foreign_new() that's screwing up the window right now --- pyfpdb/Tables_Demo.py | 2 ++ pyfpdb/WinTables.py | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Tables_Demo.py b/pyfpdb/Tables_Demo.py index ffc8d412..e141cab1 100644 --- a/pyfpdb/Tables_Demo.py +++ b/pyfpdb/Tables_Demo.py @@ -92,6 +92,8 @@ if __name__=="__main__": print "game =", table.get_game() fake = fake_hud(table) + print "fake =", fake gobject.timeout_add(100, check_on_table, table, fake) + print "calling main" gtk.main() diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index b867b83d..cb449a52 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -65,8 +65,11 @@ class Table(Table_Window): print "x = %s y = %s width = %s height = %s" % (x, y, width, height) self.x = int(x) + b_width self.y = int(y) + tb_height - self.height = int(height) - b_width - tb_height - self.width = int(width) - 2*b_width + self.width = width - x + self.height = height - y + print "x = %s y = %s width = %s height = %s" % (self.x, self.y, self.width, self.height) + #self.height = int(height) - b_width - tb_height + #self.width = int(width) - 2*b_width self.exe = self.get_nt_exe(hwnd) self.title = titles[hwnd] @@ -82,6 +85,8 @@ class Table(Table_Window): try: (x, y, width, height) = win32gui.GetWindowRect(hwnd) + width = width - x + height = height - y return {'x' : int(x) + b_width, 'y' : int(y) + tb_height, 'width' : int(height) - b_width - tb_height, @@ -128,8 +133,12 @@ class Table(Table_Window): for w in tl_windows: if w[1] == unique_name: - hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) - hud.main_window.gdkhandle.set_transient_for(self.gdkhandle) +# hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) +# hud.main_window.gdkhandle.set_transient_for(self.gdkhandle) + rect = self.gdkhandle.get_frame_extents() + (innerx, innery) = self.gdkhandle.get_origin() + b_width = rect.x - innerx + tb_height = rect.y - innery # # style = win32gui.GetWindowLong(self.number, win32con.GWL_EXSTYLE) # style |= win32con.WS_CLIPCHILDREN From eb37de359477c092098660cb0fe439c5f9797746 Mon Sep 17 00:00:00 2001 From: eblade Date: Wed, 10 Jun 2009 13:47:07 -0400 Subject: [PATCH 04/34] fix get_geometry to use the correct parameters to IsWindow and GetWindowRect (too much error trapping will create pitfalls), use main_window.window instead of window_foreign_new() to get gdkhandle for gtkwindow, remove process enumeration in topify() for windows --- pyfpdb/WinTables.py | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index cb449a52..d8f138eb 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -79,12 +79,11 @@ class Table(Table_Window): self.gdkhandle = gtk.gdk.window_foreign_new(long(self.window)) def get_geometry(self): - - if not win32gui.IsWindow(self.window): # window closed + if not win32gui.IsWindow(self.number): # window closed return None try: - (x, y, width, height) = win32gui.GetWindowRect(hwnd) + (x, y, width, height) = win32gui.GetWindowRect(self.number) width = width - x height = height - y return {'x' : int(x) + b_width, @@ -121,31 +120,32 @@ class Table(Table_Window): def topify(self, hud): """Set the specified gtk window to stayontop in MS Windows.""" - def windowEnumerationHandler(hwnd, resultList): - '''Callback for win32gui.EnumWindows() to generate list of window handles.''' - resultList.append((hwnd, win32gui.GetWindowText(hwnd))) - - unique_name = 'unique name for finding this window' - real_name = hud.main_window.get_title() - hud.main_window.set_title(unique_name) - tl_windows = [] - win32gui.EnumWindows(windowEnumerationHandler, tl_windows) - - for w in tl_windows: - if w[1] == unique_name: +# def windowEnumerationHandler(hwnd, resultList): +# '''Callback for win32gui.EnumWindows() to generate list of window handles.''' +# resultList.append((hwnd, win32gui.GetWindowText(hwnd))) +# +# unique_name = 'unique name for finding this window' +# real_name = hud.main_window.get_title() +# hud.main_window.set_title(unique_name) +# tl_windows = [] +# win32gui.EnumWindows(windowEnumerationHandler, tl_windows) +# +# for w in tl_windows: +# if w[1] == unique_name: # hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) -# hud.main_window.gdkhandle.set_transient_for(self.gdkhandle) - rect = self.gdkhandle.get_frame_extents() - (innerx, innery) = self.gdkhandle.get_origin() - b_width = rect.x - innerx - tb_height = rect.y - innery + hud.main_window.gdkhandle = hud.main_window.window + hud.main_window.gdkhandle.set_transient_for(self.gdkhandle) + rect = self.gdkhandle.get_frame_extents() + (innerx, innery) = self.gdkhandle.get_origin() + b_width = rect.x - innerx + tb_height = rect.y - innery # # style = win32gui.GetWindowLong(self.number, win32con.GWL_EXSTYLE) # style |= win32con.WS_CLIPCHILDREN # win32gui.SetWindowLong(self.number, win32con.GWL_EXSTYLE, style) - break +# break - hud.main_window.set_title(real_name) +# hud.main_window.set_title(real_name) def win_enum_handler(hwnd, titles): titles[hwnd] = win32gui.GetWindowText(hwnd) From c63e0ab46165b6991b44691dad2e500a627de2bf Mon Sep 17 00:00:00 2001 From: eblade Date: Wed, 10 Jun 2009 14:11:20 -0400 Subject: [PATCH 05/34] Q&D change for old Hud code to remove the loop from one topify_window(), as we found out how to get it when working on the new Hud stuff --- pyfpdb/Hud.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 5ff2c9d7..73f1f82c 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -339,30 +339,30 @@ class Hud: Stats.do_tip(window.e_box[r][c], tip) def topify_window(self, window): - """Set the specified gtk window to stayontop in MS Windows.""" - - def windowEnumerationHandler(hwnd, resultList): - '''Callback for win32gui.EnumWindows() to generate list of window handles.''' - resultList.append((hwnd, win32gui.GetWindowText(hwnd))) - - unique_name = 'unique name for finding this window' - real_name = window.get_title() - window.set_title(unique_name) - tl_windows = [] - win32gui.EnumWindows(windowEnumerationHandler, tl_windows) - - for w in tl_windows: - if w[1] == unique_name: +# """Set the specified gtk window to stayontop in MS Windows.""" +# +# def windowEnumerationHandler(hwnd, resultList): +# '''Callback for win32gui.EnumWindows() to generate list of window handles.''' +# resultList.append((hwnd, win32gui.GetWindowText(hwnd))) +# unique_name = 'unique name for finding this window' +# real_name = window.get_title() +# window.set_title(unique_name) +# tl_windows = [] +# win32gui.EnumWindows(windowEnumerationHandler, tl_windows) +# +# for w in tl_windows: +# if w[1] == unique_name: self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number)) - self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) +# self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) + self.main_window.gdkhandle = self.main_window.window self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) style |= win32con.WS_CLIPCHILDREN win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) - break +# break - window.set_title(real_name) +# window.set_title(real_name) class Stat_Window: From 93172a1a03330fc1b4d03f6d9ae3f025f806d15a Mon Sep 17 00:00:00 2001 From: eblade Date: Fri, 12 Jun 2009 02:30:14 -0400 Subject: [PATCH 06/34] remove the loop from the other topify function (doesn't look like we've needed that in there in months.. oops) --- pyfpdb/Hud.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 73f1f82c..d7f26304 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -577,25 +577,25 @@ class Popup_window: def topify_window(self, window): """Set the specified gtk window to stayontop in MS Windows.""" - def windowEnumerationHandler(hwnd, resultList): - '''Callback for win32gui.EnumWindows() to generate list of window handles.''' - resultList.append((hwnd, win32gui.GetWindowText(hwnd))) +# def windowEnumerationHandler(hwnd, resultList): +# '''Callback for win32gui.EnumWindows() to generate list of window handles.''' +# resultList.append((hwnd, win32gui.GetWindowText(hwnd))) - unique_name = 'unique name for finding this window' - real_name = window.get_title() - window.set_title(unique_name) - tl_windows = [] - win32gui.EnumWindows(windowEnumerationHandler, tl_windows) +# unique_name = 'unique name for finding this window' +# real_name = window.get_title() +# window.set_title(unique_name) +# tl_windows = [] +# win32gui.EnumWindows(windowEnumerationHandler, tl_windows) - for w in tl_windows: - if w[1] == unique_name: - window.set_transient_for(self.parent.main_window) - style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) - style |= win32con.WS_CLIPCHILDREN - win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) - break +# for w in tl_windows: +# if w[1] == unique_name: + window.set_transient_for(self.parent.main_window) + style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) + style |= win32con.WS_CLIPCHILDREN + win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) +# break - window.set_title(real_name) +# window.set_title(real_name) if __name__== "__main__": main_window = gtk.Window() From e00887b865d4d58e31e0441a6d8900b50959769f Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jun 2009 15:47:26 -0400 Subject: [PATCH 07/34] Make Flop_Mucked work with the 0-52 card encoding. --- pyfpdb/Mucked.py | 52 +++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 8ae6bc60..be9228d3 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -37,7 +37,7 @@ import Configuration import Database import Card -class Aux_Window: +class Aux_Window(object): def __init__(self, hud, params, config): self.hud = hud self.params = params @@ -94,9 +94,11 @@ class Aux_Window: return (card[0], card[1].upper()) def has_cards(self, cards): + """Returns the number of cards in the list.""" + n = 0 for c in cards: - if c in set('shdc'): return True - return False + if c != None and c > 0: n = n + 1 + return n class Stud_mucked(Aux_Window): def __init__(self, hud, config, params): @@ -329,21 +331,26 @@ class Stud_cards: self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[0]) self.eb[(c, r)].set_tooltip_text('') -class Flop_Mucked(Aux_Window): - """Aux_Window class for displaying mucked cards for flop games.""" +class Aux_Seats(Aux_Window): + """A super class to display an aux_window at each seat.""" def __init__(self, hud, config, params): self.hud = hud # hud object that this aux window supports self.config = config # configuration object for this aux window to use self.params = params # dict aux params from config self.positions = {} # dict of window positions -# self.rel_positions = {} # dict of window positions, relative to the table origin - self.displayed_cards = False + self.displayed = False self.timer_on = False # bool = Ture if the timeout for removing the cards is on + +class Flop_Mucked(Aux_Seats): + """Aux_Window class for displaying mucked cards for flop games.""" + + def __init__(self, hud, config, params): + super(Flop_Mucked, self).__init__(hud, config, params) self.card_images = self.get_card_images() def create(self): - self.adj = self.hud.adj_seats(0, self.config) + self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) self.m_windows = {} # windows to put the card images in @@ -364,7 +371,7 @@ class Flop_Mucked(Aux_Window): self.eb[i].connect("button_press_event", self.button_press_cb) self.m_windows[i].connect("configure_event", self.configure_event_cb, i) self.m_windows[i].add(self.eb[i]) - self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[('B', 'H')]) + self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[0]) self.eb[i].add(self.seen_cards[i]) self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) # self.rel_positions[i] = (int(x), int(y)) @@ -373,35 +380,40 @@ class Flop_Mucked(Aux_Window): self.m_windows[i].show_all() self.m_windows[i].hide() + def create_contents(self, i): + """Create the widgets for showing the contents of the Aux_seats window.""" + def update_gui(self, new_hand_id): """Prepare and show the mucked cards.""" - if self.displayed_cards: + if self.displayed: self.hide_mucked_cards() - self.displayed_cards = False + self.displayed = False for (i, cards) in self.hud.cards.iteritems(): - if self.has_cards(cards): + n_cards = self.has_cards(cards) + if n_cards > 0: # scratch is a working pixbuf, used to assemble the image scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, - int(self.params['card_wd'])*len(cards)/2, + int(self.params['card_wd'])*n_cards, int(self.params['card_ht'])) x = 0 # x coord where the next card starts in scratch - for card in [cards[k:k+2] for k in xrange(0, len(cards), 2)]: + for card in cards: # concatenate each card image to scratch - self.card_images[self.split_cards(card)].copy_area(0, 0, + if card == None or card ==0: + break + self.card_images[card].copy_area(0, 0, int(self.params['card_wd']), int(self.params['card_ht']), scratch, x, 0) x = x + int(self.params['card_wd']) self.seen_cards[i].set_from_pixbuf(scratch) -# self.m_windows[i].show_all() self.m_windows[i].resize(1,1) self.m_windows[i].show() self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back - self.displayed_cards = True + self.displayed = True for stats in self.hud.stat_dict.itervalues(): self.eb[stats['seat']].set_tooltip_text(stats['screen_name']) - if self.displayed_cards and float(self.params['timeout']) > 0: + if self.displayed and float(self.params['timeout']) > 0: self.timer_on = True gobject.timeout_add(int(1000*float(self.params['timeout'])), self.timed_out) @@ -425,7 +437,7 @@ class Flop_Mucked(Aux_Window): """Hide the mucked card windows.""" for (i, w) in self.m_windows.iteritems(): w.hide() - self.displayed_cards = False + self.displayed = False def button_press_cb(self, widget, event, *args): """Handle button clicks in the event boxes.""" @@ -458,7 +470,7 @@ class Flop_Mucked(Aux_Window): for (i, cards) in self.hud.cards.iteritems(): self.m_windows[i].show() self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back - self.displayed_cards = True + self.displayed = True def save_layout(self, *args): """Save new layout back to the aux element in the config file.""" From a30708157462b66788432daf1fe66ef3b28d327d Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jun 2009 15:51:56 -0400 Subject: [PATCH 08/34] More for Flop_Mucked with 0-52 encoding. --- pyfpdb/Database.py | 8 ++------ pyfpdb/SQL.py | 21 ++++++++------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index b6c97a29..d3abfa06 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -170,12 +170,8 @@ class Database: cards = {} c = self.connection.cursor() c.execute(self.sql.query['get_common_cards'], [hand]) - colnames = [desc[0] for desc in c.description] - for row in c.fetchall(): - s_dict = {} - for name, val in zip(colnames, row): - s_dict[name] = val - cards['common'] = (self.convert_cards(s_dict)) +# row = c.fetchone() + cards['common'] = c.fetchone() return cards def convert_cards(self, d): diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 1a9deb60..77115c50 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -541,19 +541,14 @@ class Sql: """ self.query['get_common_cards'] = """ - select - card1Value AS card1value, - card1Suit AS card1suit, - card2Value AS card2value, - card2Suit AS card2suit, - card3Value AS card3value, - card3Suit AS card3suit, - card4Value AS card4value, - card4Suit AS card4suit, - card5Value AS card5value, - card5Suit AS card5suit - from BoardCards - where handId = %s + select + boardcard1, + boardcard2, + boardcard3, + boardcard4, + boardcard5 + from Hands + where Id = %s """ self.query['get_action_from_hand'] = """ From c9572129a655ce6ae5773588fc895141f7dd7569 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jun 2009 16:48:42 -0400 Subject: [PATCH 09/34] Fix passing settings in import chain. --- pyfpdb/fpdb_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 99330bb9..3fa20b40 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -394,7 +394,7 @@ class Importer: self.hand=hand try: - handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db + handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb.db ,self.fdb.cursor, self.siteIds[site], category, hand, self.config) self.fdb.db.commit() From 462ff87596648dc2ea41327543b705263dc4f4da Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 20 Jun 2009 09:43:05 -0400 Subject: [PATCH 10/34] Add xpad and ypad to site and game elements. Cleanup some defaults. --- pyfpdb/Configuration.py | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 0ea4b371..13e7cd28 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -86,14 +86,34 @@ class Site: self.aux_window = node.getAttribute("aux_window") self.font = node.getAttribute("font") self.font_size = node.getAttribute("font_size") - self.use_frames = node.getAttribute("use_frames") + self.use_frames = node.getAttribute("use_frames") self.enabled = fix_tf(node.getAttribute("enabled"), default = True) + self.xpad = node.getAttribute("xpad") + self.ypad = node.getAttribute("ypad") self.layout = {} for layout_node in node.getElementsByTagName('layout'): lo = Layout(layout_node) self.layout[lo.max] = lo +# Site defaults + if self.xpad == "": self.xpad = 1 + else: self.xpad = int(self.xpad) + + if self.ypad == "": self.ypad = 0 + else: self.ypad = int(self.ypad) + + if self.font_size == "": self.font_size = 7 + else: self.font_size = int(self.font_size) + + if self.hudopacity == "": self.hudopacity = 1.0 + else: self.hudopacity = float(self.hudopacity) + + if self.use_frames == "": self.use_frames = False + if self.font == "": self.font = "Sans" + if self.hudbgcolor == "": self.hudbgcolor = "000000" + if self.hudfgcolor == "": self.hudfgcolor = "FFFFFF" + def __str__(self): temp = "Site = " + self.site_name + "\n" for key in dir(self): @@ -119,9 +139,16 @@ class Stat: class Game: def __init__(self, node): self.game_name = node.getAttribute("game_name") - self.db = node.getAttribute("db") self.rows = int( node.getAttribute("rows") ) self.cols = int( node.getAttribute("cols") ) + self.xpad = node.getAttribute("xpad") + self.ypad = node.getAttribute("ypad") + +# Defaults + if self.xpad == "": self.xpad = 1 + else: self.xpad = int(self.xpad) + if self.ypad == "": self.ypad = 0 + else: self.ypad = int(self.ypad) aux_text = node.getAttribute("aux") aux_list = aux_text.split(',') @@ -146,9 +173,10 @@ class Game: def __str__(self): temp = "Game = " + self.game_name + "\n" - temp = temp + " db = %s\n" % self.db temp = temp + " rows = %d\n" % self.rows temp = temp + " cols = %d\n" % self.cols + temp = temp + " xpad = %d\n" % self.xpad + temp = temp + " ypad = %d\n" % self.ypad temp = temp + " aux = %s\n" % self.aux for stat in self.stats.keys(): @@ -631,6 +659,8 @@ class Config: parms["font"] = self.supported_sites[site].font parms["font_size"] = self.supported_sites[site].font_size parms["enabled"] = self.supported_sites[site].enabled + parms["xpad"] = self.supported_sites[site].xpad + parms["ypad"] = self.supported_sites[site].ypad return parms def set_site_parameters(self, site_name, converter = None, decoder = None, @@ -681,9 +711,10 @@ class Config: param = {} if self.supported_games.has_key(name): param['game_name'] = self.supported_games[name].game_name - param['db'] = self.supported_games[name].db param['rows'] = self.supported_games[name].rows param['cols'] = self.supported_games[name].cols + param['xpad'] = self.supported_games[name].xpad + param['ypad'] = self.supported_games[name].ypad param['aux'] = self.supported_games[name].aux return param From 287394c97dfcb4e764684973ae0dde0ab88ee289 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 20 Jun 2009 10:01:52 -0400 Subject: [PATCH 11/34] Use xpad and ypad from game element. --- pyfpdb/Hud.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 56ad08f3..77381749 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -445,10 +445,10 @@ class Stat_Window: Stats.do_tip(e_box[r][c], 'stuff') if usegtkframes: - grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) + grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = game.xpad, ypadding = game.ypad) self.frame[r][c].add(e_box[r][c]) else: - grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) + grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = game.xpad, ypadding = game.ypad) label[r].append( gtk.Label('xxx') ) if usegtkframes: From ac30e912c76bc3f6a731d5657850d1ee1133a0a4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 21:39:14 +0100 Subject: [PATCH 12/34] smarten up positional stats tab (still needs configurable columns) --- pyfpdb/GuiPositionalStats.py | 184 ++++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 65 deletions(-) diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 0e20e632..dce7cb77 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -62,17 +62,46 @@ class GuiPositionalStats (threading.Thread): self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) + # ToDo: store in config + # ToDo: create popup to adjust column config + # columns to display, keys match column name returned by sql, values in tuple are: + # is column displayed, column heading, xalignment, formatting + 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) + , ["n", True, "Hds", 1.0, "%d"] + , ["avgseats", True, "Seats", 1.0, "%3.1f"] + , ["vpip", True, "VPIP", 1.0, "%3.1f"] + , ["pfr", True, "PFR", 1.0, "%3.1f"] + , ["pf3", True, "PF3", 1.0, "%3.1f"] + , ["steals", True, "Steals", 1.0, "%3.1f"] + , ["saw_f", True, "Saw_F", 1.0, "%3.1f"] + , ["sawsd", True, "SawSD", 1.0, "%3.1f"] + , ["wtsdwsf", True, "WtSDwsF", 1.0, "%3.1f"] + , ["wmsd", True, "W$SD", 1.0, "%3.1f"] + , ["flafq", True, "FlAFq", 1.0, "%3.1f"] + , ["tuafq", True, "TuAFq", 1.0, "%3.1f"] + , ["rvafq", True, "RvAFq", 1.0, "%3.1f"] + , ["pofafq", False, "PoFAFq", 1.0, "%3.1f"] + , ["net", True, "Net($)", 1.0, "%6.2f"] + , ["bbper100", True, "bb/100", 1.0, "%4.2f"] + , ["rake", True, "Rake($)", 1.0, "%6.2f"] + , ["bb100xr", True, "bbxr/100", 1.0, "%4.2f"] + , ["variance", True, "Variance", 1.0, "%5.2f"] + ] + self.stat_table = None self.stats_frame = None + self.stats_vbox = None self.main_hbox = gtk.HBox(False, 0) self.main_hbox.show() - statsFrame = gtk.Frame("Stats:") - statsFrame.set_label_align(0.0, 0.0) - statsFrame.show() - self.stats_frame = gtk.VBox(False, 0) + self.stats_frame = gtk.Frame() + self.stats_frame.set_label_align(0.0, 0.0) self.stats_frame.show() + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() # This could be stored in config eventually, or maybe configured in this window somehow. # Each posncols element is the name of a column returned by the sql @@ -90,11 +119,11 @@ class GuiPositionalStats (threading.Thread): , "PoFAFq", "Net($)", "bb/100", "$/hand", "Variance", "Hds" ) - self.fillStatsFrame(self.stats_frame) - statsFrame.add(self.stats_frame) + self.fillStatsFrame(self.stats_vbox) + self.stats_frame.add(self.stats_vbox) self.main_hbox.pack_start(self.filters.get_vbox()) - self.main_hbox.pack_start(statsFrame) + self.main_hbox.pack_start(self.stats_frame) def get_vbox(self): @@ -107,9 +136,12 @@ class GuiPositionalStats (threading.Thread): print "DEBUG: activesite set to %s" %(self.activesite) def refreshStats(self, widget, data): - try: self.stats_table.destroy() + try: self.stats_vbox.destroy() except AttributeError: pass - self.fillStatsFrame(self.stats_frame) + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() + self.stats_frame.add(self.stats_vbox) + self.fillStatsFrame(self.stats_vbox) def fillStatsFrame(self, vbox): sites = self.filters.getSites() @@ -144,66 +176,103 @@ class GuiPositionalStats (threading.Thread): self.createStatsTable(vbox, playerids, sitenos, limits, seats, dates) def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates): - self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required - self.stats_table.set_col_spacings(4) - self.stats_table.show() - vbox.add(self.stats_table) + colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 row = 0 col = 0 - for t in self.posnheads: - l = gtk.Label(self.posnheads[col]) - l.show() - self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) - col +=1 tmp = self.sql.query['playerStatsByPosition'] tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats, dates) self.cursor.execute(tmp) result = self.cursor.fetchall() + colnames = [desc[0].lower() for desc in self.cursor.description] + + liststore = gtk.ListStore(*([str] * len(colnames))) + view = gtk.TreeView(model=liststore) + view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) + vbox.pack_start(view, expand=False, padding=3) + # left-aligned cells: + textcell = gtk.CellRendererText() + # centred cells: + textcell50 = gtk.CellRendererText() + textcell50.set_property('xalign', 0.5) + # right-aligned cells: + numcell = gtk.CellRendererText() + numcell.set_property('xalign', 1.0) + listcols = [] + + for t in self.posnheads: + listcols.append(gtk.TreeViewColumn(self.posnheads[col])) + view.append_column(listcols[col]) + if col == 0: + listcols[col].pack_start(textcell, expand=True) + listcols[col].add_attribute(textcell, 'text', col) + listcols[col].set_expand(True) + elif col in (1, 2): + listcols[col].pack_start(textcell50, expand=True) + listcols[col].add_attribute(textcell50, 'text', col) + listcols[col].set_expand(True) + else: + listcols[col].pack_start(numcell, expand=True) + listcols[col].add_attribute(numcell, 'text', col) + listcols[col].set_expand(True) + col +=1 + + # Code below to be used when full column data structures implemented like in player stats: + + # Create header row eg column: ("game", True, "Game", 0.0, "%s") + #for col, column in enumerate(cols_to_show): + # if column[colalias] == 'game' and holecards: + # s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] + # else: + # s = column[colheading] + # listcols.append(gtk.TreeViewColumn(s)) + # view.append_column(listcols[col]) + # if column[colformat] == '%s': + # if column[colxalign] == 0.0: + # listcols[col].pack_start(textcell, expand=True) + # listcols[col].add_attribute(textcell, 'text', col) + # else: + # listcols[col].pack_start(textcell50, expand=True) + # listcols[col].add_attribute(textcell50, 'text', col) + # listcols[col].set_expand(True) + # else: + # listcols[col].pack_start(numcell, expand=True) + # listcols[col].add_attribute(numcell, 'text', col) + # listcols[col].set_expand(True) + # #listcols[col].set_alignment(column[colxalign]) # no effect? rows = len(result) - colnames = [desc[0].lower() for desc in self.cursor.description] last_game,last_seats,sqlrow = "","",0 while sqlrow < rows: - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" rowprinted=0 + treerow = [] avgcol = colnames.index('avgseats') for col,colname in enumerate(self.posncols): if colname in colnames: sqlcol = colnames.index(colname) else: continue - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - # print blank row between levels: if result[sqlrow][sqlcol]: if sqlrow == 0: - l = gtk.Label(result[sqlrow][sqlcol]) + value = result[sqlrow][sqlcol] rowprinted=1 elif result[sqlrow][0] != last_game: - l = gtk.Label(' ') + value = ' ' elif 'show' in seats and seats['show'] and result[sqlrow][avgcol] != last_seats: - l = gtk.Label(' ') + value = ' ' else: - l = gtk.Label(result[sqlrow][sqlcol]) + value = result[sqlrow][sqlcol] rowprinted=1 else: l = gtk.Label(' ') - if col == 0: - l.set_alignment(xalign=0.0, yalign=0.5) - elif col == 1: - l.set_alignment(xalign=0.5, yalign=0.5) + value = ' ' + if value and value != -999: + treerow.append(value) else: - l.set_alignment(xalign=1.0, yalign=0.5) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() + treerow.append(' ') + iter = liststore.append(treerow) last_game = result[sqlrow][0] last_seats = result[sqlrow][avgcol] if rowprinted: @@ -220,48 +289,33 @@ class GuiPositionalStats (threading.Thread): # blank row between main stats and totals: col = 0 - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - l = gtk.Label(' ') - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() + treerow = [' ' for x in self.posncols] + iter = liststore.append(treerow) row = row + 1 for sqlrow in range(rows): - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" + treerow = [] for col,colname in enumerate(self.posncols): if colname in colnames: sqlcol = colnames.index(colname) elif colname != "plposition": continue - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) if colname == 'plposition': l = gtk.Label('Totals') + value = 'Totals' elif result[sqlrow][sqlcol]: l = gtk.Label(result[sqlrow][sqlcol]) + value = result[sqlrow][sqlcol] else: l = gtk.Label(' ') - if col == 0: - l.set_alignment(xalign=0.0, yalign=0.5) - elif col == 1: - l.set_alignment(xalign=0.5, yalign=0.5) + value = ' ' + if value and value != -999: + treerow.append(value) else: - l.set_alignment(xalign=1.0, yalign=0.5) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() + treerow.append(' ') + iter = liststore.append(treerow) row = row + 1 + vbox.show_all() self.db.db.rollback() #end def fillStatsFrame(self, vbox): From 1fbb7d166c2ec32c2a02fbbeeb0f122df121ef22 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 21:41:41 +0100 Subject: [PATCH 13/34] remove redundant code --- pyfpdb/GuiPlayerStats.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 268aeab3..79ab75a4 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -227,11 +227,6 @@ class GuiPlayerStats (threading.Thread): if not flags: holecards = False else: holecards = flags[0] - - self.stats_table = gtk.Table(1, 1, False) - self.stats_table.set_col_spacings(4) - self.stats_table.show() - tmp = self.sql.query[query] tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats, groups, dates) self.cursor.execute(tmp) @@ -279,10 +274,6 @@ class GuiPlayerStats (threading.Thread): while sqlrow < rows: treerow = [] - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" for col,column in enumerate(cols_to_show): if column[colalias] in colnames: value = result[sqlrow][colnames.index(column[colalias])] From 699f79722b99b073ce7fc27a5bfd8d83fda0dcf5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 22:05:28 +0100 Subject: [PATCH 14/34] add time print for positional stats tab --- pyfpdb/GuiPositionalStats.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index dce7cb77..21a3bc9a 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -20,6 +20,7 @@ import pygtk pygtk.require('2.0') import gtk import os +from time import time, strftime import fpdb_import import fpdb_db @@ -177,6 +178,7 @@ class GuiPositionalStats (threading.Thread): def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates): + starttime = time() colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 row = 0 col = 0 @@ -318,6 +320,7 @@ class GuiPositionalStats (threading.Thread): vbox.show_all() self.db.db.rollback() + print "Positional Stats page displayed in %4.2f seconds" % (time() - starttime) #end def fillStatsFrame(self, vbox): def refineQuery(self, query, playerids, sitenos, limits, seats, dates): From 45a9358cbd67a111ac42a056712fbc1995f9d000 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:16:34 +0100 Subject: [PATCH 15/34] set defaults for unused params to allow new calls without needing to set them --- pyfpdb/Database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 932a8578..5bc8afe9 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -39,7 +39,7 @@ import SQL import Card class Database: - def __init__(self, c, db_name, game): + def __init__(self, c, db_name = None, game = None): # db_name and game not used any more 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 @@ -48,7 +48,7 @@ class Database: self.import_options = c.get_import_parameters() self.type = db_params['db-type'] self.backend = db_params['db-backend'] - self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-server']) + self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) self.connection.rollback() # To add to config: From 456ddb3e91ceda9d9305d562a56769f38a9ddc23 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:19:03 +0100 Subject: [PATCH 16/34] use do_connect() instead of connect() and remove settings parameter (config includes them) --- pyfpdb/Filters.py | 20 ++++---------------- pyfpdb/GuiGraphViewer.py | 2 +- pyfpdb/GuiPlayerStats.py | 2 +- pyfpdb/GuiPositionalStats.py | 2 +- 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 4846b998..9ded56b4 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -30,12 +30,11 @@ import fpdb_db import FpdbSQLQueries class Filters(threading.Thread): - def __init__(self, db, settings, config, qdict, display = {},debug=True): + def __init__(self, db, config, qdict, display = {}, debug=True): self.debug=debug #print "start of GraphViewer constructor" self.db=db self.cursor=db.cursor - self.settings=settings self.sql=qdict self.conf = config self.display = display @@ -235,7 +234,7 @@ class Filters(threading.Thread): def __set_hero_name(self, w, site): self.heroes[site] = w.get_text() -# print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site]) +# print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site]) def createSiteLine(self, hbox, site): cb = gtk.CheckButton(site) @@ -556,23 +555,12 @@ def main(argv=None): config = Configuration.Config() db = None - settings = {} - - settings.update(config.get_db_parameters()) - settings.update(config.get_tv_parameters()) - settings.update(config.get_import_parameters()) - settings.update(config.get_default_paths()) - db = fpdb_db.fpdb_db() - db.connect(settings['db-backend'], - settings['db-host'], - settings['db-databaseName'], - settings['db-user'], - settings['db-password']) + db.do_connect(config) qdict = FpdbSQLQueries.FpdbSQLQueries(db.get_backend_name()) - i = Filters(db, settings, config, qdict) + i = Filters(db, config, qdict) main_window = gtk.Window() main_window.connect('destroy', destroy) main_window.add(i.get_vbox()) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index cec91e61..fc14a536 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -63,7 +63,7 @@ class GuiGraphViewer (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(db, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh Graph") self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton2Name("Export to File") diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 79ab75a4..4ad21764 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -66,7 +66,7 @@ class GuiPlayerStats (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) self.filters.registerButton1Name("_Filters") self.filters.registerButton1Callback(self.showDetailFilter) self.filters.registerButton2Name("_Refresh") diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 21a3bc9a..6fde0617 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -59,7 +59,7 @@ class GuiPositionalStats (threading.Thread): "Button2" : False } - self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) From 14561043828eed31639787a7751a3e54b28e79d2 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:30:54 +0100 Subject: [PATCH 17/34] make graph viewer use its own db connection --- pyfpdb/GuiGraphViewer.py | 16 ++++++++-------- pyfpdb/fpdb.py | 5 ++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index fc14a536..811b1e82 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -43,14 +43,14 @@ import Filters class GuiGraphViewer (threading.Thread): - def __init__(self, db, settings, querylist, config, debug=True): + def __init__(self, querylist, config, debug=True): """Constructor for GraphViewer""" self.debug=debug #print "start of GraphViewer constructor" - self.db=db - self.cursor=db.cursor - self.settings=settings - self.sql=querylist + self.db = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql + self.db.do_connect(config) + + self.sql = querylist self.conf = config filters_display = { "Heroes" : True, @@ -63,7 +63,7 @@ class GuiGraphViewer (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(db, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh Graph") self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton2Name("Export to File") @@ -146,7 +146,7 @@ class GuiGraphViewer (threading.Thread): for site in sites: if sites[site] == True: sitenos.append(siteids[site]) - self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) + self.db.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) result = self.db.cursor.fetchall() if len(result) == 1: playerids.append(result[0][0]) @@ -226,7 +226,7 @@ class GuiGraphViewer (threading.Thread): #print "DEBUG: sql query:" #print tmp - self.cursor.execute(tmp) + self.db.cursor.execute(tmp) #returns (HandId,Winnings,Costs,Profit) winnings = self.db.cursor.fetchall() self.db.db.rollback() diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index b03e8424..172eedee 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -41,6 +41,7 @@ import GuiTableViewer import GuiAutoImport import GuiGraphViewer import GuiSessionViewer +import Database import FpdbSQLQueries import Configuration @@ -388,6 +389,8 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) + self.dbi = Database.Database(self.config) # dbi for db interface and to avoid clashes with db/database/etc + # can rename later if required self.db.db.rollback() #end def load_profile @@ -474,7 +477,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") def tabGraphViewer(self, widget, data=None): """opens a graph viewer tab""" #print "start of tabGraphViewer" - new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) + new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.querydict, self.config) self.threads.append(new_gv_thread) gv_tab=new_gv_thread.get_vbox() self.add_and_display_tab(gv_tab, "Graphs") From 0afd8e2e707dba139d879242564604f48bbcb26d Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:43:11 +0100 Subject: [PATCH 18/34] use do_connect() instead of connect() --- pyfpdb/fpdb.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 172eedee..b36c62bb 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -364,11 +364,7 @@ class fpdb: self.db = fpdb_db.fpdb_db() #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] - self.db.connect(self.settings['db-backend'], - self.settings['db-host'], - self.settings['db-databaseName'], - self.settings['db-user'], - self.settings['db-password']) + self.db.do_connect(self.config) if self.db.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) @@ -401,11 +397,7 @@ class fpdb: def obtain_global_lock(self): print "\nTaking global lock ..." self.fdb_lock = fpdb_db.fpdb_db() - self.fdb_lock.connect(self.settings['db-backend'], - self.settings['db-host'], - self.settings['db-databaseName'], - self.settings['db-user'], - self.settings['db-password']) + self.fdb_lock.do_connect(self.config) return self.fdb_lock.get_global_lock() #end def obtain_global_lock From 8cdac245179503f597cab5ef508e14e2eebb2bd3 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 23 Jun 2009 09:56:29 -0400 Subject: [PATCH 19/34] Subclass Aux_Seats from Aux_Windows. Flop_mucked now a Aux_Seats. --- pyfpdb/Mucked.py | 176 +++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 99 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index be9228d3..eb1d7c86 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -43,21 +43,12 @@ class Aux_Window(object): self.params = params self.config = config - def update_data(self, *args): - pass - - def update_gui(self, *args): - pass - - def create(self, *args): - pass - - def relocate(self, *args): - pass - - def save_layout(self, *args): - pass - +# Override these methods as needed + def update_data(self, *args): pass + def update_gui(self, *args): pass + def create(self, *args): pass + def relocate(self, *args): pass + def save_layout(self, *args): pass def destroy(self): try: self.container.destroy() @@ -89,10 +80,6 @@ class Aux_Window(object): pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) return temp_pb - def split_cards(self, card): - if card == 'xx': return ('B', 'S') - return (card[0], card[1].upper()) - def has_cards(self, cards): """Returns the number of cards in the list.""" n = 0 @@ -331,6 +318,9 @@ class Stud_cards: self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[0]) self.eb[(c, r)].set_tooltip_text('') +class Seat_Window(gtk.Window): + """Subclass gtk.Window for the seat windows.""" + class Aux_Seats(Aux_Window): """A super class to display an aux_window at each seat.""" @@ -339,55 +329,83 @@ class Aux_Seats(Aux_Window): self.config = config # configuration object for this aux window to use self.params = params # dict aux params from config self.positions = {} # dict of window positions - self.displayed = False + self.displayed = False # the seat windows are displayed + self.uses_timer = False # the Aux_seats object uses a timer to control hiding self.timer_on = False # bool = Ture if the timeout for removing the cards is on +# placeholders that should be overridden--so we don't throw errors + def create_contents(self): pass + + def create(self): + self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py + loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) + + self.m_windows = {} # windows to put the card images in + + for i in (range(1, self.hud.max + 1) + ['common']): + if i == 'common': + (x, y) = self.params['layout'][self.hud.max].common + else: + (x, y) = loc[self.adj[i]] + self.m_windows[i] = Seat_Window() + self.m_windows[i].set_decorated(False) + self.m_windows[i].set_property("skip-taskbar-hint", True) + self.m_windows[i].set_transient_for(self.hud.main_window) + self.m_windows[i].set_focus_on_map(False) + self.m_windows[i].connect("configure_event", self.configure_event_cb, i) + self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) + self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) + self.m_windows[i].set_opacity(float(self.params['opacity'])) + +# the create_contents method is supplied by the subclass + self.create_contents(self.m_windows[i], i) + + self.m_windows[i].show_all() + self.m_windows[i].hide() + +# Methods likely to be of use for any Seat_Window implementation + def destroy(self): + """Destroy all of the seat windows.""" + for i in self.m_windows.keys(): + self.m_windows[i].destroy() + del(self.m_windows[i]) + +# Methods likely to be useful for mucked card windows (or similar) only + def hide(self): + """Hide the seat windows.""" + for (i, w) in self.m_windows.iteritems(): + w.hide() + self.displayed = False + class Flop_Mucked(Aux_Seats): """Aux_Window class for displaying mucked cards for flop games.""" def __init__(self, hud, config, params): super(Flop_Mucked, self).__init__(hud, config, params) self.card_images = self.get_card_images() + self.uses_timer = True # this Aux_seats object uses a timer to control hiding - def create(self): - self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py - loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) - - self.m_windows = {} # windows to put the card images in - self.eb = {} # event boxes so we can interact with the mucked cards - self.seen_cards = {} # image objects to stash the cards in - - for i in (range(1, self.hud.max + 1) + ['common']): - if i == 'common': - (x, y) = self.params['layout'][self.hud.max].common - else: - (x, y) = loc[self.adj[i]] - self.m_windows[i] = gtk.Window() - self.m_windows[i].set_decorated(False) - self.m_windows[i].set_property("skip-taskbar-hint", True) - self.m_windows[i].set_transient_for(self.hud.main_window) - self.m_windows[i].set_focus_on_map(False) - self.eb[i] = gtk.EventBox() - self.eb[i].connect("button_press_event", self.button_press_cb) - self.m_windows[i].connect("configure_event", self.configure_event_cb, i) - self.m_windows[i].add(self.eb[i]) - self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[0]) - self.eb[i].add(self.seen_cards[i]) - self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) -# self.rel_positions[i] = (int(x), int(y)) - self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) - self.m_windows[i].set_opacity(float(self.params['opacity'])) - self.m_windows[i].show_all() - self.m_windows[i].hide() - - def create_contents(self, i): + def create_contents(self, container, i): """Create the widgets for showing the contents of the Aux_seats window.""" + container.eb = gtk.EventBox() + container.eb.connect("button_press_event", self.button_press_cb) + container.add(container.eb) + container.seen_cards = gtk.image_new_from_pixbuf(self.card_images[0]) + container.eb.add(container.seen_cards) def update_gui(self, new_hand_id): """Prepare and show the mucked cards.""" - if self.displayed: - self.hide_mucked_cards() - self.displayed = False + if self.displayed: self.hide() + +# See how many players showed a hand. Skip if only 1 shows (= hero) + n_sd = 0 + for (i, cards) in self.hud.cards.iteritems(): + n_cards = self.has_cards(cards) + if n_cards > 0: + n_sd = n_sd + 1 + if n_sd < 2: return + +# More than 1 player showed, so display the hole cards for (i, cards) in self.hud.cards.iteritems(): n_cards = self.has_cards(cards) if n_cards > 0: @@ -404,24 +422,19 @@ class Flop_Mucked(Aux_Seats): int(self.params['card_wd']), int(self.params['card_ht']), scratch, x, 0) x = x + int(self.params['card_wd']) - self.seen_cards[i].set_from_pixbuf(scratch) + self.m_windows[i].seen_cards.set_from_pixbuf(scratch) self.m_windows[i].resize(1,1) self.m_windows[i].show() self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back self.displayed = True for stats in self.hud.stat_dict.itervalues(): - self.eb[stats['seat']].set_tooltip_text(stats['screen_name']) + self.m_windows[i].eb.set_tooltip_text(stats['screen_name']) if self.displayed and float(self.params['timeout']) > 0: self.timer_on = True gobject.timeout_add(int(1000*float(self.params['timeout'])), self.timed_out) - def destroy(self): - """Destroy all of the mucked windows.""" - for w in self.m_windows.values(): - w.destroy() - def timed_out(self): # this is the callback from the timeout @@ -430,15 +443,9 @@ class Flop_Mucked(Aux_Seats): if not self.timer_on: return False else: - self.hide_mucked_cards() + self.hide() return False - def hide_mucked_cards(self): - """Hide the mucked card windows.""" - for (i, w) in self.m_windows.iteritems(): - w.hide() - self.displayed = False - def button_press_cb(self, widget, event, *args): """Handle button clicks in the event boxes.""" @@ -456,7 +463,7 @@ class Flop_Mucked(Aux_Seats): self.timer_on = False else: self.timer_on = False - self.hide_mucked_cards() + self.hide() elif event.button == 1: # left button event window = widget.get_parent() @@ -482,32 +489,3 @@ class Flop_Mucked(Aux_Seats): else: new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) - -# This test program doesn't work - -#if __name__== "__main__": -# -# def destroy(*args): # call back for terminating the main eventloop -# gtk.main_quit() # used only for testing -# -# def process_new_hand(source, condition, db_connection): #callback from stdin watch -- testing only -## there is a new hand_id to be processed -## just read it and pass it to update -# new_hand_id = sys.stdin.readline() -# new_hand_id = new_hand_id.rstrip() # remove trailing whitespace -# m.update_data(new_hand_id, db_connection) -# m.update_gui(new_hand_id) -# return(True) -# -# config = Configuration.Config() -# db_connection = Database.Database(config, 'fpdbTEST', '') -# main_window = gtk.Window() -# main_window.set_keep_above(True) -# main_window.connect("destroy", destroy) -# -# aux_to_call = "stud_mucked" -# aux_params = config.get_aux_parameters(aux_to_call) -# m = eval("%s(None, config, aux_params)" % aux_params['class']) -# -# s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand, db_connection) -# gtk.main() From 2f0c7e8167f8380349db0d4148104b91b2666327 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 23 Jun 2009 20:45:11 +0100 Subject: [PATCH 20/34] make load_profile reload HUD_config.xml and update status bar --- pyfpdb/fpdb.py | 53 ++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index b36c62bb..6c982002 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -41,6 +41,7 @@ import GuiTableViewer import GuiAutoImport import GuiGraphViewer import GuiSessionViewer +import SQL import Database import FpdbSQLQueries import Configuration @@ -179,20 +180,21 @@ class fpdb: def dia_load_profile(self, widget, data=None): """Dialogue to select a file to load a profile from""" if self.obtain_global_lock() == 0: # returns 0 if successful - try: - chooser = gtk.FileChooserDialog(title="Please select a profile file to load", - action=gtk.FILE_CHOOSER_ACTION_OPEN, - buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) - chooser.set_filename(self.profile) + #try: + # chooser = gtk.FileChooserDialog(title="Please select a profile file to load", + # action=gtk.FILE_CHOOSER_ACTION_OPEN, + # buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) + # chooser.set_filename(self.profile) - response = chooser.run() - chooser.destroy() - if response == gtk.RESPONSE_OK: - self.load_profile(chooser.get_filename()) - elif response == gtk.RESPONSE_CANCEL: - print 'User cancelled loading profile' - except: - pass + # response = chooser.run() + # chooser.destroy() + # if response == gtk.RESPONSE_OK: + # self.load_profile(chooser.get_filename()) + # elif response == gtk.RESPONSE_CANCEL: + # print 'User cancelled loading profile' + #except: + # pass + self.load_profile() self.release_global_lock() #end def dia_load_profile @@ -347,6 +349,7 @@ class fpdb: def load_profile(self): """Loads profile from the provided path name.""" + self.config = Configuration.Config(file=options.config, dbname=options.dbname) self.settings = {} if (os.sep=="/"): self.settings['os']="linuxmac" @@ -383,10 +386,18 @@ class fpdb: response = diaDbVersionWarning.run() 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.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.database, self.db.host)) + # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) - self.dbi = Database.Database(self.config) # dbi for db interface and to avoid clashes with db/database/etc - # can rename later if required + self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) + self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc + # can rename later if required self.db.db.rollback() #end def load_profile @@ -476,10 +487,9 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") #end def tabGraphViewer def __init__(self): - self.threads=[] - self.db=None - self.config = Configuration.Config(file=options.config, dbname=options.dbname) - self.load_profile() + self.threads = [] + self.db = None + self.status_bar = None self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.connect("delete_event", self.delete_event) @@ -514,11 +524,8 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.tab_main_help(None, None) - 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() - self.window.show() + self.load_profile() sys.stderr.write("fpdb starting ...") #end def __init__ From 84cc951045ee3e8981d7dc40d26d1346a250cf59 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 23 Jun 2009 22:05:22 +0100 Subject: [PATCH 21/34] comment out database creation wrongly included from my dev code --- pyfpdb/fpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 6c982002..a6d4cb3c 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -396,7 +396,7 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) - self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc + #self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc # can rename later if required self.db.db.rollback() #end def load_profile From 9b50987d0cf05d9e8cbe0c5cc97d288770e882e0 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 23 Jun 2009 23:44:37 +0100 Subject: [PATCH 22/34] add sql param to Database constructor - aim is to have just one SQL instance passed around and to use Database for db connections and methods --- pyfpdb/Database.py | 9 +++++++-- pyfpdb/fpdb.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f652d9a7..392681eb 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -39,7 +39,8 @@ import SQL import Card class Database: - def __init__(self, c, db_name = None, game = None): # db_name and game not used any more + def __init__(self, c, db_name = None, game = None, sql = None): # db_name and game not used any more + print "creating Database instance, sql =", sql 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 @@ -48,7 +49,11 @@ class Database: self.import_options = c.get_import_parameters() self.type = db_params['db-type'] self.backend = db_params['db-backend'] - self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) + # where possible avoid creating new SQL instance by using the global one passed in + if sql == None: + self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) + else: + self.sql = sql self.connection.rollback() # To add to config: diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index a6d4cb3c..6c982002 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -396,7 +396,7 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) - #self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc + self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc # can rename later if required self.db.db.rollback() #end def load_profile From 7f7ad2a13e0e342468909fae20c5545474b2e91a Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 25 Jun 2009 10:07:40 -0400 Subject: [PATCH 23/34] Further on Aux_Seats interface. Works. Not ready for prime time. --- pyfpdb/Mucked.py | 85 +++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index eb1d7c86..4c8b2eb4 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -335,6 +335,7 @@ class Aux_Seats(Aux_Window): # placeholders that should be overridden--so we don't throw errors def create_contents(self): pass + def update_contents(self): pass def create(self): self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py @@ -363,6 +364,11 @@ class Aux_Seats(Aux_Window): self.m_windows[i].show_all() self.m_windows[i].hide() + def update_gui(self, new_hand_id): + """Update the gui, LDO.""" + for i in self.m_windows.keys(): + self.update_contents(self.m_windows[i], i) + # Methods likely to be of use for any Seat_Window implementation def destroy(self): """Destroy all of the seat windows.""" @@ -377,6 +383,17 @@ class Aux_Seats(Aux_Window): w.hide() self.displayed = False + def save_layout(self, *args): + """Save new layout back to the aux element in the config file.""" + new_locs = {} +# print "adj =", self.adj + for (i, pos) in self.positions.iteritems(): + if i != 'common': + new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) + else: + new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) + self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) + class Flop_Mucked(Aux_Seats): """Aux_Window class for displaying mucked cards for flop games.""" @@ -393,6 +410,33 @@ class Flop_Mucked(Aux_Seats): container.seen_cards = gtk.image_new_from_pixbuf(self.card_images[0]) container.eb.add(container.seen_cards) + def update_contents(self, container, i): + if not self.hud.cards.has_key(i): return + cards = self.hud.cards[i] + n_cards = self.has_cards(cards) + if n_cards > 1: + +# scratch is a working pixbuf, used to assemble the image + scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, + int(self.params['card_wd'])*n_cards, + int(self.params['card_ht'])) + x = 0 # x coord where the next card starts in scratch + for card in cards: +# concatenate each card image to scratch + if card == None or card ==0: + break + self.card_images[card].copy_area(0, 0, + int(self.params['card_wd']), int(self.params['card_ht']), + scratch, x, 0) + x = x + int(self.params['card_wd']) + container.seen_cards.set_from_pixbuf(scratch) + container.resize(1,1) + container.show() + container.move(self.positions[i][0], self.positions[i][1]) # here is where I move back + self.displayed = True + if i != "common": + self.m_windows[i].eb.set_tooltip_text(self.hud.stat_dict[i]['screen_name']) + def update_gui(self, new_hand_id): """Prepare and show the mucked cards.""" if self.displayed: self.hide() @@ -403,33 +447,11 @@ class Flop_Mucked(Aux_Seats): n_cards = self.has_cards(cards) if n_cards > 0: n_sd = n_sd + 1 - if n_sd < 2: return + if n_sd < 2: + print "skipping, n_sd =", n_sd + return -# More than 1 player showed, so display the hole cards - for (i, cards) in self.hud.cards.iteritems(): - n_cards = self.has_cards(cards) - if n_cards > 0: -# scratch is a working pixbuf, used to assemble the image - scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, - int(self.params['card_wd'])*n_cards, - int(self.params['card_ht'])) - x = 0 # x coord where the next card starts in scratch - for card in cards: -# concatenate each card image to scratch - if card == None or card ==0: - break - self.card_images[card].copy_area(0, 0, - int(self.params['card_wd']), int(self.params['card_ht']), - scratch, x, 0) - x = x + int(self.params['card_wd']) - self.m_windows[i].seen_cards.set_from_pixbuf(scratch) - self.m_windows[i].resize(1,1) - self.m_windows[i].show() - self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back - self.displayed = True - - for stats in self.hud.stat_dict.itervalues(): - self.m_windows[i].eb.set_tooltip_text(stats['screen_name']) + super(Flop_Mucked, self).update_gui(new_hand_id) if self.displayed and float(self.params['timeout']) > 0: self.timer_on = True @@ -478,14 +500,3 @@ class Flop_Mucked(Aux_Seats): self.m_windows[i].show() self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back self.displayed = True - - def save_layout(self, *args): - """Save new layout back to the aux element in the config file.""" - new_locs = {} -# print "adj =", self.adj - for (i, pos) in self.positions.iteritems(): - if i != 'common': - new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) - else: - new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) - self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) From 9b4e47df9abf8a6293f9d2fc12b902307950b221 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 25 Jun 2009 23:10:37 +0100 Subject: [PATCH 24/34] comment out debug message --- pyfpdb/Tables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index ead3beba..dcd145f4 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -231,7 +231,7 @@ def discover_nt_by_name(c, tablename): titles = {} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: - print "Tbales.py: tablename =", tablename, "title =", titles[hwnd] + #print "Tables.py: tablename =", tablename, "title =", titles[hwnd] try: # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html if not tablename in titles[hwnd]: continue From a2db28ebf241ee077c7e89caa4daa084448dabc0 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 25 Jun 2009 23:14:32 +0100 Subject: [PATCH 25/34] create Database instance in import to pass into parser - will eventually replace fpdb_db --- pyfpdb/Database.py | 1 + pyfpdb/fpdb_import.py | 10 +++++++--- pyfpdb/fpdb_parse_logic.py | 9 ++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 392681eb..2cade5de 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -49,6 +49,7 @@ class Database: 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'] # where possible avoid creating new SQL instance by using the global one passed in if sql == None: self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 455c1e27..2468fecf 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -31,6 +31,7 @@ import re import fpdb_simple import fpdb_db +import Database import fpdb_parse_logic import Configuration @@ -57,7 +58,8 @@ class Importer: self.settings = settings self.caller = caller self.config = config - self.fdb = None + self.database = None # database will be the main db interface eventually + self.fdb = None # fdb may disappear or just hold the simple db connection self.cursor = None self.filelist = {} self.dirlist = {} @@ -75,6 +77,7 @@ class Importer: self.settings.setdefault("minPrint", 30) self.settings.setdefault("handCount", 0) + self.database = Database.Database(self.config) # includes .connection and .sql variables self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(self.config) self.fdb.db.rollback() @@ -392,8 +395,9 @@ class Importer: self.hand=hand try: - handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb - , self.siteIds[site], category, hand, self.config) + handsId = fpdb_parse_logic.mainParser( self.settings, self.fdb + , self.siteIds[site], category, hand + , self.config, self.database ) self.fdb.db.commit() stored += 1 diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index eff8179f..bb361f63 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -21,10 +21,13 @@ import fpdb_simple import Database #parses a holdem hand -def mainParser(settings, fdb, siteID, category, hand, config): +def mainParser(settings, fdb, siteID, category, hand, config, db = None): backend = settings['db-backend'] - #This is redundant - hopefully fdb will be a Database object in an interation soon - db = Database.Database(config, 'fpdb', '') + if db == None: + #This is redundant - hopefully fdb will be a Database object in an iteration soon + db = Database.Database(c = config, sql = None) + else: + db = db category = fpdb_simple.recogniseCategory(hand[0]) base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud" From cb323d2d6323a508c53fb430e39786c2aefdbc32 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 28 Jun 2009 17:20:41 +0100 Subject: [PATCH 26/34] remove unused queries --- pyfpdb/FpdbSQLQueries.py | 167 --------------------------------------- pyfpdb/fpdb_db.py | 1 - 2 files changed, 168 deletions(-) diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 598c0868..db2d7231 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -248,43 +248,6 @@ class FpdbSQLQueries: self.query['createHandsTable'] = """ """ - ################################ - # Create Gametypes - ################################ - - if(self.dbname == 'MySQL InnoDB'): - self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( - id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), - handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), - card1Value smallint NOT NULL, - card1Suit char(1) NOT NULL, - card2Value smallint NOT NULL, - card2Suit char(1) NOT NULL, - card3Value smallint NOT NULL, - card3Suit char(1) NOT NULL, - card4Value smallint NOT NULL, - card4Suit char(1) NOT NULL, - card5Value smallint NOT NULL, - card5Suit char(1) NOT NULL) - ENGINE=INNODB""" - elif(self.dbname == 'PostgreSQL'): - self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( - id BIGSERIAL, PRIMARY KEY (id), - handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), - card1Value smallint, - card1Suit char(1), - card2Value smallint, - card2Suit char(1), - card3Value smallint, - card3Suit char(1), - card4Value smallint, - card4Suit char(1), - card5Value smallint, - card5Suit char(1))""" - elif(self.dbname == 'SQLite'): - self.query['createBoardCardsTable'] = """ """ - - ################################ # Create TourneyTypes ################################ @@ -1550,136 +1513,6 @@ class FpdbSQLQueries: elif(self.dbname == 'SQLite'): self.query['playerStatsByPosition'] = """ """ - if(self.dbname == 'MySQL InnoDB'): - self.query['playerStatsByPositionAndHoleCards'] = """ - SELECT - concat(upper(stats.limitType), ' ' - ,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' ' - ,stats.name, ' $' - ,cast(trim(leading ' ' from - case when stats.bigBlind < 100 then format(stats.bigBlind/100.0,2) - else format(stats.bigBlind/100.0,0) - end ) as char) - ) AS Game - ,case when stats.PlPosition = -2 then 'BB' - when stats.PlPosition = -1 then 'SB' - when stats.PlPosition = 0 then 'Btn' - when stats.PlPosition = 1 then 'CO' - when stats.PlPosition = 2 then 'MP' - when stats.PlPosition = 5 then 'EP' - else '??' - end AS PlPosition - /*,stats.n*/,hprof2.n - /*,stats.vpip*/,0 - /*,stats.pfr*/,0 - /*,stats.saw_f*/,0 - /*,stats.sawsd*/,0 - /*,stats.wtsdwsf*/,0 - /*,stats.wmsd*/,0 - /*,stats.FlAFq*/,0 - /*,stats.TuAFq*/,0 - /*,stats.RvAFq*/,0 - /*,stats.PoFAFq*/,0 - /* if you have handsactions data the next 3 fields should give same answer as - following 3 commented out fields */ - /*,stats.Net - ,stats.BBper100 - ,stats.Profitperhand*/ - ,format(hprof2.sum_profit/100.0,2) AS Net - /*,format((hprof2.sum_profit/(stats.bigBlind+0.0)) / (stats.n/100.0),2)*/,0 - AS BBlPer100 - ,hprof2.profitperhand AS Profitperhand - ,format(hprof2.variance,2) AS Variance - FROM - (select /* stats from hudcache */ - gt.base - ,gt.category - ,upper(gt.limitType) as limitType - ,s.name - ,gt.bigBlind - ,hc.gametypeId - ,case when hc.position = 'B' then -2 - when hc.position = 'S' then -1 - when hc.position = 'D' then 0 - when hc.position = 'C' then 1 - when hc.position = 'M' then 2 - when hc.position = 'E' then 5 - else 9 - end as PlPosition - ,sum(HDs) AS n - ,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip - ,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr - ,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f - ,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd - ,case when sum(street1Seen) = 0 then '-' - else format(100.0*sum(sawShowdown)/sum(street1Seen),1) - end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then '-' - end AS wtsdwsf - ,case when sum(sawShowdown) = 0 then '-' - else format(100.0*sum(wonAtSD)/sum(sawShowdown),1) - end AS wmsd - ,case when sum(street1Seen) = 0 then '-' - else format(100.0*sum(street1Aggr)/sum(street1Seen),1) - end AS FlAFq - ,case when sum(street2Seen) = 0 then '-' - else format(100.0*sum(street2Aggr)/sum(street2Seen),1) - end AS TuAFq - ,case when sum(street3Seen) = 0 then '-' - else format(100.0*sum(street3Aggr)/sum(street3Seen),1) - end AS RvAFq - ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-' - else format(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) - /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),1) - end AS PoFAFq - ,format(sum(totalProfit)/100.0,2) AS Net - ,format((sum(totalProfit)/(gt.bigBlind+0.0)) / (sum(HDs)/100.0),2) - AS BBper100 - ,format( (sum(totalProfit)/100.0) / sum(HDs), 4) AS Profitperhand - from Gametypes gt - inner join Sites s on s.Id = gt.siteId - inner join HudCache hc on hc.gameTypeId = gt.Id - where hc.playerId in - # use here ? - group by gt.base - ,gt.category - ,upper(gt.limitType) - ,s.name - ,gt.bigBlind - ,hc.gametypeId - ,PlPosition - ) stats - inner join - ( select # profit from handsplayers/handsactions - hprof.gameTypeId, - case when hprof.position = 'B' then -2 - when hprof.position = 'S' then -1 - when hprof.position in ('3','4') then 2 - when hprof.position in ('6','7') then 5 - else hprof.position - end as PlPosition, - sum(hprof.profit) as sum_profit, - avg(hprof.profit/100.0) as profitperhand, - variance(hprof.profit/100.0) as variance, - count(*) as n - from - (select hp.handId, h.gameTypeId, hp.position, hp.winnings, SUM(ha.amount) as costs - , hp.winnings - SUM(ha.amount) as profit - from HandsPlayers hp - inner join Hands h ON h.id = hp.handId - left join HandsActions ha ON ha.handsPlayerId = hp.id - where hp.playerId in - # use here ? - and hp.tourneysPlayersId IS NULL - and ((hp.card1Value = and hp.card2Value = ) or (hp.card1Value = and hp.card2Value = )) - group by hp.handId, h.gameTypeId, hp.position, hp.winnings - ) hprof - group by hprof.gameTypeId, PlPosition - ) hprof2 - on ( hprof2.gameTypeId = stats.gameTypeId - and hprof2.PlPosition = stats.PlPosition) - order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as signed) - """ if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'): self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 29817af9..911618e1 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -243,7 +243,6 @@ class fpdb_db: self.cursor.execute(self.sql.query['createPlayersTable']) self.cursor.execute(self.sql.query['createAutoratesTable']) self.cursor.execute(self.sql.query['createHandsTable']) - self.cursor.execute(self.sql.query['createBoardCardsTable']) self.cursor.execute(self.sql.query['createTourneyTypesTable']) self.cursor.execute(self.sql.query['createTourneysTable']) self.cursor.execute(self.sql.query['createTourneysPlayersTable']) From dc7a3fb88ebd82f90a87c6e344474498749727d4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 28 Jun 2009 18:56:18 +0100 Subject: [PATCH 27/34] finish removal of store_board_cards() --- pyfpdb/Database.py | 3 --- pyfpdb/fpdb_simple.py | 10 ---------- 2 files changed, 13 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 2cade5de..f59476b9 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -328,7 +328,6 @@ class Database: if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) t5 = time() - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) t6 = time() if self.saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) @@ -363,8 +362,6 @@ class Database: if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - if self.saveActions: fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) return hands_id diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 34f99e2f..3e862254 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1136,16 +1136,6 @@ def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, ac cursor.executemany("INSERT INTO HandsActions (handsPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", inserts) #end def storeActions -def store_board_cards(cursor, hands_id, board_values, board_suits): -#stores into table board_cards - cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit, -card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, -card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (hands_id, board_values[0], board_suits[0], board_values[1], board_suits[1], - board_values[2], board_suits[2], board_values[3], board_suits[3], - board_values[4], board_suits[4])) -#end def store_board_cards - def storeHands(backend, conn, cursor, site_hand_no, gametype_id ,hand_start_time, names, tableName, maxSeats, hudCache, board_values, board_suits): From a3e6c2696faa9dde60316b3f091d723aa06dbd37 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 28 Jun 2009 19:19:32 +0100 Subject: [PATCH 28/34] use Database instead of fpdb_db --- pyfpdb/fpdb.py | 58 ++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 6c982002..3f6b7fb6 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -32,7 +32,7 @@ import pygtk pygtk.require('2.0') import gtk -import fpdb_db + import fpdb_simple import GuiBulkImport import GuiPlayerStats @@ -206,22 +206,23 @@ class fpdb: try: 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.database+" on "+self.db.host+" they will be deleted." + 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." 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.backend == self.fdb_lock.MYSQL_INNODB: + if self.db.fdb.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 self.release_global_lock() lock_released = True - self.db.recreate_tables() + self.db.fdb.recreate_tables() else: # for other dbs use same connection as holds global lock - self.fdb_lock.recreate_tables() + self.fdb_lock.fdb.recreate_tables() elif response == gtk.RESPONSE_NO: print 'User cancelled recreating tables' except: @@ -362,13 +363,18 @@ class fpdb: self.settings.update(self.config.get_import_parameters()) self.settings.update(self.config.get_default_paths()) - if self.db!=None: - self.db.disconnect() + if self.db != None and self.db.fdb != None: + self.db.fdb.disconnect() - self.db = fpdb_db.fpdb_db() - #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] - self.db.do_connect(self.config) - if self.db.wrongDbVersion: + self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) + self.db = Database.Database(self.config, sql = self.sql) + + + + + + + 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)) label = gtk.Label("An invalid DB version or missing tables have been detected.") @@ -387,18 +393,19 @@ 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.database, self.db.host)) + self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.fdb.get_backend_name(),self.db.fdb.database, self.db.fdb.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.database, self.db.host)) + self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.fdb.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) # Database connected to successfully, load queries to pass on to other classes - self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) - self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) - self.dbi = Database.Database(self.config, sql = self.sql) # dbi for db interface and to avoid clashes with db/database/etc - # can rename later if required - self.db.db.rollback() + self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.fdb.get_backend_name()) + self.db.fdb.db.rollback() + + + + #end def load_profile def not_implemented(self, widget, data=None): @@ -407,21 +414,22 @@ class fpdb: def obtain_global_lock(self): print "\nTaking global lock ..." - self.fdb_lock = fpdb_db.fpdb_db() - self.fdb_lock.do_connect(self.config) - return self.fdb_lock.get_global_lock() + self.fdb_lock = Database.Database(self.config, sql = self.sql) + + self.fdb_lock.fdb.do_connect(self.config) + return self.fdb_lock.fdb.get_global_lock() #end def obtain_global_lock def quit(self, widget, data=None): print "Quitting normally" #check if current settings differ from profile, if so offer to save or abort - self.db.disconnect() + self.db.fdb.disconnect() gtk.main_quit() #end def quit_cliecked def release_global_lock(self): - self.fdb_lock.db.rollback() - self.fdb_lock.disconnect() + self.fdb_lock.fdb.db.rollback() + self.fdb_lock.fdb.disconnect() print "Global lock released." #end def release_global_lock @@ -471,7 +479,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") def tab_table_viewer(self, widget, data=None): """opens a table viewer tab""" #print "start of tab_table_viewer" - new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) + new_tv_thread=GuiTableViewer.GuiTableViewer(self.db.fdb, self.settings) self.threads.append(new_tv_thread) tv_tab=new_tv_thread.get_vbox() self.add_and_display_tab(tv_tab, "Table Viewer") From a8b8ff2f4d5542aa3fab36a923cb8e69f275058b Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 30 Jun 2009 11:43:47 -0400 Subject: [PATCH 29/34] More on Aux_Seats class. This seems to work OK. --- pyfpdb/Mucked.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 4c8b2eb4..c0715632 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -87,6 +87,13 @@ class Aux_Window(object): if c != None and c > 0: n = n + 1 return n + def get_id_from_seat(self, seat): + """Determine player id from seat number, given stat_dict.""" + for id, dict in self.hud.stat_dict.iteritems(): + if seat == dict['seat']: + return id + return None + class Stud_mucked(Aux_Window): def __init__(self, hud, config, params): @@ -356,13 +363,15 @@ class Aux_Seats(Aux_Window): self.m_windows[i].connect("configure_event", self.configure_event_cb, i) self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) - self.m_windows[i].set_opacity(float(self.params['opacity'])) + if self.params.has_key('opacity'): + self.m_windows[i].set_opacity(float(self.params['opacity'])) # the create_contents method is supplied by the subclass self.create_contents(self.m_windows[i], i) self.m_windows[i].show_all() - self.m_windows[i].hide() + if self.uses_timer: + self.m_windows[i].hide() def update_gui(self, new_hand_id): """Update the gui, LDO.""" @@ -394,6 +403,10 @@ class Aux_Seats(Aux_Window): new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) + def configure_event_cb(self, widget, event, i, *args): + self.positions[i] = widget.get_position() +# self.rel_positions[i] = (self.positions[i][0] - self.hud.table.x, self.positions[i][1] - self.hud.table.y) + class Flop_Mucked(Aux_Seats): """Aux_Window class for displaying mucked cards for flop games.""" @@ -491,10 +504,6 @@ class Flop_Mucked(Aux_Seats): window = widget.get_parent() window.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time) - def configure_event_cb(self, widget, event, i, *args): - self.positions[i] = widget.get_position() -# self.rel_positions[i] = (self.positions[i][0] - self.hud.table.x, self.positions[i][1] - self.hud.table.y) - def expose_all(self): for (i, cards) in self.hud.cards.iteritems(): self.m_windows[i].show() From 71d673f64f32c8ae1ef576fa5b6861d808eceee4 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 30 Jun 2009 11:45:14 -0400 Subject: [PATCH 30/34] Added Hello_Seats to Hello.py. Demo of Aux_Seats class. --- pyfpdb/Hello.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/pyfpdb/Hello.py b/pyfpdb/Hello.py index 41262d6c..7f3f6442 100644 --- a/pyfpdb/Hello.py +++ b/pyfpdb/Hello.py @@ -34,10 +34,13 @@ import gobject # FreePokerTools modules from Mucked import Aux_Window +from Mucked import Seat_Window +from Mucked import Aux_Seats class Hello(Aux_Window): """A 'Hello World' Aux_Window demo.""" def create(self): + print "creating Hello" # This demo simply creates a label in a window. self.container = gtk.Window() self.container.add(gtk.Label("Hello World")) @@ -99,15 +102,18 @@ class Hello_plus(Aux_Window): # hands played that was updated in the "update_data()" function. self.label.set_text("Hello %s\nYou have played %d hands\n on %s." % (self.hero, self.hands_played, self.site)) -class Hello_Menu(Aux_Window): - """A 'Hello World' Aux_Window demo.""" - def create(self): -# This demo puts a menu item on the HUD mainwindow. - self.item = gtk.MenuItem('Print cards') - self.hud.menu.append(self.item) - self.item.connect("activate", self.print_cards) - self.item.show() +class Hello_Seats(Aux_Seats): + """A 'Hello World' Seat_Window demo.""" - def print_cards(self, *args): -# callback for the menu item - print "cards =", self.hud.cards + def create_contents(self, container, i): + container.label = gtk.Label("empty") + container.add(container.label) + container.show_all() + + def update_contents(self, container, i): + if i == "common": return + id = self.get_id_from_seat(i) + if id == None: + container.label.set_text("empty") + else: + container.label.set_text("player = %s" % self.hud.stat_dict[id]['screen_name']) From a3f233ca07e13bfa1c07ac8f7f44c7889792afae Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 30 Jun 2009 14:21:06 -0400 Subject: [PATCH 31/34] Comment out a DEBUG print. --- pyfpdb/Hand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 38c3609b..b9272031 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -202,7 +202,7 @@ If a player has None chips he won't be added.""" def setCommunityCards(self, street, cards): logging.debug("setCommunityCards %s %s" %(street, cards)) self.board[street] = [self.card(c) for c in cards] - print "DEBUG: self.board: %s" % self.board +# print "DEBUG: self.board: %s" % self.board def card(self,c): """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" From 04b9dd91268563e2569417a5252ababaf8376cd4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 30 Jun 2009 21:58:59 +0100 Subject: [PATCH 32/34] use Players table for global lock because Database.init() tries to access Hands --- pyfpdb/fpdb_db.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 911618e1..f89b5d6d 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -567,17 +567,18 @@ class fpdb_db: print "analyze took", atime, "seconds" #end def analyzeDB - # Currently uses an exclusive lock on the Hands table as a global lock + # Currently uses an exclusive lock on the Players table as a global lock + # ( Changed because Hands is used in Database.init() ) # Return values are Unix style, 0 for success, positive integers for errors # 1 = generic error - # 2 = hands table does not exist (error message is suppressed) + # 2 = players table does not exist (error message is suppressed) def get_global_lock(self): if self.backend == self.MYSQL_INNODB: try: - self.cursor.execute( "lock tables Hands write" ) + self.cursor.execute( "lock tables Players write" ) except: - # Table 'fpdb.hands' doesn't exist - if str(sys.exc_value).find(".Hands' doesn't exist") >= 0: + # Table 'fpdb.players' doesn't exist + if str(sys.exc_value).find(".Players' doesn't exist") >= 0: return(2) print "Error! failed to obtain global lock. Close all programs accessing " \ + "database (including fpdb) and try again (%s)." \ @@ -585,11 +586,11 @@ class fpdb_db: return(1) elif self.backend == self.PGSQL: try: - self.cursor.execute( "lock table Hands in exclusive mode nowait" ) + self.cursor.execute( "lock table Players in exclusive mode nowait" ) #print "... after lock table, status =", self.cursor.statusmessage except: - # relation "hands" does not exist - if str(sys.exc_value).find('relation "hands" does not exist') >= 0: + # relation "players" does not exist + if str(sys.exc_value).find('relation "players" does not exist') >= 0: return(2) print "Error! failed to obtain global lock. Close all programs accessing " \ + "database (including fpdb) and try again (%s)." \ From cb1a4d2d0ab6500e11666cf92b4677b8f51953dc Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 30 Jun 2009 22:00:55 +0100 Subject: [PATCH 33/34] add wrappers for fpdb_db methods (plan is to move the fpdb_db methods into Database) --- pyfpdb/Database.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f59476b9..cf80b3d3 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -40,7 +40,7 @@ import Card class Database: def __init__(self, c, db_name = None, game = None, sql = None): # db_name and game not used any more - print "creating Database instance, sql =", sql + print "\ncreating Database instance, sql =", sql 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 @@ -87,13 +87,28 @@ class Database: #row = cur.fetchone() self.saveActions = False if self.import_options['saveActions'] == False else True + def do_connect(self, c): + self.fdb.do_connect(c) def commit(self): self.fdb.db.commit() def close_connection(self): self.connection.close() + + def disconnect(self, due_to_error=False): + """Disconnects the DB (rolls back if param is true, otherwise commits""" + self.fdb.disconnect(due_to_error) + + def reconnect(self, due_to_error=False): + """Reconnects the DB""" + self.fdb.reconnect(due_to_error=False) + + def get_backend_name(self): + """Reconnects the DB""" + return self.fdb.get_backend_name() + def get_table_name(self, hand_id): c = self.connection.cursor() c.execute(self.sql.query['get_table_name'], (hand_id, )) From 56ef131bedb9dc06998250d11b2890a83b886a7c Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 30 Jun 2009 22:18:15 +0100 Subject: [PATCH 34/34] use 1 or 2 Database methods instead of the underlying fpdb_db methods (more to do) --- pyfpdb/fpdb.py | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 3f6b7fb6..cdb89894 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -364,16 +364,11 @@ class fpdb: self.settings.update(self.config.get_default_paths()) if self.db != None and self.db.fdb != None: - self.db.fdb.disconnect() + 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) - - - - - 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)) @@ -393,19 +388,15 @@ 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.fdb.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.fdb.database, self.db.fdb.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.fdb.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.fdb.database, self.db.fdb.host)) # Database connected to successfully, load queries to pass on to other classes - self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.fdb.get_backend_name()) - self.db.fdb.db.rollback() - - - - + self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) + self.db.connection.rollback() #end def load_profile def not_implemented(self, widget, data=None): @@ -415,22 +406,21 @@ class fpdb: def obtain_global_lock(self): print "\nTaking global lock ..." self.fdb_lock = Database.Database(self.config, sql = self.sql) - - self.fdb_lock.fdb.do_connect(self.config) + self.fdb_lock.do_connect(self.config) return self.fdb_lock.fdb.get_global_lock() #end def obtain_global_lock def quit(self, widget, data=None): print "Quitting normally" #check if current settings differ from profile, if so offer to save or abort - self.db.fdb.disconnect() + self.db.disconnect() gtk.main_quit() #end def quit_cliecked def release_global_lock(self): self.fdb_lock.fdb.db.rollback() self.fdb_lock.fdb.disconnect() - print "Global lock released." + print "Global lock released.\n" #end def release_global_lock def tab_abbreviations(self, widget, data=None):