diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 19e62038..1e038445 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -48,7 +48,7 @@ class Layout: self.height = int( node.getAttribute('height') ) self.location = [] - self.location = map(lambda x: None, range(self.max+1)) # there must be a better way to do this? + self.location = map(lambda x: None, range(self.max+1)) # fill array with max seats+1 empty entries for location_node in node.getElementsByTagName('location'): if location_node.getAttribute('seat') != "": @@ -230,13 +230,14 @@ class Tv: (self.combinedStealFold, self.combined2B3B, self.combinedPostflop) ) class Config: - def __init__(self, file = None): + def __init__(self, file = None, dbname = 'fpdb'): # "file" is a path to an xml file with the fpdb/HUD configuration # we check the existence of "file" and try to recover if it doesn't exist + self.dbname = dbname self.default_config_path = self.get_default_config_path() - if not file == None: # configuration file path has been passed + if file != None: # configuration file path has been passed if not os.path.exists(file): print "Configuration file %s not found. Using defaults." % (file) sys.stderr.write("Configuration file %s not found. Using defaults." % (file)) @@ -247,7 +248,7 @@ class Config: if file == None: # no config file in the normal places file = self.find_example_config() #Look for an example file to edit - if not file == None: + if file != None: pass if file == None: # that didn't work either, just die @@ -308,7 +309,7 @@ class Config: tv = Tv(node = tv_node) self.tv = tv - db = self.get_db_parameters('fpdb') + db = self.get_db_parameters() if db['db-password'] == 'YOUR MYSQL PASSWORD': df_file = self.find_default_conf() if df_file == None: # this is bad @@ -411,7 +412,7 @@ class Config: return location_node def save(self, file = None): - if not file == None: + if file != None: f = open(file, 'w') self.doc.writexml(f) f.close() @@ -448,9 +449,9 @@ class Config: else: self.aux_windows[aux_name].layout[max].location[i] = ( locations[i][0], locations[i][1] ) - def get_db_parameters(self, name = None): - if name == None: name = 'fpdb' + def get_db_parameters(self): db = {} + name = self.dbname try: db['db-databaseName'] = name except: pass @@ -476,18 +477,18 @@ class Config: def set_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None, db_pass = None, db_server = None, db_type = None): db_node = self.get_db_node(db_name) - if not db_node == None: - if not db_ip == None: db_node.setAttribute("db_ip", db_ip) - if not db_user == None: db_node.setAttribute("db_user", db_user) - if not db_pass == None: db_node.setAttribute("db_pass", db_pass) - if not db_server == None: db_node.setAttribute("db_server", db_server) - if not db_type == None: db_node.setAttribute("db_type", db_type) + if db_node != None: + if db_ip != None: db_node.setAttribute("db_ip", db_ip) + if db_user != None: db_node.setAttribute("db_user", db_user) + if db_pass != None: db_node.setAttribute("db_pass", db_pass) + if db_server != None: db_node.setAttribute("db_server", db_server) + if db_type != None: db_node.setAttribute("db_type", db_type) if self.supported_databases.has_key(db_name): - if not db_ip == None: self.supported_databases[db_name].dp_ip = db_ip - if not db_user == None: self.supported_databases[db_name].dp_user = db_user - if not db_pass == None: self.supported_databases[db_name].dp_pass = db_pass - if not db_server == None: self.supported_databases[db_name].dp_server = db_server - if not db_type == None: self.supported_databases[db_name].dp_type = db_type + if db_ip != None: self.supported_databases[db_name].dp_ip = db_ip + if db_user != None: self.supported_databases[db_name].dp_user = db_user + if db_pass != None: self.supported_databases[db_name].dp_pass = db_pass + if db_server != None: self.supported_databases[db_name].dp_server = db_server + if db_type != None: self.supported_databases[db_name].dp_type = db_type return def get_tv_parameters(self): @@ -615,19 +616,19 @@ class Config: font = None, font_size = None): """Sets the specified site parameters for the specified site.""" site_node = self.get_site_node(site_name) - if not db_node == None: - if not converter == None: site_node.setAttribute("converter", converter) - if not decoder == None: site_node.setAttribute("decoder", decoder) - if not hudbgcolor == None: site_node.setAttribute("hudbgcolor", hudbgcolor) - if not hudfgcolor == None: site_node.setAttribute("hudfgcolor", hudfgcolor) - if not hudopacity == None: site_node.setAttribute("hudopacity", hudopacity) - if not screen_name == None: site_node.setAttribute("screen_name", screen_name) - if not site_path == None: site_node.setAttribute("site_path", site_path) - if not table_finder == None: site_node.setAttribute("table_finder", table_finder) - if not HH_path == None: site_node.setAttribute("HH_path", HH_path) - if not enabled == None: site_node.setAttribute("enabled", enabled) - if not font == None: site_node.setAttribute("font", font) - if not font_size == None: site_node.setAttribute("font_size", font_size) + if db_node != None: + if converter != None: site_node.setAttribute("converter", converter) + if decoder != None: site_node.setAttribute("decoder", decoder) + if hudbgcolor != None: site_node.setAttribute("hudbgcolor", hudbgcolor) + if hudfgcolor != None: site_node.setAttribute("hudfgcolor", hudfgcolor) + if hudopacity != None: site_node.setAttribute("hudopacity", hudopacity) + if screen_name != None: site_node.setAttribute("screen_name", screen_name) + if site_path != None: site_node.setAttribute("site_path", site_path) + if table_finder != None: site_node.setAttribute("table_finder", table_finder) + if HH_path != None: site_node.setAttribute("HH_path", HH_path) + if enabled != None: site_node.setAttribute("enabled", enabled) + if font != None: site_node.setAttribute("font", font) + if font_size != None: site_node.setAttribute("font_size", font_size) return def get_aux_windows(self): diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index c3260466..24948986 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -599,37 +599,6 @@ class FpdbSQLQueries: ################################ - # Returns all cash game handIds and the money won(winnings is the final pot) - # by the playerId for a single site. - if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): - self.query['getRingWinningsAllGamesPlayerIdSite'] = """SELECT handId, winnings FROM HandsPlayers - INNER JOIN Players ON HandsPlayers.playerId = Players.id - INNER JOIN Hands ON Hands.id = HandsPlayers.handId - WHERE Players.name = %s AND Players.siteId = %s AND (tourneysPlayersId IS NULL) - ORDER BY handStart""" - elif(self.dbname == 'SQLite'): - #Probably doesn't work. - self.query['getRingWinningsAllGamesPlayerIdSite'] = """SELECT handId, winnings FROM HandsPlayers - INNER JOIN Players ON HandsPlayers.playerId = Players.id - INNER JOIN Hands ON Hands.id = HandsPlayers.handId - WHERE Players.name = %s AND Players.siteId = %s AND (tourneysPlayersId IS NULL) - ORDER BY handStart""" - - # Returns the profit for a given ring game handId, Total pot - money invested by playerId - if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): - self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions - INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id - INNER JOIN Players ON HandsPlayers.playerId = Players.id - WHERE Players.name = %s AND HandsPlayers.handId = %s - AND Players.siteId = %s AND (tourneysPlayersId IS NULL)""" - elif(self.dbname == 'SQLite'): - #Probably doesn't work. - self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions - INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id - INNER JOIN Players ON HandsPlayers.playerId = Players.id - WHERE Players.name = %s AND HandsPlayers.handId = %s - AND Players.siteId = %s AND (tourneysPlayersId IS NULL)""" - if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): self.query['getPlayerId'] = """SELECT id from Players where name = %s""" elif(self.dbname == 'SQLite'): diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 1a62a37d..e7964511 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -238,7 +238,7 @@ def main(argv=None): if os.name == 'nt': settings['os'] = 'windows' else: settings['os'] = 'linuxmac' - settings.update(config.get_db_parameters('fpdb')) + settings.update(config.get_db_parameters()) settings.update(config.get_tv_parameters()) settings.update(config.get_import_parameters()) settings.update(config.get_default_paths()) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index e03c454e..5afc4a92 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -68,13 +68,13 @@ class GuiGraphViewer (threading.Thread): if len(result) == 1: playerids.append(result[0][0]) - if sitenos == []: + if not sitenos: #Should probably pop up here. print "No sites selected - defaulting to PokerStars" sitenos = [2] - if playerids == []: + if not playerids: print "No player ids found" return diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 81e8700a..332e33c8 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -91,7 +91,7 @@ class HUD_main(object): gtk.gdk.threads_enter() try: - newlabel = gtk.Label(table.site + " - " + table_name) + newlabel = gtk.Label("%s - %s" % (table.site, table_name)) self.vb.add(newlabel) newlabel.show() self.main_window.resize_children() @@ -110,8 +110,8 @@ class HUD_main(object): self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection) self.hud_dict[table_name].stat_dict = stat_dict self.hud_dict[table_name].cards = cards - for aw in self.hud_dict[table_name].aux_windows: - aw.update_data(new_hand_id, self.db_connection) + + [aw.update_data(new_hand_id, self.db_connection) for aw in self.hud_dict[table_name].aux_windows] gobject.idle_add(idle_func) def update_HUD(self, new_hand_id, table_name, config): @@ -153,7 +153,8 @@ class HUD_main(object): stat_dict = self.db_connection.get_stats_from_hand(new_hand_id) cards = self.db_connection.get_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id) - cards['common'] = comm_cards['common'] + if comm_cards != {}: # stud! + cards['common'] = comm_cards['common'] except Exception, err: print "db error: skipping ", new_hand_id, err sys.stderr.write("Database error %s in hand %d. Skipping.\n" % (err, int(new_hand_id))) diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 20750b96..804d8ed2 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -82,7 +82,7 @@ class Hud: font = "Sans" if font_size == None: font_size = "8" - self.font = pango.FontDescription(font + " " + font_size) + self.font = pango.FontDescription("%s %s" % (font, font_size)) # do we need to add some sort of condition here for dealing with a request for a font that doesn't exist? game_params = config.get_game_parameters(self.poker_game) @@ -102,6 +102,7 @@ class Hud: self.main_window.set_title("%s FPDBHUD" % (self.table.name)) self.main_window.set_decorated(False) self.main_window.set_opacity(self.colors["hudopacity"]) + self.main_window.set_focus_on_map(False) self.ebox = gtk.EventBox() self.label = gtk.Label("FPDB Menu (Right Click)\nLeft-drag to move") @@ -173,10 +174,10 @@ class Hud: self.main_window.move(x, y) adj = self.adj_seats(self.hand, self.config) loc = self.config.get_locations(self.table.site, self.max) - for i in xrange(1, self.max + 1): + # TODO: is stat_windows getting converted somewhere from a list to a dict, for no good reason? + for i, w in enumerate(self.stat_windows.itervalues()): (x, y) = loc[adj[i]] - if i in self.stat_windows: - self.stat_windows[i].relocate(x, y) + w.relocate(x, y) return True def on_button_press(self, widget, event): @@ -196,12 +197,12 @@ class Hud: s.window.destroy() self.stat_windows = {} # also kill any aux windows - [aux.destroy() for aux in self.aux_windows] + (aux.destroy() for aux in self.aux_windows) self.aux_windows = [] def reposition_windows(self, *args): if self.stat_windows != {} and len(self.stat_windows) > 0: - map(lambda x: x.window.move(x.x, x.y), self.stat_windows.itervalues()) + (x.window.move(x.x, x.y) for x in self.stat_windows.itervalues() if type(x) != int) return True def debug_stat_windows(self, *args): @@ -217,7 +218,7 @@ class Hud: new_layout[self.stat_windows[sw].adj - 1] = new_loc self.config.edit_layout(self.table.site, self.max, locations = new_layout) # ask each aux to save its layout back to the config object - [aux.save_layout() for aux in self.aux_windows] + (aux.save_layout() for aux in self.aux_windows) # save the config object back to the file print "saving new xml file" self.config.save() @@ -227,9 +228,9 @@ class Hud: # Need range here, not xrange -> need the actual list adj = range(0, self.max + 1) # default seat adjustments = no adjustment # does the user have a fav_seat? - try: - sys.stderr.write("site = %s, max = %d, fav seat = %d\n" % (self.table.site, self.max, config.supported_sites[self.table.site].layout[self.max].fav_seat)) - if int(config.supported_sites[self.table.site].layout[self.max].fav_seat) > 0: + if int(config.supported_sites[self.table.site].layout[self.max].fav_seat) > 0: + try: + sys.stderr.write("site = %s, max = %d, fav seat = %d\n" % (self.table.site, self.max, config.supported_sites[self.table.site].layout[self.max].fav_seat)) fav_seat = config.supported_sites[self.table.site].layout[self.max].fav_seat sys.stderr.write("found fav seat = %d\n" % fav_seat) # actual_seat = self.db_connection.get_actual_seat(hand, config.supported_sites[self.table.site].screen_name) @@ -237,12 +238,14 @@ class Hud: sys.stderr.write("found actual seat = %d\n" % actual_seat) for i in xrange(0, self.max + 1): j = actual_seat + i - if j > self.max: j = j - self.max + if j > self.max: + j = j - self.max adj[j] = fav_seat + i - if adj[j] > self.max: adj[j] = adj[j] - self.max - except Exception, inst: - sys.stderr.write("exception in adj!!!\n\n") - sys.stderr.write("error is %s" % inst) # __str__ allows args to printed directly + if adj[j] > self.max: + adj[j] = adj[j] - self.max + except Exception, inst: + sys.stderr.write("exception in adj!!!\n\n") + sys.stderr.write("error is %s" % inst) # __str__ allows args to printed directly return adj def get_actual_seat(self, name): @@ -286,10 +289,12 @@ class Hud: font = self.font) self.stats = [] - for i in xrange(0, config.supported_games[self.poker_game].rows + 1): - row_list = [''] * config.supported_games[self.poker_game].cols + game = config.supported_games[self.poker_game] + + for i in xrange(0, game.rows + 1): + row_list = [''] * game.cols self.stats.append(row_list) - for stat in config.supported_games[self.poker_game].stats: + for stat in game.stats: self.stats[config.supported_games[self.poker_game].stats[stat].row] \ [config.supported_games[self.poker_game].stats[stat].col] = \ config.supported_games[self.poker_game].stats[stat].stat_name @@ -303,30 +308,30 @@ class Hud: self.update_table_position() for s in self.stat_dict: + statd = self.stat_dict[s] try: self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id'] except: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here self.max = 10 self.create(hand, config, self.stat_dict, self.cards) - self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id'] + self.stat_windows[statd['seat']].player_id = statd['player_id'] for r in xrange(0, config.supported_games[self.poker_game].rows): for c in xrange(0, config.supported_games[self.poker_game].cols): this_stat = config.supported_games[self.poker_game].stats[self.stats[r][c]] - number = Stats.do_stat(self.stat_dict, player = self.stat_dict[s]['player_id'], stat = self.stats[r][c]) - statstring = this_stat.hudprefix + str(number[1]) + this_stat.hudsuffix + number = Stats.do_stat(self.stat_dict, player = statd['player_id'], stat = self.stats[r][c]) + statstring = "%s%s%s" % (this_stat.hudprefix, str(number[1]), this_stat.hudsuffix) + window = self.stat_windows[statd['seat']] if this_stat.hudcolor != "": self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor'])) - self.stat_windows[self.stat_dict[s]['seat']].label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) - - self.stat_windows[self.stat_dict[s]['seat']].label[r][c].set_text(statstring) + window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor)) + + window.label[r][c].set_text(statstring) if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no? - self.stat_windows[self.stat_dict[s]['seat']].window.show_all() -# self.reposition_windows() - tip = self.stat_dict[s]['screen_name'] + "\n" + number[5] + "\n" + \ - number[3] + ", " + number[4] - Stats.do_tip(self.stat_windows[self.stat_dict[s]['seat']].e_box[r][c], tip) + window.window.show_all() + tip = "%s\n%s\n%s, %s" % (statd['screen_name'], number[5], number[3], number[4]) + Stats.do_tip(window.e_box[r][c], tip) def topify_window(self, window): """Set the specified gtk window to stayontop in MS Windows.""" @@ -407,9 +412,11 @@ class Stat_Window: self.window.set_title("%s" % seat) self.window.set_property("skip-taskbar-hint", True) self.window.set_transient_for(parent.main_window) + self.window.set_focus_on_map(False) - self.grid = gtk.Table(rows = self.game.rows, columns = self.game.cols, homogeneous = False) - self.window.add(self.grid) + grid = gtk.Table(rows = game.rows, columns = game.cols, homogeneous = False) + self.grid = grid + self.window.add(grid) self.window.modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor) self.e_box = [] @@ -418,12 +425,12 @@ class Stat_Window: usegtkframes = self.useframes e_box = self.e_box label = self.label - for r in xrange(self.game.rows): + for r in xrange(game.rows): if usegtkframes: self.frame.append([]) e_box.append([]) label.append([]) - for c in xrange(self.game.cols): + for c in xrange(game.cols): if usegtkframes: self.frame[r].append( gtk.Frame() ) e_box[r].append( gtk.EventBox() ) @@ -433,10 +440,10 @@ class Stat_Window: Stats.do_tip(e_box[r][c], 'stuff') if usegtkframes: - self.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 = 0, ypadding = 0) self.frame[r][c].add(e_box[r][c]) else: - self.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 = 0, ypadding = 0) label[r].append( gtk.Label('xxx') ) if usegtkframes: diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 6bc6a58a..9d70f8e3 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -39,15 +39,19 @@ import Database class Aux_Window: def __init__(self, hud, params, config): self.hud = hud + self.params = params self.config = config - def update_data(self, *parms): + def update_data(self, *args): pass - def update_gui(self, *parms): + def update_gui(self, *args): pass - def create(self, *parms): + def create(self, *args): + pass + + def relocate(self, *args): pass def save_layout(self, *args): @@ -321,6 +325,7 @@ class Flop_Mucked(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.rel_positions = {} # dict of window positions, relative to the table origin self.displayed_cards = False self.timer_on = False # bool = Ture if the timeout for removing the cards is on self.card_images = self.get_card_images() @@ -345,11 +350,13 @@ class Flop_Mucked(Aux_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[('B', 'H')]) self.eb[i].add(self.seen_cards[i]) - self.m_windows[i].move(int(x) + self.hud.table.x, int(y) + self.hud.table.y) 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() @@ -375,7 +382,7 @@ class Flop_Mucked(Aux_Window): 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].present() + 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 @@ -405,9 +412,8 @@ class Flop_Mucked(Aux_Window): def hide_mucked_cards(self): """Hide the mucked card windows.""" for (i, w) in self.m_windows.iteritems(): - self.positions[i] = w.get_position() w.hide() - self.displayed_cards = False + self.displayed_cards = False def button_press_cb(self, widget, event, *args): """Handle button clicks in the event boxes.""" @@ -432,9 +438,13 @@ class Flop_Mucked(Aux_Window): 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].present() + 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 @@ -447,8 +457,6 @@ class Flop_Mucked(Aux_Window): 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) - print "old locations =", self.params['layout'][self.hud.max] - print "saving locations =", new_locs self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) if __name__== "__main__": diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 4f150ead..0c1beb6b 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -128,14 +128,11 @@ follow : whether to tail -f the input""" logging.debug("readHandInfo: %s" % info) for key in info: if key == 'DATETIME': - datetime = info[key] - #2008/11/16 1:22:47 CET [2008/11/15 19:22:47 ET] - m2 = re.search(r".+\[(.+) ET\]", datetime) - if m2: datetime = m2.group(1) - #2009/02/26 - 15:22:55 ET - datetime = datetime.replace(" - "," ") # some are like "2009/02/26 - 15:22:55 ET" - datetime = datetime.replace(" (ET)","") # kludge for now. - datetime = datetime.replace(" ET","") # kludge for now. + #2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET] + #2008/08/17 - 01:14:43 (ET) + #2008/09/07 06:23:14 ET + m2 = re.search("(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P[0-9]+):(?P[0-9]+):(?P[0-9]+)", info[key]) + datetime = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'),m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S')) hand.starttime = time.strptime(datetime, "%Y/%m/%d %H:%M:%S") if key == 'HID': hand.handid = info[key] diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index 20dc4454..ffc50b01 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -219,7 +219,7 @@ def discover_nt(c): else: tw.site = "Unknown" sys.stderr.write("Found unknown table = %s" % tw.title) - if not tw.site == "Unknown": + if tw.site != "Unknown": eval("%s(tw)" % c.supported_sites[tw.site].decoder) else: tw.name = "Unknown" diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 5cdd3d3b..0f0f3bf3 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -23,6 +23,8 @@ from optparse import OptionParser parser = OptionParser() parser.add_option("-x", "--errorsToConsole", action="store_true", help="If passed error output will go to the console rather than .") +parser.add_option("-d", "--databaseName", dest="dbname", default="fpdb", + help="Overrides the default database name") (options, sys.argv) = parser.parse_args() if not options.errorsToConsole: @@ -337,7 +339,7 @@ class fpdb: new_ps_thread=GuiPositionalStats.GuiPositionalStats(self.db, self.config, self.querydict) self.threads.append(new_ps_thread) ps_tab=new_ps_thread.get_vbox() - self.add_and_display_tab(ps_tab, "Ppositional Stats") + self.add_and_display_tab(ps_tab, "Positional Stats") def tab_main_help(self, widget, data): @@ -371,7 +373,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") def __init__(self): self.threads=[] self.db=None - self.config = Configuration.Config() + self.config = Configuration.Config(dbname=options.dbname) self.load_profile() self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 771b79fa..eba87f52 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -59,7 +59,7 @@ class fpdb_db: self.database=database if backend==self.MYSQL_INNODB: import MySQLdb - self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database) + self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) elif backend==self.PGSQL: import psycopg2 # If DB connection is made over TCP, then the variables diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 2c33a841..6c0af7f5 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 +from time import time, strftime import traceback import math import datetime @@ -67,12 +67,10 @@ class Importer: self.pos_in_file = {} # dict to remember how far we have read in the file #Set defaults self.callHud = self.config.get_import_parameters().get("callFpdbHud") - if 'minPrint' not in self.settings: - #TODO: Is this value in the xml file? - self.settings['minPrint'] = 30 - if 'handCount' not in self.settings: - #TODO: Is this value in the xml file? - self.settings['handCount'] = 0 + + self.settings.setdefault("minPrint", 30) + self.settings.setdefault("handCount", 0) + self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(self.config) @@ -216,7 +214,7 @@ class Importer: else: removeFromFileList[file] = True self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList) - + for file in self.removeFromFileList: if file in self.filelist: del self.filelist[file] @@ -266,10 +264,10 @@ class Importer: def import_fpdb_file(self, file, site): starttime = time() - last_read_hand=0 + last_read_hand = 0 loc = 0 - if (file=="stdin"): - inputFile=sys.stdin + if file == "stdin": + inputFile = sys.stdin else: if os.path.exists(file): inputFile = open(file, "rU") @@ -282,7 +280,7 @@ class Importer: pass # Read input file into class and close file inputFile.seek(loc) - self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines()) + self.lines = fpdb_simple.removeTrailingEOL(inputFile.readlines()) self.pos_in_file[file] = inputFile.tell() inputFile.close() @@ -298,29 +296,29 @@ class Importer: #self.parseTourneyHistory() return 0 - site=fpdb_simple.recogniseSite(firstline) - category=fpdb_simple.recogniseCategory(firstline) + site = fpdb_simple.recogniseSite(firstline) + category = fpdb_simple.recogniseCategory(firstline) - startpos=0 - stored=0 #counter - duplicates=0 #counter - partial=0 #counter - errors=0 #counter + startpos = 0 + stored = 0 #counter + duplicates = 0 #counter + partial = 0 #counter + errors = 0 #counter for i in xrange (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method - if (len(self.lines[i])<2): - endpos=i - hand=self.lines[startpos:endpos] + if len(self.lines[i]) < 2: + endpos = i + hand = self.lines[startpos:endpos] - if (len(hand[0])<2): - hand=hand[1:] + if len(hand[0]) < 2: + hand = hand[1:] cancelled=False damaged=False if (site=="ftp"): for i in range (len(hand)): - if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right? - cancelled=True + if hand[i].endswith(" has been canceled"): #this is their typo. this is a typo, right? + cancelled = True #FTP generates lines looking like: #Seat 1: IOS Seat 2: kashman59 (big blind) showed [8c 9d] and won ($3.25) with a pair of Eights @@ -334,15 +332,15 @@ class Importer: hand.insert(i+1, hand[i][mo.start()+1:]) hand[i] = hand[i][0:mo.start()] - if (len(hand)<3): + if len(hand) < 3: pass #todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work. - elif (hand[0].endswith(" (partial)")): #partial hand - do nothing - partial+=1 - elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and? - partial+=1 - elif (cancelled or damaged): - partial+=1 + elif hand[0].endswith(" (partial)"): #partial hand - do nothing + partial += 1 + elif "Seat" not in hand[1] and "Seat" not in hand[2] and "Seat" not in hand[3]: + partial += 1 + elif cancelled or damaged: + partial += 1 if damaged: print """ DEBUG: Partial hand triggered by a line containing 'Seat X:' twice. This is a @@ -352,57 +350,58 @@ class Importer: print "File: %s" %(file) print "Line: %s" %(startpos) else: #normal processing - isTourney=fpdb_simple.isTourney(hand[0]) + isTourney = fpdb_simple.isTourney(hand[0]) if not isTourney: - fpdb_simple.filterAnteBlindFold(site,hand) + hand = fpdb_simple.filterAnteBlindFold(site,hand) self.hand=hand try: - handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db + handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db ,self.fdb.cursor, site, category, hand, self.config) self.fdb.db.commit() - stored+=1 + stored += 1 if self.callHud: #print "call to HUD here. handsId:",handsId #pipe the Hands.id out to the HUD self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) except fpdb_simple.DuplicateError: - duplicates+=1 + duplicates += 1 except (ValueError), fe: - errors+=1 + errors += 1 self.printEmailErrorMessage(errors, file, hand) if (self.settings['failOnError']): self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. raise except (fpdb_simple.FpdbError), fe: - errors+=1 + errors += 1 self.printEmailErrorMessage(errors, file, hand) #fe.printStackTrace() #todo: get stacktrace self.fdb.db.rollback() - if (self.settings['failOnError']): + if self.settings['failOnError']: self.fdb.db.commit() #dont remove this, in case hand processing was cancelled. raise - if (self.settings['minPrint']!=0): - if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0): + + if self.settings['minPrint']: + if not ((stored+duplicates+partial+errors) % self.settings['minPrint']): print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors - if (self.settings['handCount']!=0): - if ((stored+duplicates+partial+errors)>=self.settings['handCount']): - if (not self.settings['quiet']): + if self.settings['handCount']: + if ((stored+duplicates+partial+errors) >= self.settings['handCount']): + if not self.settings['quiet']: print "quitting due to reaching the amount of hands to be imported" print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime) sys.exit(0) - startpos=endpos + startpos = endpos ttime = time() - starttime print "\rTotal stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", ttime - if stored==0: - if duplicates>0: - for line_no in range(len(self.lines)): + if not stored: + if duplicates: + for line_no in xrange(len(self.lines)): if self.lines[line_no].find("Game #")!=-1: final_game_line=self.lines[line_no] handsId=fpdb_simple.parseSiteHandNo(final_game_line) diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index e6ff1a48..fb352064 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -64,7 +64,7 @@ def mainParser(backend, db, cursor, site, category, hand, config): fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo) - hand=fpdb_simple.filterCrap(site, hand, isTourney) + hand = fpdb_simple.filterCrap(site, hand, isTourney) #part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street fpdb_simple.classifyLines(hand, category, lineTypes, lineStreets) diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index 01bd71cc..d48f669b 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -73,7 +73,8 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, saveActions = False if import_options['saveActions'] == 'False' else True fastStoreHudCache = False if import_options['fastStoreHudCache'] == 'False' else True - # print "DEBUG: saveActions = '%s' fastStoreHudCache = '%s'"%(saveActions, fastStoreHudCache) +# print "DEBUG: saveActions = '%s' fastStoreHudCache = '%s'"%(saveActions, fastStoreHudCache) +# print "DEBUG: import_options = ", import_options t0 = time() fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index c86d3882..c690a5c8 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -384,17 +384,16 @@ def getLastInsertId(backend, conn, cursor): #returns an array of the total money paid. intending to add rebuys/addons here def calcPayin(count, buyin, fee): - result=[] - for i in xrange(count): - result.append (buyin+fee) - return result + return [buyin + fee for i in xrange(count)] #end def calcPayin def checkPositions(positions): """ verify positions are valid """ - for p in positions: - if not (p == "B" or p == "S" or (p >= 0 and p <= 9)): - raise FpdbError("invalid position '" + p + "' found in checkPositions") + if any(not (p == "B" or p == "S" or (p >= 0 and p <= 9)) for p in positions): + raise FpdbError("invalid position '"+p+"' found in checkPositions") +# for p in positions: +# if not (p == "B" or p == "S" or (p >= 0 and p <= 9)): +# raise FpdbError("invalid position '" + p + "' found in checkPositions") ### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB ### eric - position 8 could be valid - if only one blind is posted, but there's still 10 people, ie a sitout is present, and the small is dead... @@ -497,12 +496,13 @@ def convertBlindBet(actionTypes, actionAmounts): blinds=[] bets=[] for k in xrange(len(actionTypes[i][j])): - if (actionTypes[i][j][k]=="blind"): + if actionTypes[i][j][k] == "blind": blinds.append((i,j,k)) - if (len(blinds)>0 and actionTypes[i][j][k]=="bet"): + if blinds and actionTypes[i][j][k] == "bet": +# if (len(blinds)>0 and actionTypes[i][j][k]=="bet"): bets.append((i,j,k)) - if (len(bets)==1): + if len(bets) == 1: blind_amount=actionAmounts[blinds[0][0]][blinds[0][1]][blinds[0][2]] bet_amount=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]]=bet_amount-blind_amount @@ -514,7 +514,8 @@ def convertCardValues(arr): map(convertCardValuesBoard, arr) #end def convertCardValues -card_map = { "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14} +# a 0-card is one in a stud game that we did not see or was not shown +card_map = { 0: 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14} #converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details def convertCardValuesBoard(arr): @@ -612,88 +613,82 @@ def filterAnteBlindFold(site,hand): if foldeeName in line: hand[i] = None - hand = [line for line in hand if line] + return [line for line in hand if line] #end def filterAnteFold def stripEOLspaces(str): - if str[-1] == ' ': - str = str[:-1] - if str[-1] == ' ': - str = str[:-1] - return str + return str.rstrip() #removes useless lines as well as trailing spaces def filterCrap(site, hand, isTourney): #remove two trailing spaces at end of line - hand = [stripEOLspaces(line) for line in hand] + hand = [line.rstrip() for line in hand] #print "hand after trailing space removal in filterCrap:",hand #general variable position word filter/string filter for i in xrange (len(hand)): - if (hand[i].startswith("Board [")): + if hand[i].startswith("Board ["): hand[i] = False - elif (hand[i].find(" out of hand ")!=-1): + elif hand[i].find(" out of hand ")!=-1: hand[i]=hand[i][:-56] - elif (hand[i].find("($0 in chips)") != -1): + elif "($0 in chips)" in hand[i]: hand[i] = False - elif (hand[i]=="*** HOLE CARDS ***"): + elif hand[i]=="*** HOLE CARDS ***": hand[i] = False - elif (hand[i].endswith("has been disconnected")): + elif hand[i].endswith("has been disconnected"): hand[i] = False - elif (hand[i].endswith("has requested TIME")): + elif hand[i].endswith("has requested TIME"): hand[i] = False - elif (hand[i].endswith("has returned")): + elif hand[i].endswith("has returned"): hand[i] = False - elif (hand[i].endswith("will be allowed to play after the button")): + elif hand[i].endswith("will be allowed to play after the button"): hand[i] = False - elif (hand[i].endswith("has timed out")): + elif hand[i].endswith("has timed out"): hand[i] = False - elif (hand[i].endswith("has timed out while disconnected")): + elif hand[i].endswith("has timed out while disconnected"): hand[i] = False - elif (hand[i].endswith("has timed out while being disconnected")): + elif hand[i].endswith("has timed out while being disconnected"): hand[i] = False - elif (hand[i].endswith("is connected")): + elif hand[i].endswith("is connected"): hand[i] = False - elif (hand[i].endswith("is disconnected")): + elif hand[i].endswith("is disconnected"): hand[i] = False - elif (hand[i].endswith(" is feeling angry")): + elif hand[i].endswith(" is feeling angry"): hand[i] = False - elif (hand[i].endswith(" is feeling confused")): + elif hand[i].endswith(" is feeling confused"): hand[i] = False - elif (hand[i].endswith(" is feeling happy")): + elif hand[i].endswith(" is feeling happy"): hand[i] = False - elif (hand[i].endswith(" is feeling normal")): + elif hand[i].endswith(" is feeling normal"): hand[i] = False - elif (hand[i].find(" is low with [")!=-1): + elif " is low with [" in hand[i]: hand[i] = False #elif (hand[i].find("-max Seat #")!=-1 and hand[i].find(" is the button")!=-1): # toRemove.append(hand[i]) - elif (hand[i].endswith(" mucks")): + elif hand[i].endswith(" mucks"): hand[i] = False - elif (hand[i].endswith(": mucks hand")): + elif hand[i].endswith(": mucks hand"): hand[i] = False - elif (hand[i]=="No low hand qualified"): + elif hand[i] == "No low hand qualified": hand[i] = False - elif (hand[i]=="Pair on board - a double bet is allowed"): + elif hand[i] == "Pair on board - a double bet is allowed": hand[i] = False - elif (hand[i].find(" shows ")!=-1 and hand[i].find("[")==-1): + elif " shows " in hand[i] and "[" not in hand[i]: hand[i] = False - #elif (hand[i].startswith("Table '") and hand[i].endswith("-max")): - # toRemove.append(hand[i]) - elif (hand[i].startswith("The button is in seat #")): + elif hand[i].startswith("The button is in seat #"): hand[i] = False #above is alphabetic, reorder below if bored - elif (hand[i].startswith("Time has expired")): + elif hand[i].startswith("Time has expired"): hand[i] = False - elif (hand[i].endswith("has reconnected")): + elif hand[i].endswith("has reconnected"): hand[i] = False - elif (hand[i].endswith("seconds left to act")): + elif hand[i].endswith("seconds left to act"): hand[i] = False - elif (hand[i].endswith("seconds to reconnect")): + elif hand[i].endswith("seconds to reconnect"): hand[i] = False - elif (hand[i].endswith("was removed from the table for failing to post")): + elif hand[i].endswith("was removed from the table for failing to post"): hand[i] = False - elif (hand[i].find("joins the table at seat ")!=-1): + elif "joins the table at seat " in hand[i]: hand[i] = False elif (hand[i].endswith(" sits down")): hand[i] = False @@ -701,20 +696,20 @@ def filterCrap(site, hand, isTourney): hand[i] = False elif (hand[i].endswith(" stands up")): hand[i] = False - elif (hand[i].find("is high with ")!=-1): + elif "is high with" in hand[i]: hand[i] = False - elif (hand[i].endswith("doesn't show hand")): + elif hand[i].endswith("doesn't show hand"): hand[i] = False - elif (hand[i].endswith("is being treated as all-in")): + elif hand[i].endswith("is being treated as all-in"): hand[i] = False - elif (hand[i].find(" adds $")!=-1): + elif " adds $" in hand[i]: hand[i] = False - elif (hand[i]=="Betting is capped"): + elif hand[i] == "Betting is capped": hand[i] = False #site specific variable position filter - elif (hand[i].find(" said, \"")!=-1): + elif 'said, "' in hand[i]: hand[i] = False - elif (hand[i].find(": ")!=-1 and site=="ftp" and hand[i].find("Seat ")==-1 and hand[i].find(": Table")==-1): #filter ftp chat + elif site == "ftp" and ":" in hand[i] and "Seat " not in hand[i] and ": Table" not in hand[i]: # FTP chat hand[i] = False if isTourney and not hand[i] == False: if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))): @@ -732,25 +727,25 @@ def filterCrap(site, hand, isTourney): #end filterCrap #takes a poker float (including , for thousand seperator and converts it to an int -def float2int (string): - pos=string.find(",") - if (pos!=-1): #remove , the thousand seperator +def float2int(string): + pos = string.find(",") + if pos != -1: #remove , the thousand seperator string = "%s%s" % (string[0:pos], string[pos+1:]) - pos=string.find(".") - if (pos!=-1): #remove decimal point + pos = string.find(".") + if pos != -1: #remove decimal point string = "%s%s" % (string[0:pos], string[pos+1:]) result = int(string) if pos == -1: #no decimal point - was in full dollars - need to multiply with 100 - result*=100 + result *= 100 return result #end def float2int ActionLines = ( "calls $", ": calls ", "brings in for", "completes it to", "posts small blind", "posts the small blind", "posts big blind", "posts the big blind", "posts small & big blinds", "posts $", "posts a dead", "bets $", - ": bets ", "raises") + ": bets ", " raises") #returns boolean whether the passed line is an action line def isActionLine(line): @@ -760,8 +755,9 @@ def isActionLine(line): return True elif (line.startswith("Uncalled bet")): return True - - return len( [ x for x in ActionLines if x in line]) > 0 + + return any(x for x in ActionLines if x in line) +# return bool([ x for x in ActionLines if x in line]) # ret = any(True for searchstr in ActionLines if searchstr in line) # ret = len( [ x for x in ActionLines if line.find(x) > -1] ) > 0 # ret = any(searchstr in line for searchstr in ActionLines) @@ -787,10 +783,11 @@ def isTourney(topline): #end def isTourney WinLines = ( "wins the pot", "ties for the ", "wins side pot", "wins the low main pot", "wins the high main pot", + "wins the low", "wins the high pot", "wins the high side pot", "wins the main pot", "wins the side pot", "collected" ) #returns boolean whether the passed line is a win line def isWinLine(line): - return len( [ x for x in WinLines if x in line ] ) > 0 + return any(x for x in WinLines if x in line) #end def isWinLine #returns the amount of cash/chips put into the put in the given action line @@ -883,41 +880,24 @@ def goesAllInOnThisLine(line): #end def goesAllInOnThisLine #returns the action type code (see table design) of the given action line +ActionTypes = { 'calls':"call", 'brings in for':"blind", 'completes it to':"bet", ' posts $':"blind", + ' posts a dead ' : "blind", ' posts the small blind of $':"blind", ': posts big blind ':"blind", + ' posts the big blind of $':"blind", ': posts small & big blinds $':"blind", + ': posts small blind $':"blind", + ' bets' : "bet", ' raises' : "bet" + } def parseActionType(line): if (line.startswith("Uncalled bet")): return "unbet" - elif (line.endswith("folds")): + elif (line.endswith(" folds")): return "fold" - elif (line.endswith("checks")): + elif (line.endswith(" checks")): return "check" - elif (line.find("calls")!=-1): - return "call" - elif (line.find("brings in for")!=-1): - return "blind" - elif (line.find("completes it to")!=-1): - return "bet" - #todo: what if someone completes instead of bringing in? - elif (line.find(" posts $")!=-1): - return "blind" - elif (line.find(" posts a dead ")!=-1): - return "blind" - elif (line.find(": posts small blind ")!=-1): - return "blind" - elif (line.find(" posts the small blind of $")!=-1): - return "blind" - elif (line.find(": posts big blind ")!=-1): - return "blind" - elif (line.find(" posts the big blind of $")!=-1): - return "blind" - elif (line.find(": posts small & big blinds $")!=-1): - return "blind" - #todo: seperately record voluntary blind payments made to join table out of turn - elif (line.find("bets")!=-1): - return "bet" - elif (line.find("raises")!=-1): - return "bet" else: - raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) + for x in ActionTypes: + if x in line: + return ActionTypes[x] + raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) #end def parseActionType #parses the ante out of the given line and checks which player paid it, updates antes accordingly. @@ -1052,12 +1032,12 @@ def parseFee(topline): def parseHandStartTime(topline, site): #convert x:13:35 to 0x:13:35 counter=0 - while (True): - pos=topline.find(" "+str(counter)+":") - if (pos!=-1): - topline=topline[0:pos+1]+"0"+topline[pos+1:] - counter+=1 - if counter==10: break + while counter < 10: + pos = topline.find(" %d:" % counter) + if pos != -1: + topline = "%s0%s" % (topline[0:pos+1], topline[pos+1:]) + break + counter += 1 isUTC=False if site=="ftp": @@ -1101,64 +1081,58 @@ def parseHandStartTime(topline, site): #end def parseHandStartTime #parses the names out of the given lines and returns them as an array +def findName(line): + pos1 = line.find(":") + 2 + pos2 = line.rfind("(") - 1 + return unicode(line[pos1:pos2], "latin-1") + def parseNames(lines): - result = [] - for i in xrange (len(lines)): - pos1=lines[i].find(":")+2 - pos2=lines[i].rfind("(")-1 - tmp=lines[i][pos1:pos2] - #print "parseNames, tmp original:",tmp - tmp=unicode(tmp,"latin-1") - #print "parseNames, tmp after unicode latin-1 conversion:",tmp - result.append(tmp) - return result + return [findName(line) for line in lines] #end def parseNames def parsePositions(hand, names): - positions = map(lambda x: -1, names) - + positions = [-1 for i in names] + sb, bb = -1, -1 + #find blinds - sb,bb=-1,-1 - for i in xrange (len(hand)): - if (sb==-1 and hand[i].find("small blind")!=-1 and hand[i].find("dead small blind")==-1): - sb=hand[i] - #print "sb:",sb - if (bb==-1 and hand[i].find("big blind")!=-1 and hand[i].find("dead big blind")==-1): - bb=hand[i] - #print "bb:",bb + for line in hand: + if sb == -1 and "small blind" in line and "dead small blind" not in line: + sb = line + if bb == -1 and "big blind" in line and "dead big blind" not in line: + bb = line #identify blinds #print "parsePositions before recognising sb/bb. names:",names - sbExists=True - if (sb!=-1): - sb=recognisePlayerNo(sb, names, "bet") + sbExists = True + if sb != -1: + sb = recognisePlayerNo(sb, names, "bet") else: - sbExists=False - if (bb!=-1): - bb=recognisePlayerNo(bb, names, "bet") + sbExists = False + if bb != -1: + bb = recognisePlayerNo(bb, names, "bet") # print "sb = ", sb, "bb = ", bb - if bb == sb: + if bb == sb: # if big and small are same, then don't duplicate the small sbExists = False sb = -1 #write blinds into array - if (sbExists): + if sbExists: positions[sb]="S" positions[bb]="B" - #fill up rest of array - if (sbExists): - arraypos=sb-1 + if sbExists: + arraypos = sb-1 else: - arraypos=bb-1 + arraypos = bb-1 + distFromBtn=0 - while (arraypos>=0 and arraypos != bb): + while arraypos >= 0 and arraypos != bb: #print "parsePositions first while, arraypos:",arraypos,"positions:",positions - positions[arraypos]=distFromBtn - arraypos-=1 - distFromBtn+=1 + positions[arraypos] = distFromBtn + arraypos -= 1 + distFromBtn += 1 # eric - this takes into account dead seats between blinds if sbExists: @@ -1182,11 +1156,10 @@ def parsePositions(hand, names): arraypos-=1 distFromBtn+=1 - for i in xrange (len(names)): - if positions[i]==-1: - print "parsePositions names:",names - print "result:",positions - raise FpdbError ("failed to read positions") + if any(p == -1 for p in positions): + print "parsePositions names:",names + print "result:",positions + raise FpdbError ("failed to read positions") # print str(positions), "\n" return positions #end def parsePositions @@ -1254,22 +1227,23 @@ def parseTourneyNo(topline): #parses a win/collect line. manipulates the passed array winnings, no explicit return def parseWinLine(line, site, names, winnings, isTourney): #print "parseWinLine: line:",line - for i in xrange(len(names)): - if (line.startswith(names[i].encode("latin-1"))): #found a winner + for i,n in enumerate(names): + n = n.encode("latin-1") + if line.startswith(n): if isTourney: - pos1=line.rfind("collected ")+10 - if (site=="ftp"): - pos2=line.find(")", pos1) - elif (site=="ps"): - pos2=line.find(" ", pos1) - winnings[i]+=int(line[pos1:pos2]) + pos1 = line.rfind("collected ") + 10 + if site == "ftp": + pos2 = line.find(")", pos1) + elif site == "ps": + pos2 = line.find(" ", pos1) + winnings[i] += int(line[pos1:pos2]) else: - pos1=line.rfind("$")+1 - if (site=="ftp"): - pos2=line.find(")", pos1) - elif (site=="ps"): - pos2=line.find(" ", pos1) - winnings[i]+=float2int(line[pos1:pos2]) + pos1 = line.rfind("$") + 1 + if site == "ftp": + pos2 = line.find(")", pos1) + elif site == "ps": + pos2 = line.find(" ", pos1) + winnings[i] += float2int(line[pos1:pos2]) #end def parseWinLine #returns the category (as per database) string for the given line @@ -1414,20 +1388,50 @@ def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): #end def recogniseTourneyTypeId #returns the SQL ids of the names given in an array +# TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict +# { playername: id } instead of depending on it's relation to the positions list +# then this can be reduced in complexity a bit + def recognisePlayerIDs(cursor, names, site_id): - result = [] - for i in xrange(len(names)): - cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - tmp=cursor.fetchall() - if (len(tmp)==0): #new player - cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) - #print "Number of players rows inserted: %d" % cursor.rowcount - cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - tmp=cursor.fetchall() - #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp - result.append(tmp[0][0]) - return result + q = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in names]) + cursor.execute(q, names) # get all playerids by the names passed in + ids = dict(cursor.fetchall()) # convert to dict + if len(ids) != len(names): + notfound = [n for n in names if n not in ids] # make list of names not in database + if notfound: # insert them into database + cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound)) + q2 = "SELECT name,id FROM Players WHERE name=%s" % " OR name=".join(["%s" for n in notfound]) + cursor.execute(q2, notfound) # get their new ids + tmp = dict(cursor.fetchall()) + for n in tmp: # put them all into the same dict + ids[n] = tmp[n] + + # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB + return [ids[n] for n in names] #end def recognisePlayerIDs + + +# Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input +# this version could also be improved upon using list comprehensions, etc + +#def recognisePlayerIDs(cursor, names, site_id): +# result = [] +# notfound = [] +# cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names)) +# tmp = dict(cursor.fetchall()) +# for n in names: +# if n not in tmp: +# notfound.append(n) +# else: +# result.append(tmp[n]) +# if notfound: +# cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound)) +# cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound)) +# tmp = cursor.fetchall() +# for n in tmp: +# result.append(n[0]) +# +# return result #recognises the name in the given line and returns its array position in the given array def recognisePlayerNo(line, names, atype): @@ -2261,8 +2265,8 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): try: len(row) except TypeError: row=[] - - if (len(row)==0): + + if not row: #print "new huddata row" doInsert=True row=[] @@ -2275,9 +2279,11 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): else: doInsert=False + # This is making a copy of the original list, although i really don't see any reason it's being done? newrow=[] - for i in xrange(len(row)): - newrow.append(row[i]) + newrow.extend(row) +# for i in xrange(len(row)): +# newrow.append(row[i]) row=newrow if base=="hold": diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index dc65cb14..4db7b3b2 100644 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -35,6 +35,9 @@ def testGameInfo(): (u"PokerStars Game #25923772706: Badugi Limit ($0.25/$0.50) - 2009/03/13 16:40:58 ET", {'type':'ring', 'base':'draw', 'category':'badugi', 'limitType':'fl', 'sb':'0.25', 'bb':'0.50','currency':'USD'}), + (u"PokerStars Game #22073591924: Hold'em No Limit ($0.50/$1.00) - 2008/11/16 1:22:21 CET [2008/11/15 19:22:21 ET]", + {'type':'ring', 'base':'hold', 'category':'holdem', 'limitType':'nl', 'sb':'0.50', 'bb':'1.00','currency':'USD'}), + (u"PokerStars Game #25974627364: Omaha Pot Limit ($0.05/$0.10) - 2009/03/15 0:29:00 ET", {'type':'ring', 'base':'hold', 'category':'omahahi', 'limitType':'pl', 'sb':'0.05', 'bb':'0.10','currency':'USD'}) )