Merge branch 'siteneutral'

Conflicts:

	pyfpdb/GuiGraphViewer.py
This commit is contained in:
Worros 2009-04-11 20:16:37 +08:00
commit dd563aab39
10 changed files with 169 additions and 280 deletions

View File

@ -197,6 +197,15 @@ class Aux_window:
temp = temp + "%s" % self.layout[layout]
return temp
class HHC:
def __init__(self, node):
self.site = node.getAttribute("site")
self.converter = node.getAttribute("converter")
def __str__(self):
return "%s:\t%s" % (self.site, self.converter)
class Popup:
def __init__(self, node):
self.name = node.getAttribute("pu_name")
@ -277,6 +286,7 @@ class Config:
self.supported_games = {}
self.supported_databases = {}
self.aux_windows = {}
self.hhcs = {}
self.popup_windows = {}
# s_sites = doc.getElementsByTagName("supported_sites")
@ -299,6 +309,11 @@ class Config:
aw = Aux_window(node = aw_node)
self.aux_windows[aw.name] = aw
# s_dbs = doc.getElementsByTagName("mucked_windows")
for hhc_node in doc.getElementsByTagName("hhc"):
hhc = HHC(node = hhc_node)
self.hhcs[hhc.site] = hhc
# s_dbs = doc.getElementsByTagName("popup_windows")
for pu_node in doc.getElementsByTagName("pu"):
pu = Popup(node = pu_node)
@ -703,6 +718,11 @@ if __name__== "__main__":
for w in c.aux_windows.keys():
print c.aux_windows[w]
print "----------- END AUX WINDOW FORMATS -----------"
print "\n----------- HAND HISTORY CONVERTERS -----------"
for w in c.hhcs.keys():
print c.hhcs[w]
print "----------- END HAND HISTORY CONVERTERS -----------"
print "\n----------- POPUP WINDOW FORMATS -----------"
for w in c.popup_windows.keys():

View File

@ -41,8 +41,8 @@ class FpdbSQLQueries:
self.query['list_tables'] = """ """
##################################################################
# Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax
##################################################################
# Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax
##################################################################
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
self.query['drop_table'] = """DROP TABLE IF EXISTS """

View File

@ -66,10 +66,10 @@ class GuiBulkImport():
self.importer.setDropIndexes(cb_model[cb_index][0])
else:
self.importer.setDropIndexes("auto")
hhc=self.cbfilter.get_model()[self.cbfilter.get_active()][0]
sitename = self.cbfilter.get_model()[self.cbfilter.get_active()][0]
self.lab_info.set_text("Importing")
self.importer.addBulkImportImportFileOrDir(self.inputFile,filter=hhc)
self.importer.addBulkImportImportFileOrDir(self.inputFile, site = sitename)
self.importer.setCallHud(False)
starttime = time()
(stored, dups, partial, errs, ttime) = self.importer.runImport()
@ -175,11 +175,9 @@ class GuiBulkImport():
# ComboBox - filter
self.cbfilter = gtk.combo_box_new_text()
self.cbfilter.append_text("passthrough")
self.cbfilter.append_text("BetfairToFpdb")
self.cbfilter.append_text("EverleafToFpdb")
self.cbfilter.append_text("FulltiltToFpdb")
self.cbfilter.append_text("PokerStarsToFpdb")
for w in self.config.hhcs:
print w
self.cbfilter.append_text(w)
self.cbfilter.set_active(0)
self.table.attach(self.cbfilter, 3, 4, 2, 3, xpadding = 10, ypadding = 0, yoptions=gtk.SHRINK)
self.cbfilter.show()
@ -220,8 +218,8 @@ def main(argv=None):
help="Input file in quiet mode")
parser.add_option("-q", "--quiet", action="store_false", dest="gui", default=True,
help="don't start gui; deprecated (just give a filename with -f).")
parser.add_option("-c", "--convert", dest="filtername", default="passthrough", metavar="FILTER",
help="Conversion filter (*passthrough, FullTiltToFpdb, PokerStarsToFpdb, EverleafToFpdb)")
parser.add_option("-c", "--convert", dest="filtername", default="PokerStars", metavar="FILTER",
help="Conversion filter (*Full Tilt Poker, PokerStars, Everleaf)")
parser.add_option("-x", "--failOnError", action="store_true", default=False,
help="If this option is passed it quits when it encounters any error")
parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int",
@ -256,7 +254,7 @@ def main(argv=None):
importer = fpdb_import.Importer(False,settings, config)
importer.setDropIndexes("auto")
importer.setFailOnError(options.failOnError)
importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), filter=options.filtername)
importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername)
importer.setCallHud(False)
importer.runImport()
importer.clearFileList()

