Merge branch 'master' of git://git.assembla.com/fpt_fpdb

Conflicts:
	pyfpdb/Database.py
This commit is contained in:
Worros 2009-09-04 12:45:49 +08:00
commit 4f98b29b26
8 changed files with 593 additions and 90 deletions

View File

@ -42,6 +42,7 @@ import fpdb_simple
import Configuration import Configuration
import SQL import SQL
import Card import Card
import Tourney
from Exceptions import * from Exceptions import *
import logging, logging.config import logging, logging.config
@ -608,7 +609,7 @@ class Database:
hands_players_ids = self.store_hands_players_holdem_omaha_tourney( hands_players_ids = self.store_hands_players_holdem_omaha_tourney(
self.backend, category, hands_id, player_ids, start_cashes, positions self.backend, category, hands_id, player_ids, start_cashes, positions
, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids
, hudImportData) , hudImportData, tourneyTypeId)
#print "tourney holdem, backend=%d" % backend #print "tourney holdem, backend=%d" % backend
if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop':
@ -636,7 +637,7 @@ class Database:
hands_players_ids = self.store_hands_players_stud_tourney(self.backend, hands_id hands_players_ids = self.store_hands_players_stud_tourney(self.backend, hands_id
, playerIds, startCashes, antes, cardValues, cardSuits , playerIds, startCashes, antes, cardValues, cardSuits
, winnings, rakes, seatNos, tourneys_players_ids) , winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId)
if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop':
self.storeHudCache(self.backend, base, category, gametypeId, hand_start_time, playerIds, hudImportData) self.storeHudCache(self.backend, base, category, gametypeId, hand_start_time, playerIds, hudImportData)
@ -995,12 +996,10 @@ class Database:
c.execute("INSERT INTO Sites (name,currency) VALUES ('Absolute', 'USD')") c.execute("INSERT INTO Sites (name,currency) VALUES ('Absolute', 'USD')")
c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')") c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')")
if self.backend == self.SQLITE: if self.backend == self.SQLITE:
c.execute("INSERT INTO TourneyTypes VALUES (NULL, 1, 0, 0, 0, 0);") c.execute("INSERT INTO TourneyTypes (id, siteId, buyin, fee) VALUES (NULL, 1, 0, 0);")
else: else:
c.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") c.execute("INSERT INTO TourneyTypes (siteId, buyin, fee) VALUES (1, 0, 0);")
#c.execute("""INSERT INTO TourneyTypes
# (siteId,buyin,fee,knockout,rebuyOrAddon) VALUES
# (1,0,0,0,?)""",(False,) )
#end def fillDefaultData #end def fillDefaultData
def rebuild_hudcache(self): def rebuild_hudcache(self):
@ -1314,7 +1313,7 @@ class Database:
raise FpdbError("invalid category") raise FpdbError("invalid category")
inserts.append( ( inserts.append( (
hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid hands_id, player_ids[i], start_cashes[i], positions[i],
card1, card2, card3, card4, startCards, card1, card2, card3, card4, startCards,
winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i],
hudCache['street0VPI'][i], hudCache['street0Aggr'][i], hudCache['street0VPI'][i], hudCache['street0Aggr'][i],
@ -1345,7 +1344,7 @@ class Database:
c = self.get_cursor() c = self.get_cursor()
c.executemany (""" c.executemany ("""
INSERT INTO HandsPlayers INSERT INTO HandsPlayers
(handId, playerId, startCash, position, tourneyTypeId, (handId, playerId, startCash, position,
card1, card2, card3, card4, startCards, winnings, rake, seatNo, totalProfit, card1, card2, card3, card4, startCards, winnings, rake, seatNo, totalProfit,
street0VPI, street0Aggr, street0_3BChance, street0_3BDone, street0VPI, street0Aggr, street0_3BChance, street0_3BDone,
street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown,
@ -1366,7 +1365,7 @@ class Database:
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 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, %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, %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)""".replace('%s', self.sql.query['placeholder']) %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder'])
,inserts ) ,inserts )
result.append( self.get_last_insert_id(c) ) # wrong? not used currently result.append( self.get_last_insert_id(c) ) # wrong? not used currently
except: except:
@ -1416,7 +1415,7 @@ class Database:
def store_hands_players_holdem_omaha_tourney(self, backend, category, hands_id, player_ids def store_hands_players_holdem_omaha_tourney(self, backend, category, hands_id, player_ids
,start_cashes, positions, card_values, card_suits ,start_cashes, positions, card_values, card_suits
,winnings, rakes, seatNos, tourneys_players_ids ,winnings, rakes, seatNos, tourneys_players_ids
,hudCache): ,hudCache, tourneyTypeId):
#stores hands_players for tourney holdem/omaha hands #stores hands_players for tourney holdem/omaha hands
try: try:
@ -1438,7 +1437,7 @@ class Database:
else: else:
raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) raise FpdbError ("invalid card_values length:"+str(len(card_values[0])))
inserts.append( (hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid inserts.append( (hands_id, player_ids[i], start_cashes[i], positions[i], tourneyTypeId,
card1, card2, card3, card4, startCards, card1, card2, card3, card4, startCards,
winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], hudCache['totalProfit'][i], winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], hudCache['totalProfit'][i],
hudCache['street0VPI'][i], hudCache['street0Aggr'][i], hudCache['street0VPI'][i], hudCache['street0Aggr'][i],
@ -1507,7 +1506,7 @@ class Database:
#end def store_hands_players_holdem_omaha_tourney #end def store_hands_players_holdem_omaha_tourney
def store_hands_players_stud_tourney(self, backend, hands_id, player_ids, start_cashes, def store_hands_players_stud_tourney(self, backend, hands_id, player_ids, start_cashes,
antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId):
#stores hands_players for tourney stud/razz hands #stores hands_players for tourney stud/razz hands
try: try:
@ -1519,14 +1518,14 @@ class Database:
card1Value, card1Suit, card2Value, card2Suit, card1Value, card1Suit, card2Value, card2Suit,
card3Value, card3Suit, card4Value, card4Suit, card3Value, card3Suit, card4Value, card4Suit,
card5Value, card5Suit, card6Value, card6Suit, card5Value, card5Suit, card6Value, card6Suit,
card7Value, card7Suit, winnings, rake, tourneysPlayersId, seatNo) card7Value, card7Suit, winnings, rake, tourneysPlayersId, seatNo, tourneyTypeId)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']), %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']),
(hands_id, player_ids[i], start_cashes[i], antes[i], (hands_id, player_ids[i], start_cashes[i], antes[i],
card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1],
card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3],
card_values[i][4], card_suits[i][4], card_values[i][5], card_suits[i][5], card_values[i][4], card_suits[i][4], card_values[i][5], card_suits[i][5],
card_values[i][6], card_suits[i][6], winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) card_values[i][6], card_suits[i][6], winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], tourneyTypeId))
#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i]))
#result.append(cursor.fetchall()[0][0]) #result.append(cursor.fetchall()[0][0])
result.append( self.get_last_insert_id(c) ) result.append( self.get_last_insert_id(c) )
@ -1865,6 +1864,236 @@ class Database:
print "***Error sending finish: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) print "***Error sending finish: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
# end def send_finish_msg(): # end def send_finish_msg():
def tRecogniseTourneyType(self, tourney):
logging.debug("Database.tRecogniseTourneyType")
typeId = 1
# Check if Tourney exists, and if so retrieve TTypeId : in that case, check values of the ttype
cursor = self.get_cursor()
cursor.execute (self.sql.query['getTourneyTypeIdByTourneyNo'].replace('%s', self.sql.query['placeholder']),
(tourney.tourNo, tourney.siteId)
)
result=cursor.fetchone()
expectedValues = { 1 : "buyin", 2 : "fee", 4 : "isKO", 5 : "isRebuy", 6 : "speed",
7 : "isHU", 8 : "isShootout", 9 : "isMatrix" }
typeIdMatch = True
try:
len(result)
typeId = result[0]
logging.debug("Tourney found in db with Tourney_Type_ID = %d" % typeId)
for ev in expectedValues :
if ( getattr( tourney, expectedValues.get(ev) ) <> result[ev] ):
logging.debug("TypeId mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( tourney, expectedValues.get(ev)), result[ev]) )
typeIdMatch = False
#break
except:
# Tourney not found : a TourneyTypeId has to be found or created for that specific tourney
typeIdMatch = False
if typeIdMatch == False :
# Check for an existing TTypeId that matches tourney info (buyin/fee, knockout, rebuy, speed, matrix, shootout)
# if not found create it
logging.debug("Searching for a TourneyTypeId matching TourneyType data")
cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']),
(tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO,
tourney.isRebuy, tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix)
)
result=cursor.fetchone()
try:
len(result)
typeId = result[0]
logging.debug("Existing Tourney Type Id found : %d" % typeId)
except TypeError: #this means we need to create a new entry
logging.debug("Tourney Type Id not found : create one")
cursor.execute (self.sql.query['insertTourneyTypes'].replace('%s', self.sql.query['placeholder']),
(tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO, tourney.isRebuy,
tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix)
)
typeId = self.get_last_insert_id(cursor)
return typeId
#end def tRecogniseTourneyType
def tRecognizeTourney(self, tourney, dbTourneyTypeId):
logging.debug("Database.tRecognizeTourney")
tourneyID = 1
# Check if tourney exists in db (based on tourney.siteId and tourney.tourNo)
# If so retrieve all data to check for consistency
cursor = self.get_cursor()
cursor.execute (self.sql.query['getTourney'].replace('%s', self.sql.query['placeholder']),
(tourney.tourNo, tourney.siteId)
)
result=cursor.fetchone()
expectedValuesDecimal = { 2 : "entries", 3 : "prizepool", 6 : "buyInChips", 9 : "rebuyChips",
10 : "addOnChips", 11 : "rebuyAmount", 12 : "addOnAmount", 13 : "totalRebuys",
14 : "totalAddOns", 15 : "koBounty" }
expectedValues = { 7 : "tourneyName", 16 : "tourneyComment" }
tourneyDataMatch = True
tCommentTs = None
starttime = None
endtime = None
try:
len(result)
tourneyID = result[0]
logging.debug("Tourney found in db with TourneyID = %d" % tourneyID)
if result[1] <> dbTourneyTypeId:
tourneyDataMatch = False
logging.debug("Tourney has wrong type ID (expected : %s - found : %s)" % (dbTourneyTypeId, result[1]))
if (tourney.starttime is None and result[4] is not None) or ( tourney.starttime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) <> result[4]) :
tourneyDataMatch = False
logging.debug("Tourney data mismatch : wrong starttime : Tourney=%s / db=%s" % (tourney.starttime, result[4]))
if (tourney.endtime is None and result[5] is not None) or ( tourney.endtime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) <> result[5]) :
tourneyDataMatch = False
logging.debug("Tourney data mismatch : wrong endtime : Tourney=%s / db=%s" % (tourney.endtime, result[5]))
for ev in expectedValues :
if ( getattr( tourney, expectedValues.get(ev) ) <> result[ev] ):
logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( tourney, expectedValues.get(ev)), result[ev]) )
tourneyDataMatch = False
#break
for evD in expectedValuesDecimal :
if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD)) ) <> result[evD] ):
logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD)), result[evD]) )
tourneyDataMatch = False
#break
# TO DO : Deal with matrix summary mutliple parsings
except:
# Tourney not found : create
logging.debug("Tourney is not found : create")
if tourney.tourneyComment is not None :
tCommentTs = datetime.today()
if tourney.starttime is not None :
starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime)
if tourney.endtime is not None :
endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime)
# TODO : deal with matrix Id processed
cursor.execute (self.sql.query['insertTourney'].replace('%s', self.sql.query['placeholder']),
(dbTourneyTypeId, tourney.tourNo, tourney.entries, tourney.prizepool, starttime,
endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips,
tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty,
tourney.tourneyComment, tCommentTs)
)
tourneyID = self.get_last_insert_id(cursor)
# Deal with inconsistent tourney in db
if tourneyDataMatch == False :
# Update Tourney
if result[16] <> tourney.tourneyComment :
tCommentTs = datetime.today()
if tourney.starttime is not None :
starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime)
if tourney.endtime is not None :
endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime)
cursor.execute (self.sql.query['updateTourney'].replace('%s', self.sql.query['placeholder']),
(dbTourneyTypeId, tourney.entries, tourney.prizepool, starttime,
endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips,
tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty,
tourney.tourneyComment, tCommentTs, tourneyID)
)
return tourneyID
#end def tRecognizeTourney
def tStoreTourneyPlayers(self, tourney, dbTourneyId):
logging.debug("Database.tStoreTourneyPlayers")
# First, get playerids for the players and specifically the one for hero :
playersIds = fpdb_simple.recognisePlayerIDs(self, tourney.players, tourney.siteId)
# hero may be None for matrix tourneys summaries
# hero = [ tourney.hero ]
# heroId = fpdb_simple.recognisePlayerIDs(self, hero , tourney.siteId)
# logging.debug("hero Id = %s - playersId = %s" % (heroId , playersIds))
tourneyPlayersIds=[]
try:
cursor = self.get_cursor()
for i in xrange(len(playersIds)):
cursor.execute(self.sql.query['getTourneysPlayers'].replace('%s', self.sql.query['placeholder'])
,(dbTourneyId, playersIds[i]))
result=cursor.fetchone()
#print "tried SELECTing tourneys_players.id:",tmp
try:
len(result)
# checking data
logging.debug("TourneysPlayers found : checking data")
expectedValuesDecimal = { 1 : "payinAmounts", 2 : "finishPositions", 3 : "winnings", 4 : "countRebuys",
5 : "countAddOns", 6 : "countKO" }
tourneyPlayersIds.append(result[0]);
tourneysPlayersDataMatch = True
for evD in expectedValuesDecimal :
if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]] ) <> result[evD] ):
logging.debug("TourneysPlayers data mismatch for TourneysPlayer id=%d, name=%s : wrong %s : Tourney=%s / db=%s" % (result[0], tourney.players[i], expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]], result[evD]) )
tourneysPlayersDataMatch = False
#break
if tourneysPlayersDataMatch == False:
logging.debug("TourneysPlayers data update needed")
cursor.execute (self.sql.query['updateTourneysPlayers'].replace('%s', self.sql.query['placeholder']),
(tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]],
tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]],
tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]],
result[7], result[8], result[0])
)
except TypeError:
logging.debug("TourneysPlayers not found : need insert")
cursor.execute (self.sql.query['insertTourneysPlayers'].replace('%s', self.sql.query['placeholder']),
(dbTourneyId, playersIds[i],
tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]],
tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]],
tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]],
None, None)
)
tourneyPlayersIds.append(self.get_last_insert_id(cursor))
except:
raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) )
return tourneyPlayersIds
#end def tStoreTourneyPlayers
def tUpdateTourneysHandsPlayers(self, tourney, dbTourneysPlayersIds, dbTourneyTypeId):
logging.debug("Database.tCheckTourneysHandsPlayers")
try:
# Massive update seems to take quite some time ...
# query = self.sql.query['updateHandsPlayersForTTypeId2'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) )
# cursor = self.get_cursor()
# cursor.execute (query, dbTourneysPlayersIds)
query = self.sql.query['selectHandsPlayersWithWrongTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) )
#print "query : %s" % query
cursor = self.get_cursor()
cursor.execute (query, dbTourneysPlayersIds)
result=cursor.fetchall()
if (len(result) > 0):
logging.debug("%d lines need update : %s" % (len(result), result) )
listIds = []
for i in result:
listIds.append(i[0])
query2 = self.sql.query['updateHandsPlayersForTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner_id'].join([self.sql.query['placeholder'] for id in listIds]) )
cursor.execute (query2, listIds)
else:
logging.debug("No need to update, HandsPlayers are correct")
except:
raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) )
#end def tUpdateTourneysHandsPlayers
# Class used to hold all the data needed to write a hand to the db # Class used to hold all the data needed to write a hand to the db
# mainParser() in fpdb_parse_logic.py creates one of these and then passes it to # mainParser() in fpdb_parse_logic.py creates one of these and then passes it to

View File

@ -57,6 +57,13 @@ class Fulltilt(HandHistoryConverter):
(?P<PARTIAL>\(partial\))?\n (?P<PARTIAL>\(partial\))?\n
(?:.*?\n(?P<CANCELLED>Hand\s\#(?P=HID)\shas\sbeen\scanceled))? (?:.*?\n(?P<CANCELLED>Hand\s\#(?P=HID)\shas\sbeen\scanceled))?
''', re.VERBOSE|re.DOTALL) ''', re.VERBOSE|re.DOTALL)
re_TourneyExtraInfo = re.compile('''(((?P<TOURNEY_NAME>[^$]+)?
(?P<CURRENCY>\$)?(?P<BUYIN>[.0-9]+)?\s*\+\s*\$?(?P<FEE>[.0-9]+)?
(\s(?P<SPECIAL>(KO|Heads\sUp|Matrix\s\dx|Rebuy|Madness)))?
(\s(?P<SHOOTOUT>Shootout))?
(\s(?P<SNG>Sit\s&\sGo))?
(\s\((?P<TURBO>Turbo)\))?)|(?P<UNREADABLE_INFO>.+))
''', re.VERBOSE)
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE) re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE)
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[,.0-9]+)\)$', re.MULTILINE) re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[,.0-9]+)\)$', re.MULTILINE)
re_TourneyPlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[,.0-9]+)\)', re.MULTILINE) re_TourneyPlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[,.0-9]+)\)', re.MULTILINE)
@ -66,7 +73,7 @@ class Fulltilt(HandHistoryConverter):
re_TourneyInfo = re.compile('''Tournament\sSummary\s re_TourneyInfo = re.compile('''Tournament\sSummary\s
(?P<TOURNAMENT_NAME>[^$(]+)?\s* (?P<TOURNAMENT_NAME>[^$(]+)?\s*
((?P<CURRENCY>\$|)?(?P<BUYIN>[.0-9]+)\s*\+\s*\$?(?P<FEE>[.0-9]+)\s)? ((?P<CURRENCY>\$|)?(?P<BUYIN>[.0-9]+)\s*\+\s*\$?(?P<FEE>[.0-9]+)\s)?
((?P<SPECIAL>(KO|Heads\sUp|Matrix\s\dx|Rebuy))\s)? ((?P<SPECIAL>(KO|Heads\sUp|Matrix\s\dx|Rebuy|Madness))\s)?
((?P<SHOOTOUT>Shootout)\s)? ((?P<SHOOTOUT>Shootout)\s)?
((?P<SNG>Sit\s&\sGo)\s)? ((?P<SNG>Sit\s&\sGo)\s)?
(\((?P<TURBO1>Turbo)\)\s)? (\((?P<TURBO1>Turbo)\)\s)?
@ -202,16 +209,30 @@ class Fulltilt(HandHistoryConverter):
if m.group('PLAY') != None: if m.group('PLAY') != None:
hand.gametype['currency'] = 'play' hand.gametype['currency'] = 'play'
# TODO: if there's a way to figure these out, we should.. otherwise we have to stuff it with unknowns # Done: if there's a way to figure these out, we should.. otherwise we have to stuff it with unknowns
re_SNGBuyInFee = re.compile('''(?P<CURRENCY>\$)?(?P<BUYIN>[.0-9]+) \+ \$?(?P<FEE>[.0-9]+) (?P<EXTRA_INFO>[\sA-Za-z&()]+)?''') if m.group('TOURNAMENT') is not None:
# TO DO : See if important info can be retrieved from EXTRA_INFO (sould be things like Turbo, Matrix, KO, ...) n = self.re_TourneyExtraInfo.search(m.group('TOURNAMENT'))
try: if n.group('UNREADABLE_INFO') is not None:
n = re_SNGBuyInFee.search(m.group('TOURNAMENT')) hand.tourneyComment = n.group('UNREADABLE_INFO')
#print "cur %s BUYIN %s FEE %s EXTRA %s" %(n.group('CURRENCY'), n.group('BUYIN'), n.group('FEE'), n.group('EXTRA_INFO')) else:
hand.buyin = "%s%s+%s%s" %(n.group('CURRENCY'), n.group('BUYIN'), n.group('CURRENCY'), n.group('FEE')) hand.tourneyComment = n.group('TOURNEY_NAME') # can be None
except: if (n.group('CURRENCY') is not None and n.group('BUYIN') is not None and n.group('FEE') is not None):
#print "Unable to collect BuyIn/Fee Info" hand.buyin = "%s%s+%s%s" %(n.group('CURRENCY'), n.group('BUYIN'), n.group('CURRENCY'), n.group('FEE'))
logging.info("Unable to collect BuyIn/Fee Info from HandInfo") if n.group('TURBO') is not None :
hand.speed = "Turbo"
if n.group('SPECIAL') is not None :
special = n.group('SPECIAL')
if special == "Rebuy":
hand.isRebuy = True
if special == "KO":
hand.isKO = True
if special == "Head's Up":
hand.isHU = True
if re.search("Matrix", special):
hand.isMatrix = True
if special == "Shootout":
hand.isShootout = True
if hand.buyin == None: if hand.buyin == None:
hand.buyin = "$0.00+$0.00" hand.buyin = "$0.00+$0.00"
@ -405,9 +426,9 @@ class Fulltilt(HandHistoryConverter):
self.status = False self.status = False
else: else:
self.tourney = Tourney.Tourney(sitename = self.sitename, gametype = None, summaryText = summaryInfoList, builtFrom = "HHC") self.tourney = Tourney.Tourney(sitename = self.sitename, gametype = None, summaryText = summaryInfoList, builtFrom = "HHC")
self.status = self.determineTourneyType(self.tourney) self.status = self.getPlayersPositionsAndWinnings(self.tourney)
if self.status == True : if self.status == True :
self.status = status = self.getPlayersPositionsAndWinnings(self.tourney) self.status = self.determineTourneyType(self.tourney)
#print self.tourney #print self.tourney
else: else:
log.info("Parsing NOK : rejected") log.info("Parsing NOK : rejected")
@ -454,10 +475,10 @@ class Fulltilt(HandHistoryConverter):
# Additional info can be stored in the tourney object # Additional info can be stored in the tourney object
if mg['BUYIN'] is not None: if mg['BUYIN'] is not None:
tourney.buyin = mg['BUYIN'] tourney.buyin = 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))
tourney.fee = 0 tourney.fee = 0
if mg['FEE'] is not None: if mg['FEE'] is not None:
tourney.fee = mg['FEE'] tourney.fee = 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))
if mg['TOURNAMENT_NAME'] is not None: if mg['TOURNAMENT_NAME'] is not None:
# Tournament Name can have a trailing space at the end (depending on the tournament description) # Tournament Name can have a trailing space at the end (depending on the tournament description)
tourney.tourneyName = mg['TOURNAMENT_NAME'].rstrip() tourney.tourneyName = mg['TOURNAMENT_NAME'].rstrip()
@ -472,6 +493,8 @@ class Fulltilt(HandHistoryConverter):
tourney.isMatrix = True tourney.isMatrix = True
if special == "Rebuy": if special == "Rebuy":
tourney.isRebuy = True tourney.isRebuy = True
if special == "Madness":
tourney.tourneyComment = "Madness"
if mg['SHOOTOUT'] is not None: if mg['SHOOTOUT'] is not None:
tourney.isShootout = True tourney.isShootout = True
if mg['TURBO1'] is not None or mg['TURBO2'] is not None : if mg['TURBO1'] is not None or mg['TURBO2'] is not None :
@ -500,25 +523,25 @@ class Fulltilt(HandHistoryConverter):
mg = m.groupdict() mg = m.groupdict()
if tourney.isMatrix : if tourney.isMatrix :
if mg['BUYIN'] is not None: if mg['BUYIN'] is not None:
tourney.subTourneyBuyin = mg['BUYIN'] tourney.subTourneyBuyin = 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))
tourney.subTourneyFee = 0 tourney.subTourneyFee = 0
if mg['FEE'] is not None: if mg['FEE'] is not None:
tourney.subTourneyFee = mg['FEE'] tourney.subTourneyFee = 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))
else : else :
if mg['BUYIN'] is not None: if mg['BUYIN'] is not None:
if tourney.buyin is None: if tourney.buyin is None:
tourney.buyin = mg['BUYIN'] tourney.buyin = 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))
else : else :
if mg['BUYIN'] != tourney.buyin: if 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN'])) != tourney.buyin:
log.error( "Conflict between buyins read in topline (%s) and in BuyIn field (%s)" % (touney.buyin, mg['BUYIN']) ) log.error( "Conflict between buyins read in topline (%s) and in BuyIn field (%s)" % (touney.buyin, 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))) )
tourney.subTourneyBuyin = mg['BUYIN'] tourney.subTourneyBuyin = 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))
if mg['FEE'] is not None: if mg['FEE'] is not None:
if tourney.fee is None: if tourney.fee is None:
tourney.fee = mg['FEE'] tourney.fee = 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))
else : else :
if mg['FEE'] != tourney.fee: if 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE'])) != tourney.fee:
log.error( "Conflict between fees read in topline (%s) and in BuyIn field (%s)" % (touney.fee, mg['FEE']) ) log.error( "Conflict between fees read in topline (%s) and in BuyIn field (%s)" % (touney.fee, 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))) )
tourney.subTourneyFee = mg['FEE'] tourney.subTourneyFee = 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))
if tourney.buyin is None: if tourney.buyin is None:
log.info( "Unable to affect a buyin to this tournament : assume it's a freeroll" ) log.info( "Unable to affect a buyin to this tournament : assume it's a freeroll" )
@ -535,15 +558,12 @@ class Fulltilt(HandHistoryConverter):
"PRIZEPOOL" : self.re_TourneyPrizePool, "PRIZEPOOL" : self.re_TourneyPrizePool,
"REBUY_AMOUNT" : self.re_TourneyRebuyAmount, "REBUY_AMOUNT" : self.re_TourneyRebuyAmount,
"ADDON_AMOUNT" : self.re_TourneyAddOnAmount, "ADDON_AMOUNT" : self.re_TourneyAddOnAmount,
"REBUY_COUNT" : self.re_TourneyRebuyCount,
"ADDON_COUNT" : self.re_TourneyAddOnCount,
"REBUY_TOTAL" : self.re_TourneyRebuysTotal, "REBUY_TOTAL" : self.re_TourneyRebuysTotal,
"ADDONS_TOTAL" : self.re_TourneyAddOnsTotal, "ADDONS_TOTAL" : self.re_TourneyAddOnsTotal,
"REBUY_CHIPS" : self.re_TourneyRebuyChips, "REBUY_CHIPS" : self.re_TourneyRebuyChips,
"ADDON_CHIPS" : self.re_TourneyAddOnChips, "ADDON_CHIPS" : self.re_TourneyAddOnChips,
"STARTTIME" : self.re_TourneyTimeInfo, "STARTTIME" : self.re_TourneyTimeInfo,
"KO_BOUNTY_AMOUNT" : self.re_TourneyKOBounty, "KO_BOUNTY_AMOUNT" : self.re_TourneyKOBounty,
"COUNT_KO" : self.re_TourneyCountKO
} }
@ -552,15 +572,12 @@ class Fulltilt(HandHistoryConverter):
"PRIZEPOOL" : "prizepool", "PRIZEPOOL" : "prizepool",
"REBUY_AMOUNT" : "rebuyAmount", "REBUY_AMOUNT" : "rebuyAmount",
"ADDON_AMOUNT" : "addOnAmount", "ADDON_AMOUNT" : "addOnAmount",
"REBUY_COUNT" : "countRebuys",
"ADDON_COUNT" : "countAddOns",
"REBUY_TOTAL" : "totalRebuys", "REBUY_TOTAL" : "totalRebuys",
"ADDONS_TOTAL" : "totalAddOns", "ADDONS_TOTAL" : "totalAddOns",
"REBUY_CHIPS" : "rebuyChips", "REBUY_CHIPS" : "rebuyChips",
"ADDON_CHIPS" : "addOnChips", "ADDON_CHIPS" : "addOnChips",
"STARTTIME" : "starttime", "STARTTIME" : "starttime",
"KO_BOUNTY_AMOUNT" : "koBounty", "KO_BOUNTY_AMOUNT" : "koBounty"
"COUNT_KO" : "countKO"
} }
mg = {} # After the loop, mg will contain all the matching groups, including the ones that have not been used, like ENDTIME and IN-PROGRESS mg = {} # After the loop, mg will contain all the matching groups, including the ones that have not been used, like ENDTIME and IN-PROGRESS
@ -573,8 +590,43 @@ class Fulltilt(HandHistoryConverter):
if mg['IN_PROGRESS'] is not None or mg['ENDTIME'] is not None: if mg['IN_PROGRESS'] is not None or mg['ENDTIME'] is not None:
# Assign endtime to tourney (if None, that's ok, it's because the tourney wans't over over when the summary file was produced) # Assign endtime to tourney (if None, that's ok, it's because the tourney wans't over over when the summary file was produced)
tourney.endtime = mg['ENDTIME'] tourney.endtime = mg['ENDTIME']
#print mg
# Deal with hero specific information
if tourney.hero is not None :
m = self.re_TourneyRebuyCount.search(tourneyText)
if m is not None:
mg = m.groupdict()
if mg['REBUY_COUNT'] is not None :
tourney.countRebuys.update( { tourney.hero : Decimal(mg['REBUY_COUNT']) } )
m = self.re_TourneyAddOnCount.search(tourneyText)
if m is not None:
mg = m.groupdict()
if mg['ADDON_COUNT'] is not None :
tourney.countAddOns.update( { tourney.hero : Decimal(mg['ADDON_COUNT']) } )
m = self.re_TourneyCountKO.search(tourneyText)
if m is not None:
mg = m.groupdict()
if mg['COUNT_KO'] is not None :
tourney.countKO.update( { tourney.hero : Decimal(mg['COUNT_KO']) } )
# Deal with money amounts
tourney.koBounty = 100*Decimal(re.sub(u',', u'', "%s" % tourney.koBounty))
tourney.prizepool = 100*Decimal(re.sub(u',', u'', "%s" % tourney.prizepool))
tourney.rebuyAmount = 100*Decimal(re.sub(u',', u'', "%s" % tourney.rebuyAmount))
tourney.addOnAmount = 100*Decimal(re.sub(u',', u'', "%s" % tourney.addOnAmount))
# Calculate payin amounts and update winnings -- not possible to take into account nb of rebuys, addons or Knockouts for other players than hero on FTP
for p in tourney.players :
tourney.payinAmounts[p] = tourney.buyin + tourney.fee + (tourney.rebuyAmount * tourney.countRebuys[p]) + (tourney.addOnAmount * tourney.countAddOns[p])
#print " player %s : payinAmount = %d" %( p, tourney.payinAmounts[p])
if tourney.isKO :
#tourney.incrementPlayerWinnings(tourney.players[p], Decimal(tourney.koBounty)*Decimal(tourney.countKO[p]))
tourney.winnings[p] += Decimal(tourney.koBounty)*Decimal(tourney.countKO[p])
#print "player %s : winnings %d" % (p, tourney.winnings[p])
#print mg
return True return True
def getPlayersPositionsAndWinnings(self, tourney): def getPlayersPositionsAndWinnings(self, tourney):
@ -590,15 +642,15 @@ class Fulltilt(HandHistoryConverter):
rank = Decimal(a.group('RANK')) rank = Decimal(a.group('RANK'))
if a.group('WINNING') is not None: if a.group('WINNING') is not None:
winnings = a.group('WINNING') winnings = 100*Decimal(re.sub(u',', u'', "%s" % a.group('WINNING')))
else: else:
winnings = "0" winnings = "0"
tourney.addPlayer(rank, a.group('PNAME'), winnings) tourney.addPlayer(rank, a.group('PNAME'), winnings, 0, 0, 0, 0)
else: else:
print "Player finishing stats unreadable : %s" % a print "Player finishing stats unreadable : %s" % a
# Deal with KO tournaments for hero winnings calculation # Find Hero
n = self.re_TourneyHeroFinishingP.search(playersText) n = self.re_TourneyHeroFinishingP.search(playersText)
if n is not None: if n is not None:
heroName = n.group('HERO_NAME') heroName = n.group('HERO_NAME')
@ -606,9 +658,6 @@ class Fulltilt(HandHistoryConverter):
# Is this really useful ? # Is this really useful ?
if (tourney.finishPositions[heroName] != Decimal(n.group('HERO_FINISHING_POS'))): if (tourney.finishPositions[heroName] != Decimal(n.group('HERO_FINISHING_POS'))):
print "Bad parsing : finish position incoherent : %s / %s" % (tourney.finishPositions[heroName], n.group('HERO_FINISHING_POS')) print "Bad parsing : finish position incoherent : %s / %s" % (tourney.finishPositions[heroName], n.group('HERO_FINISHING_POS'))
if tourney.isKO:
#Update the winnings with the (KO amount) * (# of KO)
tourney.incrementPlayerWinnings(n.group('HERO_NAME'), Decimal(tourney.koBounty)*Decimal(tourney.countKO))
return True return True

View File

@ -64,6 +64,15 @@ class Hand(object):
self.fee = None # the Database code is looking for this one .. ? self.fee = None # the Database code is looking for this one .. ?
self.level = None self.level = None
self.mixed = None self.mixed = None
# Some attributes for hand from a tourney
self.speed = "Normal"
self.isRebuy = False
self.isKO = False
self.isHU = False
self.isMatrix = False
self.isShootout = False
self.tourneyComment = None
self.seating = [] self.seating = []
self.players = [] self.players = []
self.posted = [] self.posted = []

View File

@ -139,7 +139,8 @@ Otherwise, finish at EOF.
handsList = self.allHandsAsList() handsList = self.allHandsAsList()
log.info("Parsing %d hands" % len(handsList)) log.info("Parsing %d hands" % len(handsList))
# Determine if we're dealing with a HH file or a Summary file # Determine if we're dealing with a HH file or a Summary file
if self.isSummary(handsList[0]) == False: # quick fix : empty files make the handsList[0] fail ==> If empty file, go on with HH parsing
if len(handsList) == 0 or self.isSummary(handsList[0]) == False:
self.parsedObjectType = "HH" self.parsedObjectType = "HH"
for handText in handsList: for handText in handsList:
try: try:

View File

@ -325,8 +325,14 @@ class Sql:
siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
buyin INT NOT NULL, buyin INT NOT NULL,
fee INT NOT NULL, fee INT NOT NULL,
knockout INT NOT NULL, maxSeats INT NOT NULL DEFAULT -1,
rebuyOrAddon BOOLEAN NOT NULL) knockout BOOLEAN NOT NULL DEFAULT False,
rebuyOrAddon BOOLEAN NOT NULL DEFAULT False,
speed varchar(10),
headsUp BOOLEAN NOT NULL DEFAULT False,
shootout BOOLEAN NOT NULL DEFAULT False,
matrix BOOLEAN NOT NULL DEFAULT False
)
ENGINE=INNODB""" ENGINE=INNODB"""
elif db_server == 'postgresql': elif db_server == 'postgresql':
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
@ -334,16 +340,28 @@ class Sql:
siteId INT NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id), siteId INT NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
buyin INT NOT NULL, buyin INT NOT NULL,
fee INT NOT NULL, fee INT NOT NULL,
knockout INT NOT NULL, maxSeats INT NOT NULL DEFAULT -1,
rebuyOrAddon BOOLEAN NOT NULL)""" knockout BOOLEAN NOT NULL DEFAULT False,
rebuyOrAddon BOOLEAN NOT NULL DEFAULT False,
speed varchar(10),
headsUp BOOLEAN NOT NULL DEFAULT False,
shootout BOOLEAN NOT NULL DEFAULT False,
matrix BOOLEAN NOT NULL DEFAULT False
)"""
elif db_server == 'sqlite': elif db_server == 'sqlite':
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes ( self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
siteId INT NOT NULL, siteId INT NOT NULL,
buyin INT NOT NULL, buyin INT NOT NULL,
fee INT NOT NULL, fee INT NOT NULL,
knockout INT NOT NULL, maxSeats INT NOT NULL DEFAULT -1,
rebuyOrAddon BOOLEAN NOT NULL)""" knockout BOOLEAN NOT NULL DEFAULT 0,
rebuyOrAddon BOOLEAN NOT NULL DEFAULT 0,
speed TEXT,
headsUp BOOLEAN NOT NULL DEFAULT 0,
shootout BOOLEAN NOT NULL DEFAULT 0,
matrix BOOLEAN NOT NULL DEFAULT 0
)"""
################################ ################################
# Create Tourneys # Create Tourneys
@ -357,6 +375,17 @@ class Sql:
entries INT NOT NULL, entries INT NOT NULL,
prizepool INT NOT NULL, prizepool INT NOT NULL,
startTime DATETIME NOT NULL, startTime DATETIME NOT NULL,
endTime DATETIME,
buyinChips INT,
tourneyName varchar(20),
matrixIdProcessed TINYINT UNSIGNED DEFAULT 0, /* Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn */
rebuyChips INT DEFAULT 0,
addonChips INT DEFAULT 0,
rebuyAmount INT DEFAULT 0,
addonAmount INT DEFAULT 0,
totalRebuys INT DEFAULT 0,
totalAddons INT DEFAULT 0,
koBounty INT DEFAULT 0,
comment TEXT, comment TEXT,
commentTs DATETIME) commentTs DATETIME)
ENGINE=INNODB""" ENGINE=INNODB"""
@ -368,6 +397,17 @@ class Sql:
entries INT, entries INT,
prizepool INT, prizepool INT,
startTime timestamp without time zone, startTime timestamp without time zone,
endTime timestamp without time zone,
buyinChips INT,
tourneyName varchar(20),
matrixIdProcessed SMALLINT UNSIGNED DEFAULT 0, /* Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn */
rebuyChips INT DEFAULT 0,
addonChips INT DEFAULT 0,
rebuyAmount INT DEFAULT 0,
addonAmount INT DEFAULT 0,
totalRebuys INT DEFAULT 0,
totalAddons INT DEFAULT 0,
koBounty INT DEFAULT 0,
comment TEXT, comment TEXT,
commentTs timestamp without time zone)""" commentTs timestamp without time zone)"""
elif db_server == 'sqlite': elif db_server == 'sqlite':
@ -378,6 +418,17 @@ class Sql:
entries INT, entries INT,
prizepool INT, prizepool INT,
startTime REAL, startTime REAL,
endTime REAL,
buyinChips INT,
tourneyName TEXT,
matrixIdProcessed INT UNSIGNED DEFAULT 0, /* Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn */
rebuyChips INT DEFAULT 0,
addonChips INT DEFAULT 0,
rebuyAmount INT DEFAULT 0,
addonAmount INT DEFAULT 0,
totalRebuys INT DEFAULT 0,
totalAddons INT DEFAULT 0,
koBounty INT DEFAULT 0,
comment TEXT, comment TEXT,
commentTs REAL)""" commentTs REAL)"""
################################ ################################
@ -749,6 +800,9 @@ class Sql:
payinAmount INT NOT NULL, payinAmount INT NOT NULL,
rank INT NOT NULL, rank INT NOT NULL,
winnings INT NOT NULL, winnings INT NOT NULL,
nbRebuys INT DEFAULT 0,
nbAddons INT DEFAULT 0,
nbKO INT DEFAULT 0,
comment TEXT, comment TEXT,
commentTs DATETIME) commentTs DATETIME)
ENGINE=INNODB""" ENGINE=INNODB"""
@ -760,6 +814,9 @@ class Sql:
payinAmount INT, payinAmount INT,
rank INT, rank INT,
winnings INT, winnings INT,
nbRebuys INT DEFAULT 0,
nbAddons INT DEFAULT 0,
nbKO INT DEFAULT 0,
comment TEXT, comment TEXT,
commentTs timestamp without time zone)""" commentTs timestamp without time zone)"""
elif db_server == 'sqlite': elif db_server == 'sqlite':
@ -2758,7 +2815,144 @@ class Sql:
self.query['isAlreadyInDB'] = """SELECT id FROM Hands self.query['isAlreadyInDB'] = """SELECT id FROM Hands
WHERE gametypeId=%s AND siteHandNo=%s WHERE gametypeId=%s AND siteHandNo=%s
""" """
self.query['getTourneyTypeIdByTourneyNo'] = """SELECT tt.id,
tt.buyin,
tt.fee,
tt.maxSeats,
tt.knockout,
tt.rebuyOrAddon,
tt.speed,
tt.headsUp,
tt.shootout,
tt.matrix
FROM TourneyTypes tt
INNER JOIN Tourneys t ON (t.tourneyTypeId = tt.id)
WHERE t.siteTourneyNo=%s AND tt.siteId=%s
"""
self.query['getTourneyTypeId'] = """SELECT id
FROM TourneyTypes
WHERE siteId=%s
AND buyin=%s
AND fee=%s
AND knockout=%s
AND rebuyOrAddon=%s
AND speed=%s
AND headsUp=%s
AND shootout=%s
AND matrix=%s
"""
self.query['insertTourneyTypes'] = """INSERT INTO TourneyTypes
(siteId, buyin, fee, knockout, rebuyOrAddon
,speed, headsUp, shootout, matrix)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
self.query['getTourney'] = """SELECT t.id,
t.tourneyTypeId,
t.entries,
t.prizepool,
t.startTime,
t.endTime,
t.buyinChips,
t.tourneyName,
t.matrixIdProcessed,
t.rebuyChips,
t.addonChips,
t.rebuyAmount,
t.addonAmount,
t.totalRebuys,
t.totalAddons,
t.koBounty,
t.comment
FROM Tourneys t
INNER JOIN TourneyTypes tt ON (t.tourneyTypeId = tt.id)
WHERE t.siteTourneyNo=%s AND tt.siteId=%s
"""
self.query['insertTourney'] = """INSERT INTO Tourneys
(tourneyTypeId, siteTourneyNo, entries, prizepool,
startTime, endTime, buyinChips, tourneyName, matrixIdProcessed,
rebuyChips, addonChips, rebuyAmount, addonAmount, totalRebuys,
totalAddons, koBounty, comment, commentTs)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s, %s, %s)
"""
self.query['updateTourney'] = """UPDATE Tourneys
SET tourneyTypeId = %s,
entries = %s,
prizepool = %s,
startTime = %s,
endTime = %s,
buyinChips = %s,
tourneyName = %s,
matrixIdProcessed = %s,
rebuyChips = %s,
addonChips = %s,
rebuyAmount = %s,
addonAmount = %s,
totalRebuys = %s,
totalAddons = %s,
koBounty = %s,
comment = %s,
commentTs = %s
WHERE id=%s
"""
self.query['getTourneysPlayers'] = """SELECT id,
payinAmount,
rank,
winnings,
nbRebuys,
nbAddons,
nbKO,
comment,
commentTs
FROM TourneysPlayers
WHERE tourneyId=%s AND playerId+0=%s
"""
self.query['updateTourneysPlayers'] = """UPDATE TourneysPlayers
SET payinAmount = %s,
rank = %s,
winnings = %s,
nbRebuys = %s,
nbAddons = %s,
nbKO = %s,
comment = %s,
commentTs = %s
WHERE id=%s
"""
self.query['insertTourneysPlayers'] = """INSERT INTO TourneysPlayers
(tourneyId, playerId, payinAmount, rank, winnings, nbRebuys, nbAddons, nbKO, comment, commentTs)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
self.query['selectHandsPlayersWithWrongTTypeId'] = """SELECT id
FROM HandsPlayers
WHERE tourneyTypeId <> %s AND (TourneysPlayersId+0=%s)
"""
# self.query['updateHandsPlayersForTTypeId2'] = """UPDATE HandsPlayers
# SET tourneyTypeId= %s
# WHERE (TourneysPlayersId+0=%s)
# """
self.query['updateHandsPlayersForTTypeId'] = """UPDATE HandsPlayers
SET tourneyTypeId= %s
WHERE (id=%s)
"""
self.query['handsPlayersTTypeId_joiner'] = " OR TourneysPlayersId+0="
self.query['handsPlayersTTypeId_joiner_id'] = " OR id="
if db_server == 'mysql': if db_server == 'mysql':
self.query['placeholder'] = u'%s' self.query['placeholder'] = u'%s'
elif db_server == 'postgresql': elif db_server == 'postgresql':

