diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 54690979..a8456294 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -787,7 +787,8 @@ class Database: def get_player_id(self, config, site, player_name): c = self.connection.cursor() - c.execute(self.sql.query['get_player_id'], (player_name, site)) + p_name = Charset.to_utf8(player_name) + c.execute(self.sql.query['get_player_id'], (p_name, site)) row = c.fetchone() if row: return row[0] @@ -1327,6 +1328,8 @@ class Database: c.execute("INSERT INTO Sites (name,currency) VALUES ('Absolute', 'USD')") c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')") c.execute("INSERT INTO Sites (name,currency) VALUES ('Partouche', 'EUR')") + c.execute("INSERT INTO Sites (name,currency) VALUES ('Carbon', 'USD')") + c.execute("INSERT INTO Sites (name,currency) VALUES ('PKR', 'USD')") if self.backend == self.SQLITE: c.execute("INSERT INTO TourneyTypes (id, siteId, buyin, fee) VALUES (NULL, 1, 0, 0);") elif self.backend == self.PGSQL: diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index fa6d2400..7f75cc4e 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -42,6 +42,26 @@ class Filters(threading.Thread): self.conf = db.config self.display = display + # text used on screen stored here so that it can be configured + self.filterText = {'limitsall':'All', 'limitsnone':'None', 'limitsshow':'Show _Limits' + ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' + ,'playerstitle':'Hero:', 'sitestitle':'Sites:', 'gamestitle':'Games:' + ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' + ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' + ,'datestitle':'Date:' + ,'groupsall':'All Players' + ,'limitsFL':'FL', 'limitsNL':'NL', 'limitsPL':'PL', 'ring':'Ring', 'tour':'Tourney' + } + + # Outer Packing box + self.mainVBox = gtk.VBox(False, 0) + + self.label = {} + self.callback = {} + + self.make_filter() + + def make_filter(self): self.sites = {} self.games = {} self.limits = {} @@ -60,16 +80,6 @@ class Filters(threading.Thread): else: print "Either 0 or more than one site matched - EEK" - - # text used on screen stored here so that it can be configured - self.filterText = {'limitsall':'All', 'limitsnone':'None', 'limitsshow':'Show _Limits' - ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players' - ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:' - ,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:' - ,'groupsall':'All Players' - ,'limitsFL':'FL', 'limitsNL':'NL', 'limitsPL':'PL', 'ring':'Ring', 'tour':'Tourney' - } - # For use in date ranges. self.start_date = gtk.Entry(max=12) self.end_date = gtk.Entry(max=12) @@ -80,34 +90,28 @@ class Filters(threading.Thread): self.sbGroups = {} self.numHands = 0 - # Outer Packing box - self.mainVBox = gtk.VBox(False, 0) - - playerFrame = gtk.Frame("Hero:") + playerFrame = gtk.Frame() playerFrame.set_label_align(0.0, 0.0) vbox = gtk.VBox(False, 0) self.fillPlayerFrame(vbox, self.display) playerFrame.add(vbox) - self.boxes['player'] = vbox - sitesFrame = gtk.Frame("Sites:") + sitesFrame = gtk.Frame() sitesFrame.set_label_align(0.0, 0.0) vbox = gtk.VBox(False, 0) self.fillSitesFrame(vbox) sitesFrame.add(vbox) - self.boxes['sites'] = vbox # Game types - gamesFrame = gtk.Frame("Games:") + gamesFrame = gtk.Frame() gamesFrame.set_label_align(0.0, 0.0) gamesFrame.show() vbox = gtk.VBox(False, 0) self.fillGamesFrame(vbox) gamesFrame.add(vbox) - self.boxes['games'] = vbox # Limits limitsFrame = gtk.Frame() @@ -144,14 +148,13 @@ class Filters(threading.Thread): groupsFrame.add(vbox) # Date - dateFrame = gtk.Frame("Date:") + dateFrame = gtk.Frame() dateFrame.set_label_align(0.0, 0.0) dateFrame.show() vbox = gtk.VBox(False, 0) self.fillDateFrame(vbox) dateFrame.add(vbox) - self.boxes['date'] = vbox # Buttons self.Button1=gtk.Button("Unnamed 1") @@ -192,6 +195,17 @@ class Filters(threading.Thread): if "Button2" not in self.display or self.display["Button2"] == False: self.Button2.hide() + if 'button1' in self.label and self.label['button1']: + self.Button1.set_label( self.label['button1'] ) + if 'button2' in self.label and self.label['button2']: + self.Button2.set_label( self.label['button2'] ) + if 'button1' in self.callback and self.callback['button1']: + self.Button1.connect("clicked", self.callback['button1'], "clicked") + self.Button1.set_sensitive(True) + if 'button2' in self.callback and self.callback['button2']: + self.Button2.connect("clicked", self.callback['button2'], "clicked") + self.Button2.set_sensitive(True) + def get_vbox(self): """returns the vbox of this thread""" return self.mainVBox @@ -237,17 +251,21 @@ class Filters(threading.Thread): def registerButton1Name(self, title): self.Button1.set_label(title) + self.label['button1'] = title def registerButton1Callback(self, callback): self.Button1.connect("clicked", callback, "clicked") self.Button1.set_sensitive(True) + self.callback['button1'] = callback def registerButton2Name(self, title): self.Button2.set_label(title) + self.label['button2'] = title def registerButton2Callback(self, callback): self.Button2.connect("clicked", callback, "clicked") self.Button2.set_sensitive(True) + self.callback['button2'] = callback def cardCallback(self, widget, data=None): print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()]) @@ -255,7 +273,7 @@ class Filters(threading.Thread): def createPlayerLine(self, hbox, site, player): print 'DEBUG :: add:"%s"' % player label = gtk.Label(site +" id:") - hbox.pack_start(label, False, False, 0) + hbox.pack_start(label, False, False, 3) pname = gtk.Entry() pname.set_text(player) @@ -464,9 +482,22 @@ class Filters(threading.Thread): print "self.groups[%s] set to %s" %(group, self.groups[group]) def fillPlayerFrame(self, vbox, display): + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['playerstitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="refresh", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__refresh, 'players') + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['players'] = vbox1 + for site in self.conf.get_supported_sites(): hBox = gtk.HBox(False, 0) - vbox.pack_start(hBox, False, True, 0) + vbox1.pack_start(hBox, False, True, 0) player = self.conf.supported_sites[site].screen_name _pname = Charset.to_gui(player) @@ -474,7 +505,7 @@ class Filters(threading.Thread): if "GroupsAll" in display and display["GroupsAll"] == True: hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, False, 0) + vbox1.pack_start(hbox, False, False, 0) cb = gtk.CheckButton(self.filterText['groupsall']) cb.connect('clicked', self.__set_group_select, 'allplayers') hbox.pack_start(cb, False, False, 0) @@ -490,11 +521,30 @@ class Filters(threading.Thread): phands.set_width_chars(8) hbox.pack_start(phands, False, False, 0) phands.connect("changed", self.__set_num_hands, site) + top_hbox.pack_start(showb, expand=False, padding=1) def fillSitesFrame(self, vbox): + top_hbox = gtk.HBox(False, 0) + top_hbox.show() + vbox.pack_start(top_hbox, False, False, 0) + + lbl_title = gtk.Label(self.filterText['sitestitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'sites') + showb.show() + top_hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + self.boxes['sites'] = vbox1 + vbox.pack_start(vbox1, False, False, 0) + for site in self.conf.get_supported_sites(): hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, True, 0) + vbox1.pack_start(hbox, False, True, 0) self.createSiteLine(hbox, site) #Get db site id for filtering later #self.cursor.execute(self.sql.query['getSiteId'], (site,)) @@ -505,12 +555,26 @@ class Filters(threading.Thread): # print "Either 0 or more than one site matched - EEK" def fillGamesFrame(self, vbox): + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['gamestitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'games') + top_hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['games'] = vbox1 + self.cursor.execute(self.sql.query['getGames']) result = self.db.cursor.fetchall() if len(result) >= 1: for line in result: hbox = gtk.HBox(False, 0) - vbox.pack_start(hbox, False, True, 0) + vbox1.pack_start(hbox, False, True, 0) self.createGameLine(hbox, line[0]) else: print "INFO: No games returned from database" @@ -705,8 +769,22 @@ class Filters(threading.Thread): def fillDateFrame(self, vbox): # Hat tip to Mika Bostrom - calendar code comes from PokerStats + top_hbox = gtk.HBox(False, 0) + vbox.pack_start(top_hbox, False, False, 0) + lbl_title = gtk.Label(self.filterText['datestitle']) + lbl_title.set_alignment(xalign=0.0, yalign=0.5) + top_hbox.pack_start(lbl_title, expand=True, padding=3) + showb = gtk.Button(label="hide", stock=None, use_underline=True) + showb.set_alignment(xalign=1.0, yalign=0.5) + showb.connect('clicked', self.__toggle_box, 'dates') + top_hbox.pack_start(showb, expand=False, padding=1) + + vbox1 = gtk.VBox(False, 0) + vbox.pack_start(vbox1, False, False, 0) + self.boxes['dates'] = vbox1 + hbox = gtk.HBox() - vbox.pack_start(hbox, False, True, 0) + vbox1.pack_start(hbox, False, True, 0) lbl_start = gtk.Label('From:') @@ -720,7 +798,7 @@ class Filters(threading.Thread): #New row for end date hbox = gtk.HBox() - vbox.pack_start(hbox, False, True, 0) + vbox1.pack_start(hbox, False, True, 0) lbl_end = gtk.Label(' To:') btn_end = gtk.Button() @@ -736,10 +814,13 @@ class Filters(threading.Thread): hbox.pack_start(btn_clear, expand=False, padding=15) + def __refresh(self, widget, entry): + for w in self.mainVBox.get_children(): + w.destroy() + self.make_filter() + def __toggle_box(self, widget, entry): - if "Limits" not in self.display or self.display["Limits"] == False: - self.boxes[entry].hide() - elif self.boxes[entry].props.visible: + if self.boxes[entry].props.visible: self.boxes[entry].hide() widget.set_label("show") else: diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index f0eca2f1..ce9648ae 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -176,17 +176,46 @@ class GuiGraphViewer (threading.Thread): (green, blue, red) = self.getRingProfitGraph(playerids, sitenos, limits, games) print "Graph generated in: %s" %(time() - starttime) - self.ax.set_title("Profit graph for ring games") #Set axis labels and grid overlay properites self.ax.set_xlabel("Hands", fontsize = 12) self.ax.set_ylabel("$", fontsize = 12) self.ax.grid(color='g', linestyle=':', linewidth=0.2) if green == None or green == []: + self.ax.set_title("No Data for Player(s) Found") + green = ([ 0., 0., 0., 0., 500., 1000., 900., 800., + 700., 600., 500., 400., 300., 200., 100., 0., + 500., 1000., 1000., 1000., 1000., 1000., 1000., 1000., + 1000., 1000., 1000., 1000., 1000., 1000., 875., 750., + 625., 500., 375., 250., 125., 0., 0., 0., + 0., 500., 1000., 900., 800., 700., 600., 500., + 400., 300., 200., 100., 0., 500., 1000., 1000.]) + red = ([ 0., 0., 0., 0., 500., 1000., 900., 800., + 700., 600., 500., 400., 300., 200., 100., 0., + 0., 0., 0., 0., 0., 0., 125., 250., + 375., 500., 500., 500., 500., 500., 500., 500., + 500., 500., 375., 250., 125., 0., 0., 0., + 0., 500., 1000., 900., 800., 700., 600., 500., + 400., 300., 200., 100., 0., 500., 1000., 1000.]) + blue = ([ 0., 0., 0., 0., 500., 1000., 900., 800., + 700., 600., 500., 400., 300., 200., 100., 0., + 0., 0., 0., 0., 0., 0., 125., 250., + 375., 500., 625., 750., 875., 1000., 875., 750., + 625., 500., 375., 250., 125., 0., 0., 0., + 0., 500., 1000., 900., 800., 700., 600., 500., + 400., 300., 200., 100., 0., 500., 1000., 1000.]) + + self.ax.plot(green, color='green', label='Hands: %d\nProfit: $%.2f' %(len(green), green[-1])) + self.ax.plot(blue, color='blue', label='Showdown: $%.2f' %(blue[-1])) + self.ax.plot(red, color='red', label='Non-showdown: $%.2f' %(red[-1])) + self.graphBox.add(self.canvas) + self.canvas.show() + self.canvas.draw() #TODO: Do something useful like alert user - print "No hands returned by graph query" + #print "No hands returned by graph query" else: + self.ax.set_title("Profit graph for ring games") #text = "Profit: $%.2f\nTotal Hands: %d" %(green[-1], len(green)) #self.ax.annotate(text, # xy=(10, -10), @@ -203,7 +232,6 @@ class GuiGraphViewer (threading.Thread): else: self.ax.legend(loc='best', fancybox=True, shadow=True, prop=FontProperties(size='smaller')) - self.graphBox.add(self.canvas) self.canvas.show() self.canvas.draw() @@ -292,7 +320,7 @@ class GuiGraphViewer (threading.Thread): self.db.rollback() if winnings == (): - return None + return (None, None, None) green = map(lambda x:float(x[1]), winnings) blue = map(lambda x: float(x[1]) if x[2] == True else 0.0, winnings) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 564513f0..11b14274 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -274,7 +274,7 @@ class GuiPlayerStats (threading.Thread): except: a = 0.0 try: b = float(b) except: b = 0.0 - if n == 0: + if n == 0 and grid == 1: #make sure it only works on the starting hands a1,a2,a3 = ranks[a[0]], ranks[a[1]], (a+'o')[2] b1,b2,b3 = ranks[b[0]], ranks[b[1]], (b+'o')[2] if a1 > b1 or ( a1 == b1 and (a2 > b2 or (a2 == b2 and a3 > b3) ) ): diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index c072fb54..a6f48605 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -358,21 +358,24 @@ class Aux_Seats(Aux_Window): except AttributeError: return loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) + width = self.hud.table.width + height = self.hud.table.height + for i in (range(1, self.hud.max + 1) + ['common']): if i == 'common': (x, y) = self.params['layout'][self.hud.max].common else: (x, y) = loc[adj[i]] - self.positions[i] = self.card_positions(x, self.hud.table.x, y, self.hud.table.y) + self.positions[i] = self.card_positions((x * width) / 1000, self.hud.table.x, (y * height) /1000, self.hud.table.y) self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) - def create(self): self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) self.m_windows = {} # windows to put the card images in - + width = self.hud.table.width + height = self.hud.table.height for i in (range(1, self.hud.max + 1) + ['common']): if i == 'common': (x, y) = self.params['layout'][self.hud.max].common @@ -384,7 +387,7 @@ class Aux_Seats(Aux_Window): self.m_windows[i].set_transient_for(self.hud.main_window) self.m_windows[i].set_focus_on_map(False) self.m_windows[i].connect("configure_event", self.configure_event_cb, i) - self.positions[i] = self.card_positions(x, self.hud.table.x, y, self.hud.table.y) + self.positions[i] = self.card_positions((x * width) / 1000, self.hud.table.x, (y * height) /1000, self.hud.table.y) self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) if self.params.has_key('opacity'): self.m_windows[i].set_opacity(float(self.params['opacity'])) @@ -426,11 +429,13 @@ class Aux_Seats(Aux_Window): """Save new layout back to the aux element in the config file.""" new_locs = {} # print "adj =", self.adj + witdh = self.hud.table.width + height = self.hud.table.height for (i, pos) in self.positions.iteritems(): - if i != 'common': - new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) - else: - new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) + if i != 'common': + new_locs[self.adj[int(i)]] = ((pos[0] - self.hud.table.x) * 1000 / witdh, (pos[1] - self.hud.table.y) * 1000 / height) + else: + new_locs[i] = ((pos[0] - self.hud.table.x) * 1000 / witdh, (pos[1] - self.hud.table.y) * 1000 / height) self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) def configure_event_cb(self, widget, event, i, *args): diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 2a4fbdb6..c8bfea70 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -46,9 +46,9 @@ class PokerStars(HandHistoryConverter): PokerStars\sGame\s\#(?P[0-9]+):\s+ (Tournament\s\# # open paren of tournament info (?P\d+),\s - (?P[%(LS)s\+\d\.]+ # here's how I plan to use LS - \s?(?P%(LEGAL_ISO)s)? - )\s)? # close paren of tournament info + # here's how I plan to use LS + (?P([%(LS)s\+\d\.]+\s?(?P%(LEGAL_ISO)s)?)|Freeroll)\s+)? + # close paren of tournament info (?PHORSE|8\-Game|HOSE)?\s?\(? (?PHold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|5\sCard\sDraw)\s (?PNo\sLimit|Limit|Pot\sLimit)\)?,?\s @@ -205,9 +205,12 @@ class PokerStars(HandHistoryConverter): if key == 'TOURNO': hand.tourNo = info[key] if key == 'BUYIN': - #FIXME: The key looks like: '€0.82+€0.18 EUR' - # This should be parsed properly and used - hand.buyin = info[key] + if info[key] == 'Freeroll': + hand.buyin = '$0+$0' + else: + #FIXME: The key looks like: '€0.82+€0.18 EUR' + # This should be parsed properly and used + hand.buyin = info[key] if key == 'LEVEL': hand.level = info[key] diff --git a/run_fpdb.py b/run_fpdb.py index 78e2803b..570b7dc5 100755 --- a/run_fpdb.py +++ b/run_fpdb.py @@ -24,7 +24,6 @@ sys.path[0] = sys.path[0]+os.sep+"pyfpdb" os.chdir(sys.path[0]) #print "sys.path[0] =", sys.path[0], "cwd =", os.getcwd() - import fpdb