diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 8c7ef50d..d3deb578 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -126,6 +126,7 @@ class Database: , {'tab':'Hands', 'col':'gametypeId', 'drop':0} # mct 22/3/09 #, {'tab':'Hands', 'col':'siteHandNo', 'drop':0} unique indexes not dropped , {'tab':'HandsActions', 'col':'handsPlayerId', 'drop':0} + , {'tab':'HandsActions', 'col':'actionId', 'drop':1} , {'tab':'HandsPlayers', 'col':'handId', 'drop':1} , {'tab':'HandsPlayers', 'col':'playerId', 'drop':1} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} @@ -149,6 +150,8 @@ class Database: , {'tab':'HandsPlayers', 'col':'handId', 'drop':0} , {'tab':'HandsPlayers', 'col':'playerId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} + , {'tab':'HandsActions', 'col':'handsPlayerId', 'drop':0} + , {'tab':'HandsActions', 'col':'actionId', 'drop':1} , {'tab':'HudCache', 'col':'gametypeId', 'drop':1} , {'tab':'HudCache', 'col':'playerId', 'drop':0} , {'tab':'HudCache', 'col':'tourneyTypeId', 'drop':0} @@ -172,6 +175,7 @@ class Database: , {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'tourneysPlayersId','rtab':'TourneysPlayers','rcol':'id', 'drop':1} , {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1} + , {'fktab':'HandsActions', 'fkcol':'actionId', 'rtab':'Actions', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':0} , {'fktab':'HudCache', 'fkcol':'tourneyTypeId', 'rtab':'TourneyTypes', 'rcol':'id', 'drop':1} @@ -181,6 +185,7 @@ class Database: , {'fktab':'HandsPlayers', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1} , {'fktab':'HandsActions', 'fkcol':'handsPlayerId', 'rtab':'HandsPlayers', 'rcol':'id', 'drop':1} + , {'fktab':'HandsActions', 'fkcol':'actionId', 'rtab':'Actions', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'HudCache', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':0} , {'fktab':'HudCache', 'fkcol':'tourneyTypeId', 'rtab':'TourneyTypes', 'rcol':'id', 'drop':1} @@ -302,7 +307,7 @@ class Database: tables=self.cursor.execute(self.sql.query['list_tables']) tables=self.cursor.fetchall() - for table in (u'Autorates', u'Backings', u'Gametypes', u'Hands', u'HandsActions', u'HandsPlayers', u'HudCache', u'Players', u'RawHands', u'RawTourneys', u'Settings', u'Sites', u'TourneyTypes', u'Tourneys', u'TourneysPlayers'): + for table in (u'Actions', u'Autorates', u'Backings', u'Gametypes', u'Hands', u'HandsActions', u'HandsPlayers', u'HudCache', u'Players', u'RawHands', u'RawTourneys', u'Settings', u'Sites', u'TourneyTypes', u'Tourneys', u'TourneysPlayers'): print "table:", table result+="###################\nTable "+table+"\n###################\n" rows=self.cursor.execute(self.sql.query['get'+table]) @@ -1151,6 +1156,7 @@ class Database: c.execute(self.sql.query['createSettingsTable']) log.debug("Creating tables") + c.execute(self.sql.query['createActionsTable']) c.execute(self.sql.query['createSitesTable']) c.execute(self.sql.query['createGametypesTable']) c.execute(self.sql.query['createPlayersTable']) @@ -1422,6 +1428,7 @@ class Database: def fillDefaultData(self): c = self.get_cursor() c.execute("INSERT INTO Settings (version) VALUES (%s);" % (DB_VERSION)) + #Fill Sites c.execute("INSERT INTO Sites (name,code) VALUES ('Full Tilt Poker', 'FT')") c.execute("INSERT INTO Sites (name,code) VALUES ('PokerStars', 'PS')") c.execute("INSERT INTO Sites (name,code) VALUES ('Everleaf', 'EV')") @@ -1436,6 +1443,22 @@ class Database: c.execute("INSERT INTO Sites (name,code) VALUES ('PKR', 'PK')") c.execute("INSERT INTO Sites (name,code) VALUES ('iPoker', 'IP')") c.execute("INSERT INTO Sites (name,code) VALUES ('Winamax', 'WM')") + #Fill Actions + c.execute("INSERT INTO Actions (name,code) VALUES ('ante', 'A')") + c.execute("INSERT INTO Actions (name,code) VALUES ('small blind', 'SB')") + c.execute("INSERT INTO Actions (name,code) VALUES ('secondsb', 'SSB')") + c.execute("INSERT INTO Actions (name,code) VALUES ('big blind', 'BB')") + c.execute("INSERT INTO Actions (name,code) VALUES ('both', 'SBBB')") + c.execute("INSERT INTO Actions (name,code) VALUES ('calls', 'C')") + c.execute("INSERT INTO Actions (name,code) VALUES ('raises', 'R')") + c.execute("INSERT INTO Actions (name,code) VALUES ('bets', 'B')") + c.execute("INSERT INTO Actions (name,code) VALUES ('stands pat', 'S')") + c.execute("INSERT INTO Actions (name,code) VALUES ('folds', 'F')") + c.execute("INSERT INTO Actions (name,code) VALUES ('checks', 'K')") + c.execute("INSERT INTO Actions (name,code) VALUES ('discards', 'D')") + c.execute("INSERT INTO Actions (name,code) VALUES ('bringin', 'I')") + c.execute("INSERT INTO Actions (name,code) VALUES ('completes', 'P')") + #end def fillDefaultData def rebuild_indexes(self, start=None): @@ -1653,6 +1676,7 @@ class Database: pp.pprint(pdata) inserts = [] + hpid = {} for p in pdata: inserts.append( (hid, pids[p], @@ -1757,39 +1781,41 @@ class Database: #print "DEBUG: inserts: %s" %inserts #print "DEBUG: q: %s" % q c = self.get_cursor() - c.executemany(q, inserts) + + for r in inserts: + c.execute(q, r) + hpid[(r[0], r[1])] = self.get_last_insert_id(c) + + return hpid - def storeHandsActions(self, hid, pids, adata, printdata = False): + def storeHandsActions(self, hid, pids, hpid, adata, printdata = False): #print "DEBUG: %s %s %s" %(hid, pids, adata) if printdata: import pprint pp = pprint.PrettyPrinter(indent=4) pp.pprint(adata) - #inserts = [] - #for p in pdata: - # inserts.append( (hid, - # pids[p], - # adata[p]['startCash'], - # adata[p]['seatNo'], - # adata[p]['sitout'], - # adata[p]['card1'], - - #handsPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), - #street SMALLINT NOT NULL, - #actionNo SMALLINT NOT NULL, - #action CHAR(5) NOT NULL, - #allIn BOOLEAN NOT NULL, - #amount INT NOT NULL, - + inserts = [] + for a in adata: + inserts.append( (hpid[(hid, pids[adata[a]['player']])], + #self.getHandsPlayerId(self.hid, pids[adata[a]['player']]), + adata[a]['street'], + adata[a]['actionNo'], + adata[a]['streetActionNo'], + adata[a]['actionId'], + adata[a]['amount'], + adata[a]['raiseTo'], + adata[a]['amountCalled'], + adata[a]['numDiscarded'], + adata[a]['cardsDiscarded'], + adata[a]['allIn'] + ) ) q = self.sql.query['store_hands_actions'] - #q = q.replace('%s', self.sql.query['placeholder']) + q = q.replace('%s', self.sql.query['placeholder']) - #print "DEBUG: inserts: %s" %inserts - #print "DEBUG: q: %s" % q - #c = self.get_cursor() - #c.executemany(q, inserts) + c = self.get_cursor() + c.executemany(q, inserts) def storeHudCache(self, gid, pids, starttime, pdata): """Update cached statistics. If update fails because no record exists, do an insert.""" diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 1172d1f0..131ee3a3 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -23,13 +23,6 @@ import logging # logging has been set up in fpdb.py or HUD_main.py, use their settings: log = logging.getLogger("parser") -DEBUG = False - -if DEBUG: - import pprint - pp = pprint.PrettyPrinter(indent=4) - - class DerivedStats(): def __init__(self, hand): self.hand = hand @@ -93,17 +86,9 @@ class DerivedStats(): self.assembleHands(self.hand) self.assembleHandsPlayers(self.hand) - if DEBUG: + if self.hand.saveActions: self.assembleHandsActions(self.hand) - if DEBUG: - #print "Hands:" - #pp.pprint(self.hands) - #print "HandsPlayers:" - #pp.pprint(self.handsplayers) - print "HandsActions:" - pp.pprint(self.handsactions) - def getHands(self): return self.hands @@ -216,9 +201,35 @@ class DerivedStats(): # Squeeze, Ratchet? def assembleHandsActions(self, hand): - print "DEBUG: hand.actions" - pp.pprint(hand.actions) - pass + k = 0 + for i, street in enumerate(hand.actionStreets): + for j, act in enumerate(hand.actions[street]): + k += 1 + self.handsactions[k] = {} + #default values + self.handsactions[k]['amount'] = 0 + self.handsactions[k]['raiseTo'] = 0 + self.handsactions[k]['amountCalled'] = 0 + self.handsactions[k]['numDiscarded'] = 0 + self.handsactions[k]['cardsDiscarded'] = None + self.handsactions[k]['allIn'] = False + #Insert values from hand.actions + self.handsactions[k]['player'] = act[0] + self.handsactions[k]['street'] = i-1 + self.handsactions[k]['actionNo'] = k + self.handsactions[k]['streetActionNo'] = (j+1) + self.handsactions[k]['actionId'] = hand.ACTION[act[1]] + if act[1] not in ('discards') and len(act) > 2: + self.handsactions[k]['amount'] = int(100 * act[2]) + if act[1] in ('raises', 'completes'): + self.handsactions[k]['raiseTo'] = int(100 * act[3]) + self.handsactions[k]['amountCalled'] = int(100 * act[4]) + if act[1] in ('discards'): + self.handsactions[k]['numDiscarded'] = int(act[2]) + if act[1] in ('discards') and len(act) > 3: + self.handsactions[k]['cardsDiscarded'] = act[3] + if len(act) > 3 and act[1] not in ('discards'): + self.handsactions[k]['allIn'] = act[-1] def setPositions(self, hand): """Sets the position for each player in HandsPlayers diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 6d780aa2..0909d42d 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -49,11 +49,14 @@ class Hand(object): LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} SYMBOL = {'USD': '$', 'EUR': u'$', 'GBP': '$', 'T$': '', 'play': ''} MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE', 'ha': 'HA'} + ACTION = {'ante': 1, 'small blind': 2, 'secondsb': 3, 'big blind': 4, 'both': 5, 'calls': 6, 'raises': 7, + 'bets': 8, 'stands pat': 9, 'folds': 10, 'checks': 11, 'discards': 12, 'bringin': 13, 'completes': 14} def __init__(self, config, sitename, gametype, handText, builtFrom = "HHC"): #log.debug( _("Hand.init(): handText is ") + str(handText) ) self.config = config + self.saveActions = self.config.get_import_parameters().get('saveActions') #log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log) self.sitename = sitename self.siteId = self.config.get_site_id(sitename) @@ -65,6 +68,7 @@ class Hand(object): self.cancelled = False self.dbid_hands = 0 self.dbid_pids = None + self.dbid_hpid = None self.dbid_gt = 0 self.tablename = "" self.hero = "" @@ -262,10 +266,11 @@ db: a connected Database object""" hh['seats'] = len(self.dbid_pids) self.dbid_hands = db.storeHand(hh) - db.storeHandsPlayers(self.dbid_hands, self.dbid_pids, self.stats.getHandsPlayers(), printdata = printtest) - # TODO HandsActions - all actions for all players for all streets - self.actions - # HudCache data can be generated from HandsActions (HandsPlayers?) - #db.storeHandsActions(self.dbid_hands, self.dbid_pids, self.stats.getHandsActions(), printdata = printtest) + self.dbid_hpid = db.storeHandsPlayers(self.dbid_hands, self.dbid_pids, + self.stats.getHandsPlayers(), printdata = printtest) + if self.saveActions: + db.storeHandsActions(self.dbid_hands, self.dbid_pids, self.dbid_hpid, + self.stats.getHandsActions(), printdata = printtest) else: log.info(_("Hand.insert(): hid #: %s is a duplicate") % hh['siteHandNo']) self.is_duplicate = True # i.e. don't update hudcache @@ -350,7 +355,7 @@ For sites (currently only Carbon Poker) which record "all in" as a special actio ante = re.sub(u',', u'', ante) #some sites have commas self.bets['BLINDSANTES'][player].append(Decimal(ante)) self.stacks[player] -= Decimal(ante) - act = (player, 'posts', "ante", ante, self.stacks[player]==0) + act = (player, 'ante', Decimal(ante), self.stacks[player]==0) self.actions['BLINDSANTES'].append(act) # self.pot.addMoney(player, Decimal(ante)) self.pot.addCommonMoney(player, Decimal(ante)) @@ -369,7 +374,7 @@ For sites (currently only Carbon Poker) which record "all in" as a special actio if player is not None: amount = re.sub(u',', u'', amount) #some sites have commas self.stacks[player] -= Decimal(amount) - act = (player, 'posts', blindtype, amount, self.stacks[player]==0) + act = (player, blindtype, Decimal(amount), self.stacks[player]==0) self.actions['BLINDSANTES'].append(act) if blindtype == 'both': @@ -402,7 +407,7 @@ For sites (currently only Carbon Poker) which record "all in" as a special actio #self.lastBet[street] = Decimal(amount) self.stacks[player] -= Decimal(amount) #print "DEBUG %s calls %s, stack %s" % (player, amount, self.stacks[player]) - act = (player, 'calls', amount, self.stacks[player]==0) + act = (player, 'calls', Decimal(amount), self.stacks[player]==0) self.actions[street].append(act) self.pot.addMoney(player, Decimal(amount)) @@ -463,11 +468,11 @@ Add a raise on [street] by [player] to [amountTo] Rb = Rt - C - Bc self._addRaise(street, player, C, Rb, Rt) - def _addRaise(self, street, player, C, Rb, Rt): + def _addRaise(self, street, player, C, Rb, Rt, action = 'raises'): log.debug(_("%s %s raise %s") %(street, player, Rt)) self.bets[street][player].append(C + Rb) self.stacks[player] -= (C + Rb) - act = (player, 'raises', Rb, Rt, C, self.stacks[player]==0) + act = (player, action, Rb, Rt, C, self.stacks[player]==0) self.actions[street].append(act) self.lastBet[street] = Rt # TODO check this is correct self.pot.addMoney(player, C+Rb) @@ -481,7 +486,7 @@ Add a raise on [street] by [player] to [amountTo] self.bets[street][player].append(Decimal(amount)) self.stacks[player] -= Decimal(amount) #print "DEBUG %s bets %s, stack %s" % (player, amount, self.stacks[player]) - act = (player, 'bets', amount, self.stacks[player]==0) + act = (player, 'bets', Decimal(amount), self.stacks[player]==0) self.actions[street].append(act) self.lastBet[street] = Decimal(amount) self.pot.addMoney(player, Decimal(amount)) @@ -1020,7 +1025,7 @@ class DrawHand(Hand): self.bets['DEAL'][player].append(Decimal(amount)) self.stacks[player] -= Decimal(amount) #print "DEBUG %s posts, stack %s" % (player, self.stacks[player]) - act = (player, 'posts', blindtype, amount, self.stacks[player]==0) + act = (player, blindtype, Decimal(amount), self.stacks[player]==0) self.actions['BLINDSANTES'].append(act) self.pot.addMoney(player, Decimal(amount)) if blindtype == 'big blind': @@ -1050,10 +1055,10 @@ class DrawHand(Hand): def addDiscard(self, street, player, num, cards): self.checkPlayerExists(player) if cards: - act = (player, 'discards', num, cards) + act = (player, 'discards', Decimal(num), cards) self.discardDrawHoleCards(cards, player, street) else: - act = (player, 'discards', num) + act = (player, 'discards', Decimal(num)) self.actions[street].append(act) def holecardsAsSet(self, street, player): @@ -1246,7 +1251,7 @@ Add a complete on [street] by [player] to [amountTo] Rt = Decimal(amountTo) C = Bp - Bc Rb = Rt - C - self._addRaise(street, player, C, Rb, Rt) + self._addRaise(street, player, C, Rb, Rt, 'completes') #~ self.bets[street][player].append(C + Rb) #~ self.stacks[player] -= (C + Rb) #~ act = (player, 'raises', Rb, Rt, C, self.stacks[player]==0) @@ -1259,7 +1264,7 @@ Add a complete on [street] by [player] to [amountTo] log.debug(_("Bringin: %s, %s") % (player , bringin)) self.bets['THIRD'][player].append(Decimal(bringin)) self.stacks[player] -= Decimal(bringin) - act = (player, 'bringin', bringin, self.stacks[player]==0) + act = (player, 'bringin', Decimal(bringin), self.stacks[player]==0) self.actions['THIRD'].append(act) self.lastBet['THIRD'] = Decimal(bringin) self.pot.addMoney(player, Decimal(bringin)) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 2994515f..25dd36e5 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -153,7 +153,28 @@ class Sql: tourneyId BIGINT NOT NULL, rawTourney TEXT NOT NULL, complain BOOLEAN NOT NULL DEFAULT FALSE)""" - + + ################################ + # Create Actions + ################################ + + if db_server == 'mysql': + self.query['createActionsTable'] = """CREATE TABLE Actions ( + id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + name varchar(32) NOT NULL, + code char(2) NOT NULL) + ENGINE=INNODB""" + elif db_server == 'postgresql': + self.query['createActionsTable'] = """CREATE TABLE Actions ( + id SERIAL, PRIMARY KEY (id), + name varchar(32), + code char(2))""" + elif db_server == 'sqlite': + self.query['createActionsTable'] = """CREATE TABLE Actions ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + code TEXT NOT NULL)""" + ################################ # Create Sites ################################ @@ -989,11 +1010,14 @@ class Sql: handsPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), street SMALLINT NOT NULL, actionNo SMALLINT NOT NULL, - action CHAR(5) NOT NULL, - allIn BOOLEAN NOT NULL, + streetActionNo SMALLINT NOT NULL, + actionId SMALLINT NOT NULL, FOREIGN KEY (actionId) REFERENCES Actions(id), amount INT NOT NULL, - comment TEXT, - commentTs DATETIME) + raiseTo INT NOT NULL, + amountCalled INT NOT NULL, + numDiscarded SMALLINT NOT NULL, + cardsDiscarded varchar(14), + allIn BOOLEAN NOT NULL) ENGINE=INNODB""" elif db_server == 'postgresql': self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( @@ -1001,24 +1025,31 @@ class Sql: handsPlayerId BIGINT, FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), street SMALLINT, actionNo SMALLINT, - action CHAR(5), - allIn BOOLEAN, + streetActionNo SMALLINT, + actionId SMALLINT, FOREIGN KEY (actionId) REFERENCES Actions(id), amount INT, - comment TEXT, - commentTs timestamp without time zone)""" + raiseTo INT, + amountCalled INT, + numDiscarded SMALLINT, + cardsDiscarded varchar(14), + allIn BOOLEAN)""" elif db_server == 'sqlite': self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions ( id INTEGER PRIMARY KEY, handsPlayerId BIGINT, street SMALLINT, actionNo SMALLINT, - action CHAR(5), - allIn INT, + streetActionNo SMALLINT, + actionId SMALLINT, amount INT, - comment TEXT, - commentTs timestamp without time zone, - FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id) - )""" + raiseTo INT, + amountCalled INT, + numDiscarded SMALLINT, + cardsDiscarded TEXT, + allIn BOOLEAN, + FOREIGN KEY (handsPlayerId) REFERENCES HandsPlayers(id), + FOREIGN KEY (actionId) REFERENCES Actions(id) ON DELETE CASCADE + )""" ################################ @@ -4251,11 +4282,17 @@ class Sql: handsPlayerId, street, actionNo, - action, - allIn, - amount + streetActionNo, + actionId, + amount, + raiseTo, + amountCalled, + numDiscarded, + cardsDiscarded, + allIn ) VALUES ( + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )"""