From b3d2a95796bfbe91ad94f359a1b906c1f22dfc53 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 30 Nov 2009 21:14:03 +0800 Subject: [PATCH 01/38] fix return tuple in import_file_dict, fix text from autoimport to actually show up in autoimport window --- pyfpdb/fpdb.py | 15 +++++++-------- pyfpdb/fpdb_import.py | 11 ++++++++--- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index d5f4faec..b960da05 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -115,7 +115,7 @@ class fpdb: self.pages.append(new_page) self.tabs.append(event_box) self.tab_names.append(new_tab_name) - + #self.nb.append_page(new_page, gtk.Label(new_tab_name)) self.nb.append_page(page, event_box) self.nb_tabs.append(new_tab_name) @@ -135,12 +135,12 @@ class fpdb: self.nb.set_current_page(tab_no) def create_custom_tab(self, text, nb): - #create a custom tab for notebook containing a + #create a custom tab for notebook containing a #label and a button with STOCK_ICON eventBox = gtk.EventBox() tabBox = gtk.HBox(False, 2) tabLabel = gtk.Label(text) - tabBox.pack_start(tabLabel, False) + tabBox.pack_start(tabLabel, False) eventBox.add(tabBox) if nb.get_n_pages() > 0: @@ -157,7 +157,7 @@ class fpdb: return eventBox def add_icon_to_button(self, button): - iconBox = gtk.HBox(False, 0) + iconBox = gtk.HBox(False, 0) image = gtk.Image() image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_SMALL_TOOLBAR) gtk.Button.set_relief(button, gtk.RELIEF_NONE) @@ -168,8 +168,8 @@ class fpdb: iconBox.pack_start(image, True, False, 0) button.add(iconBox) iconBox.show() - return - + return + # Remove a page from the notebook def remove_tab(self, button, data): (nb, text) = data @@ -183,7 +183,7 @@ class fpdb: #print " removing page", page del self.nb_tabs[page] nb.remove_page(page) - # Need to refresh the widget -- + # Need to refresh the widget -- # This forces the widget to redraw itself. #nb.queue_draw_area(0,0,-1,-1) needed or not?? @@ -752,7 +752,6 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") sys.stderr.write("fpdb starting ...") def window_state_event_cb(self, window, event): - print "window_state_event", event if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED: # -20 = GWL_EXSTYLE can't find it in the pywin32 libs #bits = win32api.GetWindowLong(self.window.window.handle, -20) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 19bf18d1..b6cfb821 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -359,10 +359,15 @@ class Importer: # print "file",counter," updated", os.path.basename(file), stat_info.st_size, self.updatedsize[file], stat_info.st_mtime, self.updatedtime[file] try: if not os.path.isdir(file): - self.caller.addText("\n"+file) + self.caller.addText("\n"+os.path.basename(file)) except KeyError: # TODO: What error happens here? pass - self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None) + (stored, duplicates, partial, errors, ttime) = self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None) + try: + if not os.path.isdir(file): + self.caller.addText(" %d stored, %d duplicates, %d partial, %d errors (time = %d)" % (stored, duplicates, partial, errors, ttime)) + except KeyError: # TODO: Again, what error happens here? fix when we find out .. + pass self.updatedsize[file] = stat_info.st_size self.updatedtime[file] = time() else: @@ -393,7 +398,7 @@ class Importer: if os.path.isdir(file): self.addToDirList[file] = [site] + [filter] - return + return (0,0,0,0,0) conv = None (stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, 0) From d3d8b4afbb426bf3af65e50e66706712d19fab68 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 30 Nov 2009 22:08:30 +0800 Subject: [PATCH 02/38] ttime = float with us to ms resolution --- pyfpdb/fpdb_import.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index b6cfb821..541b018f 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -21,7 +21,7 @@ import os # todo: remove this once import_dir is in fpdb_import import sys -from time import time, strftime, sleep +from time import time, strftime, sleep, clock import traceback import math import datetime @@ -101,6 +101,8 @@ class Importer: self.NEWIMPORT = Configuration.NEWIMPORT + clock() # init clock in windows + #Set functions def setCallHud(self, value): self.callHud = value @@ -365,7 +367,7 @@ class Importer: (stored, duplicates, partial, errors, ttime) = self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None) try: if not os.path.isdir(file): - self.caller.addText(" %d stored, %d duplicates, %d partial, %d errors (time = %d)" % (stored, duplicates, partial, errors, ttime)) + self.caller.addText(" %d stored, %d duplicates, %d partial, %d errors (time = %f)" % (stored, duplicates, partial, errors, ttime)) except KeyError: # TODO: Again, what error happens here? fix when we find out .. pass self.updatedsize[file] = stat_info.st_size @@ -477,10 +479,13 @@ class Importer: self.pos_in_file[file] = inputFile.tell() inputFile.close() + x = clock() (stored, duplicates, partial, errors, ttime, handsId) = self.import_fpdb_lines(db, self.lines, starttime, file, site, q) db.commit() - ttime = time() - starttime + y = clock() + ttime = y - x + #ttime = time() - starttime if q is None: log.info("Total stored: %(stored)d\tduplicates:%(duplicates)d\terrors:%(errors)d\ttime:%(ttime)s" % locals()) From c38efd61ef0f8bbd588b3761896f33507f003461 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Mon, 30 Nov 2009 22:51:47 +0800 Subject: [PATCH 03/38] trap IOError on hud pipe write when hud closed without autoimport stopping, turn off hud --- pyfpdb/fpdb_import.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 541b018f..d735de04 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -564,7 +564,11 @@ class Importer: #print "call to HUD here. handsId:",handsId #pipe the Hands.id out to the HUD # print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud - self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) + try: + self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) + except IOError: # hud closed + self.callHud = False + pass # continue import without hud except Exceptions.DuplicateError: duplicates += 1 db.rollback() From 48c36c319bb0a53618f98d9322d4d3b749add7ba Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Tue, 1 Dec 2009 05:43:29 +0800 Subject: [PATCH 04/38] improve rebuild hudcache and indexes dialogs --- pyfpdb/Database.py | 17 ++++++++----- pyfpdb/fpdb.py | 63 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index cd6ad298..1c44bb61 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -58,7 +58,8 @@ class Database: PGSQL = 3 SQLITE = 4 - hero_hudstart_def = '1999-12-31' # default for length of Hero's stats in HUD + hero_hudstart_def = '1999-12-31' # default for length of Hero's stats in HUD + villain_hudstart_def = '1999-12-31' # default for length of Villain's stats in HUD # Data Structures for index and foreign key creation # drop_code is an int with possible values: 0 - don't drop for bulk import @@ -1324,7 +1325,7 @@ class Database: self.dropAllForeignKeys() self.createAllForeignKeys() - def rebuild_hudcache(self, start=None): + def rebuild_hudcache(self, h_start=None, v_start=None): """clears hudcache and rebuilds from the individual handsplayers records""" try: @@ -1344,13 +1345,17 @@ class Database: if p_id: self.hero_ids[site_id] = int(p_id) - if start is None: - start = self.hero_hudstart_def + if h_start is None: + h_start = self.hero_hudstart_def + if v_start is None: + v_start = self.villain_hudstart_def if self.hero_ids == {}: where = "" else: - where = "where hp.playerId not in " + str(tuple(self.hero_ids.values())) \ - + " or h.handStart > '" + start + "'" + where = "where ( hp.playerId not in " + str(tuple(self.hero_ids.values())) \ + + " and h.handStart > '" + v_start + "')" \ + + " or ( hp.playerId in " + str(tuple(self.hero_ids.values())) \ + + " and h.handStart > '" + h_start + "')" rebuild_sql = self.sql.query['rebuildHudCache'].replace('', where) self.get_cursor().execute(self.sql.query['clearHudCache']) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index b960da05..7da93e87 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -334,27 +334,48 @@ class fpdb: diastring = "Please confirm that you want to re-create the HUD cache." self.dia_confirm.format_secondary_text(diastring) - hb = gtk.HBox(True, 1) + hb1 = gtk.HBox(True, 1) + self.h_start_date = gtk.Entry(max=12) + self.h_start_date.set_text( self.db.get_hero_hudcache_start() ) + lbl = gtk.Label(" Hero's cache starts: ") + btn = gtk.Button() + btn.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) + btn.connect('clicked', self.__calendar_dialog, self.h_start_date) + + hb1.pack_start(lbl, expand=True, padding=3) + hb1.pack_start(self.h_start_date, expand=True, padding=2) + hb1.pack_start(btn, expand=False, padding=3) + self.dia_confirm.vbox.add(hb1) + hb1.show_all() + + hb2 = gtk.HBox(True, 1) self.start_date = gtk.Entry(max=12) self.start_date.set_text( self.db.get_hero_hudcache_start() ) - lbl = gtk.Label(" Hero's cache starts: ") + lbl = gtk.Label(" Villains' cache starts: ") btn = gtk.Button() btn.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) btn.connect('clicked', self.__calendar_dialog, self.start_date) - hb.pack_start(lbl, expand=True, padding=3) - hb.pack_start(self.start_date, expand=True, padding=2) - hb.pack_start(btn, expand=False, padding=3) - self.dia_confirm.vbox.add(hb) - hb.show_all() + hb2.pack_start(lbl, expand=True, padding=3) + hb2.pack_start(self.start_date, expand=True, padding=2) + hb2.pack_start(btn, expand=False, padding=3) + self.dia_confirm.vbox.add(hb2) + hb2.show_all() response = self.dia_confirm.run() - self.dia_confirm.destroy() if response == gtk.RESPONSE_YES: - self.db.rebuild_hudcache( self.start_date.get_text() ) + lbl = gtk.Label(" Rebuilding HUD Cache ... ") + self.dia_confirm.vbox.add(lbl) + lbl.show() + while gtk.events_pending(): + gtk.main_iteration_do(False) + + self.db.rebuild_hudcache( self.h_start_date.get_text(), self.start_date.get_text() ) elif response == gtk.RESPONSE_NO: print 'User cancelled rebuilding hud cache' + self.dia_confirm.destroy() + self.release_global_lock() def dia_rebuild_indexes(self, widget, data=None): @@ -368,14 +389,28 @@ class fpdb: self.dia_confirm.format_secondary_text(diastring) response = self.dia_confirm.run() - self.dia_confirm.destroy() if response == gtk.RESPONSE_YES: + lbl = gtk.Label(" Rebuilding Indexes ... ") + self.dia_confirm.vbox.add(lbl) + lbl.show() + while gtk.events_pending(): + gtk.main_iteration_do(False) self.db.rebuild_indexes() + + lbl.set_text(" Cleaning Database ... ") + while gtk.events_pending(): + gtk.main_iteration_do(False) self.db.vacuumDB() + + lbl.set_text(" Analyzing Database ... ") + while gtk.events_pending(): + gtk.main_iteration_do(False) self.db.analyzeDB() elif response == gtk.RESPONSE_NO: print 'User cancelled rebuilding db indexes' + self.dia_confirm.destroy() + self.release_global_lock() def __calendar_dialog(self, widget, entry): @@ -397,10 +432,13 @@ class fpdb: d.show_all() def __get_dates(self): - t1 = self.start_date.get_text() + t1 = self.h_start_date.get_text() if t1 == '': t1 = '1970-01-01' - return (t1) + t2 = self.start_date.get_text() + if t2 == '': + t2 = '1970-01-01' + return (t1, t2) def __get_date(self, widget, calendar, entry, win): # year and day are correct, month is 0..11 @@ -834,6 +872,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") gtk.main() return 0 + if __name__ == "__main__": me = fpdb() me.main() From 117c377fff326a6e558164370a11c79406370830 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 3 Dec 2009 16:46:10 +0800 Subject: [PATCH 05/38] Repair recent damage to Options --- pyfpdb/Options.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py index 9859e7d2..ab226124 100644 --- a/pyfpdb/Options.py +++ b/pyfpdb/Options.py @@ -36,8 +36,11 @@ def fpdb_options(): action="store_true", help="Indicates program was restarted with a different path (only allowed once).") parser.add_option("-i", "--infile", - dest="config", default=None, + dest="infile", default="Slartibartfast", help="Input file") + parser.add_option("-k", "--konverter", + dest="hhc", default="PokerStarsToFpdb", + help="Module name for Hand History Converter") (options, argv) = parser.parse_args() return (options, argv) From 5913c9092a58bc69ba00270109d829459b281e2d Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Thu, 3 Dec 2009 20:22:33 +0800 Subject: [PATCH 06/38] Add some basic error handling at the very beginning of startup, to deal with missing imports and such, update about box --- pyfpdb/fpdb.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 7da93e87..239bfbec 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -37,14 +37,20 @@ if os.name == 'nt' and sys.version[0:3] not in ('2.5', '2.6') and '-r' not in sy os.execvpe('python.exe', ('python.exe', 'fpdb.py', '-r'), os.environ) # first arg is ignored (name of program being run) else: print "\npython 2.5 not found, please install python 2.5 or 2.6 for fpdb\n" - exit + raw_input("Press ENTER to continue.") + exit() else: pass #print "debug - not changing path" if os.name == 'nt': - import win32api - import win32con + try: + import win32api + import win32con + except ImportError: + print "We appear to be running in Windows, but the Windows Python Extensions are not loading. Please install the PYWIN32 package from http://sourceforge.net/projects/pywin32/" + raw_input("Press ENTER to continue.") + exit() print "Python " + sys.version[0:3] + '...\n' @@ -62,9 +68,14 @@ if not options.errorsToConsole: import logging -import pygtk -pygtk.require('2.0') -import gtk +try: + import pygtk + pygtk.require('2.0') + import gtk +except: + print "Unable to load PYGTK modules required for GUI. Please install PyCairo, PyGObject, and PyGTK from www.pygtk.org." + raw_input("Press ENTER to continue.") + exit() import interlocks @@ -196,14 +207,14 @@ class fpdb: def dia_about(self, widget, data=None): #self.warning_box("About FPDB:\n\nFPDB was originally created by a guy named Steffen, sometime in 2008, \nand is mostly worked on these days by people named Eratosthenes, s0rrow, _mt, EricBlade, sqlcoder, and other strange people.\n\n", "ABOUT FPDB") dia = gtk.AboutDialog() - dia.set_name("FPDB") + dia.set_name("Free Poker Database (FPDB)") dia.set_version(VERSION) - dia.set_copyright("2008-2009, Steffen, Eratosthenes, s0rrow, EricBlade, _mt, sqlcoder, and others") + dia.set_copyright("2008-2010, Steffen, Eratosthenes, s0rrow, EricBlade, _mt, sqlcoder, Bostik, and others") dia.set_comments("GTK AboutDialog comments here") dia.set_license("GPL v3") dia.set_website("http://fpdb.sourceforge.net/") - dia.set_authors("Steffen, Eratosthenes, s0rrow, EricBlade, _mt, and others") - dia.set_program_name("FPDB") + dia.set_authors("Steffen, Eratosthenes, s0rrow, EricBlade, _mt, sqlcoder, Bostik, and others") + dia.set_program_name("Free Poker Database (FPDB)") dia.run() dia.destroy() From a6429957fed38e9de81486640688a2a66fbbb64f Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Thu, 3 Dec 2009 20:24:12 +0800 Subject: [PATCH 07/38] comment out some prints, apparently mysqlcoder and my editors do not agree well with each other on spacing. --- pyfpdb/Hud.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 944eacd0..ae20212a 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -173,26 +173,26 @@ class Hud: item = gtk.CheckMenuItem(' All Levels') self.aggMenu.append(item) item.connect("activate", self.set_aggregation, ('P',10000)) - setattr(self, 'h_aggBBmultItem10000', item) - # + setattr(self, 'h_aggBBmultItem10000', item) + # item = gtk.MenuItem('For #Seats:') self.aggMenu.append(item) - # + # item = gtk.CheckMenuItem(' Any Number') self.aggMenu.append(item) item.connect("activate", self.set_seats_style, ('P','A')) setattr(self, 'h_seatsStyleOptionA', item) - # + # item = gtk.CheckMenuItem(' Custom') self.aggMenu.append(item) item.connect("activate", self.set_seats_style, ('P','C')) - setattr(self, 'h_seatsStyleOptionC', item) - # + setattr(self, 'h_seatsStyleOptionC', item) + # item = gtk.CheckMenuItem(' Exact') self.aggMenu.append(item) item.connect("activate", self.set_seats_style, ('P','E')) - setattr(self, 'h_seatsStyleOptionE', item) - # + setattr(self, 'h_seatsStyleOptionE', item) + # item = gtk.MenuItem('Since:') self.aggMenu.append(item) # @@ -242,26 +242,26 @@ class Hud: item = gtk.CheckMenuItem(' All Levels') self.aggMenu.append(item) item.connect("activate", self.set_aggregation, ('O',10000)) - setattr(self, 'aggBBmultItem10000', item) - # + setattr(self, 'aggBBmultItem10000', item) + # item = gtk.MenuItem('For #Seats:') self.aggMenu.append(item) - # + # item = gtk.CheckMenuItem(' Any Number') self.aggMenu.append(item) item.connect("activate", self.set_seats_style, ('O','A')) setattr(self, 'seatsStyleOptionA', item) - # + # item = gtk.CheckMenuItem(' Custom') self.aggMenu.append(item) item.connect("activate", self.set_seats_style, ('O','C')) - setattr(self, 'seatsStyleOptionC', item) - # + setattr(self, 'seatsStyleOptionC', item) + # item = gtk.CheckMenuItem(' Exact') self.aggMenu.append(item) item.connect("activate", self.set_seats_style, ('O','E')) - setattr(self, 'seatsStyleOptionE', item) - # + setattr(self, 'seatsStyleOptionE', item) + # item = gtk.MenuItem('Since:') self.aggMenu.append(item) # @@ -358,7 +358,7 @@ class Hud: def change_max_seats(self, widget): if self.max != widget.ms: - print 'change_max_seats', widget.ms + #print 'change_max_seats', widget.ms self.max = widget.ms try: self.kill() @@ -402,7 +402,7 @@ class Hud: else: param = 'seats_style' prefix = '' - + if style == 'A' and getattr(self, prefix+'seatsStyleOptionA').get_active(): self.hud_params[param] = 'A' getattr(self, prefix+'seatsStyleOptionC').set_active(False) @@ -681,7 +681,7 @@ class Stat_Window: return True def kill_popup(self, popup): - print "remove popup", popup + #print "remove popup", popup self.popups.remove(popup) popup.window.destroy() From 3f30878bbd6963c02c909ce13e283017b1e14d82 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 4 Dec 2009 17:56:56 +0800 Subject: [PATCH 08/38] [NEWIMPORT] Partially fix number of hands parsed reporting --- pyfpdb/HandHistoryConverter.py | 16 +++++++++------- pyfpdb/fpdb_import.py | 4 ++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 41b7b3d0..27bb9b1a 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -71,6 +71,8 @@ follow : whether to tail -f the input""" self.out_path = out_path self.processedHands = [] + self.numHands = 0 + self.numErrors = 0 # Tourney object used to store TourneyInfo when called to deal with a Summary file self.tourney = None @@ -135,17 +137,17 @@ Otherwise, finish at EOF. return try: - numHands = 0 - numErrors = 0 + self.numHands = 0 + self.numErrors = 0 if self.follow: #TODO: See how summary files can be handled on the fly (here they should be rejected as before) log.info("Tailing '%s'" % self.in_path) for handText in self.tailHands(): try: self.processHand(handText) - numHands += 1 + self.numHands += 1 except FpdbParseError, e: - numErrors += 1 + self.numErrors += 1 log.warning("Failed to convert hand %s" % e.hid) log.warning("Exception msg: '%s'" % str(e)) log.debug(handText) @@ -160,13 +162,13 @@ Otherwise, finish at EOF. try: self.processedHands.append(self.processHand(handText)) except FpdbParseError, e: - numErrors += 1 + self.numErrors += 1 log.warning("Failed to convert hand %s" % e.hid) log.warning("Exception msg: '%s'" % str(e)) log.debug(handText) - numHands = len(handsList) + self.numHands = len(handsList) endtime = time.time() - log.info("Read %d hands (%d failed) in %.3f seconds" % (numHands, numErrors, endtime - starttime)) + log.info("Read %d hands (%d failed) in %.3f seconds" % (self.numHands, self.numErrors, endtime - starttime)) else: self.parsedObjectType = "Summary" summaryParsingStatus = self.readSummaryInfo(handsList) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index d735de04..7a25fc70 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -434,8 +434,12 @@ class Importer: self.pos_in_file[file] = hhc.getLastCharacterRead() for hand in handlist: + #try, except duplicates here? #hand.prepInsert() hand.insert(self.database) + + errors = getattr(hhc, 'numErrors') + stored = getattr(hhc, 'numHands') else: # conversion didn't work # TODO: appropriate response? From 7212760c67348661b018fba74e15559875112373 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 5 Dec 2009 20:15:28 +0800 Subject: [PATCH 09/38] Newimport - comments for a getPosition function. Decided that I needed some test functions before I kick on --- pyfpdb/DerivedStats.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index c244f019..a63a3636 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -149,6 +149,42 @@ class DerivedStats(): for i, card in enumerate(hcs[:7], 1): self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) + # position, + #Stud 3rd street card test + # denny501: brings in for $0.02 + # s0rrow: calls $0.02 + # TomSludge: folds + # Soroka69: calls $0.02 + # rdiezchang: calls $0.02 (Seat 8) + # u.pressure: folds (Seat 1) + # 123smoothie: calls $0.02 + # gashpor: calls $0.02 + # tourneyTypeId, + # startCards, + # street0_3BChance,street0_3BDone, + # otherRaisedStreet1-4 + # foldToOtherRaisedStreet1-4 + # stealAttemptChance,stealAttempted, + # foldBbToStealChance,foldedBbToSteal, + # foldSbToStealChance,foldedSbToSteal, + # foldToStreet1-4CBChance, foldToStreet1-4CBDone, + # street1-4CheckCallRaiseChance, street1-4CheckCallRaiseDone, + + # Additional stats + # 3betSB, 3betBB + # Squeeze, Ratchet? + + + def getPosition(hand, seat): + """Returns position value like 'B', 'S', 0, 1, ...""" + # Flop/Draw games with blinds + # Need a better system??? + # -2 BB - B (all) + # -1 SB - S (all) + # 0 Button + # 1 Cutoff + # 2 Hijack + def assembleHudCache(self, hand): pass From b3f1fc2f8c70b48db5c1cf21cccbaaf28f4c7c83 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 5 Dec 2009 20:18:47 +0800 Subject: [PATCH 10/38] Add beginings of test for sawShowdown - unfinished. Some sort of weird commit problem going on. Conmmitiing to work on htat --- pyfpdb/test_PokerStars.py | 44 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index 6c97c2d4..f7959134 100644 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -74,12 +74,52 @@ def testFlopImport(): # """regression-test-files/tour/Stars/Flop/NLHE-USD-MTT-5r-200710.txt""", site="PokerStars") importer.addBulkImportImportFileOrDir( """regression-test-files/cash/Stars/Flop/PLO8-6max-USD-0.01-0.02-200911.txt""", site="PokerStars") + #HID - 36185273365 + # Besides the horrible play it contains lots of useful cases + # Preflop: raise, then 3bet chance for seat 2 + # Flop: Checkraise by hero, 4bet chance not taken by villain + # Turn: Turn continuation bet by hero, called + # River: hero (continuation bets?) all-in and is not called + importer.addBulkImportImportFileOrDir( + """regression-test-files/cash/Stars/Flop/NLHE-6max-USD-0.05-0.10-200912.Stats-comparision.txt""", site="PokerStars") importer.setCallHud(False) (stored, dups, partial, errs, ttime) = importer.runImport() + print "DEBUG: stored: %s dups: %s partial: %s errs: %s ttime: %s" %(stored, dups, partial, errs, ttime) importer.clearFileList() - # Should actually do some testing here - assert 1 == 1 + q = """SELECT + s.name, + g.category, + g.base, + g.type, + g.limitType, + g.hilo, + round(g.smallBlind / 100.0,2) as sb, + round(g.bigBlind / 100.0,2) as bb, + round(g.smallBet / 100.0,2) as SB, + round(g.bigBet / 100.0,2) as BB, + s.currency, + hp.playerId, + hp.sawShowdown +FROM + Hands as h, + Sites as s, + Gametypes as g, + HandsPlayers as hp, + Players as p +WHERE + h.siteHandNo = 36185273365 +and g.id = h.gametypeid +and hp.handid = h.id +and p.id = hp.playerid +and s.id = p.siteid""" + c = db.get_cursor() + c.execute(q) + result = c.fetchall() + print "DEBUG: result: %s" %result + + + assert 1 == 0 def testStudImport(): db.recreate_tables() From 9cade444727b768950d9c4bf1e572ce40f46b7c5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 6 Dec 2009 06:20:44 +0800 Subject: [PATCH 11/38] move print message to log --- pyfpdb/Database.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 1c44bb61..36fdd2d2 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -474,8 +474,9 @@ class Database: else: h_seats_min, h_seats_max = 0, 10 print "bad h_seats_style value:", h_seats_style - print "opp seats style", seats_style, "hero seats style", h_seats_style - print "opp seats:", seats_min, seats_max, " hero seats:", h_seats_min, h_seats_max + log.info("opp seats style %s %d %d hero seats style %s %d %d" + % (seats_style, seats_min, seats_max + ,h_seats_style, h_seats_min, h_seats_max) ) if hud_style == 'S' or h_hud_style == 'S': self.get_stats_from_hand_session(hand, stat_dict, hero_id From 1d53e32f1e07cce028075680e0df7df19eb26dd6 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Sun, 6 Dec 2009 20:08:27 +0800 Subject: [PATCH 12/38] Enclose dict key lookup in try-except block Some recent changes moved the dictionary access outside try-except block again. Widen the block enough again. --- pyfpdb/HUD_main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 7e2d5fa6..108b89c7 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -159,10 +159,10 @@ class HUD_main(object): # function idle_func() to be run by the gui thread, at its leisure. def idle_func(): gtk.gdk.threads_enter() - self.hud_dict[table_name].update(new_hand_id, config) + try: + self.hud_dict[table_name].update(new_hand_id, config) # The HUD could get destroyed in the above call ^^, which leaves us with a KeyError here vv # if we ever get an error we need to expect ^^ then we need to handle it vv - Eric - try: [aw.update_gui(new_hand_id) for aw in self.hud_dict[table_name].aux_windows] except KeyError: pass From 68b4ebdb573b529fa675ef5de730649ce4f86175 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 6 Dec 2009 22:52:45 +0800 Subject: [PATCH 13/38] [NEWIMPORT] Fix sawShowdown stat --- pyfpdb/DerivedStats.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index a63a3636..e4072d8a 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -231,8 +231,9 @@ class DerivedStats(): pas = set.union(self.pfba(actions) - self.pfba(actions, l=('folds',)), alliners) self.hands['playersAtShowdown'] = len(pas) - for player in pas: - self.handsplayers[player]['sawShowdown'] = True + if self.hands['playersAtShowdown'] > 1: + for player in pas: + self.handsplayers[player]['sawShowdown'] = True def streetXRaises(self, hand): # self.actions[street] is a list of all actions in a tuple, contining the action as the second element From d4989fcd1173ea8b2a33ddc7606bc28be8ad762d Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 6 Dec 2009 22:56:29 +0800 Subject: [PATCH 14/38] Make test file use real database. Please note this could be destructive --- pyfpdb/HUD_config.test.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/HUD_config.test.xml b/pyfpdb/HUD_config.test.xml index 52905a70..1a5f77fa 100644 --- a/pyfpdb/HUD_config.test.xml +++ b/pyfpdb/HUD_config.test.xml @@ -574,7 +574,7 @@ Left-Drag to Move" - + From 135a6eaf202caaedf589b4c88846c6b227d8bce0 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 6 Dec 2009 22:57:27 +0800 Subject: [PATCH 15/38] Add test for Stars sawShowdown. Test currently fails in the old import code and passes on NEWIMPORT Tests for uncalled allin bet on river, which has been erronously marked as showdown previously --- pyfpdb/test_PokerStars.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index f7959134..e3e45c35 100644 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -87,19 +87,12 @@ def testFlopImport(): print "DEBUG: stored: %s dups: %s partial: %s errs: %s ttime: %s" %(stored, dups, partial, errs, ttime) importer.clearFileList() + col = { 'sawShowdown': 2 + } + q = """SELECT s.name, - g.category, - g.base, - g.type, - g.limitType, - g.hilo, - round(g.smallBlind / 100.0,2) as sb, - round(g.bigBlind / 100.0,2) as bb, - round(g.smallBet / 100.0,2) as SB, - round(g.bigBet / 100.0,2) as BB, - s.currency, - hp.playerId, + p.name, hp.sawShowdown FROM Hands as h, @@ -116,10 +109,10 @@ and s.id = p.siteid""" c = db.get_cursor() c.execute(q) result = c.fetchall() - print "DEBUG: result: %s" %result - - - assert 1 == 0 + for row, data in enumerate(result): + print "DEBUG: result[%s]: %s" %(row, result[row]) + # Assert if any sawShowdown = True + assert result[row][col['sawShowdown']] == 0 def testStudImport(): db.recreate_tables() From 3584e6dcc1e9ef396dd59f15f7436dfd6f2e0104 Mon Sep 17 00:00:00 2001 From: Worros Date: Sun, 6 Dec 2009 23:02:07 +0800 Subject: [PATCH 16/38] [NEWIMPORT] Add call to HUD for auto import Make sure the matching db_handid is recorded in the Hand object for later use --- pyfpdb/Hand.py | 5 +++-- pyfpdb/fpdb_import.py | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index efa9c0b6..9ff78249 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -54,6 +54,7 @@ class Hand(object): self.starttime = 0 self.handText = handText self.handid = 0 + self.dbid_hands = 0 self.tablename = "" self.hero = "" self.maxseats = None @@ -218,8 +219,8 @@ db: a connected fpdb_db object""" # seats TINYINT NOT NULL, hh['seats'] = len(sqlids) - handid = db.storeHand(hh) - db.storeHandsPlayers(handid, sqlids, self.stats.getHandsPlayers()) + self.dbid_hands = db.storeHand(hh) + db.storeHandsPlayers(self.dbid_hands, sqlids, self.stats.getHandsPlayers()) # HandsActions - all actions for all players for all streets - self.actions # HudCache data can be generated from HandsActions (HandsPlayers?) # Tourneys ? diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 7a25fc70..760e1f01 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -437,6 +437,11 @@ class Importer: #try, except duplicates here? #hand.prepInsert() hand.insert(self.database) + if self.callHud and hand.dbid_hands != 0: + #print "DEBUG: call to HUD: handsId: %s" % hand.dbid_hands + #pipe the Hands.id out to the HUD + # print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud + self.caller.pipe_to_hud.stdin.write("%s" % (hand.dbid_hands) + os.linesep) errors = getattr(hhc, 'numErrors') stored = getattr(hhc, 'numHands') From eaa698eb1a288354aa855b8f1b89eb47ab6c2733 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 12 Dec 2009 20:08:48 +0800 Subject: [PATCH 17/38] default guiprefs window to larger size --- pyfpdb/fpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 239bfbec..10daeffe 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -224,7 +224,7 @@ class fpdb: gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT)) - dia.set_default_size(500, 500) + dia.set_default_size(700, 500) prefs = GuiPrefs.GuiPrefs(self.config, self.window, dia.vbox) response = dia.run() if response == gtk.RESPONSE_ACCEPT: From 2470b9a292f30d7090eb16e842948660cc94d0c4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 12 Dec 2009 20:09:58 +0800 Subject: [PATCH 18/38] add name to nodes --- pyfpdb/GuiPrefs.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyfpdb/GuiPrefs.py b/pyfpdb/GuiPrefs.py index ada9cb51..b85b3f6a 100755 --- a/pyfpdb/GuiPrefs.py +++ b/pyfpdb/GuiPrefs.py @@ -91,10 +91,15 @@ class GuiPrefs: #iter = self.configStore.append( parent, [node.nodeValue, None] ) iter = None if node.nodeType != node.TEXT_NODE and node.nodeType != node.COMMENT_NODE: + name = "" iter = self.configStore.append( parent, [node, setting, value] ) if node.hasAttributes(): for i in xrange(node.attributes.length): self.configStore.append( iter, [node, node.attributes.item(i).localName, node.attributes.item(i).value] ) + if node.attributes.item(i).localName in ('site_name', 'game_name', 'stat_name', 'name', 'db_server', 'site'): + name = " " + node.attributes.item(i).value + if name != "": + self.configStore.set_value(iter, 1, setting+name) if node.hasChildNodes(): for elem in node.childNodes: self.addTreeRows(iter, elem) @@ -156,7 +161,7 @@ if __name__=="__main__": gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT)) - dia.set_default_size(500, 500) + dia.set_default_size(700, 500) prefs = GuiPrefs(config, win, dia.vbox) response = dia.run() if response == gtk.RESPONSE_ACCEPT: From c8734604c770b06085a82bc335dc632e24ca411d Mon Sep 17 00:00:00 2001 From: Carl Gherardi Date: Sun, 13 Dec 2009 13:47:14 +0800 Subject: [PATCH 19/38] [NEWIMPORT] Enable printInsert, disable hud pipe --- pyfpdb/fpdb_import.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 760e1f01..ca321de1 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -435,13 +435,13 @@ class Importer: for hand in handlist: #try, except duplicates here? - #hand.prepInsert() + hand.prepInsert(self.database) hand.insert(self.database) if self.callHud and hand.dbid_hands != 0: #print "DEBUG: call to HUD: handsId: %s" % hand.dbid_hands #pipe the Hands.id out to the HUD - # print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud - self.caller.pipe_to_hud.stdin.write("%s" % (hand.dbid_hands) + os.linesep) + print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud + #self.caller.pipe_to_hud.stdin.write("%s" % (hand.dbid_hands) + os.linesep) errors = getattr(hhc, 'numErrors') stored = getattr(hhc, 'numHands') From e62c47f963335dbc247b13a510574416a6ad0b03 Mon Sep 17 00:00:00 2001 From: Carl Gherardi Date: Sun, 13 Dec 2009 13:48:17 +0800 Subject: [PATCH 20/38] [NEWIMPORT] Move database prep into prepInsert --- pyfpdb/Hand.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 9ff78249..6901340e 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -55,6 +55,8 @@ class Hand(object): self.handText = handText self.handid = 0 self.dbid_hands = 0 + self.dbid_pids = None + self.dbid_gt = 0 self.tablename = "" self.hero = "" self.maxseats = None @@ -189,22 +191,21 @@ dealt whether they were seen in a 'dealt to' line self.holecards[street][player] = [open, closed] def prepInsert(self, db): - pass + ##### + # Players, Gametypes, TourneyTypes are all shared functions that are needed for additional tables + # These functions are intended for prep insert eventually + ##### + # Players - base playerid and siteid tuple + self.dbid_pids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId) + + #Gametypes + self.dbid_gt = db.getGameTypeId(self.siteId, self.gametype) def insert(self, db): """ Function to insert Hand into database Should not commit, and do minimal selects. Callers may want to cache commits db: a connected fpdb_db object""" - ##### - # Players, Gametypes, TourneyTypes are all shared functions that are needed for additional tables - # These functions are intended for prep insert eventually - ##### - # Players - base playerid and siteid tuple - sqlids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId) - - #Gametypes - gtid = db.getGameTypeId(self.siteId, self.gametype) self.stats.getStats(self) @@ -213,14 +214,14 @@ db: a connected fpdb_db object""" ##### hh = self.stats.getHands() - if not db.isDuplicate(gtid, hh['siteHandNo']): + if not db.isDuplicate(self.dbid_gt, hh['siteHandNo']): # Hands - Summary information of hand indexed by handId - gameinfo - hh['gameTypeId'] = gtid + hh['gameTypeId'] = self.dbid_gt # seats TINYINT NOT NULL, - hh['seats'] = len(sqlids) + hh['seats'] = len(self.dbid_pids) self.dbid_hands = db.storeHand(hh) - db.storeHandsPlayers(self.dbid_hands, sqlids, self.stats.getHandsPlayers()) + db.storeHandsPlayers(self.dbid_hands, self.dbid_pids, self.stats.getHandsPlayers()) # HandsActions - all actions for all players for all streets - self.actions # HudCache data can be generated from HandsActions (HandsPlayers?) # Tourneys ? From d0725f8787c29b813664db55d13e3dbeb683e785 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 13 Dec 2009 20:55:15 +0800 Subject: [PATCH 21/38] reload profile after editing Prefs if no other tabs are open, otherwise suggest restart --- pyfpdb/fpdb.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 10daeffe..bded6069 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -225,11 +225,19 @@ class fpdb: (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT)) dia.set_default_size(700, 500) + prefs = GuiPrefs.GuiPrefs(self.config, self.window, dia.vbox) response = dia.run() if response == gtk.RESPONSE_ACCEPT: # save updated config self.config.save() + if len(self.nb_tab_names) == 1: + # only main tab open, reload profile + self.load_profile() + else: + self.warning_box("Updated preferences have not been loaded because " + + "windows are open. Re-start fpdb to load them.") + dia.destroy() def dia_create_del_database(self, widget, data=None): @@ -543,7 +551,7 @@ class fpdb: ('LoadProf', None, '_Load Profile (broken)', 'L', 'Load your profile', self.dia_load_profile), ('EditProf', None, '_Edit Profile (todo)', 'E', 'Edit your profile', self.dia_edit_profile), ('SaveProf', None, '_Save Profile (todo)', 'S', 'Save your profile', self.dia_save_profile), - ('Preferences', None, '_Preferences', None, 'Edit your preferences', self.dia_preferences), + ('Preferences', None, 'Pre_ferences', 'F', 'Edit your preferences', self.dia_preferences), ('import', None, '_Import'), ('sethharchive', None, '_Set HandHistory Archive Directory', None, 'Set HandHistory Archive Directory', self.select_hhArchiveBase), ('bulkimp', None, '_Bulk Import', 'B', 'Bulk Import', self.tab_bulk_import), From 0b711628f992e46f6fc21005d9ca80c286436c0c Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 14 Dec 2009 17:52:08 +0800 Subject: [PATCH 22/38] [NEWIMPORT] Stub remaining HandsPlayers stats --- pyfpdb/Database.py | 113 +++++++++++++++++++++++++++-------------- pyfpdb/DerivedStats.py | 32 ++++++++---- 2 files changed, 98 insertions(+), 47 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 36fdd2d2..fa80bbc7 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1608,6 +1608,40 @@ class Database: pdata[p]['street2Bets'], pdata[p]['street3Bets'], pdata[p]['street4Bets'], + pdata[p]['position'], + pdata[p]['tourneyTypeId'], + pdata[p]['startCards'], + pdata[p]['street0_3BChance'], + pdata[p]['street0_3BDone'], + pdata[p]['otherRaisedStreet1'], + pdata[p]['otherRaisedStreet2'], + pdata[p]['otherRaisedStreet3'], + pdata[p]['otherRaisedStreet4'], + pdata[p]['foldToOtherRaisedStreet1'], + pdata[p]['foldToOtherRaisedStreet2'], + pdata[p]['foldToOtherRaisedStreet3'], + pdata[p]['foldToOtherRaisedStreet4'], + pdata[p]['stealAttemptChance'], + pdata[p]['stealAttempted'], + pdata[p]['foldBbToStealChance'], + pdata[p]['foldedBbToSteal'], + pdata[p]['foldSbToStealChance'], + pdata[p]['foldedSbToSteal'], + pdata[p]['foldToStreet1CBChance'], + pdata[p]['foldToStreet1CBDone'], + pdata[p]['foldToStreet2CBChance'], + pdata[p]['foldToStreet2CBDone'], + pdata[p]['foldToStreet3CBChance'], + pdata[p]['foldToStreet3CBDone'], + pdata[p]['foldToStreet4CBChance'], + pdata[p]['foldToStreet4CBDone'], + pdata[p]['street1CheckCallRaiseChance'], + pdata[p]['street1CheckCallRaiseDone'], + pdata[p]['street2CheckCallRaiseChance'], + pdata[p]['street2CheckCallRaiseDone'], + pdata[p]['street3CheckCallRaiseChance'], + pdata[p]['street3CheckCallRaiseDone'], + pdata[p]['street4CheckCallRaiseChance'] ) ) q = """INSERT INTO HandsPlayers ( @@ -1655,9 +1689,50 @@ class Database: street1Bets, street2Bets, street3Bets, - street4Bets + street4Bets, + position, + tourneyTypeId, + startCards, + street0_3BChance, + street0_3BDone, + otherRaisedStreet1, + otherRaisedStreet2, + otherRaisedStreet3, + otherRaisedStreet4, + foldToOtherRaisedStreet1, + foldToOtherRaisedStreet2, + foldToOtherRaisedStreet3, + foldToOtherRaisedStreet4, + stealAttemptChance, + stealAttempted, + foldBbToStealChance, + foldedBbToSteal, + foldSbToStealChance, + foldedSbToSteal, + foldToStreet1CBChance, + foldToStreet1CBDone, + foldToStreet2CBChance, + foldToStreet2CBDone, + foldToStreet3CBChance, + foldToStreet3CBDone, + foldToStreet4CBChance, + foldToStreet4CBDone, + street1CheckCallRaiseChance, + street1CheckCallRaiseDone, + street2CheckCallRaiseChance, + street2CheckCallRaiseDone, + street3CheckCallRaiseChance, + street3CheckCallRaiseDone, + street4CheckCallRaiseChance ) VALUES ( + %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, @@ -1669,42 +1744,6 @@ class Database: %s, %s, %s, %s, %s )""" -# position, -# tourneyTypeId, -# startCards, -# street0_3BChance, -# street0_3BDone, -# otherRaisedStreet1, -# otherRaisedStreet2, -# otherRaisedStreet3, -# otherRaisedStreet4, -# foldToOtherRaisedStreet1, -# foldToOtherRaisedStreet2, -# foldToOtherRaisedStreet3, -# foldToOtherRaisedStreet4, -# stealAttemptChance, -# stealAttempted, -# foldBbToStealChance, -# foldedBbToSteal, -# foldSbToStealChance, -# foldedSbToSteal, -# foldToStreet1CBChance, -# foldToStreet1CBDone, -# foldToStreet2CBChance, -# foldToStreet2CBDone, -# foldToStreet3CBChance, -# foldToStreet3CBDone, -# foldToStreet4CBChance, -# foldToStreet4CBDone, -# street1CheckCallRaiseChance, -# street1CheckCallRaiseDone, -# street2CheckCallRaiseChance, -# street2CheckCallRaiseDone, -# street3CheckCallRaiseChance, -# street3CheckCallRaiseDone, -# street4CheckCallRaiseChance, -# street4CheckCallRaiseDone, - q = q.replace('%s', self.sql.query['placeholder']) #print "DEBUG: inserts: %s" %inserts diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index e4072d8a..c1edb737 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -53,6 +53,27 @@ class DerivedStats(): self.handsplayers[player[1]]['street%dCBChance' %i] = False self.handsplayers[player[1]]['street%dCBDone' %i] = False + #FIXME - Everything below this point is incomplete. + self.handsplayers[player[1]]['position'] = 2 + self.handsplayers[player[1]]['tourneyTypeId'] = 0 + self.handsplayers[player[1]]['startCards'] = 0 + self.handsplayers[player[1]]['street0_3BChance'] = False + self.handsplayers[player[1]]['street0_3BDone'] = False + self.handsplayers[player[1]]['stealAttemptChance'] = False + self.handsplayers[player[1]]['stealAttempted'] = False + self.handsplayers[player[1]]['foldBbToStealChance'] = False + self.handsplayers[player[1]]['foldBbToStealChance'] = False + self.handsplayers[player[1]]['foldSbToStealChance'] = False + self.handsplayers[player[1]]['foldedSbToSteal'] = False + self.handsplayers[player[1]]['foldedBbToSteal'] = False + for i in range(1,5): + self.handsplayers[player[1]]['otherRaisedStreet%d' %i] = False + self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False + self.handsplayers[player[1]]['foldToStreet%dCBChance' %i] = False + self.handsplayers[player[1]]['foldToStreet%dCBDone' %i] = False + self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False + self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False + self.assembleHands(self.hand) self.assembleHandsPlayers(self.hand) @@ -149,6 +170,7 @@ class DerivedStats(): for i, card in enumerate(hcs[:7], 1): self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) + # position, #Stud 3rd street card test # denny501: brings in for $0.02 @@ -159,16 +181,6 @@ class DerivedStats(): # u.pressure: folds (Seat 1) # 123smoothie: calls $0.02 # gashpor: calls $0.02 - # tourneyTypeId, - # startCards, - # street0_3BChance,street0_3BDone, - # otherRaisedStreet1-4 - # foldToOtherRaisedStreet1-4 - # stealAttemptChance,stealAttempted, - # foldBbToStealChance,foldedBbToSteal, - # foldSbToStealChance,foldedSbToSteal, - # foldToStreet1-4CBChance, foldToStreet1-4CBDone, - # street1-4CheckCallRaiseChance, street1-4CheckCallRaiseDone, # Additional stats # 3betSB, 3betBB From 318cd105518a0798ba2b0758e16b252e94066d45 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 14 Dec 2009 18:01:24 +0800 Subject: [PATCH 23/38] [NEWIMPORT] Move HandsPlayers insert statement into SQL.py --- pyfpdb/Database.py | 101 +-------------------------------------------- pyfpdb/SQL.py | 101 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 102 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index fa80bbc7..408844ae 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1644,106 +1644,7 @@ class Database: pdata[p]['street4CheckCallRaiseChance'] ) ) - q = """INSERT INTO HandsPlayers ( - handId, - playerId, - startCash, - seatNo, - card1, - card2, - card3, - card4, - card5, - card6, - card7, - winnings, - rake, - totalProfit, - street0VPI, - street1Seen, - street2Seen, - street3Seen, - street4Seen, - sawShowdown, - wonAtSD, - street0Aggr, - street1Aggr, - street2Aggr, - street3Aggr, - street4Aggr, - street1CBChance, - street2CBChance, - street3CBChance, - street4CBChance, - street1CBDone, - street2CBDone, - street3CBDone, - street4CBDone, - wonWhenSeenStreet1, - street0Calls, - street1Calls, - street2Calls, - street3Calls, - street4Calls, - street0Bets, - street1Bets, - street2Bets, - street3Bets, - street4Bets, - position, - tourneyTypeId, - startCards, - street0_3BChance, - street0_3BDone, - otherRaisedStreet1, - otherRaisedStreet2, - otherRaisedStreet3, - otherRaisedStreet4, - foldToOtherRaisedStreet1, - foldToOtherRaisedStreet2, - foldToOtherRaisedStreet3, - foldToOtherRaisedStreet4, - stealAttemptChance, - stealAttempted, - foldBbToStealChance, - foldedBbToSteal, - foldSbToStealChance, - foldedSbToSteal, - foldToStreet1CBChance, - foldToStreet1CBDone, - foldToStreet2CBChance, - foldToStreet2CBDone, - foldToStreet3CBChance, - foldToStreet3CBDone, - foldToStreet4CBChance, - foldToStreet4CBDone, - street1CheckCallRaiseChance, - street1CheckCallRaiseDone, - street2CheckCallRaiseChance, - street2CheckCallRaiseDone, - street3CheckCallRaiseChance, - street3CheckCallRaiseDone, - street4CheckCallRaiseChance - ) - VALUES ( - %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s - )""" - + q = self.sql.query['store_hands_players'] q = q.replace('%s', self.sql.query['placeholder']) #print "DEBUG: inserts: %s" %inserts diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index e38bc122..e670cfa4 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3325,8 +3325,105 @@ class Sql: %s, %s, %s, %s, %s, %s, %s, %s, %s)""" - - + self.query['store_hands_players'] = """INSERT INTO HandsPlayers ( + handId, + playerId, + startCash, + seatNo, + card1, + card2, + card3, + card4, + card5, + card6, + card7, + winnings, + rake, + totalProfit, + street0VPI, + street1Seen, + street2Seen, + street3Seen, + street4Seen, + sawShowdown, + wonAtSD, + street0Aggr, + street1Aggr, + street2Aggr, + street3Aggr, + street4Aggr, + street1CBChance, + street2CBChance, + street3CBChance, + street4CBChance, + street1CBDone, + street2CBDone, + street3CBDone, + street4CBDone, + wonWhenSeenStreet1, + street0Calls, + street1Calls, + street2Calls, + street3Calls, + street4Calls, + street0Bets, + street1Bets, + street2Bets, + street3Bets, + street4Bets, + position, + tourneyTypeId, + startCards, + street0_3BChance, + street0_3BDone, + otherRaisedStreet1, + otherRaisedStreet2, + otherRaisedStreet3, + otherRaisedStreet4, + foldToOtherRaisedStreet1, + foldToOtherRaisedStreet2, + foldToOtherRaisedStreet3, + foldToOtherRaisedStreet4, + stealAttemptChance, + stealAttempted, + foldBbToStealChance, + foldedBbToSteal, + foldSbToStealChance, + foldedSbToSteal, + foldToStreet1CBChance, + foldToStreet1CBDone, + foldToStreet2CBChance, + foldToStreet2CBDone, + foldToStreet3CBChance, + foldToStreet3CBDone, + foldToStreet4CBChance, + foldToStreet4CBDone, + street1CheckCallRaiseChance, + street1CheckCallRaiseDone, + street2CheckCallRaiseChance, + street2CheckCallRaiseDone, + street3CheckCallRaiseChance, + street3CheckCallRaiseDone, + street4CheckCallRaiseChance + ) + VALUES ( + %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s + )""" if db_server == 'mysql': self.query['placeholder'] = u'%s' From 22a0c75adf73920d9270e120ea5b833be1552ff6 Mon Sep 17 00:00:00 2001 From: Worros Date: Mon, 14 Dec 2009 19:03:01 +0800 Subject: [PATCH 24/38] Fix thinko in stub --- pyfpdb/DerivedStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index c1edb737..1064a600 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -55,7 +55,7 @@ class DerivedStats(): #FIXME - Everything below this point is incomplete. self.handsplayers[player[1]]['position'] = 2 - self.handsplayers[player[1]]['tourneyTypeId'] = 0 + self.handsplayers[player[1]]['tourneyTypeId'] = 1 self.handsplayers[player[1]]['startCards'] = 0 self.handsplayers[player[1]]['street0_3BChance'] = False self.handsplayers[player[1]]['street0_3BDone'] = False From f527fe60a807cb0f11b4728277cf41bcb59bc663 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 15 Dec 2009 22:56:18 +0800 Subject: [PATCH 25/38] Fix a couple of typos --- pyfpdb/fpdb_db.py | 2 +- pyfpdb/fpdb_import.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 8a0ec54e..90c6a98b 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -154,7 +154,7 @@ class fpdb_db: if not os.path.isdir(Configuration.DIR_DATABASES) and not database == ":memory:": print "Creating directory: '%s'" % (Configuration.DIR_DATABASES) os.mkdir(Configuration.DIR_DATABASES) - database = os.path.join(Configuration.DIR_DATABASE, database) + database = os.path.join(Configuration.DIR_DATABASES, database) self.db = sqlite3.connect(database, detect_types=sqlite3.PARSE_DECLTYPES ) sqlite3.register_converter("bool", lambda x: bool(int(x))) sqlite3.register_adapter(bool, lambda x: "1" if x else "0") diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index ca321de1..dd46d7c6 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -440,8 +440,8 @@ class Importer: if self.callHud and hand.dbid_hands != 0: #print "DEBUG: call to HUD: handsId: %s" % hand.dbid_hands #pipe the Hands.id out to the HUD - print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud - #self.caller.pipe_to_hud.stdin.write("%s" % (hand.dbid_hands) + os.linesep) + print "fpdb_import: sending hand to hud", hand.dbid_hands, "pipe =", self.caller.pipe_to_hud + self.caller.pipe_to_hud.stdin.write("%s" % (hand.dbid_hands) + os.linesep) errors = getattr(hhc, 'numErrors') stored = getattr(hhc, 'numHands') From b3d6da833928b8467ecc92cbc69ae2effbbe7bab Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 16 Dec 2009 22:41:48 +0800 Subject: [PATCH 26/38] [NEWIMPORT] Convert start stack to cents --- pyfpdb/DerivedStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 1064a600..aaaea60a 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -135,7 +135,7 @@ class DerivedStats(): #hand.players = [[seat, name, chips],[seat, name, chips]] for player in hand.players: self.handsplayers[player[1]]['seatNo'] = player[0] - self.handsplayers[player[1]]['startCash'] = player[2] + self.handsplayers[player[1]]['startCash'] = int(100 * player[2]) for i, street in enumerate(hand.actionStreets[2:]): self.seen(self.hand, i+1) From c1464d64ff83147516284965d7dea60dd0293b9e Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 16 Dec 2009 22:48:38 +0800 Subject: [PATCH 27/38] [NEWIMPORT] Fix startCash fix --- pyfpdb/DerivedStats.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index aaaea60a..c6216306 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -17,6 +17,7 @@ #fpdb modules import Card +from decimal import Decimal DEBUG = False @@ -135,7 +136,7 @@ class DerivedStats(): #hand.players = [[seat, name, chips],[seat, name, chips]] for player in hand.players: self.handsplayers[player[1]]['seatNo'] = player[0] - self.handsplayers[player[1]]['startCash'] = int(100 * player[2]) + self.handsplayers[player[1]]['startCash'] = int(100 * Decimal(player[2])) for i, street in enumerate(hand.actionStreets[2:]): self.seen(self.hand, i+1) From a717eb437c6d9dfdf2ab4772a5bea0078deff2f4 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 16 Dec 2009 22:58:54 +0800 Subject: [PATCH 28/38] [NEWIMPOR] Fix insert type for wonAtSD --- pyfpdb/DerivedStats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index c6216306..88d8b452 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -46,7 +46,7 @@ class DerivedStats(): self.handsplayers[player[1]]['street4Aggr'] = False self.handsplayers[player[1]]['wonWhenSeenStreet1'] = False self.handsplayers[player[1]]['sawShowdown'] = False - self.handsplayers[player[1]]['wonAtSD'] = False + self.handsplayers[player[1]]['wonAtSD'] = 0.0 for i in range(5): self.handsplayers[player[1]]['street%dCalls' % i] = 0 self.handsplayers[player[1]]['street%dBets' % i] = 0 @@ -158,7 +158,7 @@ class DerivedStats(): if self.handsplayers[player]['street1Seen'] == True: self.handsplayers[player]['wonWhenSeenStreet1'] = True if self.handsplayers[player]['sawShowdown'] == True: - self.handsplayers[player]['wonAtSD'] = True + self.handsplayers[player]['wonAtSD'] = 1.0 for player in hand.pot.committed: self.handsplayers[player]['totalProfit'] = int(self.handsplayers[player]['winnings'] - (100*hand.pot.committed[player])) From 5e4cc1c5eb18e589d34b53de3160dc2f0ab2fee3 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 16 Dec 2009 23:11:08 +0800 Subject: [PATCH 29/38] [NEWIMPORT] 'correct' the type for wonWhenSeenStreet1 --- pyfpdb/DerivedStats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 88d8b452..1a34db1e 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -44,7 +44,7 @@ class DerivedStats(): self.handsplayers[player[1]]['totalProfit'] = 0 self.handsplayers[player[1]]['street4Seen'] = False self.handsplayers[player[1]]['street4Aggr'] = False - self.handsplayers[player[1]]['wonWhenSeenStreet1'] = False + self.handsplayers[player[1]]['wonWhenSeenStreet1'] = 0.0 self.handsplayers[player[1]]['sawShowdown'] = False self.handsplayers[player[1]]['wonAtSD'] = 0.0 for i in range(5): @@ -156,7 +156,7 @@ class DerivedStats(): # Should be fine for split-pots, but won't be accurate for multi-way pots self.handsplayers[player]['rake'] = int(100* hand.rake)/len(hand.collectees) if self.handsplayers[player]['street1Seen'] == True: - self.handsplayers[player]['wonWhenSeenStreet1'] = True + self.handsplayers[player]['wonWhenSeenStreet1'] = 1.0 if self.handsplayers[player]['sawShowdown'] == True: self.handsplayers[player]['wonAtSD'] = 1.0 From 72cf9a61ca3c7fdbdc3d4db2313a9d9427b7202a Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 00:40:36 +0800 Subject: [PATCH 30/38] [NEWIMPORT] Add a commit at the end of the fpdb_import cycle --- pyfpdb/fpdb_import.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index dd46d7c6..3fc35339 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -442,6 +442,7 @@ class Importer: #pipe the Hands.id out to the HUD print "fpdb_import: sending hand to hud", hand.dbid_hands, "pipe =", self.caller.pipe_to_hud self.caller.pipe_to_hud.stdin.write("%s" % (hand.dbid_hands) + os.linesep) + self.database.commit() errors = getattr(hhc, 'numErrors') stored = getattr(hhc, 'numHands') From 03deefc1a348ec19293ef307fe4aedee428f5c48 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 01:55:48 +0800 Subject: [PATCH 31/38] [NEWIMPORT] Fix thinko on insertPlayer Was returning the player name instead of id in the case where the player exists in the database, but wasn't cached already Removing some merge gunge too --- pyfpdb/Database.py | 6 ++++-- pyfpdb/SQL.py | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 408844ae..36d5bc93 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1857,8 +1857,10 @@ class Database: ,(name, site_id)) #Get last id might be faster here. #c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) - tmp = [self.get_last_insert_id(c)] - return tmp[0] + result = self.get_last_insert_id(c) + else: + result = tmp[1] + return result def insertGameTypes(self, row): c = self.get_cursor() diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index e670cfa4..2ccd7f90 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -2787,8 +2787,6 @@ class Sql: ,hp.tourneyTypeId ,date_format(h.handStart, 'd%y%m%d') """ -#>>>>>>> 28ca49d592c8e706ad6ee58dd26655bcc33fc5fb:pyfpdb/SQL.py -#""" elif db_server == 'postgresql': self.query['rebuildHudCache'] = """ INSERT INTO HudCache From f829ed937e2dae90352dff3228620375eac52599 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 02:24:57 +0800 Subject: [PATCH 32/38] [NEWIMPORT] Move hud call to after database commit HUD still doesn't quite work, but getting closer - suspect hud_cache rebuild isn't happening --- pyfpdb/fpdb_import.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 3fc35339..7b3dd4f1 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -432,18 +432,21 @@ class Importer: #This code doesn't do anything yet handlist = hhc.getProcessedHands() self.pos_in_file[file] = hhc.getLastCharacterRead() + to_hud = [] for hand in handlist: #try, except duplicates here? hand.prepInsert(self.database) hand.insert(self.database) if self.callHud and hand.dbid_hands != 0: - #print "DEBUG: call to HUD: handsId: %s" % hand.dbid_hands - #pipe the Hands.id out to the HUD - print "fpdb_import: sending hand to hud", hand.dbid_hands, "pipe =", self.caller.pipe_to_hud - self.caller.pipe_to_hud.stdin.write("%s" % (hand.dbid_hands) + os.linesep) + to_hud.append(hand.dbid_hands) self.database.commit() + #pipe the Hands.id out to the HUD + for hid in to_hud: + print "fpdb_import: sending hand to hud", hand.dbid_hands, "pipe =", self.caller.pipe_to_hud + self.caller.pipe_to_hud.stdin.write("%s" % (hid) + os.linesep) + errors = getattr(hhc, 'numErrors') stored = getattr(hhc, 'numHands') else: From e18af681cb1e31df45a1fae9be1d1e8f29c28ad7 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 15:59:29 +0800 Subject: [PATCH 33/38] Add test hand - Hand cancelled --- ...LO8-6max-USD-0.05-0.10-20090315.Hand-cancelled.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 pyfpdb/regression-test-files/cash/Stars/Flop/LO8-6max-USD-0.05-0.10-20090315.Hand-cancelled.txt diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/LO8-6max-USD-0.05-0.10-20090315.Hand-cancelled.txt b/pyfpdb/regression-test-files/cash/Stars/Flop/LO8-6max-USD-0.05-0.10-20090315.Hand-cancelled.txt new file mode 100644 index 00000000..9959180c --- /dev/null +++ b/pyfpdb/regression-test-files/cash/Stars/Flop/LO8-6max-USD-0.05-0.10-20090315.Hand-cancelled.txt @@ -0,0 +1,11 @@ +PokerStars Game #25979907808: Omaha Pot Limit ($0.05/$0.10 USD) - 2009/03/15 6:20:33 ET +Table 'Waterman' 6-max Seat #1 is the button +Seat 1: s0rrow ($11.65 in chips) +s0rrow: posts small blind $0.05 +ritalinIV: is sitting out +Hand cancelled +*** SUMMARY *** +Seat 1: s0rrow (button) collected ($0) + + + From ff0872f8def0aecae01758e251fde6c1024c19b6 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 15:53:12 +0800 Subject: [PATCH 34/38] Add some code to kinda detect hand cancellation hhc.readHandInfo(self) hhc.readPlayerStacks(self) hhc.compilePlayerRegexs(self) hhc.markStreets(self) Is the order, the first correctly failing regex is markStreets --- pyfpdb/Hand.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 6901340e..32140256 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -54,6 +54,7 @@ class Hand(object): self.starttime = 0 self.handText = handText self.handid = 0 + self.cancelled = False self.dbid_hands = 0 self.dbid_pids = None self.dbid_gt = 0 @@ -263,6 +264,8 @@ If a player has None chips he won't be added.""" log.debug("markStreets:\n"+ str(self.streets)) else: log.error("markstreets didn't match") + log.error(" - Assuming hand cancelled") + self.cancelled = True def checkPlayerExists(self,player): if player not in [p[1] for p in self.players]: @@ -613,6 +616,8 @@ class HoldemOmahaHand(Hand): hhc.readPlayerStacks(self) hhc.compilePlayerRegexs(self) hhc.markStreets(self) + if self.cancelled: + return hhc.readBlinds(self) hhc.readAntes(self) hhc.readButton(self) From 9650fe7a0df68e90b67420926e5236f74bed9796 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 18 Dec 2009 10:27:43 +0800 Subject: [PATCH 35/38] [NEWIMPORT] Add stubbed variable to insert --- pyfpdb/Database.py | 3 ++- pyfpdb/SQL.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 36d5bc93..e0bbf70a 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -1641,7 +1641,8 @@ class Database: pdata[p]['street2CheckCallRaiseDone'], pdata[p]['street3CheckCallRaiseChance'], pdata[p]['street3CheckCallRaiseDone'], - pdata[p]['street4CheckCallRaiseChance'] + pdata[p]['street4CheckCallRaiseChance'], + pdata[p]['street4CheckCallRaiseDone'] ) ) q = self.sql.query['store_hands_players'] diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 2ccd7f90..3e7a2c76 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3402,10 +3402,11 @@ class Sql: street2CheckCallRaiseDone, street3CheckCallRaiseChance, street3CheckCallRaiseDone, - street4CheckCallRaiseChance + street4CheckCallRaiseChance, + street4CheckCallRaiseDone ) VALUES ( - %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, From ff88823c1a1bb456bf4dbcc4c14c562dd9344fe0 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 18 Dec 2009 13:32:09 +0800 Subject: [PATCH 36/38] [NEWIMPORT] Fix syntax to be 2.5 compatible. Python 2.6 enumerate() function contains a useful 'start' paramater, apparently this did not exist in 2.5. Patch frim Mika Bostrom --- pyfpdb/DerivedStats.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 1a34db1e..5943a10f 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -168,8 +168,10 @@ class DerivedStats(): for player in hand.players: hcs = hand.join_holecards(player[1], asList=True) hcs = hcs + [u'0x', u'0x', u'0x', u'0x', u'0x'] - for i, card in enumerate(hcs[:7], 1): - self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) + #for i, card in enumerate(hcs[:7], 1): #Python 2.6 syntax + # self.handsplayers[player[1]]['card%s' % i] = Card.encodeCard(card) + for i, card in enumerate(hcs[:7]): + self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card) # position, @@ -266,13 +268,17 @@ class DerivedStats(): # Then no bets before the player with initiatives first action on current street # ie. if player on street-1 had initiative # and no donkbets occurred - for i, street in enumerate(hand.actionStreets[2:], start=1): - name = self.lastBetOrRaiser(hand.actionStreets[i]) + + # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' + # came there + #for i, street in enumerate(hand.actionStreets[2:], start=1): + for i, street in enumerate(hand.actionStreets[2:]: + name = self.lastBetOrRaiser(hand.actionStreets[i+1]) if name: - chance = self.noBetsBefore(hand.actionStreets[i+1], name) - self.handsplayers[name]['street%dCBChance' %i] = True + chance = self.noBetsBefore(hand.actionStreets[i+2], name) + self.handsplayers[name]['street%dCBChance' % (i+1)] = True if chance == True: - self.handsplayers[name]['street%dCBDone' %i] = self.betStreet(hand.actionStreets[i+1], name) + self.handsplayers[name]['street%dCBDone' % (i+1)] = self.betStreet(hand.actionStreets[i+2], name) def seen(self, hand, i): pas = set() From 4c49d7163b4bb335de17c692e53b611c3536a0b8 Mon Sep 17 00:00:00 2001 From: Worros Date: Sat, 19 Dec 2009 10:07:53 +0800 Subject: [PATCH 37/38] [NEWIMPORT] Syntax fix --- pyfpdb/DerivedStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 5943a10f..dbd655a3 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -272,7 +272,7 @@ class DerivedStats(): # XXX: enumerate(list, start=x) is python 2.6 syntax; 'start' # came there #for i, street in enumerate(hand.actionStreets[2:], start=1): - for i, street in enumerate(hand.actionStreets[2:]: + for i, street in enumerate(hand.actionStreets[2:]): name = self.lastBetOrRaiser(hand.actionStreets[i+1]) if name: chance = self.noBetsBefore(hand.actionStreets[i+2], name) From f8dccd43a317fd87b04abc855f3ddf766fe975ea Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 17 Dec 2009 18:42:50 +0800 Subject: [PATCH 38/38] Add ability to import Stars archive files. PokerStars support can provide a HH archive. The format is similar but not the same as a a standard hh format as it contains an additional line "Hand #X" between each hand. Patch adds an option -s to GuiBulkImport, which when specified will strip these lines out and continue parsing. --- pyfpdb/GuiBulkImport.py | 4 ++++ pyfpdb/Hand.py | 1 + pyfpdb/HandHistoryConverter.py | 8 +++++++- pyfpdb/fpdb_import.py | 19 +++++++++++++------ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 7db420c7..16131ab2 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -326,6 +326,8 @@ def main(argv=None): help="How often to print a one-line status report (0 (default) means never)") parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False, help="Print some useful one liners") + parser.add_option("-s", "--starsarchive", action="store_true", dest="starsArchive", default=False, + help="Do the required conversion for Stars Archive format (ie. as provided by support") (options, argv) = parser.parse_args(args = argv) if options.usage == True: @@ -369,6 +371,8 @@ def main(argv=None): importer.setThreads(-1) importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername) importer.setCallHud(False) + if options.starsArchive: + importer.setStarsArchive(True) (stored, dups, partial, errs, ttime) = importer.runImport() importer.clearFileList() print 'GuiBulkImport done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec'\ diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 32140256..3467216a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -266,6 +266,7 @@ If a player has None chips he won't be added.""" log.error("markstreets didn't match") log.error(" - Assuming hand cancelled") self.cancelled = True + raise FpdbParseError def checkPlayerExists(self,player): if player not in [p[1] for p in self.players]: diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 27bb9b1a..a18797df 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -57,7 +57,7 @@ class HandHistoryConverter(): codepage = "cp1252" - def __init__(self, in_path = '-', out_path = '-', follow=False, index=0, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) @@ -66,6 +66,7 @@ follow : whether to tail -f the input""" log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) ) self.index = 0 + self.starsArchive = starsArchive self.in_path = in_path self.out_path = out_path @@ -254,6 +255,11 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. self.readFile() self.obs = self.obs.strip() self.obs = self.obs.replace('\r\n', '\n') + if self.starsArchive == True: + log.debug("Converting starsArchive format to readable") + m = re.compile('^Hand #\d+', re.MULTILINE) + self.obs = m.sub('', self.obs) + if self.obs is None or self.obs == "": log.info("Read no hands.") return [] diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 7b3dd4f1..8921d9d8 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -91,6 +91,7 @@ class Importer: self.settings.setdefault("writeQMaxWait", 10) # not used self.settings.setdefault("dropIndexes", "don't drop") self.settings.setdefault("dropHudCache", "don't drop") + self.settings.setdefault("starsArchive", False) self.writeq = None self.database = Database.Database(self.config, sql = self.sql) @@ -134,6 +135,9 @@ class Importer: def setDropHudCache(self, value): self.settings['dropHudCache'] = value + def setStarsArchive(self, value): + self.settings['starsArchive'] = value + # def setWatchTime(self): # self.updated = time() @@ -425,7 +429,7 @@ class Importer: mod = __import__(filter) obj = getattr(mod, filter_name, None) if callable(obj): - hhc = obj(in_path = file, out_path = out_path, index = 0) # Index into file 0 until changeover + hhc = obj(in_path = file, out_path = out_path, index = 0, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover if hhc.getStatus() and self.NEWIMPORT == False: (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(db, out_path, site, q) elif hhc.getStatus() and self.NEWIMPORT == True: @@ -435,11 +439,14 @@ class Importer: to_hud = [] for hand in handlist: - #try, except duplicates here? - hand.prepInsert(self.database) - hand.insert(self.database) - if self.callHud and hand.dbid_hands != 0: - to_hud.append(hand.dbid_hands) + if hand is not None: + #try, except duplicates here? + hand.prepInsert(self.database) + hand.insert(self.database) + if self.callHud and hand.dbid_hands != 0: + to_hud.append(hand.dbid_hands) + else: + log.error("Hand processed but empty") self.database.commit() #pipe the Hands.id out to the HUD