From 5611f115cddeae2948a2e538860a7d15baf114b1 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 30 Jun 2009 18:32:30 +0800 Subject: [PATCH 01/73] Remove DEBUG line that wasn't supposed to make the last commit --- pyfpdb/Hand.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 38c3609b..61e06930 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -202,7 +202,6 @@ If a player has None chips he won't be added.""" def setCommunityCards(self, street, cards): logging.debug("setCommunityCards %s %s" %(street, cards)) self.board[street] = [self.card(c) for c in cards] - print "DEBUG: self.board: %s" % self.board def card(self,c): """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" From 3c438a92985881430a5705d2705237f021a11c83 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 30 Jun 2009 18:32:58 +0800 Subject: [PATCH 02/73] Make site selection behave like other options --- pyfpdb/GuiGraphViewer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index cec91e61..2dfb0173 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -154,7 +154,7 @@ class GuiGraphViewer (threading.Thread): if not sitenos: #Should probably pop up here. print "No sites selected - defaulting to PokerStars" - sitenos = [2] + return if not playerids: print "No player ids found" From 79d0ba35b0294782567dfa3648bd7f5d4bde616c Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 14 Jul 2009 06:39:49 +0800 Subject: [PATCH 03/73] Initial commit of BossMedia importer. Contributed by Thomas Wigele (twigele gmail com - star-fox on sourceforge) Sample HH - http://www.pastebin.ca/1490652 --- pyfpdb/Win2dayToFpdb.py | 384 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 pyfpdb/Win2dayToFpdb.py diff --git a/pyfpdb/Win2dayToFpdb.py b/pyfpdb/Win2dayToFpdb.py new file mode 100644 index 00000000..0417dcb1 --- /dev/null +++ b/pyfpdb/Win2dayToFpdb.py @@ -0,0 +1,384 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2008, Carl Gherardi +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +######################################################################## + +import sys +from HandHistoryConverter import * + +# Win2day HH Format + +class Win2day(HandHistoryConverter): + + # Static regexes + # + + #'^$' + re_GameInfo = re.compile('^', re.MULTILINE) + re_SplitHands = re.compile('') + re_HandInfo = re.compile("^Table \'(?P[- a-zA-Z]+)\'(?P.+?$)?", re.MULTILINE) + re_Button = re.compile('\n\n\n + re_PlayerInfo = re.compile('^', re.MULTILINE) + re_Card = re.compile('^', re.MULTILINE) + re_BoardLast = re.compile('^', re.MULTILINE) + + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): + HandHistoryConverter.__init__(self, in_path, out_path, sitename="Win2day", follow=follow) + logging.info("Initialising Win2day converter class") + self.filetype = "text" + self.codepage = "cp1252" + self.sideID = 4 + if autostart: + self.start() + + + def compilePlayerRegexs(self, hand): + players = set([player[1] for player in hand.players]) + if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' + # we need to recompile the player regexs. + self.compiledPlayers = players + player_re = "(?P" + "|".join(map(re.escape, players)) + ")" + logging.debug("player_re: " + player_re) + # + + self.re_PostSB = re.compile(r'^' % player_re, re.MULTILINE) + self.re_PostBB = re.compile(r'^' % player_re, re.MULTILINE) + self.re_Antes = re.compile(r"^%s: posts the ante \$?(?P[.0-9]+)" % player_re, re.MULTILINE) + self.re_BringIn = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P[.0-9]+)" % player_re, re.MULTILINE) + self.re_PostBoth = re.compile(r'^' % player_re, re.MULTILINE) + + #r'\n\n' + self.re_HeroCards = re.compile(r'\n(?P\n)' % player_re, re.MULTILINE) + + #'^' + self.re_Action = re.compile(r'^' % player_re, re.MULTILINE) + + self.re_ShowdownAction = re.compile(r'\n(?P\n)' % player_re, re.MULTILINE) + # + # + self.re_CollectPot = re.compile(r'' % player_re, re.MULTILINE) + self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE) + self.re_ShownCards = re.compile("^Seat (?P[0-9]+): %s \(.*\) showed \[(?P.*)\].*" % player_re, re.MULTILINE) + + + def readSupportedGames(self): + return [["ring", "hold", "nl"], + ["ring", "hold", "pl"], + ["ring", "hold", "fl"], + ["ring", "stud", "fl"], + ["ring", "draw", "fl"], + ["ring", "omaha", "pl"] + ] + + def determineGameType(self, handText): + info = {'type':'ring'} + + m = self.re_GameInfo.search(handText) + if not m: + print "determineGameType:", handText + return None + + mg = m.groupdict() + + # translations from captured groups to our info strings + #limits = { 'NL':'nl', 'PL':'pl', 'Limit':'fl' } + limits = { 'NL':'nl', 'PL':'pl'} + games = { # base, category + "GAME_THM" : ('hold','holdem'), + # 'Omaha' : ('hold','omahahi'), + #'Omaha Hi/Lo' : ('hold','omahahilo'), + # 'Razz' : ('stud','razz'), + #'7 Card Stud' : ('stud','studhi'), + # 'Badugi' : ('draw','badugi') + } + if 'LIMIT' in mg: + info['limitType'] = limits[mg['LIMIT']] + if 'GAME' in mg: + (info['base'], info['category']) = games[mg['GAME']] + if 'SB' in mg: + info['sb'] = mg['SB'] + if 'BB' in mg: + info['bb'] = mg['BB'] + if 'CURRENCY' in mg: + info['currency'] = mg['CURRENCY'] + # NB: SB, BB must be interpreted as blinds or bets depending on limit type. + + return info + + + def readHandInfo(self, hand): + info = {} + m = self.re_HandInfo.search(hand.handText,re.DOTALL) + if m: + info.update(m.groupdict()) + # TODO: Be less lazy and parse maxseats from the HandInfo regex + if m.group('TABLEATTRIBUTES'): + m2 = re.search("\s*(\d+)-max", m.group('TABLEATTRIBUTES')) + hand.maxseats = int(m2.group(1)) + m = self.re_GameInfo.search(hand.handText) + if m: info.update(m.groupdict()) + m = self.re_Button.search(hand.handText) + if m: info.update(m.groupdict()) + # TODO : I rather like the idea of just having this dict as hand.info + logging.debug("readHandInfo: %s" % info) + for key in info: + if key == 'DATETIME': + # Win2day uses UTC timestamp + # 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(time.gmtime(info[key])) + # hand.starttime = time.gmtime(int(info[key])) + hand.starttime = time.gmtime(int(info[key])) + if key == 'HID': + hand.handid = info[key] + if key == 'TABLE': + hand.tablename = info[key] + if key == 'BUTTON': + hand.buttonpos = info[key] + + def readButton(self, hand): + m = self.re_Button.search(hand.handText) + if m: + for player in hand.players: + if player[1] == m.group('BUTTON'): + hand.buttonpos = player[0] + break + else: + logging.info('readButton: not found') + + def readPlayerStacks(self, hand): + logging.debug("readPlayerStacks") + m = self.re_PlayerInfo.finditer(hand.handText) + players = [] + for a in m: + hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH')) + + def markStreets(self, hand): + # PREFLOP = ** Dealing down cards ** + # This re fails if, say, river is missing; then we don't get the ** that starts the river. + if hand.gametype['base'] in ("hold"): + #m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P.+(?=\*\*\* FLOP \*\*\*)|.+)" + # r"(\*\*\* FLOP \*\*\*(?P \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?" + # r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?" + # r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P\[\S\S\].+))?", hand.handText,re.DOTALL) + + m = re.search('(?P.+(?=.+(?=.+(?=.+(?= 38): + retCard += 's' + elif(card > 25): + retCard += 'h' + elif(card > 12): + retCard += 'c' + else: + retCard += 'd' + + return(retCard) + + def readDrawCards(self, hand, street): + logging.debug("readDrawCards") + m = self.re_HeroCards.finditer(hand.streets[street]) + if m == None: + hand.involved = False + else: + for player in m: + hand.hero = player.group('PNAME') # Only really need to do this once + newcards = player.group('NEWCARDS') + oldcards = player.group('OLDCARDS') + if newcards == None: + newcards = set() + else: + newcards = set(newcards.split(' ')) + if oldcards == None: + oldcards = set() + else: + oldcards = set(oldcards.split(' ')) + hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) + + + def readStudPlayerCards(self, hand, street): + # See comments of reference implementation in FullTiltToFpdb.py + logging.debug("readStudPlayerCards") + m = self.re_HeroCards.finditer(hand.streets[street]) + for player in m: + #~ logging.debug(player.groupdict()) + (pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS')) + if oldcards: + oldcards = [c.strip() for c in oldcards.split(' ')] + if newcards: + newcards = [c.strip() for c in newcards.split(' ')] + if street=='ANTES': + return + elif street=='THIRD': + # we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS' + # hero: [xx][o] + # others: [o] + hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards) + elif street in ('FOURTH', 'FIFTH', 'SIXTH'): + # 4th: + # hero: [xxo] [o] + # others: [o] [o] + # 5th: + # hero: [xxoo] [o] + # others: [oo] [o] + # 6th: + # hero: [xxooo] [o] + # others: [ooo] [o] + hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards) + # we may additionally want to check the earlier streets tally with what we have but lets trust it for now. + elif street=='SEVENTH' and newcards: + # hero: [xxoooo] [x] + # others: not reported. + hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards) + + def readAction(self, hand, street): + m = self.re_Action.finditer(hand.streets[street]) + for action in m: + if action.group('ATYPE') == 'ACTION_RAISE': + hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') ) + elif action.group('ATYPE') == 'ACTION_CALL': + hand.addCall( street, action.group('PNAME'), action.group('BET') ) + elif action.group('ATYPE') == 'ACTION_ALLIN': + hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') ) + elif action.group('ATYPE') == 'ACTION_BET': + hand.addBet( street, action.group('PNAME'), action.group('BET') ) + elif action.group('ATYPE') == 'ACTION_FOLD': + hand.addFold( street, action.group('PNAME')) + elif action.group('ATYPE') == 'ACTION_CHECK': + hand.addCheck( street, action.group('PNAME')) + elif action.group('ATYPE') == 'ACTION_DISCARD': + hand.addDiscard(street, action.group('PNAME'), action.group('NODISCARDED'), action.group('DISCARDED')) + elif action.group('ATYPE') == 'ACTION_STAND': + hand.addStandsPat( street, action.group('PNAME')) + else: + print "DEBUG: unimplemented readAction: '%s' '%s'" %(action.group('PNAME'),action.group('ATYPE'),) + + + def readShowdownActions(self, hand): + for shows in self.re_ShowdownAction.finditer(hand.handText): + showdownCards = set([]) + for card in self.re_Card.finditer(shows.group('CARDS')): + print "DEBUG:", card, card.group('CARD'), self.convertWin2dayCards(card.group('CARD')) + showdownCards.add(self.convertWin2dayCards(card.group('CARD'))) + + hand.addShownCards(showdownCards, shows.group('PNAME')) + + def readCollectPot(self,hand): + for m in self.re_CollectPot.finditer(hand.handText): + potcoll = Decimal(m.group('POT')) + if potcoll > 0: + hand.addCollectPot(player=m.group('PNAME'),pot=potcoll) + + def readShownCards(self,hand): + for m in self.re_ShownCards.finditer(hand.handText): + if m.group('CARDS') is not None: + cards = m.group('CARDS') + cards = set(cards.split(' ')) + hand.addShownCards(cards=cards, player=m.group('PNAME')) + +if __name__ == "__main__": + parser = OptionParser() + parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="-") + parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-") + parser.add_option("-f", "--follow", dest="follow", help="follow (tail -f) the input", action="store_true", default=False) + parser.add_option("-q", "--quiet", + action="store_const", const=logging.CRITICAL, dest="verbosity", default=logging.INFO) + parser.add_option("-v", "--verbose", + action="store_const", const=logging.INFO, dest="verbosity") + parser.add_option("--vv", + action="store_const", const=logging.DEBUG, dest="verbosity") + + (options, args) = parser.parse_args() + + LOG_FILENAME = './logging.out' + logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity) + + e = Win2day(in_path = options.ipath, out_path = options.opath, follow = options.follow) From dc6a1c45f9fae72155dde1dc97dd404dc459a4a8 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Tue, 14 Jul 2009 00:04:10 +0100 Subject: [PATCH 04/73] sqlite - connecting and (re)creating some tables --- pyfpdb/Configuration.py | 2 + pyfpdb/FpdbSQLQueries.py | 66 +++++++++++++++--- pyfpdb/fpdb.py | 8 ++- pyfpdb/fpdb_db.py | 144 ++++++++++++++++++++++++++++----------- pyfpdb/fpdb_import.py | 1 + 5 files changed, 170 insertions(+), 51 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 0ea4b371..27e06b3d 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -493,6 +493,8 @@ class Config: db['db-backend'] = 2 elif string.lower(self.supported_databases[name].db_server) == 'postgresql': db['db-backend'] = 3 + elif string.lower(self.supported_databases[name].db_server) == 'sqlite': + db['db-backend'] = 4 else: db['db-backend'] = None # this is big trouble return db diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py index 598c0868..b7e5679e 100644 --- a/pyfpdb/FpdbSQLQueries.py +++ b/pyfpdb/FpdbSQLQueries.py @@ -38,7 +38,9 @@ class FpdbSQLQueries: elif(self.dbname == 'PostgreSQL'): self.query['list_tables'] = """SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'""" elif(self.dbname == 'SQLite'): - self.query['list_tables'] = """ """ + self.query['list_tables'] = """SELECT name FROM sqlite_master + WHERE type='table' + ORDER BY name;""" ################################################################## # Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax @@ -63,8 +65,8 @@ class FpdbSQLQueries: self.query['createSettingsTable'] = """CREATE TABLE Settings (version SMALLINT)""" elif(self.dbname == 'SQLite'): - #Probably doesn't work. - self.query['createSettingsTable'] = """ """ + self.query['createSettingsTable'] = """CREATE TABLE Settings + (version INTEGER) """ ################################ @@ -83,7 +85,10 @@ class FpdbSQLQueries: name varchar(32), currency char(3))""" elif(self.dbname == 'SQLite'): - self.query['createSitesTable'] = """ """ + self.query['createSitesTable'] = """CREATE TABLE Sites ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + currency TEXT NOT NULL)""" ################################ @@ -118,7 +123,19 @@ class FpdbSQLQueries: smallBet int, bigBet int)""" elif(self.dbname == 'SQLite'): - self.query['createGametypesTable'] = """ """ + self.query['createGametypesTable'] = """CREATE TABLE GameTypes ( + id INTEGER PRIMARY KEY, + siteId INTEGER, + type TEXT, + base TEXT, + category TEXT, + limitType TEXT, + hiLo TEXT, + smallBlind INTEGER, + bigBlind INTEGER, + smallBet INTEGER, + bigBet INTEGER, + FOREIGN KEY(siteId) REFERENCES Sites(id) ON DELETE CASCADE)""" ################################ @@ -141,7 +158,13 @@ class FpdbSQLQueries: comment text, commentTs timestamp without time zone)""" elif(self.dbname == 'SQLite'): - self.query['createPlayersTable'] = """ """ + self.query['createPlayersTable'] = """CREATE TABLE Players ( + id INTEGER PRIMARY KEY, + name TEXT, + siteId INTEGER, + comment TEXT, + commentTs BLOB, + FOREIGN KEY(siteId) REFERENCES Sites(id) ON DELETE CASCADE)""" ################################ @@ -245,11 +268,22 @@ class FpdbSQLQueries: comment TEXT, commentTs timestamp without time zone)""" elif(self.dbname == 'SQLite'): - self.query['createHandsTable'] = """ """ + self.query['createHandsTable'] = """CREATE TABLE Hands ( + id INTEGER PRIMARY KEY, + tableName TEXT(20), + siteHandNo INTEGER, + gametypeId INTEGER, + handStart BLOB, + importTime BLOB, + seats INTEGER, + maxSeats INTEGER, + comment TEXT, + commentTs BLOB, + FOREIGN KEY(gametypeId) REFERENCES Gametypes(id) ON DELETE CASCADE)""" ################################ - # Create Gametypes + # Create BoardCards ################################ if(self.dbname == 'MySQL InnoDB'): @@ -336,7 +370,14 @@ class FpdbSQLQueries: comment TEXT, commentTs timestamp without time zone)""" elif(self.dbname == 'SQLite'): - self.query['createTourneysTable'] = """ """ + self.query['createTourneysTable'] = """CREATE TABLE TourneyTypes ( + id INTEGER PRIMARY KEY, + siteId INTEGER, + buyin INTEGER, + fee INTEGER, + knockout INTEGER, + rebuyOrAddon BOOL, + FOREIGN KEY(siteId) REFERENCES Sites(id) ON DELETE CASCADE)""" ################################ # Create HandsPlayers @@ -869,6 +910,13 @@ class FpdbSQLQueries: elif(self.dbname == 'SQLite'): self.query['addPlayersIndex'] = """ """ + + if(self.dbname == 'MySQL InnoDB' or self.dbname == 'PostgreSQL'): + self.query['set tx level'] = """SET SESSION TRANSACTION + ISOLATION LEVEL READ COMMITTED""" + elif(self.dbname == 'SQLite'): + self.query['set tx level'] = """ """ + ################################ # Queries used in GuiGraphViewer ################################ diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index b03e8424..61f5f111 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -19,7 +19,6 @@ import os import sys import Options import string - cl_options = string.join(sys.argv[1:]) (options, sys.argv) = Options.fpdb_options() @@ -28,6 +27,8 @@ if not options.errorsToConsole: errorFile = open('fpdb-error-log.txt', 'w', 0) sys.stderr = errorFile +import logging + import pygtk pygtk.require('2.0') import gtk @@ -481,6 +482,11 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") #end def tabGraphViewer def __init__(self): + LOG_FILENAME = './logging.out' + LOG_FORMAT = "%(asctime)-15s %(levelname)-8s %(message)s" + logging.basicConfig(filename=LOG_FILENAME,level=10,format=LOG_FORMAT) + logging.info("Fpdb started") + self.threads=[] self.db=None self.config = Configuration.Config(file=options.config, dbname=options.dbname) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 29817af9..c52a2e56 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -18,20 +18,21 @@ import os import re import sys +import logging from time import time, strftime import fpdb_simple import FpdbSQLQueries class fpdb_db: + MYSQL_INNODB = 2 + PGSQL = 3 + SQLITE = 4 def __init__(self): """Simple constructor, doesnt really do anything""" self.db = None self.cursor = None self.sql = {} - self.MYSQL_INNODB = 2 - self.PGSQL = 3 - self.SQLITE = 4 # Data Structures for index and foreign key creation # drop_code is an int with possible values: 0 - don't drop for bulk import @@ -72,6 +73,8 @@ class fpdb_db: , {'tab':'TourneysPlayers', 'col':'tourneyId', 'drop':0} , {'tab':'TourneyTypes', 'col':'siteId', 'drop':0} ] + , [ # indexes for sqlite (list index 4) + ] ] self.foreignKeys = [ @@ -146,12 +149,12 @@ class fpdb_db: self.settings = {} self.settings['os'] = "linuxmac" if os.name != "nt" else "windows" - self.settings.update(config.get_db_parameters()) - self.connect(self.settings['db-backend'], - self.settings['db-host'], - self.settings['db-databaseName'], - self.settings['db-user'], - self.settings['db-password']) + db = config.get_db_parameters() + self.connect(backend=db['db-backend'], + host=db['db-host'], + database=db['db-databaseName'], + user=db['db-user'], + password=db['db-password']) #end def do_connect def connect(self, backend=None, host=None, database=None, @@ -164,13 +167,13 @@ class fpdb_db: self.user=user self.password=password self.database=database - if backend==self.MYSQL_INNODB: + if backend==fpdb_db.MYSQL_INNODB: import MySQLdb try: self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) except: raise fpdb_simple.FpdbError("MySQL connection failed") - elif backend==self.PGSQL: + elif backend==fpdb_db.PGSQL: import psycopg2 import psycopg2.extensions psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) @@ -201,12 +204,19 @@ class fpdb_db: msg = "PostgreSQL connection to database (%s) user (%s) failed." % (database, user) print msg raise fpdb_simple.FpdbError(msg) + elif backend==fpdb_db.SQLITE: + logging.info("Connecting to SQLite:(%s)") + import sqlite3 + self.db = sqlite3.connect(database,detect_types=sqlite3.PARSE_DECLTYPES) + sqlite3.register_converter("bool", lambda x: bool(int(x))) + sqlite3.register_adapter(bool, lambda x: "1" if x else "0") + else: raise fpdb_simple.FpdbError("unrecognised database backend:"+backend) self.cursor=self.db.cursor() - self.cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED') # Set up query dictionary as early in the connection process as we can. self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name()) + self.cursor.execute(self.sql.query['set tx level']) self.wrongDbVersion=False try: self.cursor.execute("SELECT * FROM Settings") @@ -237,7 +247,9 @@ class fpdb_db: def create_tables(self): #todo: should detect and fail gracefully if tables already exist. + logging.debug(self.sql.query['createSettingsTable']) self.cursor.execute(self.sql.query['createSettingsTable']) + logging.debug(self.sql.query['createSitesTable']) self.cursor.execute(self.sql.query['createSitesTable']) self.cursor.execute(self.sql.query['createGametypesTable']) self.cursor.execute(self.sql.query['createPlayersTable']) @@ -275,10 +287,12 @@ class fpdb_db: for table in tables: self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade') elif(self.get_backend_name() == 'SQLite'): - #todo: sqlite version here - print "Empty function here" + self.cursor.execute(self.sql.query['list_tables']) + for table in self.cursor.fetchall(): + logging.debug(self.sql.query['drop_table'] + table[0]) + self.cursor.execute(self.sql.query['drop_table'] + table[0]) - self.db.commit() + self.db.commit() #end def drop_tables def drop_referential_integrity(self): @@ -307,6 +321,8 @@ class fpdb_db: return "MySQL InnoDB" elif self.backend==3: return "PostgreSQL" + elif self.backend==4: + return "SQLite" else: raise fpdb_simple.FpdbError("invalid backend") #end def get_backend_name @@ -316,11 +332,14 @@ class fpdb_db: #end def get_db_info def fillDefaultData(self): - self.cursor.execute("INSERT INTO Settings VALUES (118);") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');") - self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Everleaf', 'USD');") - self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") + logging.debug("INSERT INTO Settings (version) VALUES (118);") + self.cursor.execute("INSERT INTO Settings (version) VALUES (118);") + self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('Full Tilt Poker', 'USD')") + self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('PokerStars', 'USD')") + self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('Everleaf', 'USD')") + self.cursor.execute("""INSERT INTO TourneyTypes + (siteId,buyin,fee,knockout,rebuyOrAddon) VALUES + (1,0,0,0,?)""",(False,) ) #end def fillDefaultData def recreate_tables(self): @@ -617,7 +636,7 @@ class fpdb_db: ret = -1 else: ret = row[0] - elif self.backend == self.SQLITE: + elif self.backend == fpdb_db.SQLITE: # don't know how to do this in sqlite print "getLastInsertId(): not coded for sqlite yet" ret = -1 @@ -628,27 +647,70 @@ class fpdb_db: def storeHand(self, p): #stores into table hands: - self.cursor.execute ("""INSERT INTO Hands - (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats - ,boardcard1, boardcard2, boardcard3, boardcard4, boardcard5 - ,playersVpi, playersAtStreet1, playersAtStreet2 - ,playersAtStreet3, playersAtStreet4, playersAtShowdown - ,street0Raises, street1Raises, street2Raises - ,street3Raises, street4Raises, street1Pot - ,street2Pot, street3Pot, street4Pot - ,showdownPot + self.cursor.execute ("""INSERT INTO Hands ( + tablename, + sitehandno, + gametypeid, + handstart, + importtime, + seats, + maxseats, + boardcard1, + boardcard2, + boardcard3, + boardcard4, + boardcard5, +-- texture, + playersVpi, + playersAtStreet1, + playersAtStreet2, + playersAtStreet3, + playersAtStreet4, + playersAtShowdown, + street0Raises, + street1Raises, + street2Raises, + street3Raises, + street4Raises, +-- street1Pot, +-- street2Pot, +-- street3Pot, +-- street4Pot, +-- showdownPot ) VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" - ,(p['siteHandNo'], gametype_id, p['handStart'], len(names), p['tableName'], datetime.datetime.today(), p['maxSeats'] - ,p['boardcard1'], ['boardcard2'], p['boardcard3'], ['boardcard4'], ['boardcard5'] - ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] - ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] - ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] - ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] - ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] - ,hudCache['showdownPot'] - ) - ) + (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s)""", + ( + p['tablename'], + p['sitehandno'], + p['gametypeid'], + p['handStart'], + datetime.datetime.today(), + len(p['names']), + p['maxSeats'], + p['boardcard1'], + p['boardcard2'], + p['boardcard3'], + p['boardcard4'], + p['boardcard5'], + hudCache['playersVpi'], + hudCache['playersAtStreet1'], + hudCache['playersAtStreet2'], + hudCache['playersAtStreet3'], + hudCache['playersAtStreet4'], + hudCache['playersAtShowdown'], + hudCache['street0Raises'], + hudCache['street1Raises'], + hudCache['street2Raises'], + hudCache['street3Raises'], + hudCache['street4Raises'], + hudCache['street1Pot'], + hudCache['street2Pot'], + hudCache['street3Pot'], + hudCache['street4Pot'], + hudCache['showdownPot'] + ) + ) #return getLastInsertId(backend, conn, cursor) #end class fpdb_db diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 455c1e27..bcc5d02f 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -22,6 +22,7 @@ import os # todo: remove this once import_dir is in fpdb_import import sys from time import time, strftime +import logging import traceback import math import datetime From b252e350d619089fcbe5cd54e9f242689f236704 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Tue, 14 Jul 2009 23:34:47 +0100 Subject: [PATCH 05/73] fix my breakage.. --- pyfpdb/HandHistoryConverter.py | 79 ++++++++-------------------------- 1 file changed, 19 insertions(+), 60 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index f5c4c2a5..cd3a1db0 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -28,91 +28,51 @@ import codecs from decimal import Decimal import operator from xml.dom.minidom import Node -# from pokereval import PokerEval import time import datetime -import gettext -#from pokerengine.pokercards import * -# provides letter2name{}, letter2names{}, visible_card(), not_visible_card(), is_visible(), card_value(), class PokerCards -# but it's probably not installed so here are the ones we may want: -letter2name = { - 'A': 'Ace', - 'K': 'King', - 'Q': 'Queen', - 'J': 'Jack', - 'T': 'Ten', - '9': 'Nine', - '8': 'Eight', - '7': 'Seven', - '6': 'Six', - '5': 'Five', - '4': 'Four', - '3': 'Trey', - '2': 'Deuce' - } - -letter2names = { - 'A': 'Aces', - 'K': 'Kings', - 'Q': 'Queens', - 'J': 'Jacks', - 'T': 'Tens', - '9': 'Nines', - '8': 'Eights', - '7': 'Sevens', - '6': 'Sixes', - '5': 'Fives', - '4': 'Fours', - '3': 'Treys', - '2': 'Deuces' - } - -import gettext -gettext.install('myapplication') +#import gettext +#gettext.install('fpdb') class HandHistoryConverter(): READ_CHUNK_SIZE = 10000 # bytes to read at a time from file (in tail mode) def __init__(self, in_path = '-', out_path = '-', sitename = None, follow=False): - logging.info("HandHistory init called") + logging.info("HandHistory init") # default filetype and codepage. Subclasses should set these properly. self.filetype = "text" self.codepage = "utf8" - + self.in_path = in_path self.out_path = out_path - if self.out_path == '-': - # write to stdout + + if in_path == '-': + self.in_fh = sys.stdin + + if out_path == '-': self.out_fh = sys.stdout else: - # TODO: out_path should be sanity checked before opening. Perhaps in fpdb_import? - # I'm not sure what we're looking for, although we don't want out_path==in_path!='-' - self.out_fh = open(self.out_path, 'w') # doomswitch is now on :| + # TODO: out_path should be sanity checked. + self.out_fh = open(self.out_path, 'w') + self.sitename = sitename self.follow = follow self.compiledPlayers = set() self.maxseats = 10 def __str__(self): - #TODO : I got rid of most of the hhdir stuff. - tmp = "HandHistoryConverter: '%s'\n" % (self.sitename) - #tmp = tmp + "\thhbase: '%s'\n" % (self.hhbase) - #tmp = tmp + "\thhdir: '%s'\n" % (self.hhdir) - tmp = tmp + "\tfiletype: '%s'\n" % (self.filetype) - tmp = tmp + "\tinfile: '%s'\n" % (self.in_path) - tmp = tmp + "\toutfile: '%s'\n" % (self.out_path) - #tmp = tmp + "\tgametype: '%s'\n" % (self.gametype[0]) - #tmp = tmp + "\tgamebase: '%s'\n" % (self.gametype[1]) - #tmp = tmp + "\tlimit: '%s'\n" % (self.gametype[2]) - #tmp = tmp + "\tsb/bb: '%s/%s'\n" % (self.gametype[3], self.gametype[4]) - return tmp + return """ +HandHistoryConverter: '%(sitename)s' + filetype: '%(filetype)s' + in_path: '%(in_path)s' + out_path: '%(out_path)s' + """ % { 'sitename':self.sitename, 'filetype':self.filetype, 'in_path':self.in_path, 'out_path':self.out_path } def start(self): """process a hand at a time from the input specified by in_path. If in follow mode, wait for more data to turn up. -Otherwise, finish at eof... +Otherwise, finish at eof. """ starttime = time.time() @@ -224,7 +184,6 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. base = gametype['base'] limit = gametype['limitType'] l = [type] + [base] + [limit] - hand = None if l in self.readSupportedGames(): hand = None if gametype['base'] == 'hold': From 806d61ae2368315bc6f9d18e86a89e9066cb06cf Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Wed, 15 Jul 2009 00:14:25 +0100 Subject: [PATCH 06/73] log line --- pyfpdb/fpdb_db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index c52a2e56..a0f6ca92 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -205,7 +205,7 @@ class fpdb_db: print msg raise fpdb_simple.FpdbError(msg) elif backend==fpdb_db.SQLITE: - logging.info("Connecting to SQLite:(%s)") + logging.info("Connecting to SQLite:%(database)s" % {'database':database}) import sqlite3 self.db = sqlite3.connect(database,detect_types=sqlite3.PARSE_DECLTYPES) sqlite3.register_converter("bool", lambda x: bool(int(x))) From 70f271ef78bd8e4f722540718f426b6cbdb3bc12 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Wed, 15 Jul 2009 00:15:04 +0100 Subject: [PATCH 07/73] location of test PS horse hh --- pyfpdb/PokerStarsToFpdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 5350713c..4b66e899 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -1,4 +1,4 @@ - #!/usr/bin/env python +#!/usr/bin/env python # -*- coding: utf-8 -*- # # Copyright 2008, Carl Gherardi @@ -320,7 +320,7 @@ follow : whether to tail -f the input""" if __name__ == "__main__": parser = OptionParser() - parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/pokerstars/HH20090226 Natalie V - $0.10-$0.20 - HORSE.txt") + parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/stars/horse/HH20090226 Natalie V - $0.10-$0.20 - HORSE.txt") parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-") parser.add_option("-f", "--follow", dest="follow", help="follow (tail -f) the input", action="store_true", default=False) parser.add_option("-q", "--quiet", From 021b9934eab2804009183ccce90ced20c9ba712f Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 14 Jul 2009 19:18:38 -0400 Subject: [PATCH 08/73] Fix writing of mixed tournament hands. Other minor changes. --- pyfpdb/Hand.py | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 1846b240..a14ecaeb 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -545,22 +545,25 @@ Map the tuple self.gametype onto the pokerstars string describing it return ("%s: stands pat" %(act[0])) def getStakesAsString(self): - retstring = "%s%s/%s%s" % (self.SYMBOL[self.gametype['currency']], self.sb, self.SYMBOL[self.gametype['currency']], self.bb) - return retstring + """Return a string of the stakes of the current hand.""" + return "%s%s/%s%s" % (self.sym, self.sb, self.sym, self.bb) def writeGameLine(self): -# print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) - game_string = "PokerStars Game #%s: " % self.handid - if self.tourNo != None: - game_string = game_string + "Tournament #%s, %s %s - Level %s (%s) - " % (self.tourNo, + """Return the first HH line for the current hand.""" + gs = "PokerStars Game #%s: " % self.handid + + if self.tourNo != None and self.mixed != None: # mixed tournament + gs = gs + "Tournament #%s, %s %s (%s) - Level %s (%s) - " % (self.tourNo, self.buyin, self.MS[self.mixed], self.getGameTypeAsString(), self.level, self.getStakesAsString()) + elif self.tourNo != None: # all other tournaments + gs = gs + "Tournament #%s, %s %s - Level %s (%s) - " % (self.tourNo, self.buyin, self.getGameTypeAsString(), self.level, self.getStakesAsString()) - elif self.mixed != None: - game_string = game_string + " %s (%s, %s) - " % (self.MS[self.mixed], + elif self.mixed != None: # all other mixed games + gs = gs + " %s (%s, %s) - " % (self.MS[self.mixed], self.getGameTypeAsString(), self.getStakesAsString()) - else: - game_string = game_string + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString()) - game_string = game_string + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET') - return game_string + else: # non-mixed cash games + gs = gs + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString()) + + return gs + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET') def writeTableLine(self): @@ -723,12 +726,10 @@ class HoldemOmahaHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done print >>fh, self.writeGameLine() print >>fh, self.writeTableLine() -# print >>fh, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) - players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) logging.debug(self.actions['PREFLOP']) for player in [x for x in self.players if x[1] in players_who_act_preflop]: @@ -972,9 +973,8 @@ class DrawHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d %H:%M:%S ET', self.starttime))) + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done print >>fh, self.writeGameLine() -# print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) print >>fh, self.writeTableLine() players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']])) @@ -1188,16 +1188,14 @@ Add a complete on [street] by [player] to [amountTo] def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) # TODO: # Hole cards are not currently correctly written. Currently the down cards for non-heros # are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix # but mind got boggled, will try again. -# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done print >>fh, self.writeGameLine() print >>fh, self.writeTableLine() -# print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) From 35a5cffb77b07399b4dec80cfbec9451e2b2bc51 Mon Sep 17 00:00:00 2001 From: Matt Turnbull Date: Wed, 15 Jul 2009 00:26:53 +0100 Subject: [PATCH 09/73] Working on PS HORSE file now.. --- pyfpdb/HandHistoryConverter.py | 4 ++-- pyfpdb/PokerStarsToFpdb.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 590ee065..47ddecf5 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -31,8 +31,8 @@ from xml.dom.minidom import Node import time import datetime -#import gettext -#gettext.install('fpdb') +import gettext +gettext.install('fpdb') class HandHistoryConverter(): diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 41b3c67f..b855586b 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -298,7 +298,7 @@ follow : whether to tail -f the input""" hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True) for street, text in hand.streets.iteritems(): - if street in ('PREFLOP', 'DEAL'): continue # already done these + if not text or street in ('PREFLOP', 'DEAL'): continue # already done these m = self.re_HeroCards.finditer(hand.streets[street]) for found in m: player = found.group('PNAME') From 521e17f8568b1bcd21b5a0a4cb08f879f5d94381 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 15 Jul 2009 12:22:46 +0800 Subject: [PATCH 10/73] Add some boilerplate stuff for Boss Media/Win2day plugin --- pyfpdb/HUD_config.xml.example | 46 +++++++++++++++++++++++++++++++++- pyfpdb/HandHistoryConverter.py | 2 +- pyfpdb/Win2dayToFpdb.py | 0 pyfpdb/fpdb_db.py | 1 + 4 files changed, 47 insertions(+), 2 deletions(-) mode change 100644 => 100755 pyfpdb/Win2dayToFpdb.py diff --git a/pyfpdb/HUD_config.xml.example b/pyfpdb/HUD_config.xml.example index ef30fb9b..3cd592cc 100644 --- a/pyfpdb/HUD_config.xml.example +++ b/pyfpdb/HUD_config.xml.example @@ -159,6 +159,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -292,6 +336,7 @@ + @@ -300,4 +345,3 @@ - diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index fc6567f0..7e08554b 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -114,7 +114,7 @@ class HandHistoryConverter(): If in follow mode, wait for more data to turn up. Otherwise, finish at eof... -""" +""" starttime = time.time() if not self.sanityCheck(): print "Cowardly refusing to continue after failed sanity check" diff --git a/pyfpdb/Win2dayToFpdb.py b/pyfpdb/Win2dayToFpdb.py old mode 100644 new mode 100755 diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index f89b5d6d..0af29aa1 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -319,6 +319,7 @@ class fpdb_db: self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');") self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');") self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Everleaf', 'USD');") + self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Win2day', 'USD');") self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") #end def fillDefaultData From ec9ce544ca6cef56c7b1cc46003a3a4d09e7c85c Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 15 Jul 2009 23:32:17 +0800 Subject: [PATCH 11/73] Fix if database hasn't been created yet. Still broken on my setup, but at least fpdb now starts --- pyfpdb/Database.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0f354054..d4e667df 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -71,20 +71,23 @@ class Database: # a new session) cur = self.connection.cursor() - self.hand_1day_ago = 0 - cur.execute(self.sql.query['get_hand_1day_ago']) - row = cur.fetchone() - if row and row[0]: - self.hand_1day_ago = row[0] - #print "hand 1day ago =", self.hand_1day_ago + if self.fdb.wrongDbVersion == False: + self.hand_1day_ago = 0 + cur.execute(self.sql.query['get_hand_1day_ago']) + row = cur.fetchone() + if row and row[0]: + self.hand_1day_ago = row[0] + #print "hand 1day ago =", self.hand_1day_ago - d = timedelta(days=self.hud_days) - now = datetime.utcnow() - d - self.date_ndays_ago = "d%02d%02d%02d" % (now.year-2000, now.month, now.day) + d = timedelta(days=self.hud_days) + now = datetime.utcnow() - d + self.date_ndays_ago = "d%02d%02d%02d" % (now.year-2000, now.month, now.day) - self.hand_nhands_ago = 0 # todo - #cur.execute(self.sql.query['get_table_name'], (hand_id, )) - #row = cur.fetchone() + self.hand_nhands_ago = 0 # todo + #cur.execute(self.sql.query['get_table_name'], (hand_id, )) + #row = cur.fetchone() + else: + print "Bailing on DB query, not sure it exists yet" self.saveActions = False if self.import_options['saveActions'] == False else True def do_connect(self, c): From 0e76c3a6767e24e3ad7089558e396f4678d9ec34 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 11:48:58 -0400 Subject: [PATCH 12/73] Fix findHeroCards() for empty streets. --- pyfpdb/PokerStarsToFpdb.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 5661e16e..dbed145b 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -299,6 +299,7 @@ follow : whether to tail -f the input""" for street, text in hand.streets.iteritems(): if street in ('PREFLOP', 'DEAL'): continue # already done these + if hand.streets[street] == None: continue # don't regex a None m = self.re_HeroCards.finditer(hand.streets[street]) for found in m: player = found.group('PNAME') @@ -398,7 +399,7 @@ follow : whether to tail -f the input""" def readShowdownActions(self, hand): -# TODO: pick up mucks also +# TODO: pick up mucks also?? for shows in self.re_ShowdownAction.finditer(hand.handText): cards = shows.group('CARDS').split(' ') hand.addShownCards(cards, shows.group('PNAME')) From bd2db9861210d673d012c03569e837a704beba59 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 11:50:27 -0400 Subject: [PATCH 13/73] Housecleaning. Refactoring writeHand() = not finished. --- pyfpdb/Hand.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index a14ecaeb..8cac4e7a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -32,7 +32,7 @@ import pprint import DerivedStats import Card -class Hand: +class Hand(object): ###############################################################3 # Class Variables @@ -575,6 +575,13 @@ Map the tuple self.gametype onto the pokerstars string describing it return table_string + def writeHand(self, fh=sys.__stdout__): + # PokerStars format. + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done + print >>fh, self.writeGameLine() + print >>fh, self.writeTableLine() + + class HoldemOmahaHand(Hand): def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None): if gametype['base'] != 'hold': @@ -726,9 +733,7 @@ class HoldemOmahaHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. - self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done - print >>fh, self.writeGameLine() - print >>fh, self.writeTableLine() + super(HoldemOmahaHand, self).writeHand(fh) players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) logging.debug(self.actions['PREFLOP']) @@ -973,9 +978,7 @@ class DrawHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. - self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done - print >>fh, self.writeGameLine() - print >>fh, self.writeTableLine() + super(DrawHand, self).writeHand(fh) players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']])) @@ -1193,9 +1196,7 @@ Add a complete on [street] by [player] to [amountTo] # Hole cards are not currently correctly written. Currently the down cards for non-heros # are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix # but mind got boggled, will try again. - self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done - print >>fh, self.writeGameLine() - print >>fh, self.writeTableLine() + super(StudHand, self).writeHand(fh) players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) From b92feee021229886e5baabaa9a3d8c7d3732d9c6 Mon Sep 17 00:00:00 2001 From: Worros Date: Wed, 15 Jul 2009 23:58:34 +0800 Subject: [PATCH 14/73] Revert Matts change for sqlite until fixed. Previous syntax failed to insert the required line into TourneyTypes --- pyfpdb/fpdb_db.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 30101d0c..2b75ea12 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -336,9 +336,10 @@ class fpdb_db: self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('PokerStars', 'USD')") self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('Everleaf', 'USD')") self.cursor.execute("INSERT INTO Sites (name,currency) VALUES ('Win2day', 'USD')") - self.cursor.execute("""INSERT INTO TourneyTypes - (siteId,buyin,fee,knockout,rebuyOrAddon) VALUES - (1,0,0,0,?)""",(False,) ) + self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") + #self.cursor.execute("""INSERT INTO TourneyTypes + # (siteId,buyin,fee,knockout,rebuyOrAddon) VALUES + # (1,0,0,0,?)""",(False,) ) #end def fillDefaultData def recreate_tables(self): From 427999b69cbb2c4b0afa3ed8807d10d66847c728 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 21:22:07 -0400 Subject: [PATCH 15/73] Correctly write stud holecards in writeHand(). --- pyfpdb/Hand.py | 58 +++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 8c1e2173..fbb4b491 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -286,6 +286,7 @@ If a player has None chips he won't be added.""" def setCommunityCards(self, street, cards): logging.debug("setCommunityCards %s %s" %(street, cards)) self.board[street] = [self.card(c) for c in cards] +# print "DEBUG: self.board: %s" % self.board def card(self,c): """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" @@ -1060,7 +1061,7 @@ class StudHand(Hand): self.actionStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order - self.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] + self.holeStreets = ['THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] Hand.__init__(self, sitename, gametype, handText) self.sb = gametype['sb'] self.bb = gametype['bb'] @@ -1097,9 +1098,9 @@ class StudHand(Hand): else: # self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) self.addHoleCards('THIRD', player, open=[cards[2]], closed=cards[0:2], shown=shown, mucked=mucked) - self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[], shown=shown, mucked=mucked) - self.addHoleCards('FIFTH', player, open=[cards[4]], closed=[], shown=shown, mucked=mucked) - self.addHoleCards('SIXTH', player, open=[cards[5]], closed=[], shown=shown, mucked=mucked) + self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[cards[2]], shown=shown, mucked=mucked) + self.addHoleCards('FIFTH', player, open=[cards[4]], closed=cards[2:4], shown=shown, mucked=mucked) + self.addHoleCards('SIXTH', player, open=[cards[5]], closed=cards[2:5], shown=shown, mucked=mucked) self.addHoleCards('SEVENTH', player, open=[], closed=[cards[6]], shown=shown, mucked=mucked) @@ -1216,7 +1217,8 @@ Add a complete on [street] by [player] to [amountTo] dealt+=1 if dealt==1: print >>fh, _("*** 3RD STREET ***") - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "] " if closed else " ", "[" + " ".join(open) + "]" if open else "") +# print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "] " if closed else " ", "[" + " ".join(open) + "]" if open else "") + print >>fh, self.writeHoleCards('THIRD', player) for act in self.actions['THIRD']: #FIXME: Need some logic here for bringin vs completes print >>fh, self.actionString(act) @@ -1226,15 +1228,10 @@ Add a complete on [street] by [player] to [amountTo] #~ print >>fh, _("*** 4TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: if player in self.holecards['FOURTH']: - old = [] - (o,c) = self.holecards['THIRD'][player] - if o:old.extend(o) - if c:old.extend(c) - new = self.holecards['FOURTH'][player][0] dealt+=1 if dealt==1: print >>fh, _("*** 4TH STREET ***") - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") + print >>fh, self.writeHoleCards('FOURTH', player) for act in self.actions['FOURTH']: print >>fh, self.actionString(act) @@ -1243,16 +1240,10 @@ Add a complete on [street] by [player] to [amountTo] #~ print >>fh, _("*** 5TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: if self.holecards['FIFTH'].has_key(player): - old = [] - for street in ('THIRD','FOURTH'): - (o,c) = self.holecards[street][player] - if o:old.extend(o) - if c:old.extend(c) - new = self.holecards['FIFTH'][player][0] dealt+=1 if dealt==1: print >>fh, _("*** 5TH STREET ***") - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") + print >>fh, self.writeHoleCards('FIFTH', player) for act in self.actions['FIFTH']: print >>fh, self.actionString(act) @@ -1261,16 +1252,10 @@ Add a complete on [street] by [player] to [amountTo] #~ print >>fh, _("*** 6TH STREET ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: if self.holecards['SIXTH'].has_key(player): - old = [] - for street in ('THIRD','FOURTH','FIFTH'): - (o,c) = self.holecards[street][player] - if o:old.extend(o) - if c:old.extend(c) - new = self.holecards['SIXTH'][player][0] dealt += 1 if dealt == 1: print >>fh, _("*** 6TH STREET ***") - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") + print >>fh, self.writeHoleCards('SIXTH', player) for act in self.actions['SIXTH']: print >>fh, self.actionString(act) @@ -1279,17 +1264,11 @@ Add a complete on [street] by [player] to [amountTo] # Then we have no 'dealt to' lines, no action lines, but still 7th street should appear. # The only way I can see to know whether to print this line is by knowing the state of the hand # i.e. are all but one players folded; is there an allin showdown; and all that. - print >>fh, _("*** 7TH STREET ***") + print >>fh, _("*** RIVER ***") for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: if self.holecards['SEVENTH'].has_key(player): - old = [] - for street in ('THIRD','FOURTH','FIFTH','SIXTH'): - (o,c) = self.holecards[street][player] - if o:old.extend(o) - if c:old.extend(c) - new = self.holecards['SEVENTH'][player][0] - if new: - print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") + if self.writeHoleCards('SEVENTH', player): + print >>fh, self.writeHoleCards('SEVENTH', player) for act in self.actions['SEVENTH']: print >>fh, self.actionString(act) @@ -1341,6 +1320,17 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, "\n\n" + def writeHoleCards(self, street, player): + hc = "Dealt to %s [" % player + if street == 'THIRD': + if player == self.hero: + return hc + " ".join(self.holecards[street][player][1]) + " " + " ".join(self.holecards[street][player][0]) + ']' + else: + return hc + " ".join(self.holecards[street][player][0]) + ']' + + if street == 'SEVENTH' and player != self.hero: return # only write 7th st line for hero, LDO + return hc + " ".join(self.holecards[street][player][1]) + "][" + " ".join(self.holecards[street][player][0]) + "]" + def join_holecards(self, player): holecards = [] for street in self.holeStreets: From 12db3c0d55b660c6f9045d3373f856f930411c5d Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 21:46:45 -0400 Subject: [PATCH 16/73] Add a space to make stud holecard printing perfect. --- pyfpdb/Hand.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index fbb4b491..c97e88f1 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -733,6 +733,7 @@ class HoldemOmahaHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. +# TODO: board cards (in summary) not printed in correct order super(HoldemOmahaHand, self).writeHand(fh) players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) @@ -1329,7 +1330,7 @@ Add a complete on [street] by [player] to [amountTo] return hc + " ".join(self.holecards[street][player][0]) + ']' if street == 'SEVENTH' and player != self.hero: return # only write 7th st line for hero, LDO - return hc + " ".join(self.holecards[street][player][1]) + "][" + " ".join(self.holecards[street][player][0]) + "]" + return hc + " ".join(self.holecards[street][player][1]) + "] [" + " ".join(self.holecards[street][player][0]) + "]" def join_holecards(self, player): holecards = [] From 3253d5a234a4f68e8b0de7ef63ad04f1bc1f84b6 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 22:11:23 -0400 Subject: [PATCH 17/73] Get stud shown cards right in writeHand(). --- pyfpdb/Hand.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index c97e88f1..95fd74a5 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -1336,7 +1336,15 @@ Add a complete on [street] by [player] to [amountTo] holecards = [] for street in self.holeStreets: if self.holecards[street].has_key(player): - holecards = holecards + self.holecards[street][player][0] + if street == 'THIRD': + holecards = holecards + self.holecards[street][player][1] + self.holecards[street][player][0] + elif street == 'SEVENTH': + if player == self.hero: + holecards = holecards + self.holecards[street][player][0] + else: + holecards = holecards + self.holecards[street][player][1] + else: + holecards = holecards + self.holecards[street][player][0] return " ".join(holecards) class Pot(object): From e0dc556a679e7b6991a68db05c04c9d31f0c2218 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 22:15:20 -0400 Subject: [PATCH 18/73] Clean up some methods previously commented out. --- pyfpdb/Hand.py | 92 -------------------------------------------------- 1 file changed, 92 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 95fd74a5..f5a07644 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -905,21 +905,6 @@ class DrawHand(Hand): self.addHoleCards('DRAWTHREE', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) -# def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False): -# """\ -#Assigns observed holecards to a player. -#cards list of card bigrams e.g. ['2h','Jc'] -#player (string) name of player -#""" -# try: -# self.checkPlayerExists(player) -## if shown and len(cardset) > 0: -## self.shown.add(player) -# self.holecards[street][player] = (newcards,oldcards) -# except FpdbParseError, e: -# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) - - def discardDrawHoleCards(self, cards, player, street): logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street)) self.discards[street][player] = set([cards]) @@ -935,48 +920,6 @@ class DrawHand(Hand): self.actions[street].append(act) -# def addShownCards(self, cards, player, holeandboard=None, shown=False, mucked=False): -# """\ -#For when a player shows cards for any reason (for showdown or out of choice). -#Card ranks will be uppercased -#""" -# logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) -# if cards is not None: -# self.shown.add(player) -# self.addHoleCards(cards,player) -# elif holeandboard is not None: -# holeandboard = set([self.card(c) for c in holeandboard]) -# board = set([c for s in self.board.values() for c in s]) -# self.addHoleCards(holeandboard.difference(board),player,shown=True) - - -# def addHoleCards(self, cards, player, shown, mucked, dealt=False): -# """\ -#Assigns observed holecards to a player. -#cards list of card bigrams e.g. ['2h','Jc'] -#player (string) name of player -#shown whether they were revealed at showdown -#mucked whether they were mucked at showdown -#dealt whether they were seen in a 'dealt to' line -#""" -## I think this only gets called for shown cards. -# logging.debug("addHoleCards %s %s" % (cards, player)) -# try: -# self.checkPlayerExists(player) -# except FpdbParseError, e: -# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) -# return -# -# if dealt: -# self.dealt.add(player) -# if shown: -# self.shown.add(player) -# if mucked: -# self.mucked.add(player) -# if player != self.hero: #skip hero, we know his cards -# print "player, cards =", player, cards -# self.holecards[self.holeStreets[-1]][player] = (cards, set([])) - def writeHand(self, fh=sys.__stdout__): # PokerStars format. super(DrawHand, self).writeHand(fh) @@ -1122,41 +1065,6 @@ closed likewise, but known only to player except FpdbParseError, e: print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) -# def addHoleCards(self, cards, player, shown, mucked, dealt=False): -# """\ -#Assigns observed holecards to a player. -#cards list of card bigrams e.g. ['2h','Jc'] -#player (string) name of player -#shown whether they were revealed at showdown -#mucked whether they were mucked at showdown -#dealt whether they were seen in a 'dealt to' line -#""" -## -## For stud games we just need to do the routine setting of shown/mucked/etc -## and then update the cards 'THIRD' and 'SEVENTH' -# logging.debug("addHoleCards %s %s" % (cards, player)) -# try: -# self.checkPlayerExists(player) -# except FpdbParseError, e: -# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) -# return -# -# if dealt: -# self.dealt.add(player) -# if shown: -# self.shown.add(player) -# if mucked: -# self.mucked.add(player) -# if player == self.hero: -# if len(cards) > 2: -# self.holecards['THIRD'][player] = ([cards[0:3]], []) -# if len(cards) > 6: -# self.holecards['SEVENTH'][player] = ([cards[6]], []) -# else: -# if len(cards) > 2: -# self.holecards['THIRD'][player] = ([cards[0]], cards[1:3]) -# if len(cards) > 6: -# self.holecards['SEVENTH'][player] = ([], [cards[6]]) # TODO: def addComplete(self, player, amount): def addComplete(self, street, player, amountTo): # assert street=='THIRD' From 889aea48b6805ab42121048a17c264a85842b3c4 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 22:30:41 -0400 Subject: [PATCH 19/73] Make the board in the summary of flop games print in the right order. --- pyfpdb/Hand.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index f5a07644..65745c2c 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -808,8 +808,8 @@ class HoldemOmahaHand(Hand): print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) board = [] - for s in self.board.values(): - board += s + for street in ["FLOP", "TURN", "RIVER"]: + board += self.board[street] if board: # sometimes hand ends preflop without a board print >>fh, ("Board [%s]" % (" ".join(board))) From b5b0b6a7b70a791124fb0f29d9b79bf487e440de Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 23:04:16 -0400 Subject: [PATCH 20/73] Get rid of hard wired $ in writeHand. Replace with appropriate symbol based on ring, tournament, play, etc. --- pyfpdb/Hand.py | 54 +++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 65745c2c..5f2174b8 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -523,22 +523,22 @@ Map the tuple self.gametype onto the pokerstars string describing it elif act[1] == 'checks': return ("%s: checks " %(act[0])) elif act[1] == 'calls': - return ("%s: calls $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: calls %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'bets': - return ("%s: bets $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: bets %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'raises': - return ("%s: raises $%s to $%s%s" %(act[0], act[2], act[3], ' and is all-in' if act[5] else '')) + return ("%s: raises %s%s to %s%s%s" %(act[0], self.sym, act[2], self.sym, act[3], ' and is all-in' if act[5] else '')) elif act[1] == 'completea': - return ("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: completes to %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'posts': if(act[2] == "small blind"): - return ("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts small blind %s%s%s" %(act[0], self.sym, act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "big blind"): - return ("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts big blind %s%s%s" %(act[0], self.sym, act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "both"): - return ("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts small & big blinds %s%s%s" %(act[0], self.sym, act[3], ' and is all-in' if act[4] else '')) elif act[1] == 'bringin': - return ("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: brings in for %s%s%s" %(act[0], self.sym, act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'discards': return ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else '')) elif act[1] == 'stands pat': @@ -645,8 +645,8 @@ class HoldemOmahaHand(Hand): def render_stack(context,data): pat = context.tag.patternGenerator('list_item') for player in data: - x = "Seat %s: %s ($%s in chips) " %(player[0], player[1], - player[2]) + x = "Seat %s: %s (%s%s in chips) " %(player[0], player[1], + self.sym, player[2]) context.tag[ pat().fillSlots('playerStack', x)] return context.tag @@ -800,12 +800,12 @@ class HoldemOmahaHand(Hand): # Immediately before the summary. # The current importer uses those lines for importing winning rather than the summary for name in self.pot.returned: - print >>fh, ("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name)) + print >>fh, ("Uncalled bet (%s%s) returned to %s" %(self.sym, self.pot.returned[name],name)) for entry in self.collected: - print >>fh, ("%s collected $%s from x pot" %(entry[0], entry[1])) + print >>fh, ("%s collected %s%s from x pot" %(entry[0], self.sym, entry[1])) print >>fh, ("*** SUMMARY ***") - print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) + print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake) board = [] for street in ["FLOP", "TURN", "RIVER"]: @@ -817,9 +817,9 @@ class HoldemOmahaHand(Hand): seatnum = player[0] name = player[1] if name in self.collectees and name in self.shown: - print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]), self.collectees[name])) + print >>fh, ("Seat %d: %s showed [%s] and won (%s%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]), self.sym, self.collectees[name])) elif name in self.collectees: - print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) + print >>fh, ("Seat %d: %s collected (%s%s)" % (seatnum, name, self.sym, self.collectees[name])) #~ elif name in self.shown: #~ print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']))) elif name in self.folded: @@ -928,11 +928,11 @@ class DrawHand(Hand): for player in [x for x in self.players if x[1] in players_who_act_ondeal]: #Only print stacks of players who do something on deal - print >>fh, _("Seat %s: %s ($%s in chips) " %(player[0], player[1], player[2])) + print >>fh, _("Seat %s: %s (%s%s in chips) " %(player[0], player[1], self.sym, player[2])) if 'BLINDSANTES' in self.actions: for act in self.actions['BLINDSANTES']: - print >>fh, _("%s: %s %s $%s" %(act[0], act[1], act[2], act[3])) + print >>fh, _("%s: %s %s %s%s" %(act[0], act[1], act[2], self.sym, act[3])) if 'DEAL' in self.actions: print >>fh, _("*** DEALING HANDS ***") @@ -985,12 +985,12 @@ class DrawHand(Hand): # Immediately before the summary. # The current importer uses those lines for importing winning rather than the summary for name in self.pot.returned: - print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name)) + print >>fh, _("Uncalled bet (%s%s) returned to %s" %(self.sym, self.pot.returned[name],name)) for entry in self.collected: - print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1])) + print >>fh, _("%s collected %s%s from x pot" %(entry[0], self.sym, entry[1])) print >>fh, _("*** SUMMARY ***") - print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) + print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake) print >>fh, "\n\n" @@ -1111,11 +1111,11 @@ Add a complete on [street] by [player] to [amountTo] for player in [x for x in self.players if x[1] in players_who_post_antes]: #Only print stacks of players who do something preflop - print >>fh, _("Seat %s: %s ($%s)" %(player[0], player[1], player[2])) + print >>fh, _("Seat %s: %s (%s%s)" %(player[0], player[1], self.sym, player[2])) if 'ANTES' in self.actions: for act in self.actions['ANTES']: - print >>fh, _("%s: posts the ante $%s" %(act[0], act[3])) + print >>fh, _("%s: posts the ante %s%s" %(act[0], self.sym, act[3])) if 'THIRD' in self.actions: dealt = 0 @@ -1196,12 +1196,12 @@ Add a complete on [street] by [player] to [amountTo] # Immediately before the summary. # The current importer uses those lines for importing winning rather than the summary for name in self.pot.returned: - print >>fh, _("Uncalled bet ($%s) returned to %s" %(self.pot.returned[name],name)) + print >>fh, _("Uncalled bet (%s%s) returned to %s" %(self.sym, self.pot.returned[name],name)) for entry in self.collected: - print >>fh, _("%s collected $%s from x pot" %(entry[0], entry[1])) + print >>fh, _("%s collected %s%s from x pot" %(entry[0], self.sym, entry[1])) print >>fh, _("*** SUMMARY ***") - print >>fh, "%s | Rake $%.2f" % (self.pot, self.rake) + print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake) #print >>fh, _("Total pot $%s | Rake $%.2f" % (self.totalpot, self.rake)) # TODO: side pots board = [] @@ -1214,9 +1214,9 @@ Add a complete on [street] by [player] to [amountTo] seatnum = player[0] name = player[1] if name in self.collectees and name in self.shown: - print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, self.join_holecards(name), self.collectees[name])) + print >>fh, _("Seat %d: %s showed [%s] and won (%s%s)" % (seatnum, name, self.join_holecards(name), self.sym, self.collectees[name])) elif name in self.collectees: - print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) + print >>fh, _("Seat %d: %s collected (%s%s)" % (seatnum, name, self.sym, self.collectees[name])) elif name in self.shown: print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, self.join_holecards(name))) elif name in self.mucked: From 52fcbd79667ef4556e8b898bf8ae8e702f4d4953 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Jul 2009 23:40:07 -0400 Subject: [PATCH 21/73] Remove completed TODOs(plenty left!). Remove obsolete comments. --- pyfpdb/Hand.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 5f2174b8..d4a1ca44 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -81,7 +81,6 @@ class Hand(object): self.holecards[street] = {} # dict from player names to holecards self.discards[street] = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards # Collections indexed by player names -# self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards self.stacks = {} self.collected = [] #list of ? self.collectees = {} # dict from player names to amounts collected (?) @@ -92,7 +91,6 @@ class Hand(object): self.shown = set() # cards were shown self.mucked = set() # cards were mucked at showdown -# self.action = [] # Things to do with money self.pot = Pot() self.totalpot = None @@ -733,7 +731,6 @@ class HoldemOmahaHand(Hand): def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# TODO: board cards (in summary) not printed in correct order super(HoldemOmahaHand, self).writeHand(fh) players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) @@ -859,8 +856,6 @@ class DrawHand(Hand): # Read actions in street order for street in self.streetList: if self.streets[street]: - # hhc.readCommunityCards(self, street) -# hhc.readDrawCards(self, street) hhc.readAction(self, street) hhc.readCollectPot(self) hhc.readShownCards(self) @@ -1020,13 +1015,11 @@ class StudHand(Hand): hhc.readAntes(self) hhc.readBringIn(self) hhc.readHeroCards(self) - #hhc.readShowdownActions(self) # not done yet # Read actions in street order for street in self.streetList: if self.streets[street]: logging.debug(street) logging.debug(self.streets[street]) -# hhc.readStudPlayerCards(self, street) hhc.readAction(self, street) hhc.readCollectPot(self) hhc.readShownCards(self) # not done yet @@ -1040,7 +1033,6 @@ class StudHand(Hand): if shown: self.shown.add(player) if mucked: self.mucked.add(player) else: -# self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) self.addHoleCards('THIRD', player, open=[cards[2]], closed=cards[0:2], shown=shown, mucked=mucked) self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[cards[2]], shown=shown, mucked=mucked) self.addHoleCards('FIFTH', player, open=[cards[4]], closed=cards[2:4], shown=shown, mucked=mucked) @@ -1060,8 +1052,6 @@ closed likewise, but known only to player try: self.checkPlayerExists(player) self.holecards[street][player] = (open, closed) -# cards = set([self.card(c) for c in cards]) -# self.holecards[player].update(cards) except FpdbParseError, e: print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) @@ -1101,17 +1091,13 @@ Add a complete on [street] by [player] to [amountTo] def writeHand(self, fh=sys.__stdout__): # PokerStars format. -# TODO: -# Hole cards are not currently correctly written. Currently the down cards for non-heros -# are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix -# but mind got boggled, will try again. super(StudHand, self).writeHand(fh) players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) for player in [x for x in self.players if x[1] in players_who_post_antes]: #Only print stacks of players who do something preflop - print >>fh, _("Seat %s: %s (%s%s)" %(player[0], player[1], self.sym, player[2])) + print >>fh, _("Seat %s: %s (%s%s in chips)" %(player[0], player[1], self.sym, player[2])) if 'ANTES' in self.actions: for act in self.actions['ANTES']: @@ -1202,7 +1188,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("*** SUMMARY ***") print >>fh, "%s | Rake %s%.2f" % (self.pot, self.sym, self.rake) - #print >>fh, _("Total pot $%s | Rake $%.2f" % (self.totalpot, self.rake)) # TODO: side pots +# TODO: side pots board = [] for s in self.board.values(): From d8df3ea11ad75c5226c250d6ec094072cd14adf6 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 16 Jul 2009 11:46:52 +0800 Subject: [PATCH 22/73] Possible fix for 2.6 versions of Matplotlib Long standing issue with multiple plots being added to a single canvas. Calling canvas.draw() appears to be the "correct" way to do this in pythin 2.6 Need someone to test if this still works in python 2.5 --- pyfpdb/GuiGraphViewer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index e3f08b75..c52ebe1d 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -126,11 +126,12 @@ class GuiGraphViewer (threading.Thread): #end def get_vbox def clearGraphData(self): - self.fig.clf() + self.fig.clear() if self.canvas is not None: self.canvas.destroy() - self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea + if self.canvas == None: + self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea def generateGraph(self, widget, data): self.clearGraphData() @@ -197,6 +198,7 @@ class GuiGraphViewer (threading.Thread): self.graphBox.add(self.canvas) self.canvas.show() + self.canvas.draw() #self.exportButton.set_sensitive(True) #end of def showClicked From 2fa37813491447fd18fa02b963d65927528c115c Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Jul 2009 00:54:09 -0400 Subject: [PATCH 23/73] Make euros print as $ in writeHand. --- pyfpdb/Hand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index d4a1ca44..6355eef4 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -38,7 +38,7 @@ class Hand(object): # Class Variables UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} - SYMBOL = {'USD': '$', 'EUR': u'E', 'T$': '', 'play': ''} + SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''} MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE'} From 0d5af4c9741f5f22a1940f6aeeb935fdead95a76 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 16 Jul 2009 12:58:39 +0800 Subject: [PATCH 24/73] Make Win2day client use updated readHeroCards api --- pyfpdb/HandHistoryConverter.py | 2 +- pyfpdb/Win2dayToFpdb.py | 31 ++++++++++++++----------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 16a89267..94ca5fec 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -173,6 +173,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. def processHand(self, handText): gametype = self.determineGameType(handText) logging.debug("gametype %s" % gametype) + hand = None if gametype is None: l = None gametype = "unmatched" @@ -185,7 +186,6 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. limit = gametype['limitType'] l = [type] + [base] + [limit] if l in self.readSupportedGames(): - hand = None if gametype['base'] == 'hold': logging.debug("hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handtext)") hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handText) diff --git a/pyfpdb/Win2dayToFpdb.py b/pyfpdb/Win2dayToFpdb.py index 0417dcb1..ab66ab5e 100755 --- a/pyfpdb/Win2dayToFpdb.py +++ b/pyfpdb/Win2dayToFpdb.py @@ -19,6 +19,7 @@ ######################################################################## import sys +import datetime from HandHistoryConverter import * # Win2day HH Format @@ -140,11 +141,7 @@ class Win2day(HandHistoryConverter): for key in info: if key == 'DATETIME': # Win2day uses UTC timestamp - # 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(time.gmtime(info[key])) - # hand.starttime = time.gmtime(int(info[key])) - hand.starttime = time.gmtime(int(info[key])) + hand.starttime = datetime.datetime.fromtimestamp(int(info[key])) if key == 'HID': hand.handid = info[key] if key == 'TABLE': @@ -225,18 +222,18 @@ class Win2day(HandHistoryConverter): hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB')) def readHeroCards(self, hand): - m = self.re_HeroCards.search(hand.handText) - if(m == None): - #Not involved in hand - hand.involved = False - else: +# streets PREFLOP, PREDRAW, and THIRD are special cases beacause +# we need to grab hero's cards + m = self.re_HeroCards.finditer(hand.streets['PREFLOP']) + newcards = [] + for found in m: + hand.hero = found.group('PNAME') + for card in self.re_Card.finditer(found.group('CARDS')): + print self.convertWin2dayCards(card.group('CARD')) + newcards.append(self.convertWin2dayCards(card.group('CARD'))) - hand.hero = m.group('PNAME') - holeCards = set([]) - for card in self.re_Card.finditer(m.group('CARDS')): - holeCards.add(self.convertWin2dayCards(card.group('CARD'))) - - hand.addHoleCards(holeCards, m.group('PNAME')) + #hand.addHoleCards(holeCards, m.group('PNAME')) + hand.addHoleCards('PREFLOP', hand.hero, closed=newcards, shown=False, mucked=False, dealt=True) def convertWin2dayCards(self, card): card = int(card) @@ -346,7 +343,7 @@ class Win2day(HandHistoryConverter): for shows in self.re_ShowdownAction.finditer(hand.handText): showdownCards = set([]) for card in self.re_Card.finditer(shows.group('CARDS')): - print "DEBUG:", card, card.group('CARD'), self.convertWin2dayCards(card.group('CARD')) + #print "DEBUG:", card, card.group('CARD'), self.convertWin2dayCards(card.group('CARD')) showdownCards.add(self.convertWin2dayCards(card.group('CARD'))) hand.addShownCards(showdownCards, shows.group('PNAME')) From 152f16c7a0fa928db707b1aa9a2ad97fec87c809 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 16 Jul 2009 13:54:41 +0800 Subject: [PATCH 25/73] Make euros print as $ in writeHand. fpdb_simple avoidance at the moment. --- pyfpdb/Hand.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 7d27828e..48d2c38f 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -38,7 +38,7 @@ class Hand: # Class Variables UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} - SYMBOL = {'USD': '$', 'EUR': u'E', 'T$': '', 'play': ''} + SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''} MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE'} From 26a199635382bc31f7a792d3b1922b96aa9972a1 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Jul 2009 12:13:24 -0400 Subject: [PATCH 26/73] Change Pot object to support variable currency symbol. --- pyfpdb/Hand.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 6355eef4..67f565a7 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -96,6 +96,9 @@ class Hand(object): self.totalpot = None self.totalcollected = None self.rake = None + # currency symbol for this hand + self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done + self.pot.setSym(self.sym) def __str__(self): vars = ( ("BB", self.bb), @@ -575,7 +578,6 @@ Map the tuple self.gametype onto the pokerstars string describing it def writeHand(self, fh=sys.__stdout__): # PokerStars format. - self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done print >>fh, self.writeGameLine() print >>fh, self.writeTableLine() @@ -1249,6 +1251,10 @@ class Pot(object): self.committed = {} self.total = None self.returned = {} + self.sym = u'$' # this is the default currency symbol + + def setSym(self, sym): + self.sym = sym def addPlayer(self,player): self.committed[player] = Decimal(0) @@ -1300,16 +1306,16 @@ class Pot(object): raise FpdbParseError - +# TODO: This really neeads to be a loop to handle multiple side pots if len(self.pots) == 1: # (only use Total pot) - return "Total pot $%.2f" % (self.total,) + return "Total pot %s%.2f" % (self.sym, self.total,) elif len(self.pots) == 2: - return "Total pot $%.2f Main pot $%.2f. Side pot $%2.f." % (self.total, self.pots[0], self.pots[1]) + return "Total pot %s%.2f Main pot %s%.2f. Side pot %s%2.f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1]) elif len(self.pots) == 3: - return "Total pot $%.2f Main pot $%.2f. Side pot-1 $%2.2f. Side pot-2 $%.2f." % (self.total, self.pots[0], self.pots[1], self.pots[2]) + return "Total pot %s%.2f Main pot $%.2f. Side pot-1 %s%2.2f. Side pot-2 %s%.2f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1], self.sym, self.pots[2]) elif len(self.pots) == 0: # no small blind and walk in bb (hopefully) - return "Total pot $%.2f" % (self.total,) + return "Total pot %s%.2f" % (self.sym, self.total,) else: return ("too many pots.. no small blind and walk in bb?. self.pots: %s" %(self.pots)) # I don't know stars format for a walk in the bb when sb doesn't post. From 61b0b8f4fe35171873300c88238b401ba349d040 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 17 Jul 2009 17:16:06 +0800 Subject: [PATCH 27/73] Prep work for inserting directly from HHC --- pyfpdb/fpdb_import.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 3129c22c..8323a790 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -83,6 +83,8 @@ class Importer: self.fdb.do_connect(self.config) self.fdb.db.rollback() + self.NEWIMPORT = False + #Set functions def setCallHud(self, value): self.callHud = value @@ -311,8 +313,16 @@ class Importer: obj = getattr(mod, filter_name, None) if callable(obj): conv = obj(in_path = file, out_path = out_path) - if(conv.getStatus()): + if(conv.getStatus() and self.NEWIMPORT == False): (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(out_path, site) + elif (conv.getStatus() and self.NEWIMPORT == True): + #This code doesn't do anything yet + handlist = hhc.getProcessedHands() + self.pos_in_file[file] = hhc.getLastCharacterRead() + + for hand in handlist: + hand.prepInsert() + hand.insert() else: # conversion didn't work # TODO: appropriate response? From 34932c14eeace93d3f0e48bd1ad360ba2a4a3687 Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 17 Jul 2009 17:45:22 +0800 Subject: [PATCH 28/73] Add index parameter to Plugins Change constructor to HHC to accept an index arg, so that file reads can seek --- pyfpdb/BetfairToFpdb.py | 4 ++-- pyfpdb/EverleafToFpdb.py | 4 ++-- pyfpdb/FulltiltToFpdb.py | 4 ++-- pyfpdb/HandHistoryConverter.py | 8 +++++++- pyfpdb/PokerStarsToFpdb.py | 4 ++-- pyfpdb/UltimateBetToFpdb.py | 4 ++-- pyfpdb/Win2dayToFpdb.py | 4 ++-- pyfpdb/fpdb_import.py | 2 +- 8 files changed, 20 insertions(+), 14 deletions(-) diff --git a/pyfpdb/BetfairToFpdb.py b/pyfpdb/BetfairToFpdb.py index 672e858a..1ccec5d0 100755 --- a/pyfpdb/BetfairToFpdb.py +++ b/pyfpdb/BetfairToFpdb.py @@ -34,12 +34,12 @@ class Betfair(HandHistoryConverter): re_PlayerInfo = re.compile("Seat (?P[0-9]+): (?P.*)\s\(\s(\$(?P[.0-9]+)) \)") re_Board = re.compile(ur"\[ (?P.+) \]") - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="Betfair", follow=follow) # Call super class init. + HandHistoryConverter.__init__(self, in_path, out_path, sitename="Betfair", follow=follow, index) # Call super class init. logging.info("Initialising Betfair converter class") self.filetype = "text" self.codepage = "cp1252" diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index ee4942f1..10468378 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -37,7 +37,7 @@ class Everleaf(HandHistoryConverter): re_Board = re.compile(ur"\[ (?P.+) \]") - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, debugging=False): + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, debugging=False, index=0): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) @@ -45,7 +45,7 @@ follow : whether to tail -f the input autostart: whether to run the thread (or you can call start() yourself) debugging: if False, pass on partially supported game types. If true, have a go and error...""" print "DEBUG: XXXXXXXXXXXXXXX" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow) + HandHistoryConverter.__init__(self, in_path, out_path, sitename="Everleaf", follow=follow, index=index) logging.info("Initialising Everleaf converter class") self.filetype = "text" self.codepage = "cp1252" diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index f7b834a6..173489f7 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -36,12 +36,12 @@ class Fulltilt(HandHistoryConverter): re_Board = re.compile(r"\[(?P.+)\]") # NB: if we ever match "Full Tilt Poker" we should also match "FullTiltPoker", which PT Stud erroneously exports. - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="Fulltilt", follow=follow) + HandHistoryConverter.__init__(self, in_path, out_path, sitename="Fulltilt", follow=follow, index=index) logging.info("Initialising Fulltilt converter class") self.filetype = "text" self.codepage = "cp1252" diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 94ca5fec..712260f9 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -37,12 +37,13 @@ gettext.install('fpdb') class HandHistoryConverter(): READ_CHUNK_SIZE = 10000 # bytes to read at a time from file (in tail mode) - def __init__(self, in_path = '-', out_path = '-', sitename = None, follow=False): + def __init__(self, in_path = '-', out_path = '-', sitename = None, follow=False, index=0): logging.info("HandHistory init") # default filetype and codepage. Subclasses should set these properly. self.filetype = "text" self.codepage = "utf8" + self.index = 0 self.in_path = in_path self.out_path = out_path @@ -330,7 +331,9 @@ or None if we fail to get the info """ else: logging.debug("Opening %s with %s" % (self.in_path, self.codepage)) in_fh = codecs.open(self.in_path, 'r', self.codepage) + in_fh.seek(self.index) self.obs = in_fh.read() + self.index = in_fh.tell() in_fh.close() elif(self.filetype == "xml"): try: @@ -346,3 +349,6 @@ or None if we fail to get the info """ def getProcessedFile(self): return self.out_path + + def getLastCharacterRead(self): + return self.index diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index b855586b..4e1bbf29 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -55,12 +55,12 @@ class PokerStars(HandHistoryConverter): mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} - def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): + def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" - HandHistoryConverter.__init__(self, in_path, out_path, sitename="PokerStars", follow=follow) + HandHistoryConverter.__init__(self, in_path, out_path, sitename="PokerStars", follow=follow, index=index) logging.info("Initialising PokerStars converter class") self.filetype = "text" self.codepage = "cp1252" diff --git a/pyfpdb/UltimateBetToFpdb.py b/pyfpdb/UltimateBetToFpdb.py index b57e789e..cce2df4c 100755 --- a/pyfpdb/UltimateBetToFpdb.py +++ b/pyfpdb/UltimateBetToFpdb.py @@ -33,12 +33,12 @@ class UltimateBet(HandHistoryConverter): re_Board = re.compile(r"\[(?P.+)\]") # self.re_setHandInfoRegex('.*#(?P[0-9]+): Table (?P
[ a-zA-Z]+) - \$?(?P[.0-9]+)/\$?(?P[.0-9]+) - (?P.*) - (?P
[0-9]+):(?P[0-9]+) ET - (?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+)Table (?P
[ a-zA-Z]+)\nSeat (?P
[- a-zA-Z]+) (\((?P.+)\) )?- \$?(?P[.0-9]+)/\$?(?P[.0-9]+) (Ante \$(?P[.0-9]+) )?- (?P[a-zA-Z\' ]+) - (?P.*)') + re_HandInfo = re.compile('''.*\#(?P[0-9]+):\s + Table\s(?P
[-\sa-zA-Z]+)\s + (\((?P.+)\)\s)?-\s + \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$(?P[.0-9]+)\s)?-\s + (?P[a-zA-Z\/\'\s]+)\s-\s + (?P.*) + ''', re.VERBOSE) re_Button = re.compile('^The button is in seat #(?P
[-\sa-zA-Z]+)\s + (?:(?P.+)\s\((?P\d+)\),\s)? + Table\s(?P
[-\s\da-zA-Z]+)\s (\((?P.+)\)\s)?-\s \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$(?P[.0-9]+)\s)?-\s (?P[a-zA-Z\/\'\s]+)\s-\s (?P.*) ''', re.VERBOSE) re_Button = re.compile('^The button is in seat #(?P
[-\s\da-zA-Z]+)\s + Table\s + (?PPlay\sChip\s|PC) + (?P
[-\s\da-zA-Z]+)\s (\((?P.+)\)\s)?-\s - \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$(?P[.0-9]+)\s)?-\s + \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$?(?P[.0-9]+)\s)?-\s (?P[a-zA-Z\/\'\s]+)\s-\s (?P.*) ''', re.VERBOSE) @@ -109,7 +111,6 @@ follow : whether to tail -f the input""" m = self.re_GameInfo.search(handText) if not m: return None - mg = m.groupdict() # translations from captured groups to our info strings @@ -119,8 +120,8 @@ follow : whether to tail -f the input""" 'Omaha Hi' : ('hold','omahahi'), 'Omaha H/L' : ('hold','omahahilo'), 'Razz' : ('stud','razz'), - '7 Card Stud' : ('stud','studhi'), - 'Stud H/L' : ('stud', 'studhilo') + 'Stud Hi' : ('stud','studhi'), + 'Stud H/L' : ('stud','studhilo') } currencies = { u' €':'EUR', '$':'USD', '':'T$' } info['limitType'] = limits[mg['LIMIT']] @@ -137,7 +138,7 @@ follow : whether to tail -f the input""" def readHandInfo(self, hand): m = self.re_HandInfo.search(hand.handText,re.DOTALL) - + print "m =", m.groupdict() if(m == None): logging.info("Didn't match re_HandInfo") logging.info(hand.handText) @@ -150,8 +151,8 @@ follow : whether to tail -f the input""" hand.maxseats = int(m2.group(2)) hand.tourNo = m.group('TOURNO') -# if key == 'PLAY' and info['PLAY'] != None: -# hand.gametype['currency'] = 'play' + if m.group('PLAY') != None: + hand.gametype['currency'] = 'play' # These work, but the info is already in the Hand class - should be used for tourneys though. # m.group('SB') @@ -214,6 +215,7 @@ follow : whether to tail -f the input""" m = self.re_Antes.finditer(hand.handText) for player in m: logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))) +# if player.group() != hand.addAnte(player.group('PNAME'), player.group('ANTE')) def readBringIn(self, hand): From 9d803957cb7638b1ad775ad6193f27c7f8e7af4f Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 22 Jul 2009 10:24:29 -0400 Subject: [PATCH 49/73] Detect mixed games in FTP HH. Fix typos. --- pyfpdb/FulltiltToFpdb.py | 11 ++++++++++- pyfpdb/Hand.py | 3 ++- pyfpdb/HandHistoryConverter.py | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index b860fe94..be3b6ba5 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -42,7 +42,7 @@ class Fulltilt(HandHistoryConverter): re_HandInfo = re.compile('''.*\#(?P[0-9]+):\s (?:(?P.+)\s\((?P\d+)\),\s)? Table\s - (?PPlay\sChip\s|PC) + (?PPlay\sChip\s|PC)? (?P
[-\s\da-zA-Z]+)\s (\((?P.+)\)\s)?-\s \$?(?P[.0-9]+)/\$?(?P[.0-9]+)\s(Ante\s\$?(?P[.0-9]+)\s)?-\s @@ -52,8 +52,11 @@ class Fulltilt(HandHistoryConverter): re_Button = re.compile('^The button is in seat #(?P