View File

@ -46,7 +46,6 @@ class Tourney(object):
def __init__(self, sitename, gametype, summaryText, builtFrom = "HHC"): def __init__(self, sitename, gametype, summaryText, builtFrom = "HHC"):
print "Tourney.__init__"
self.sitename = sitename self.sitename = sitename
self.siteId = self.SITEIDS[sitename] self.siteId = self.SITEIDS[sitename]
self.gametype = gametype self.gametype = gametype
@ -74,21 +73,21 @@ class Tourney(object):
self.subTourneyFee = None self.subTourneyFee = None
self.rebuyChips = 0 self.rebuyChips = 0
self.addOnChips = 0 self.addOnChips = 0
self.countRebuys = 0
self.countAddOns = 0
self.rebuyAmount = 0 self.rebuyAmount = 0
self.addOnAmount = 0 self.addOnAmount = 0
self.totalRebuys = 0 self.totalRebuys = 0
self.totalAddOns = 0 self.totalAddOns = 0
self.koBounty = 0 self.koBounty = 0
self.countKO = 0 #To use for winnings calculation which is not counted in the rest of the summary file self.tourneyComment = None
self.players = [] self.players = []
# Collections indexed by player names # Collections indexed by player names
self.finishPositions = {} self.finishPositions = {}
self.winnings = {} self.winnings = {}
self.payinAmounts = {}
self.countRebuys = {}
self.countAddOns = {}
self.countKO = {}
# currency symbol for this summary # currency symbol for this summary
self.sym = None self.sym = None
@ -122,20 +121,20 @@ class Tourney(object):
("ADDON CHIPS", self.addOnChips), ("ADDON CHIPS", self.addOnChips),
("REBUY AMOUNT", self.rebuyAmount), ("REBUY AMOUNT", self.rebuyAmount),
("ADDON AMOUNT", self.addOnAmount), ("ADDON AMOUNT", self.addOnAmount),
("COUNT REBUYS", self.countRebuys),
("COUNT ADDONS", self.countAddOns),
("NB REBUYS", self.countRebuys),
("NB ADDONS", self.countAddOns),
("TOTAL REBUYS", self.totalRebuys), ("TOTAL REBUYS", self.totalRebuys),
("TOTAL ADDONS", self.totalAddOns), ("TOTAL ADDONS", self.totalAddOns),
("KO BOUNTY", self.koBounty), ("KO BOUNTY", self.koBounty),
("NB OF KO", self.countKO) ("TOURNEY COMMENT", self.tourneyComment)
) )
structs = ( ("GAMETYPE", self.gametype), structs = ( ("GAMETYPE", self.gametype),
("PLAYERS", self.players), ("PLAYERS", self.players),
("PAYIN AMOUNTS", self.payinAmounts),
("POSITIONS", self.finishPositions), ("POSITIONS", self.finishPositions),
("WINNINGS", self.winnings), ("WINNINGS", self.winnings),
("COUNT REBUYS", self.countRebuys),
("COUNT ADDONS", self.countAddOns),
("NB OF KO", self.countKO)
) )
str = '' str = ''
for (name, var) in vars: for (name, var) in vars:
@ -152,7 +151,6 @@ class Tourney(object):
pass pass
def insert(self, db): def insert(self, db):
print "TODO: Insert Tourney in DB"
# First : check all needed info is filled in the object, especially for the initial select # First : check all needed info is filled in the object, especially for the initial select
# Notes on DB Insert # Notes on DB Insert
@ -163,6 +161,19 @@ class Tourney(object):
# Starttime may not match the one in the Summary file : HH = time of the first Hand / could be slighltly different from the one in the summary file # Starttime may not match the one in the Summary file : HH = time of the first Hand / could be slighltly different from the one in the summary file
# Note: If the TourneyNo could be a unique id .... this would really be a relief to deal with matrix matches ==> Ask on the IRC / Ask Fulltilt ?? # Note: If the TourneyNo could be a unique id .... this would really be a relief to deal with matrix matches ==> Ask on the IRC / Ask Fulltilt ??
dbTourneyTypeId = db.tRecogniseTourneyType(self)
logging.debug("Tourney Type ID = %d" % dbTourneyTypeId)
dbTourneyId = db.tRecognizeTourney(self, dbTourneyTypeId)
logging.debug("Tourney ID = %d" % dbTourneyId)
dbTourneysPlayersIds = db.tStoreTourneyPlayers(self, dbTourneyId)
logging.debug("TourneysPlayersId = %s" % dbTourneysPlayersIds)
db.tUpdateTourneysHandsPlayers(self, dbTourneysPlayersIds, dbTourneyTypeId)
logging.debug("tUpdateTourneysHandsPlayers done")
logging.debug("Tourney Insert done")
# TO DO : Return what has been done (tourney created, updated, nothing)
# ?? stored = 1 if tourney is fully created / duplicates = 1, if everything was already here and correct / partial=1 if some things were already here (between tourney, tourneyPlayers and handsplayers)
# if so, prototypes may need changes to know what has been done or make some kind of dict in Tourney object that could be updated during the insert process to store that information
stored = 0 stored = 0
duplicates = 0 duplicates = 0
partial = 0 partial = 0
@ -246,18 +257,21 @@ db: a connected fpdb_db object"""
def addPlayer(self, rank, name, winnings): def addPlayer(self, rank, name, winnings, payinAmount, nbRebuys, nbAddons, nbKO):
"""\ """\
Adds a player to the tourney, and initialises data structures indexed by player. Adds a player to the tourney, and initialises data structures indexed by player.
rank (int) indicating the finishing rank (can be -1 if unknown) rank (int) indicating the finishing rank (can be -1 if unknown)
name (string) player name name (string) player name
winnings (string) the money the player ended the tourney with (can be 0, or -1 if unknown) winnings (decimal) the money the player ended the tourney with (can be 0, or -1 if unknown)
""" """
log.debug("addPlayer: rank:%s - name : '%s' - Winnings (%s)" % (rank, name, winnings)) log.debug("addPlayer: rank:%s - name : '%s' - Winnings (%s)" % (rank, name, winnings))
winnings = re.sub(u',', u'', winnings) #some sites have commas
self.players.append(name) self.players.append(name)
self.finishPositions.update( { name : Decimal(rank) } ) self.finishPositions.update( { name : Decimal(rank) } )
self.winnings.update( { name : Decimal(winnings) } ) self.winnings.update( { name : Decimal(winnings) } )
self.payinAmounts.update( {name : Decimal(payinAmount) } )
self.countRebuys.update( {name: Decimal(nbRebuys) } )
self.countAddOns.update( {name: Decimal(nbAddons) } )
self.countKO.update( {name : Decimal(nbKO) } )
def incrementPlayerWinnings(self, name, additionnalWinnings): def incrementPlayerWinnings(self, name, additionnalWinnings):
@ -269,11 +283,6 @@ winnings (string) the money the player ended the tourney with (can be 0, or -
self.players.append([-1, name, 0]) self.players.append([-1, name, 0])
self.winnings[name] = oldWins + Decimal(additionnalWinnings) self.winnings[name] = oldWins + Decimal(additionnalWinnings)
def calculatePayinAmount(self):
return self.buyin + self.fee + (self.rebuyAmount * self.countRebuys) + (self.addOnAmount * self.countAddOns )
def checkPlayerExists(self,player): def checkPlayerExists(self,player):
if player not in [p[1] for p in self.players]: if player not in [p[1] for p in self.players]:

View File

@ -68,7 +68,8 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non
tourneyStartTime= handStartTime #todo: read tourney start time tourneyStartTime= handStartTime #todo: read tourney start time
rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0]) rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0])
tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(db.get_cursor(), siteID, buyin, fee, knockout, rebuyOrAddon) ## The tourney site id has to be searched because it may already be in db with a TourneyTypeId which is different from the one automatically calculated (Summary import first)
tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(db, siteID, siteTourneyNo, buyin, fee, knockout, rebuyOrAddon)
else: else:
siteTourneyNo = -1 siteTourneyNo = -1
buyin = -1 buyin = -1

View File

@ -943,17 +943,28 @@ def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, c
return result[0] return result[0]
#end def recogniseGametypeID #end def recogniseGametypeID
def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebuyOrAddon):
cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon)) cursor = db.get_cursor()
# First we try to find the tourney itself (by its tourneySiteId) in case it has already been inserted before (by a summary file for instance)
# The reason is that some tourneys may not be identified correctly in the HH toplines (especially Buy-In and Fee which are used to search/create the TourneyTypeId)
#TODO: When the summary file will be dumped to BD, if the tourney is already in, Buy-In/Fee may need an update (e.g. creation of a new type and link to the Tourney)
cursor.execute (db.sql.query['getTourneyTypeIdByTourneyNo'].replace('%s', db.sql.query['placeholder']), (tourneySiteId, siteId))
result=cursor.fetchone() result=cursor.fetchone()
#print "tried SELECTing gametypes.id, result:",result
try: try:
len(result) len(result)
except TypeError:#this means we need to create a new entry except:
cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon)) cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon))
cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon))
result=cursor.fetchone() result=cursor.fetchone()
#print "tried SELECTing gametypes.id, result:",result
try:
len(result)
except TypeError:#this means we need to create a new entry
cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon))
cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon))
result=cursor.fetchone()
return result[0] return result[0]
#end def recogniseTourneyTypeId #end def recogniseTourneyTypeId