From 7d75e4af91cfba062df3e4edf9c56c6adbcc1e06 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 8 Dec 2008 14:10:45 -0500 Subject: [PATCH 01/27] Add winner and pot to Mucked list list box + intfac imp. --- pyfpdb/Database.py | 11 ++++- pyfpdb/Hud.py | 3 +- pyfpdb/Mucked.py | 112 ++++++++++++++++----------------------------- pyfpdb/SQL.py | 8 ++++ pyfpdb/Tables.py | 4 +- 5 files changed, 62 insertions(+), 76 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 95abdd71..154edec5 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -151,7 +151,16 @@ class Database: act = row[1:] action[street].append(act) return action - + + def get_winners_from_hand(self, hand): + """Returns a hash of winners:amount won, given a hand number.""" + winners = {} + c = self.connection.cursor() + c.execute(self.sql.query['get_winners_from_hand'], (hand)) + for row in c.fetchall(): + winners[row[0]] = row[1] + return winners + def get_stats_from_hand(self, hand, aggregate = False): c = self.connection.cursor() diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 80ec9a82..8dbb53a6 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -55,6 +55,7 @@ class Hud: self.db_name = db_name self.deleted = False self.stacked = True + self.site = table.site self.colors = config.get_default_colors(self.table.site) self.stat_windows = {} @@ -212,7 +213,7 @@ class Hud: game_params = config.get_game_parameters(self.poker_game) if not game_params['aux'] == "": aux_params = config.get_aux_parameters(game_params['aux']) - self.aux_windows.append(eval("%s.%s(gtk.Window(), config, 'fpdb')" % (aux_params['module'], aux_params['class']))) + self.aux_windows.append(eval("%s.%s(gtk.Window(), self, config, 'fpdb')" % (aux_params['module'], aux_params['class']))) def update(self, hand, config, stat_dict): self.hand = hand # this is the last hand, so it is available later diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index e220bf32..aeb77103 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -22,14 +22,9 @@ Mucked cards display for FreePokerTools HUD. ######################################################################## # to do -# problem with hand 30586 # Standard Library modules import sys -import os -import string -import xml.dom.minidom -from xml.dom.minidom import Node # pyGTK modules import pygtk @@ -39,28 +34,30 @@ import gobject # FreePokerTools modules import Configuration import Database -import Tables -import Hud -import HandHistory class Aux_Window: - def __init__(self, parent, config, db_name): + def __init__(self, parent, hud, config, db_name): + self.config = hud self.config = config - self.parent = parent #this is the parent of the mucked cards widget + self.parent = parent self.db_name = db_name self.vbox = gtk.VBox() self.parent.add(self.vbox) - def update(self): + def update_data(self): + pass + + def update_gui(self): pass class Stud_mucked(Aux_Window): - def __init__(self, parent, config, db_name): + def __init__(self, parent, hud, config, db_name): - self.config = config - self.parent = parent #this is the parent of the mucked cards widget - self.db_name = db_name + self.hud = hud # hud object that this aux window supports + self.config = config # configuration object for this aux window to use + self.parent = parent # parent container for this aux window widget + self.db_name = db_name # database for this aux window to use self.vbox = gtk.VBox() self.parent.add(self.vbox) @@ -71,9 +68,11 @@ class Stud_mucked(Aux_Window): self.parent.show_all() def update_data(self, new_hand_id): + self.mucked_cards.update_data(new_hand_id) self.mucked_list.update_data(new_hand_id) def update_gui(self, new_hand_id): + self.mucked_cards.update_gui(new_hand_id) self.mucked_list.update_gui(new_hand_id) class Stud_list: @@ -89,16 +88,18 @@ class Stud_list: self.parent.add(self.scrolled_window) # create a ListStore to use as the model - self.liststore = gtk.ListStore(str, str, str) + self.liststore = gtk.ListStore(str, str, str, str) self.treeview = gtk.TreeView(self.liststore) self.tvcolumn0 = gtk.TreeViewColumn('HandID') self.tvcolumn1 = gtk.TreeViewColumn('Cards') self.tvcolumn2 = gtk.TreeViewColumn('Net') + self.tvcolumn3 = gtk.TreeViewColumn('Winner') # add tvcolumn to treeview self.treeview.append_column(self.tvcolumn0) self.treeview.append_column(self.tvcolumn1) self.treeview.append_column(self.tvcolumn2) + self.treeview.append_column(self.tvcolumn3) # create a CellRendererText to render the data self.cell = gtk.CellRendererText() @@ -107,11 +108,16 @@ class Stud_list: self.tvcolumn0.pack_start(self.cell, True) self.tvcolumn1.pack_start(self.cell, True) self.tvcolumn2.pack_start(self.cell, True) + self.tvcolumn3.pack_start(self.cell, True) self.tvcolumn0.add_attribute(self.cell, 'text', 0) self.tvcolumn1.add_attribute(self.cell, 'text', 1) self.tvcolumn2.add_attribute(self.cell, 'text', 2) + self.tvcolumn3.add_attribute(self.cell, 'text', 3) # resize the cols if nec self.tvcolumn0.set_resizable(True) + self.tvcolumn1.set_resizable(True) + self.tvcolumn2.set_resizable(True) + self.tvcolumn3.set_resizable(True) self.treeview.connect("row-activated", self.activated_event) self.scrolled_window.add_with_viewport(self.treeview) @@ -119,22 +125,25 @@ class Stud_list: def activated_event(self, path, column, data=None): sel = self.treeview.get_selection() (model, iter) = sel.get_selected() - self.mucked_cards.update(model.get_value(iter, 0)) - - def update(self, new_hand_id): -# info_row = self.db_connection.get_hand_info(new_hand_id) - info_row = ((new_hand_id, "xxxx", 0), ) - iter = self.liststore.append(info_row[0]) - sel = self.treeview.get_selection() - sel.select_iter(iter) - - vadj = self.scrolled_window.get_vadjustment() - vadj.set_value(vadj.upper) - self.mucked_cards.update(new_hand_id) + self.mucked_cards.update_data(model.get_value(iter, 0)) + self.mucked_cards.update_gui(model.get_value(iter, 0)) def update_data(self, new_hand_id): - self.info_row = ((new_hand_id, "xxxx", 0), ) - self.mucked_cards.update_data(new_hand_id) + """Updates the data needed for the list box.""" + + db_connection = Database.Database(self.config, 'fpdb', '') + self.winners = db_connection.get_winners_from_hand(new_hand_id) + db_connection.close_connection() + pot = 0 + winners = '' + for player in self.winners.keys(): + pot = pot + int(self.winners[player]) + if not winners == '': + winners = winners + ", " + winners = winners + player + pot_dec = "%.2f" % (float(pot)/100) + + self.info_row = ((new_hand_id, "xxxx", pot_dec, winners), ) def update_gui(self, new_hand_id): iter = self.liststore.append(self.info_row[0]) @@ -143,7 +152,6 @@ class Stud_list: vadj = self.scrolled_window.get_vadjustment() vadj.set_value(vadj.upper) - self.mucked_cards.update_gui(new_hand_id) class Stud_cards: def __init__(self, parent, config, db_name = 'fpdb'): @@ -204,46 +212,6 @@ class Stud_cards: old_cards[c][key] = ranks[old_cards[c][rank]] + old_cards[c][suit] return old_cards - def update(self, new_hand_id): - db_connection = Database.Database(self.config, 'fpdb', '') - cards = db_connection.get_cards(new_hand_id) - self.clear() - cards = self.translate_cards(cards) - for c in cards.keys(): - self.grid_contents[(1, cards[c]['seat_number'] - 1)].set_text(cards[c]['screen_name']) - for i in ((0, 'hole_card_1'), (1, 'hole_card_2'), (2, 'hole_card_3'), (3, 'hole_card_4'), - (4, 'hole_card_5'), (5, 'hole_card_6'), (6, 'hole_card_7')): - if not cards[c][i[1]] == "xx": - self.seen_cards[(i[0], cards[c]['seat_number'] - 1)]. \ - set_from_pixbuf(self.card_images[self.split_cards(cards[c][i[1]])]) - - tips = [] - action = db_connection.get_action_from_hand(new_hand_id) - for street in action: - temp = '' - for act in street: - temp = temp + act[0] + " " + act[1] + "s " - if act[2] > 0: - if act[2]%100 > 0: - temp = temp + "%4.2f\n" % (float(act[2])/100) - else: - temp = temp + "%d\n" % (act[2]/100) - else: - temp = temp + "\n" - tips.append(temp) - -## action in tool tips for 3rd street cards - for c in (0, 1, 2): - for r in range(0, self.rows): - self.eb[(c, r)].set_tooltip_text(tips[0]) - -# action in tools tips for later streets - round_to_col = (0, 3, 4, 5, 6) - for round in range(1, len(tips)): - for r in range(0, self.rows): - self.eb[(round_to_col[round], r)].set_tooltip_text(tips[round]) - db_connection.close_connection() - def update_data(self, new_hand_id): db_connection = Database.Database(self.config, 'fpdb', '') cards = db_connection.get_cards(new_hand_id) @@ -330,7 +298,7 @@ if __name__== "__main__": main_window.connect("destroy", destroy) aux_to_call = "Stud_mucked" - m = eval("%s(main_window, config, 'fpdb')" % aux_to_call) + m = eval("%s(main_window, None, config, 'fpdb')" % aux_to_call) main_window.show_all() s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 45b0c60f..724ba8ed 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -320,6 +320,14 @@ class Sql: """ # WHERE handId = %s AND Players.id LIKE %s + self.query['get_winners_from_hand'] = """ + SELECT name, winnings + FROM HandsPlayers, Players + WHERE winnings > 0 + AND Players.id = HandsPlayers.playerId + AND handId = %s; + """ + self.query['get_table_name'] = """ select tableName, maxSeats, category from Hands,Gametypes diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index 9f5360e2..3e7bacc6 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -429,8 +429,8 @@ def discover_mac_by_name(c, tablename): if __name__=="__main__": c = Configuration.Config() - print discover_table_by_name(c, "Howard Lederer") - print discover_tournament_table(c, "118942908", "3") + print discover_table_by_name(c, "Daddy Nasty") +# print discover_tournament_table(c, "118942908", "3") tables = discover(c) for t in tables.keys(): From 2d6412c8a797ffaa8bc85a998cb277b611e969d1 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Tue, 9 Dec 2008 15:32:37 +0000 Subject: [PATCH 02/27] pseudo stars! --- pyfpdb/EverleafToFpdb.py | 7 ++ pyfpdb/HandHistoryConverter.py | 114 +++++++++++---------------------- 2 files changed, 46 insertions(+), 75 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index 1a1196c5..a5aa5514 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -79,6 +79,7 @@ class Everleaf(HandHistoryConverter): self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P.*)\s\[ (?P\S\S), (?P\S\S) \]') self.rexx.setActionStepRegex('.*\n(?P.*) (?Pbets|checks|raises|calls|folds)(\s\[\$ (?P[.\d]+) USD\])?') self.rexx.setShowdownActionRegex('.*\n(?P.*) shows \[ (?P.*) \]') + self.rexx.setCollectPotRegex('.*\n(?P.*) wins \$ (?P[.\d]+) USD.*') self.rexx.compileRegexes() def readSupportedGames(self): @@ -184,6 +185,12 @@ class Everleaf(HandHistoryConverter): print cards hand.addHoleCards(cards, shows.group('PNAME')) + def readCollectPot(self,hand): + m = self.rexx.collect_pot_re.search(hand.string) + print m.groups() + print m.group('PNAME') + #for collection in m: + hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT')) def getRake(self, hand): hand.rake = hand.totalpot * Decimal('0.05') # probably not quite right diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 06a59064..5e6804c5 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -78,6 +78,8 @@ class HandHistoryConverter: for street in hand.streets.groupdict(): self.readAction(hand, street) + self.readCollectPot(hand) + # finalise it (total the pot) hand.totalPot() self.getRake(hand) @@ -124,6 +126,7 @@ class HandHistoryConverter: def readBlinds(self, hand): abstract def readHeroCards(self, hand): abstract def readAction(self, hand, street): abstract + def readCollectPot(self, hand): abstract # Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated # so that an inheriting class can calculate it for the specific site if need be. @@ -177,66 +180,6 @@ class HandHistoryConverter: except: traceback.print_exc(file=sys.stderr) - def writeHand(self, file, hand): - """Write out parsed data""" - print "DEBUG: *************************" - print "DEBUG: Start of print hand" - print "DEBUG: *************************" - - print "%s Game #%s: %s ($%s/$%s) - %s" %(hand.sitename, hand.handid, "XXXXhand.gametype", hand.sb, hand.bb, hand.starttime) - print "Table '%s' %d-max Seat #%s is the button" %(hand.tablename, hand.maxseats, hand.buttonpos) - - for player in hand.players: - print "Seat %s: %s ($%s)" %(player[0], player[1], player[2]) - - if(hand.posted[0] == "FpdbNBP"): - print "No small blind posted" - else: - print "%s: posts small blind $%s" %(hand.posted[0], hand.sb) - - #May be more than 1 bb posting - print "%s: posts big blind $%s" %(hand.posted[1], hand.bb) - if(len(hand.posted) > 2): - # Need to loop on all remaining big blinds - lazy - print "XXXXXXXXX FIXME XXXXXXXX" - - print "*** HOLE CARDS ***" - print "Dealt to %s [%s %s]" %(hand.hero , hand.holecards[0], hand.holecards[1]) - - for act in hand.actions['PREFLOP']: - self.printActionLine(act, 0) - - if 'PREFLOP' in hand.actions: - for act in hand.actions['PREFLOP']: - print "PF action" - - if 'FLOP' in hand.actions: - print "*** FLOP *** [%s %s %s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3")) - for act in hand.actions['FLOP']: - self.printActionLine(act, 0) - - if 'TURN' in hand.actions: - print "*** TURN *** [%s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1")) - for act in hand.actions['TURN']: - self.printActionLine(act, 0) - - if 'RIVER' in hand.actions: - print "*** RIVER *** [%s %s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"), hand.streets.group("RIVER1")) - for act in hand.actions['RIVER']: - self.printActionLine(act, 0) - - print "*** SUMMARY ***" - print "XXXXXXXXXXXX Need sumary info XXXXXXXXXXX" - - - def printActionLine(self, act, pot): - if act[1] == 'folds' or act[1] == 'checks': - print "%s: %s " %(act[0], act[1]) - if act[1] == 'calls': - print "%s: %s $%s" %(act[0], act[1], act[2]) - if act[1] == 'raises': - print "%s: %s $%s to XXXpottotalXXX" %(act[0], act[1], act[2]) - #takes a poker float (including , for thousand seperator and converts it to an int def float2int (self, string): @@ -282,6 +225,7 @@ class Hand: self.hero = "Hiro" self.holecards = {} # dict from player names to lists of hole cards self.board = {} # dict from street names to community cards + self.collected = {} # dict from player names to amounts collected self.action = [] self.totalpot = None @@ -373,7 +317,16 @@ class Hand: self.bets[street][name].append(Decimal(amount)) self.orderedBets[street].append(Decimal(amount)) self.actions[street] += [[player, 'bets', amount]] - + + def addCollectPot(self,player, pot): + if player not in self.collected: + self.collected[player] = pot + else: + # possibly lines like "p collected $ from pot" appear during the showdown + # but they are usually unique in the summary. + print "%s collected pot more than once; avoidable by reading winnings only from summary lines?" + + def totalPot(self): """If all bets and blinds have been added, totals up the total pot size Known bug: doesn't take into account side pots""" @@ -443,16 +396,29 @@ Known bug: doesn't take into account side pots""" #print self.board for player in self.players: - if self.holecards[player[1]]: # empty list default is false - hole = self.holecards[player[1]] - #print self.board.values() - board = [] - for s in self.board.values(): - board += s - playerhand = self.bestHand('hi', board+hole) - print "Seat %d: %s showed %s and won/lost with %s" % (player[0], player[1], hole, playerhand) + if player[1] in self.collected and self.holecards[player[1]]: + print "Seat %d: %s showed [%s %s] and won ($%s)" % (player[0], player[1], self.holecards[player[1]][0], self.holecards[player[1]][1], self.collected[player[1]]) + elif player[1] in self.collected: + print "Seat %d: %s collected ($%s)" % (player[0], player[1], self.collected[player[1]]) + elif self.holecards[player[1]]: + print "Seat %d: %s showed [%s %s]" % (player[0], player[1], self.holecards[player[1]][0], self.holecards[player[1]][1]) else: - print "Seat %d: %s mucked or folded" % (player[0], player[1]) + print "Seat %d: %s folded (or mucked..)" % (player[0], player[1]) + + # TODO: + # logic for side pots + # logic for which players get to showdown + # I'm just not sure we need to do this so heavily.. and if we do, it's probably better to use pokerlib + #if self.holecards[player[1]]: # empty list default is false + #hole = self.holecards[player[1]] + ##board = [] + ##for s in self.board.values(): + ##board += s + ##playerhand = self.bestHand('hi', board+hole) + ##print "Seat %d: %s showed %s and won/lost with %s" % (player[0], player[1], hole, playerhand) + #print "Seat %d: %s showed %s" % (player[0], player[1], hole) + #else: + #print "Seat %d: %s mucked or folded" % (player[0], player[1]) def printActionLine(self, act): @@ -463,10 +429,8 @@ Known bug: doesn't take into account side pots""" if act[1] == 'raises': print "%s: %s $%s to $%s" %(act[0], act[1], act[2], act[3]) - # going to use pokereval to figure out hands + # going to use pokereval to figure out hands at some point. # these functions are copied from pokergame.py - # im thinking perhaps its best to use all the functionality of pokergame instead - # of reinventing the wheel def bestHand(self, side, cards): #if self.variant == "omaha" or self.variant == "omaha8": #hand = self.serial2player[serial].hand.tolist(True) @@ -477,13 +441,13 @@ Known bug: doesn't take into account side pots""" print cards return HandHistoryConverter.eval.best('hi', cards, []) + # from pokergame.py def bestHandValue(self, side, serial): (value, cards) = self.bestHand(side, serial) return value - + # from pokergame.py def readableHandValueLong(self, side, value, cards): - cards = self.eval.card2string(cards) if value == "NoPair": if side == "low": if cards[0][0] == '5': From 7ac433fede89103c91b84447318b2c2f9a0f6105 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Tue, 9 Dec 2008 15:35:16 +0000 Subject: [PATCH 03/27] 2 decimal places for rake --- pyfpdb/HandHistoryConverter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 5e6804c5..63b51bb0 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -391,7 +391,7 @@ Known bug: doesn't take into account side pots""" print "what do they show" print "*** SUMMARY ***" - print "Total pot $%s | Rake $%s)" % (self.totalpot, self.rake) + print "Total pot $%s | Rake $%.2f)" % (self.totalpot, self.rake) # TODO side pots print "Board [%s %s %s %s %s]" % (self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1")) #print self.board From 6b0dcc37d42ecea4f1f23b337e74709cd5f34c1a Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Tue, 9 Dec 2008 23:30:58 +0000 Subject: [PATCH 04/27] I set it up with Speed_Kuala_full.txt and now it's time to go through them all fixing the bugs. --- pyfpdb/EverleafToFpdb.py | 38 ++++++++++++---- pyfpdb/HandHistoryConverter.py | 82 ++++++++++++++++++++++++++-------- 2 files changed, 94 insertions(+), 26 deletions(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index a5aa5514..e1f9bcbf 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -70,7 +70,7 @@ class Everleaf(HandHistoryConverter): self.sitename = "Everleaf" self.setFileType("text") self.rexx.setGameInfoRegex('.*Blinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+)') - self.rexx.setSplitHandRegex('\n\n\n\n') + self.rexx.setSplitHandRegex('\n\n+') self.rexx.setHandInfoRegex('.*#(?P[0-9]+)\n.*\nBlinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+) (?P.*) - (?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+) - (?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)\nTable (?P[ a-zA-Z]+)\nSeat (?P
[ a-zA-Z]+)\nSeat (?P
[ a-zA-Z]+)\nSeat (?P