View File

@ -12,13 +12,13 @@
screen_name="YOUR SCREEN NAME HERE"
site_path="C:/Program Files/PokerStars/"
HH_path="C:/Program Files/PokerStars/HandHistory/YOUR SCREEN NAME HERE/"
decoder="pokerstars_decode_table"
decoder="pokerstars_decode_table"
converter="PokerStarsToFpdb"
bgcolor="#000000"
fgcolor="#FFFFFF"
hudopacity="1.0"
font="Sans"
font_size="8"
converter="passthrough"
supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo">
<layout max="8" width="792" height="546" fav_seat="0">
<location seat="1" x="684" y="61"> </location>
@ -74,12 +74,12 @@
site_path="C:/Program Files/Full Tilt Poker/"
HH_path="C:/Program Files/Full Tilt Poker/HandHistory/YOUR SCREEN NAME HERE/"
decoder="fulltilt_decode_table"
converter="FulltiltToFpdb"
bgcolor="#000000"
fgcolor="#FFFFFF"
hudopacity="1.0"
font="Sans"
font_size="8"
converter="passthrough"
supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo">
<layout fav_seat="0" height="547" max="8" width="794">
<location seat="1" x="640" y="64"> </location>
@ -123,7 +123,7 @@
site_path=""
HH_path=""
decoder="everleaf_decode_table"
converter="EverleafToFpdb"
converter="EverleafToFpdb"
supported_games="holdem">
<layout fav_seat="0" height="547" max="8" width="794">
<location seat="1" x="640" y="64"> </location>
@ -288,6 +288,12 @@
</aw>
</aux_windows>
<hhcs>
<hhc site="PokerStars" converter="PokerStarsToFpdb"/>
<hhc site="Full Tilt Poker" converter="FulltiltToFpdb"/>
<hhc site="Everleaf" converter="EverleafToFpdb"/>
</hhcs>
<supported_databases>
<database db_name="fpdb" db_server="mysql" db_ip="localhost" db_user="fpdb" db_pass="YOUR MYSQL PASSWORD" db_type="fpdb"></database>
</supported_databases>

View File

