Added support for board cards in FTP run it twice (RIT) hands. Hands continues to store the standard board for the hand, while run it twice board cards dealt after the all in are stored in the new Boards table. Designed to allow for more than 2 boards if a hand history allows it. Can be enabled for other sites by adding regex to detect multiple FLOP|TURN|RIVER deals in hhc.markStreets, and by updating hhc.readCommunityCards to save RIT streets and set hand.runItTimes with the number of deals. The Hands table now includes a 'runIt' BOOL indicating if a hands was run multiple times and board inserts are done in the storeHand method.
This commit is contained in:
parent
f55cd5569d
commit
d98a28ea0a
|
@ -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
|
||||
|
||||
|
|
|
@ -144,6 +144,20 @@ class DerivedStats():
|
|||
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()
|
||||
totals = [int(100*i) for i in totals]
|
||||
|
|
|
@ -381,10 +381,16 @@ class Fulltilt(HandHistoryConverter):
|
|||
def markStreets(self, hand):
|
||||
|
||||
if hand.gametype['base'] == 'hold':
|
||||
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
|
||||
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
|
||||
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
|
||||
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL)
|
||||
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP (1\s)?\*\*\*)|.+)"
|
||||
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN (1\s)?\*\*\*)|.+))?"
|
||||
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER (1\s)?\*\*\*)|.+))?"
|
||||
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?"
|
||||
r"(\*\*\* FLOP 1 \*\*\*(?P<FLOP1> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN 1 \*\*\*)|.+))?"
|
||||
r"(\*\*\* TURN 1 \*\*\* \[\S\S \S\S \S\S] (?P<TURN1>\[\S\S\].+(?=\*\*\* RIVER 1 \*\*\*)|.+))?"
|
||||
r"(\*\*\* RIVER 1 \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER1>\[\S\S\].))?"
|
||||
r"(\*\*\* FLOP 2 \*\*\*(?P<FLOP2> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN 2 \*\*\*)|.+))?"
|
||||
r"(\*\*\* TURN 2 \*\*\* \[\S\S \S\S \S\S] (?P<TURN2>\[\S\S\].+(?=\*\*\* RIVER 2 \*\*\*)|.+))?"
|
||||
r"(\*\*\* RIVER 2 \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER2>\[\S\S\].+))?", hand.handText,re.DOTALL)
|
||||
elif hand.gametype['base'] == "stud":
|
||||
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3RD STREET \*\*\*)|.+)"
|
||||
r"(\*\*\* 3RD STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
@ -470,6 +473,42 @@ class Sql:
|
|||
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)"""
|
||||
|
||||
|
||||
################################
|
||||
# Create TourneyTypes
|
||||
|
@ -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 (
|
||||
|
@ -5053,6 +5094,20 @@ class Sql:
|
|||
%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
|
||||
################################
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user