diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0bf5bd5b..f017f601 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -73,7 +73,7 @@ except ImportError: use_numpy = False -DB_VERSION = 153 +DB_VERSION = 154 # Variance created as sqlite has a bunch of undefined aggregate functions. @@ -129,6 +129,7 @@ class Database: , {'tab':'HandsActions', 'col':'handId', 'drop':1} , {'tab':'HandsActions', 'col':'playerId', 'drop':1} , {'tab':'HandsActions', 'col':'actionId', 'drop':1} + , {'tab':'Boards', 'col':'handId', 'drop':1} , {'tab':'HandsPlayers', 'col':'handId', 'drop':1} , {'tab':'HandsPlayers', 'col':'playerId', 'drop':1} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} @@ -153,6 +154,7 @@ class Database: , [ # indexes for sqlite (list index 4) {'tab':'Hands', 'col':'gametypeId', 'drop':0} , {'tab':'Hands', 'col':'fileId', 'drop':0} + , {'tab':'Boards', 'col':'handId', 'drop':0} , {'tab':'HandsPlayers', 'col':'handId', 'drop':0} , {'tab':'HandsPlayers', 'col':'playerId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} @@ -182,6 +184,7 @@ class Database: , [ # foreign keys for mysql (index 2) {'fktab':'Hands', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'Hands', 'fkcol':'fileId', 'rtab':'Files', 'rcol':'id', 'drop':1} + , {'fktab':'Boards', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'tourneysPlayersId','rtab':'TourneysPlayers','rcol':'id', 'drop':1} @@ -198,6 +201,7 @@ class Database: , [ # foreign keys for postgres (index 3) {'fktab':'Hands', 'fkcol':'gametypeId', 'rtab':'Gametypes', 'rcol':'id', 'drop':1} , {'fktab':'Hands', 'fkcol':'fileId', 'rtab':'Files', 'rcol':'id', 'drop':1} + , {'fktab':'Boards', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} , {'fktab':'HandsPlayers', 'fkcol':'playerId', 'rtab':'Players', 'rcol':'id', 'drop':1} , {'fktab':'HandsActions', 'fkcol':'handId', 'rtab':'Hands', 'rcol':'id', 'drop':1} @@ -336,7 +340,7 @@ class Database: tables=self.cursor.execute(self.sql.query['list_tables']) tables=self.cursor.fetchall() - for table in (u'Actions', u'Autorates', u'Backings', u'Gametypes', u'Hands', u'HandsActions', u'HandsPlayers', u'Files', u'HudCache', u'SessionsCache', 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'Boards', u'HandsActions', u'HandsPlayers', u'Files', u'HudCache', u'SessionsCache', 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]) @@ -1265,6 +1269,7 @@ class Database: c.execute(self.sql.query['createPlayersTable']) c.execute(self.sql.query['createAutoratesTable']) c.execute(self.sql.query['createHandsTable']) + c.execute(self.sql.query['createBoardsTable']) c.execute(self.sql.query['createTourneyTypesTable']) c.execute(self.sql.query['createTourneysTable']) c.execute(self.sql.query['createTourneysPlayersTable']) @@ -1875,6 +1880,7 @@ class Database: hdata['boardcard3'], hdata['boardcard4'], hdata['boardcard5'], + hdata['runIt'], hdata['playersAtStreet1'], hdata['playersAtStreet2'], hdata['playersAtStreet3'], @@ -1890,19 +1896,28 @@ class Database: hdata['street3Pot'], hdata['street4Pot'], hdata['showdownPot'], + hdata['boards'], hdata['id'] ]) if doinsert: + bbulk = [] for h in hbulk: id = h.pop() if hdata['sc'] and hdata['gsc']: h[4] = hdata['sc'][id]['id'] h[5] = hdata['gsc'][id]['id'] + boards = h.pop() + for b in boards: + bbulk += [[id] + b] q = self.sql.query['store_hand'] q = q.replace('%s', self.sql.query['placeholder']) c = self.get_cursor() c.executemany(q, hbulk) + q = self.sql.query['store_boards'] + q = q.replace('%s', self.sql.query['placeholder']) + c = self.get_cursor() + c.executemany(q, bbulk) self.commit() return hbulk diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index d29a33ad..6cc97d09 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -143,6 +143,20 @@ class DerivedStats(): self.hands['boardcard3'] = cards[2] self.hands['boardcard4'] = cards[3] self.hands['boardcard5'] = cards[4] + + self.hands['boards'] = [] + self.hands['runIt'] = False + for i in range(hand.runItTimes): + self.hands['runIt'] = True + boardcards = [] + for street in hand.communityStreets: + boardId = i+1 + street_i = street + str(boardId) + if street_i in hand.board: + boardcards += hand.board[street_i] + boardcards = [u'0x', u'0x', u'0x', u'0x', u'0x'] + boardcards + cards = [Card.encodeCard(c) for c in boardcards[-5:]] + self.hands['boards'] += [[boardId] + cards] #print "DEBUG: self.getStreetTotals = (%s, %s, %s, %s, %s)" % hand.getStreetTotals() totals = hand.getStreetTotals() diff --git a/pyfpdb/FulltiltToFpdb.py b/pyfpdb/FulltiltToFpdb.py index 4e956650..31f889b0 100755 --- a/pyfpdb/FulltiltToFpdb.py +++ b/pyfpdb/FulltiltToFpdb.py @@ -381,10 +381,16 @@ class Fulltilt(HandHistoryConverter): def markStreets(self, hand): if hand.gametype['base'] == '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(r"\*\*\* HOLE CARDS \*\*\*(?P.+(?=\*\*\* FLOP (1\s)?\*\*\*)|.+)" + r"(\*\*\* FLOP \*\*\*(?P \[\S\S \S\S \S\S\].+(?=\*\*\* TURN (1\s)?\*\*\*)|.+))?" + r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P\[\S\S\].+(?=\*\*\* RIVER (1\s)?\*\*\*)|.+))?" + r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P\[\S\S\].+))?" + r"(\*\*\* FLOP 1 \*\*\*(?P \[\S\S \S\S \S\S\].+(?=\*\*\* TURN 1 \*\*\*)|.+))?" + r"(\*\*\* TURN 1 \*\*\* \[\S\S \S\S \S\S] (?P\[\S\S\].+(?=\*\*\* RIVER 1 \*\*\*)|.+))?" + r"(\*\*\* RIVER 1 \*\*\* \[\S\S \S\S \S\S \S\S] (?P\[\S\S\].))?" + r"(\*\*\* FLOP 2 \*\*\*(?P \[\S\S \S\S \S\S\].+(?=\*\*\* TURN 2 \*\*\*)|.+))?" + r"(\*\*\* TURN 2 \*\*\* \[\S\S \S\S \S\S] (?P\[\S\S\].+(?=\*\*\* RIVER 2 \*\*\*)|.+))?" + r"(\*\*\* RIVER 2 \*\*\* \[\S\S \S\S \S\S \S\S] (?P\[\S\S\].+))?", hand.handText,re.DOTALL) elif hand.gametype['base'] == "stud": m = re.search(r"(?P.+(?=\*\*\* 3RD STREET \*\*\*)|.+)" r"(\*\*\* 3RD STREET \*\*\*(?P.+(?=\*\*\* 4TH STREET \*\*\*)|.+))?" @@ -403,10 +409,13 @@ class Fulltilt(HandHistoryConverter): def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP) - #print "DEBUG readCommunityCards:", street, hand.streets.group(street) + #print "DEBUG readCommunityCards:", street, hand.streets[street] m = self.re_Board.search(hand.streets[street]) hand.setCommunityCards(street, m.group('CARDS').split(' ')) - + if street in ('FLOP1', 'TURN1', 'RIVER1', 'FLOP2', 'TURN2', 'RIVER2'): + m = self.re_Board.search(hand.streets[street]) + hand.setCommunityCards(street, m.group('CARDS').split(' ')) + hand.runItTimes = 2 def readBlinds(self, hand): try: diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 4e5249a3..ae53bafa 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -77,6 +77,7 @@ class Hand(object): self.maxseats = None self.counted_seats = 0 self.buttonpos = 0 + self.runItTimes = 0 #tourney stuff self.tourNo = None @@ -887,9 +888,8 @@ class HoldemOmahaHand(Hand): hhc.readHeroCards(self) hhc.readShowdownActions(self) # Read actions in street order - for street in self.communityStreets: - if self.streets[street]: - hhc.readCommunityCards(self, street) + for street, text in self.streets.iteritems(): + if text: hhc.readCommunityCards(self, street) for street in self.actionStreets: if self.streets[street]: hhc.readAction(self, street) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index cf054d7e..a7cc824e 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -372,6 +372,7 @@ class Sql: boardcard4 smallint, boardcard5 smallint, texture smallint, + runIt BOOLEAN, playersVpi SMALLINT NOT NULL, /* num of players vpi */ playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */ playersAtStreet2 SMALLINT NOT NULL, @@ -412,6 +413,7 @@ class Sql: boardcard4 smallint, boardcard5 smallint, texture smallint, + runIt BOOLEAN, playersVpi SMALLINT NOT NULL, /* num of players vpi */ playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */ playersAtStreet2 SMALLINT NOT NULL, @@ -451,6 +453,7 @@ class Sql: boardcard4 INT, boardcard5 INT, texture INT, + runIt BOOLEAN, playersVpi INT NOT NULL, /* num of players vpi */ playersAtStreet1 INT NOT NULL, /* num of players seeing flop/street4 */ playersAtStreet2 INT NOT NULL, @@ -469,6 +472,42 @@ class Sql: showdownPot INT, /* pot size at sd/street7 */ comment TEXT, commentTs REAL)""" + + ################################ + # Create Hands + ################################ + + if db_server == 'mysql': + self.query['createBoardsTable'] = """CREATE TABLE Boards ( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), + handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), + boardId smallint, + boardcard1 smallint, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */ + boardcard2 smallint, + boardcard3 smallint, + boardcard4 smallint, + boardcard5 smallint) + ENGINE=INNODB""" + elif db_server == 'postgresql': + self.query['createBoardsTable'] = """CREATE TABLE Boards ( + id BIGSERIAL, PRIMARY KEY (id), + handId BIGINT NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), + boardId smallint, + boardcard1 smallint, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */ + boardcard2 smallint, + boardcard3 smallint, + boardcard4 smallint, + boardcard5 smallint)""" + elif db_server == 'sqlite': + self.query['createBoardsTable'] = """CREATE TABLE Boards ( + id INTEGER PRIMARY KEY, + handId INT NOT NULL, + boardId INT, + boardcard1 INT, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */ + boardcard2 INT, + boardcard3 INT, + boardcard4 INT, + boardcard5 INT)""" ################################ @@ -4865,6 +4904,7 @@ class Sql: boardcard3, boardcard4, boardcard5, + runIt, playersAtStreet1, playersAtStreet2, playersAtStreet3, @@ -4884,7 +4924,8 @@ class Sql: values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s)""" self.query['store_hands_players'] = """insert into HandsPlayers ( @@ -5052,6 +5093,20 @@ class Sql: %s, %s, %s, %s, %s, %s, %s )""" + + self.query['store_boards'] = """insert into Boards ( + handId, + boardId, + boardcard1, + boardcard2, + boardcard3, + boardcard4, + boardcard5 + ) + values ( + %s, %s, %s, %s, %s, + %s, %s + )""" ################################ # queries for Files Table diff --git a/pyfpdb/TestHandsPlayers.py b/pyfpdb/TestHandsPlayers.py index 72f99bfe..b94344de 100755 --- a/pyfpdb/TestHandsPlayers.py +++ b/pyfpdb/TestHandsPlayers.py @@ -152,6 +152,7 @@ def compare_hands_file(filename, importer, errors): # Delete unused data from hash del ghash['gsc'] del ghash['sc'] + del ghash['boards'] for datum in ghash: #print "DEBUG: hand: '%s'" % datum try: @@ -164,7 +165,8 @@ def compare_hands_file(filename, importer, errors): or datum == 'sessionId' or datum == 'tourneyId' or datum == 'gameSessionId' - or datum == 'fileId'): + or datum == 'fileId' + or datum == 'runIt'): # Not an error. gametypeIds are dependent on the order added to the db. #print "DEBUG: Skipping mismatched gamtypeId" pass