@ -73,7 +73,7 @@ follow : whether to tail -f the input"""
["ring", "hold", "pl"],
["ring", "hold", "fl"],
["ring", "stud", "fl"],
["ring", "draw", "fl"],
#["ring", "draw", "fl"],
["ring", "omaha", "pl"]
]

View File

@ -381,7 +381,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
self.window.connect("destroy", self.destroy)
self.window.set_title("Free Poker DB - v%s or higher" % (VERSION, ))
self.window.set_border_width(1)
self.window.set_size_request(1020,400)
self.window.set_default_size(900,720)
self.window.set_resizable(True)
self.menu_items = (
@ -449,7 +449,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
self.tab_main_help(None, None)
self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host)
self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host))
self.main_vbox.pack_end(self.status_bar, False, True, 0)
self.status_bar.show()

View File

@ -58,13 +58,14 @@ class Importer:
self.cursor = None
self.filelist = {}
self.dirlist = {}
self.siteIds = {}
self.addToDirList = {}
self.removeFromFileList = {} # to remove deleted files
self.monitor = False
self.updated = {} #Time last import was run {file:mtime}
self.updated = {} #Time last import was run {file:mtime}
self.lines = None
self.faobs = None #File as one big string
self.pos_in_file = {} # dict to remember how far we have read in the file
self.faobs = None # File as one big string
self.pos_in_file = {} # dict to remember how far we have read in the file
#Set defaults
self.callHud = self.config.get_import_parameters().get("callFpdbHud")
@ -109,20 +110,32 @@ class Importer:
def addImportFile(self, filename, site = "default", filter = "passthrough"):
#TODO: test it is a valid file -> put that in config!!
self.filelist[filename] = [site] + [filter]
if site not in self.siteIds:
# Get id from Sites table in DB
self.fdb.cursor.execute(self.fdb.sql.query['getSiteId'], (site,))
result = self.fdb.cursor.fetchall()
if len(result) == 1:
self.siteIds[site] = result[0][0]
else:
if len(result) == 0:
print "[ERROR] Database ID for %s not found" % site
else:
print "[ERROR] More than 1 Database ID found for %s - Multiple currencies not implemented yet" % site
# Called from GuiBulkImport to add a file or directory.
def addBulkImportImportFileOrDir(self, inputPath,filter = "passthrough"):
def addBulkImportImportFileOrDir(self, inputPath, site = "PokerStars"):
"""Add a file or directory for bulk import"""
filter = self.config.hhcs[site].converter
# Bulk import never monitors
# if directory, add all files in it. Otherwise add single file.
# TODO: only add sane files?
if os.path.isdir(inputPath):
for subdir in os.walk(inputPath):
for file in subdir[2]:
self.addImportFile(os.path.join(inputPath, subdir[0], file), site="default", filter=filter)
self.addImportFile(os.path.join(inputPath, subdir[0], file), site=site, filter=filter)
else:
self.addImportFile(inputPath, site="default", filter=filter)
self.addImportFile(inputPath, site=site, filter=filter)
#Add a directory of files to filelist
#Only one import directory per site supported.
#dirlist is a hash of lists:
@ -193,7 +206,7 @@ class Importer:
self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1])
for file in self.filelist:
if os.path.exists(file):
if os.path.exists(file):
stat_info = os.stat(file)
try:
lastupdate = self.updated[file]
@ -213,8 +226,8 @@ class Importer:
#self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
else:
removeFromFileList[file] = True
self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList)
self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList)
for file in self.removeFromFileList:
if file in self.filelist:
del self.filelist[file]
@ -294,10 +307,9 @@ class Importer:
print "TODO: implement importing tournament summaries"
#self.faobs = readfile(inputFile)
#self.parseTourneyHistory()
return 0
site = fpdb_simple.recogniseSite(firstline)
category = fpdb_simple.recogniseCategory(firstline)
return (0,0,0,1,0)
category=fpdb_simple.recogniseCategory(firstline)
startpos = 0
stored = 0 #counter
@ -305,61 +317,30 @@ class Importer:
partial = 0 #counter
errors = 0 #counter
for i in xrange (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method
if len(self.lines[i]) < 2:
endpos = i
hand = self.lines[startpos:endpos]
for i in xrange (len(self.lines)):
if (len(self.lines[i])<2): #Wierd way to detect for '\r\n' or '\n'
endpos=i
hand=self.lines[startpos:endpos]
if len(hand[0]) < 2:
hand = hand[1:]
cancelled=False
damaged=False
if (site=="ftp"):
for i in range (len(hand)):
if hand[i].endswith(" has been canceled"): #this is their typo. this is a typo, right?
cancelled = True
if (len(hand[0])<2):
hand=hand[1:]
#FTP generates lines looking like:
#Seat 1: IOS Seat 2: kashman59 (big blind) showed [8c 9d] and won ($3.25) with a pair of Eights
#ie. Seat X multiple times on the same line in the summary section, when a new player sits down in the
#middle of the hand.
#TODO: Deal with this properly, either fix the file or make the parsing code work with this line.
if "Seat" in hand[i]:
mo = re.search(" Seat [0-9]+: ", hand[i])
if mo:
print "mo=", mo, "\nmo.start=", mo.start(),"\nhand[i]=",hand[i]
hand.insert(i+1, hand[i][mo.start()+1:])
hand[i] = hand[i][0:mo.start()]
if len(hand) < 3:
if (len(hand)<3):
pass
#todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work.
elif hand[0].endswith(" (partial)"): #partial hand - do nothing
partial += 1
elif "Seat" not in hand[1] and "Seat" not in hand[2] and "Seat" not in hand[3]:
partial += 1
elif cancelled or damaged:
partial += 1
if damaged:
print """
DEBUG: Partial hand triggered by a line containing 'Seat X:' twice. This is a
bug in the FTP software when a player sits down in the middle of a hand.
Adding a newline after the player name will fix the issue
"""
print "File: %s" %(file)
print "Line: %s" %(startpos)
else: #normal processing
isTourney = fpdb_simple.isTourney(hand[0])
#TODO: This is ugly - we didn't actually find the start of the
# hand with the outer loop so we test again...
else:
isTourney=fpdb_simple.isTourney(hand[0])
if not isTourney:
hand = fpdb_simple.filterAnteBlindFold(site,hand)
hand = fpdb_simple.filterAnteBlindFold(hand)
self.hand=hand
try:
handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db
,self.fdb.cursor, site, category, hand, self.config)
,self.fdb.cursor, self.siteIds[site], category, hand, self.config)
self.fdb.db.commit()
stored += 1
if self.callHud:
#print "call to HUD here. handsId:",handsId
@ -370,7 +351,7 @@ class Importer:
except (ValueError), fe:
errors += 1
self.printEmailErrorMessage(errors, file, hand)
if (self.settings['failOnError']):
self.fdb.db.commit() #dont remove this, in case hand processing was cancelled.
raise
@ -378,26 +359,25 @@ class Importer:
errors += 1
self.printEmailErrorMessage(errors, file, hand)
#fe.printStackTrace() #todo: get stacktrace
self.fdb.db.rollback()
if self.settings['failOnError']:
self.fdb.db.commit() #dont remove this, in case hand processing was cancelled.
raise
if self.settings['minPrint']:
if not ((stored+duplicates+partial+errors) % self.settings['minPrint']):
print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors
if not ((stored+duplicates+errors) % self.settings['minPrint']):
print "stored:", stored, "duplicates:", duplicates, "errors:", errors
if self.settings['handCount']:
if ((stored+duplicates+partial+errors) >= self.settings['handCount']):
if ((stored+duplicates+errors) >= self.settings['handCount']):
if not self.settings['quiet']:
print "quitting due to reaching the amount of hands to be imported"
print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime)
print "Total stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", (time() - starttime)
sys.exit(0)
startpos = endpos
ttime = time() - starttime
print "\rTotal stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", ttime
print "\rTotal stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", ttime
if not stored:
if duplicates:
@ -408,16 +388,11 @@ class Importer:
else:
print "failed to read a single hand from file:", inputFile
handsId=0
#todo: this will cause return of an unstored hand number if the last hand was error or partial
#todo: this will cause return of an unstored hand number if the last hand was error
self.fdb.db.commit()
self.handsId=handsId
return (stored, duplicates, partial, errors, ttime)
def parseTourneyHistory(self):
print "Tourney history parser stub"
#Find tournament boundaries.
#print self.foabs
def printEmailErrorMessage(self, errors, filename, line):
traceback.print_exc(file=sys.stderr)
print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it."

View File

@ -21,11 +21,11 @@ import fpdb_simple
import fpdb_save_to_db
#parses a holdem hand
def mainParser(backend, db, cursor, site, category, hand, config):
def mainParser(backend, db, cursor, siteID, category, hand, config):
category = fpdb_simple.recogniseCategory(hand[0])
base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud"
#part 0: create the empty arrays
lineTypes = [] #char, valid values: header, name, cards, action, win, rake, ignore
lineStreets = [] #char, valid values: (predeal, preflop, flop, turn, river)
@ -34,9 +34,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
#part 1: read hand no and check for duplicate
siteHandNo = fpdb_simple.parseSiteHandNo(hand[0])
handStartTime = fpdb_simple.parseHandStartTime(hand[0], site)
siteID = fpdb_simple.recogniseSiteID(cursor, site)
#print "parse logic, siteID:",siteID,"site:",site
handStartTime = fpdb_simple.parseHandStartTime(hand[0])
isTourney = fpdb_simple.isTourney(hand[0])
smallBlindLine = 0
@ -46,11 +44,9 @@ def mainParser(backend, db, cursor, site, category, hand, config):
smallBlindLine = i
break
#print "small blind line:",smallBlindLine
gametypeID = fpdb_simple.recogniseGametypeID(backend, db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney)
if isTourney:
if site != "ps":
raise fpdb_simple.FpdbError("tourneys are only supported on PS right now")
siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0])
buyin = fpdb_simple.parseBuyin(hand[0])
fee = fpdb_simple.parseFee(hand[0])
@ -61,10 +57,10 @@ def mainParser(backend, db, cursor, site, category, hand, config):
rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0])
tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon)
fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo)
hand = fpdb_simple.filterCrap(site, hand, isTourney)
hand = fpdb_simple.filterCrap(hand, isTourney)
#part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street
fpdb_simple.classifyLines(hand, category, lineTypes, lineStreets)
@ -74,10 +70,10 @@ def mainParser(backend, db, cursor, site, category, hand, config):
for i, line in enumerate(hand):
if lineTypes[i] == "name":
seatLines.append(line)
names = fpdb_simple.parseNames(seatLines)
playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID)
tmp = fpdb_simple.parseCashesAndSeatNos(seatLines, site)
tmp = fpdb_simple.parseCashesAndSeatNos(seatLines)
startCashes = tmp['startCashes']
seatNos = tmp['seatNos']
@ -90,30 +86,27 @@ def mainParser(backend, db, cursor, site, category, hand, config):
#part 4: take appropriate action for each line based on linetype
for i, line in enumerate(hand):
if lineTypes[i] == "cards":
fpdb_simple.parseCardLine(site, category, lineStreets[i], line, names, cardValues, cardSuits, boardValues, boardSuits)
fpdb_simple.parseCardLine(category, lineStreets[i], line, names, cardValues, cardSuits, boardValues, boardSuits)
#if category=="studhilo":
# print "hand[i]:", hand[i]
# print "cardValues:", cardValues
# print "cardSuits:", cardSuits
elif lineTypes[i] == "action":
fpdb_simple.parseActionLine(site, base, isTourney, line, lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
fpdb_simple.parseActionLine(base, isTourney, line, lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
elif lineTypes[i] == "win":
fpdb_simple.parseWinLine(line, site, names, winnings, isTourney)
fpdb_simple.parseWinLine(line, names, winnings, isTourney)
elif lineTypes[i] == "rake":
totalRake = 0 if isTourney else fpdb_simple.parseRake(line)
fpdb_simple.splitRake(winnings, rakes, totalRake)
elif lineTypes[i]=="header" or lineTypes[i]=="rake" or lineTypes[i]=="name" or lineTypes[i]=="ignore":
pass
elif lineTypes[i]=="ante":
fpdb_simple.parseAnteLine(line, site, isTourney, names, antes)
fpdb_simple.parseAnteLine(line, isTourney, names, antes)
elif lineTypes[i]=="table":
tableResult=fpdb_simple.parseTableLine(site, base, line)
tableResult=fpdb_simple.parseTableLine(base, line)
else:
raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i])
if site == "ftp":
tableResult = fpdb_simple.parseTableLine(site, base, hand[0])
maxSeats = tableResult['maxSeats']
tableName = tableResult['tableName']
#print "before part5, antes:", antes
@ -128,7 +121,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, ))
limit_type = cursor.fetchone()[0]
fpdb_simple.convert3B4B(site, category, limit_type, actionTypes, actionAmounts)
fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts)
totalWinnings = sum(winnings)
@ -141,7 +134,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes
, allIns, actionTypeByNo, winnings, totalWinnings, None
, actionTypes, actionAmounts, antes)
if isTourney:
ranks = map(lambda x: 0, names) # create an array of 0's equal to the length of names
payin_amounts = fpdb_simple.calcPayin(len(names), buyin, fee)
@ -165,7 +158,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
, allIns, actionAmounts, actionNos, hudImportData, maxSeats
, tableName, seatNos)
else:
raise fpdb_simple.FpdbError("unrecognised category") # it's impossible to get here, but w/e
raise fpdb_simple.FpdbError("unrecognised category")
else:
if base == "hold":
result = fpdb_save_to_db.ring_holdem_omaha(
@ -183,7 +176,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
, actionAmounts, actionNos, hudImportData, maxSeats, tableName
, seatNos)
else:
raise fpdb_simple.FpdbError ("unrecognised category") # also impossible to get here
raise fpdb_simple.FpdbError ("unrecognised category")
db.commit()
return result
#end def mainParser

View File

@ -32,8 +32,7 @@ saveActions = True # set this to False to avoid storing action data
# Pros: speeds up imports
# Cons: no action data is saved, so you need to keep the hand histories
# variance not available on stats page
# no graphs
# : No graphs
#stores a stud/razz hand into the database
def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time
,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes

View File

@ -391,10 +391,6 @@ def checkPositions(positions):
""" verify positions are valid """
if any(not (p == "B" or p == "S" or (p >= 0 and p <= 9)) for p in positions):
raise FpdbError("invalid position '"+p+"' found in checkPositions")
# for p in positions:
# if not (p == "B" or p == "S" or (p >= 0 and p <= 9)):
# raise FpdbError("invalid position '" + p + "' found in checkPositions")
### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB
### eric - position 8 could be valid - if only one blind is posted, but there's still 10 people, ie a sitout is present, and the small is dead...
@ -445,7 +441,7 @@ def classifyLines(hand, category, lineTypes, lineStreets):
currentStreet=3
elif line.startswith("*** 7") or line == "*** RIVER ***":
lineTypes.append("ignore")
currentStreet=4
currentStreet=4
elif isWinLine(line):
lineTypes.append("win")
elif line.startswith("Total pot ") and "Rake" in line:
@ -461,7 +457,7 @@ def classifyLines(hand, category, lineTypes, lineStreets):
lineStreets.append(currentStreet)
#end def classifyLines
def convert3B4B(site, category, limit_type, actionTypes, actionAmounts):
def convert3B4B(category, limit_type, actionTypes, actionAmounts):
"""calculates the actual bet amounts in the given amount array and changes it accordingly."""
for i in xrange(len(actionTypes)):
for j in xrange(len(actionTypes[i])):
@ -571,7 +567,7 @@ def fillCardArrays(player_count, base, category, card_values, card_suits):
#filters out a player that folded before paying ante or blinds. This should be called
#before calling the actual hand parser. manipulates hand, no return.
def filterAnteBlindFold(site,hand):
def filterAnteBlindFold(hand):
#todo: this'll only get rid of one ante folder, not multiple ones
#todo: in tourneys this should not be removed but
#print "start of filterAnteBlindFold"
@ -609,7 +605,7 @@ def stripEOLspaces(str):
return str.rstrip()
#removes useless lines as well as trailing spaces
def filterCrap(site, hand, isTourney):
def filterCrap(hand, isTourney):
#remove two trailing spaces at end of line
hand = [line.rstrip() for line in hand]
@ -642,18 +638,8 @@ def filterCrap(site, hand, isTourney):
hand[i] = False
elif hand[i].endswith("is disconnected"):
hand[i] = False
elif hand[i].endswith(" is feeling angry"):
elif hand[i].find(" is low with [")!=-1:
hand[i] = False
elif hand[i].endswith(" is feeling confused"):
hand[i] = False
elif hand[i].endswith(" is feeling happy"):
hand[i] = False
elif hand[i].endswith(" is feeling normal"):
hand[i] = False
elif " is low with [" in hand[i]:
hand[i] = False
#elif (hand[i].find("-max Seat #")!=-1 and hand[i].find(" is the button")!=-1):
# toRemove.append(hand[i])
elif hand[i].endswith(" mucks"):
hand[i] = False
elif hand[i].endswith(": mucks hand"):
@ -679,13 +665,9 @@ def filterCrap(site, hand, isTourney):
hand[i] = False
elif "joins the table at seat " in hand[i]:
hand[i] = False
elif (hand[i].endswith(" sits down")):
hand[i] = False
elif (hand[i].endswith("leaves the table")):
hand[i] = False
elif (hand[i].endswith(" stands up")):
hand[i] = False
elif "is high with" in hand[i]:
elif "is high with " in hand[i]:
hand[i] = False
elif hand[i].endswith("doesn't show hand"):
hand[i] = False
@ -695,11 +677,9 @@ def filterCrap(site, hand, isTourney):
hand[i] = False
elif hand[i] == "Betting is capped":
hand[i] = False
#site specific variable position filter
elif 'said, "' in hand[i]:
hand[i] = False
elif site == "ftp" and ":" in hand[i] and "Seat " not in hand[i] and ": Table" not in hand[i]: # FTP chat
elif (hand[i].find(" said, \"")!=-1):
hand[i] = False
if isTourney and not hand[i] == False:
if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))):
hand[i] = False
@ -780,7 +760,7 @@ def isWinLine(line):
#end def isWinLine
#returns the amount of cash/chips put into the put in the given action line
def parseActionAmount(line, atype, site, isTourney):
def parseActionAmount(line, atype, isTourney):
#if (line.endswith(" and is all-in")):
# line=line[:-14]
#elif (line.endswith(", and is all in")):
@ -794,19 +774,14 @@ def parseActionAmount(line, atype, site, isTourney):
if atype == "fold" or atype == "check":
amount = 0
elif atype == "unbet":
if site == "ftp":
pos1 = line.find("$") + 1
pos2 = line.find(" returned to")
amount = float2int(line[pos1:pos2])
elif site == "ps":
pos1 = line.find("$") + 1
if pos1 == 0:
pos1 = line.find("(") + 1
pos2 = line.find(")")
amount = float2int(line[pos1:pos2])
elif atype == "bet" and site == "ps" and line.find(": raises $")!=-1 and line.find("to $")!=-1:
pos = line.find("to $")+4
amount = float2int(line[pos:])
pos1 = line.find("$") + 1
if pos1 == 0:
pos1 = line.find("(") + 1
pos2 = line.find(")")
amount = float2int(line[pos1:pos2])
elif atype == "bet" and line.find(": raises $")!=-1 and line.find("to $")!=-1:
pos=line.find("to $")+4
amount=float2int(line[pos:])
else:
if not isTourney:
pos = line.rfind("$")+1
@ -827,7 +802,7 @@ def parseActionAmount(line, atype, site, isTourney):
#doesnt return anything, simply changes the passed arrays action_types and
# action_amounts. For stud this expects numeric streets (3-7), for
# holdem/omaha it expects predeal, preflop, flop, turn or river
def parseActionLine(site, base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo):
def parseActionLine(base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo):
if street == "predeal" or street == "preflop":
street = 0
elif street == "flop":
@ -846,7 +821,7 @@ def parseActionLine(site, base, isTourney, line, street, playerIDs, names, actio
(line, allIn) = goesAllInOnThisLine(line)
atype = parseActionType(line)
playerno = recognisePlayerNo(line, names, atype)
amount = parseActionAmount(line, atype, site, isTourney)
amount = parseActionAmount(line, atype, isTourney)
action_types[street][playerno].append(atype)
allIns[street][playerno].append(allIn)
@ -898,7 +873,7 @@ def parseActionType(line):
#end def parseActionType
#parses the ante out of the given line and checks which player paid it, updates antes accordingly.
def parseAnteLine(line, site, isTourney, names, antes):
def parseAnteLine(line, isTourney, names, antes):
for i, name in enumerate(names):
if line.startswith(name.encode("latin-1")):
pos = line.rfind("$") + 1
@ -924,7 +899,7 @@ def parseBuyin(topline):
#parses a card line and changes the passed arrays accordingly
#todo: reorganise this messy method
def parseCardLine(site, category, street, line, names, cardValues, cardSuits, boardValues, boardSuits):
def parseCardLine(category, street, line, names, cardValues, cardSuits, boardValues, boardSuits):
if line.startswith("Dealt to") or " shows [" in line or "mucked [" in line:
playerNo = recognisePlayerNo(line, names, "card") #anything but unbet will be ok for that string
@ -998,7 +973,7 @@ def parseCardLine(site, category, street, line, names, cardValues, cardSuits, bo
raise FpdbError ("unrecognised line:"+line)
#end def parseCardLine
def parseCashesAndSeatNos(lines, site):
def parseCashesAndSeatNos(lines):
"""parses the startCashes and seatNos of each player out of the given lines and returns them as a dictionary of two arrays"""
cashes = []
seatNos = []
@ -1009,10 +984,7 @@ def parseCashesAndSeatNos(lines, site):
pos1=lines[i].rfind("($")+2
if pos1==1: #for tourneys - it's 1 instead of -1 due to adding 2 above
pos1=lines[i].rfind("(")+1
if (site=="ftp"):
pos2=lines[i].rfind(")")
elif (site=="ps"):
pos2=lines[i].find(" in chips")
pos2=lines[i].find(" in chips")
cashes.append(float2int(lines[i][pos1:pos2]))
return {'startCashes':cashes, 'seatNos':seatNos}
#end def parseCashesAndSeatNos
@ -1026,7 +998,7 @@ def parseFee(topline):
#end def parsefee
#returns a datetime object with the starttime indicated in the given topline
def parseHandStartTime(topline, site):
def parseHandStartTime(topline):
#convert x:13:35 to 0x:13:35
counter=0
while counter < 10:
@ -1037,41 +1009,25 @@ def parseHandStartTime(topline, site):
counter += 1
isUTC=False
if site=="ftp":
# Full Tilt Sit'n'Go
# Full Tilt Poker Game #10311865543: $1 + $0.25 Sit & Go (78057629), Table 1 - 25/50 - No Limit Hold'em - 0:07:45 ET - 2009/01/29
# Cash Game:
# Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09
# Full Tilt Poker Game #9468383505: Table Bike (deep 6) - $0.05/$0.10 - No Limit Hold'em - 5:09:36 ET - 2008/12/13
pos = topline.find(" ", len(topline)-26)+1
tmp = topline[pos:]
rexx = '(?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+) ET [\- ]+(?P<YEAR>[0-9]{4})\/(?P<MON>[0-9]{2})\/(?P<DAY>[0-9]{2})'
m = re.search(rexx,tmp)
result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
elif site=="ps":
if topline.find("UTC")!=-1:
pos1 = topline.find("-")+2
pos2 = topline.find("UTC")
tmp=topline[pos1:pos2]
isUTC=True
else:
tmp=topline
#print "parsehandStartTime, tmp:", tmp
pos = tmp.find("-")+2
tmp = tmp[pos:]
#Need to match either
# 2008/09/07 06:23:14 ET or
# 2008/08/17 - 01:14:43 (ET) or
# 2008/11/12 9:33:31 CET [2008/11/12 3:33:31 ET]
rexx = '(?P<YEAR>[0-9]{4})\/(?P<MON>[0-9]{2})\/(?P<DAY>[0-9]{2})[\- ]+(?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+)'
m = re.search(rexx,tmp)
#print "year:", int(m.group('YEAR')), "month", int(m.group('MON')), "day", int(m.group('DAY')), "hour", int(m.group('HR')), "minute", int(m.group('MIN')), "second", int(m.group('SEC'))
result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
if topline.find("UTC")!=-1:
pos1 = topline.find("-")+2
pos2 = topline.find("UTC")
tmp=topline[pos1:pos2]
isUTC=True
else:
raise FpdbError("invalid site in parseHandStartTime")
tmp=topline
#print "parsehandStartTime, tmp:", tmp
pos = tmp.find("-")+2
tmp = tmp[pos:]
#Need to match either
# 2008/09/07 06:23:14 ET or
# 2008/08/17 - 01:14:43 (ET) or
# 2008/11/12 9:33:31 CET [2008/11/12 3:33:31 ET]
rexx = '(?P<YEAR>[0-9]{4})\/(?P<MON>[0-9]{2})\/(?P<DAY>[0-9]{2})[\- ]+(?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+)'
m = re.search(rexx,tmp)
result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
if (site=="ftp" or site=="ps") and not isUTC: #these use US ET
if not isUTC: #these use US ET
result+=datetime.timedelta(hours=5)
return result
@ -1175,42 +1131,15 @@ def parseSiteHandNo(topline):
return topline[pos1:pos2]
#end def parseSiteHandNo
def parseTableLine(site, base, line):
def parseTableLine(base, line):
"""returns a dictionary with maxSeats and tableName"""
if site=="ps":
pos1=line.find('\'')+1
pos2=line.find('\'', pos1)
#print "table:",line[pos1:pos2]
pos3=pos2+2
pos4=line.find("-max")
#print "seats:",line[pos3:pos4]
return {'maxSeats':int(line[pos3:pos4]), 'tableName':line[pos1:pos2]}
elif site=="ftp":
pos1=line.find("Table ")+6
pos2=line.find("-")-1
if base=="hold":
maxSeats=9
elif base=="stud":
maxSeats=8
if line.find("6 max")!=-1:
maxSeats=6
elif line.find("4 max")!=-1:
maxSeats=4
elif line.find("heads up")!=-1:
maxSeats=2
tableName = line[pos1:pos2]
for pattern in [' \(6 max\)', ' \(heads up\)', ' \(deep\)',
' \(deep hu\)', ' \(deep 6\)', ' \(2\)',
' \(edu\)', ' \(edu, 6 max\)', ' \(6\)',
' \(speed\)',
' no all-in', ' fast', ',', ' 50BB min', '\s+$']:
tableName = re.sub(pattern, '', tableName)
tableName = tableName.rstrip()
return {'maxSeats':maxSeats, 'tableName':tableName}
else:
raise FpdbError("invalid site ID")
pos1=line.find('\'')+1
pos2=line.find('\'', pos1)
#print "table:",line[pos1:pos2]
pos3=pos2+2
pos4=line.find("-max")
#print "seats:",line[pos3:pos4]
return {'maxSeats':int(line[pos3:pos4]), 'tableName':line[pos1:pos2]}
#end def parseTableLine
#returns the hand no assigned by the poker site
@ -1222,24 +1151,18 @@ def parseTourneyNo(topline):
#end def parseTourneyNo
#parses a win/collect line. manipulates the passed array winnings, no explicit return
def parseWinLine(line, site, names, winnings, isTourney):
def parseWinLine(line, names, winnings, isTourney):
#print "parseWinLine: line:",line
for i,n in enumerate(names):
n = n.encode("latin-1")
if line.startswith(n):
if isTourney:
pos1 = line.rfind("collected ") + 10
if site == "ftp":
pos2 = line.find(")", pos1)
elif site == "ps":
pos2 = line.find(" ", pos1)
winnings[i] += int(line[pos1:pos2])
pos2 = line.find(" ", pos1)
winnings[i]+=int(line[pos1:pos2])
else:
pos1 = line.rfind("$") + 1
if site == "ftp":
pos2 = line.find(")", pos1)
elif site == "ps":
pos2 = line.find(" ", pos1)
pos2 = line.find(" ", pos1)
winnings[i] += float2int(line[pos1:pos2])
#end def parseWinLine
@ -1285,10 +1208,7 @@ def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, c
pos1=pos2+2
if isTourney:
pos1-=1
if (site_id==1): #ftp
pos2=topline.find(" ", pos1)
elif (site_id==2): #ps
pos2=topline.find(")")
pos2=topline.find(")")
if pos2<=pos1:
pos2=topline.find(")", pos1)
@ -1471,28 +1391,6 @@ def recognisePlayerNo(line, names, atype):
raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype)
#end def recognisePlayerNo
#returns the site abbreviation for the given site
def recogniseSite(line):
if (line.startswith("Full Tilt Poker") or line.startswith("FullTiltPoker")):
return "ftp"
elif (line.startswith("PokerStars")):
return "ps"
else:
raise FpdbError("failed to recognise site, line:"+line)
#end def recogniseSite
#returns the ID of the given site
def recogniseSiteID(cursor, site):
if (site=="ftp"):
return 1
#cursor.execute("SELECT id FROM Sites WHERE name = ('Full Tilt Poker')")
elif (site=="ps"):
return 2
#cursor.execute("SELECT id FROM Sites WHERE name = ('PokerStars')")
else:
raise FpdbError("invalid site in recogniseSiteID: "+site)
return cursor.fetchall()[0][0]
#end def recogniseSiteID
#removes trailing \n from the given array
def removeTrailingEOL(arr):
@ -2276,7 +2174,7 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData):
except TypeError:
row=[]
if not row:
if not row:
#print "new huddata row"
doInsert=True
row=[]