Merge branch 'master' into siteneutral

Conflicts:

	pyfpdb/fpdb_import.py
	pyfpdb/fpdb_parse_logic.py
	pyfpdb/fpdb_simple.py
This commit is contained in:
Worros 2009-03-28 00:54:13 +09:00
commit 0b3b7f66d6
10 changed files with 256 additions and 246 deletions

View File

@ -48,7 +48,7 @@ class Layout:
self.height = int( node.getAttribute('height') )
self.location = []
self.location = map(lambda x: None, range(self.max+1)) # there must be a better way to do this?
self.location = map(lambda x: None, range(self.max+1)) # fill array with max seats+1 empty entries
for location_node in node.getElementsByTagName('location'):
if location_node.getAttribute('seat') != "":
@ -239,13 +239,14 @@ class Tv:
(self.combinedStealFold, self.combined2B3B, self.combinedPostflop) )
class Config:
def __init__(self, file = None):
def __init__(self, file = None, dbname = 'fpdb'):
# "file" is a path to an xml file with the fpdb/HUD configuration
# we check the existence of "file" and try to recover if it doesn't exist
self.dbname = dbname
self.default_config_path = self.get_default_config_path()
if not file == None: # configuration file path has been passed
if file != None: # configuration file path has been passed
if not os.path.exists(file):
print "Configuration file %s not found. Using defaults." % (file)
sys.stderr.write("Configuration file %s not found. Using defaults." % (file))
@ -256,7 +257,7 @@ class Config:
if file == None: # no config file in the normal places
file = self.find_example_config() #Look for an example file to edit
if not file == None:
if file != None:
pass
if file == None: # that didn't work either, just die
@ -323,7 +324,7 @@ class Config:
tv = Tv(node = tv_node)
self.tv = tv
db = self.get_db_parameters('fpdb')
db = self.get_db_parameters()
if db['db-password'] == 'YOUR MYSQL PASSWORD':
df_file = self.find_default_conf()
if df_file == None: # this is bad
@ -426,7 +427,7 @@ class Config:
return location_node
def save(self, file = None):
if not file == None:
if file != None:
f = open(file, 'w')
self.doc.writexml(f)
f.close()
@ -463,9 +464,9 @@ class Config:
else:
self.aux_windows[aux_name].layout[max].location[i] = ( locations[i][0], locations[i][1] )
def get_db_parameters(self, name = None):
if name == None: name = 'fpdb'
def get_db_parameters(self):
db = {}
name = self.dbname
try: db['db-databaseName'] = name
except: pass
@ -491,18 +492,18 @@ class Config:
def set_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None,
db_pass = None, db_server = None, db_type = None):
db_node = self.get_db_node(db_name)
if not db_node == None:
if not db_ip == None: db_node.setAttribute("db_ip", db_ip)
if not db_user == None: db_node.setAttribute("db_user", db_user)
if not db_pass == None: db_node.setAttribute("db_pass", db_pass)
if not db_server == None: db_node.setAttribute("db_server", db_server)
if not db_type == None: db_node.setAttribute("db_type", db_type)
if db_node != None:
if db_ip != None: db_node.setAttribute("db_ip", db_ip)
if db_user != None: db_node.setAttribute("db_user", db_user)
if db_pass != None: db_node.setAttribute("db_pass", db_pass)
if db_server != None: db_node.setAttribute("db_server", db_server)
if db_type != None: db_node.setAttribute("db_type", db_type)
if self.supported_databases.has_key(db_name):
if not db_ip == None: self.supported_databases[db_name].dp_ip = db_ip
if not db_user == None: self.supported_databases[db_name].dp_user = db_user
if not db_pass == None: self.supported_databases[db_name].dp_pass = db_pass
if not db_server == None: self.supported_databases[db_name].dp_server = db_server
if not db_type == None: self.supported_databases[db_name].dp_type = db_type
if db_ip != None: self.supported_databases[db_name].dp_ip = db_ip
if db_user != None: self.supported_databases[db_name].dp_user = db_user
if db_pass != None: self.supported_databases[db_name].dp_pass = db_pass
if db_server != None: self.supported_databases[db_name].dp_server = db_server
if db_type != None: self.supported_databases[db_name].dp_type = db_type
return
def get_tv_parameters(self):
@ -630,19 +631,19 @@ class Config:
font = None, font_size = None):
"""Sets the specified site parameters for the specified site."""
site_node = self.get_site_node(site_name)
if not db_node == None:
if not converter == None: site_node.setAttribute("converter", converter)
if not decoder == None: site_node.setAttribute("decoder", decoder)
if not hudbgcolor == None: site_node.setAttribute("hudbgcolor", hudbgcolor)
if not hudfgcolor == None: site_node.setAttribute("hudfgcolor", hudfgcolor)
if not hudopacity == None: site_node.setAttribute("hudopacity", hudopacity)
if not screen_name == None: site_node.setAttribute("screen_name", screen_name)
if not site_path == None: site_node.setAttribute("site_path", site_path)
if not table_finder == None: site_node.setAttribute("table_finder", table_finder)
if not HH_path == None: site_node.setAttribute("HH_path", HH_path)
if not enabled == None: site_node.setAttribute("enabled", enabled)
if not font == None: site_node.setAttribute("font", font)
if not font_size == None: site_node.setAttribute("font_size", font_size)
if db_node != None:
if converter != None: site_node.setAttribute("converter", converter)
if decoder != None: site_node.setAttribute("decoder", decoder)
if hudbgcolor != None: site_node.setAttribute("hudbgcolor", hudbgcolor)
if hudfgcolor != None: site_node.setAttribute("hudfgcolor", hudfgcolor)
if hudopacity != None: site_node.setAttribute("hudopacity", hudopacity)
if screen_name != None: site_node.setAttribute("screen_name", screen_name)
if site_path != None: site_node.setAttribute("site_path", site_path)
if table_finder != None: site_node.setAttribute("table_finder", table_finder)
if HH_path != None: site_node.setAttribute("HH_path", HH_path)
if enabled != None: site_node.setAttribute("enabled", enabled)
if font != None: site_node.setAttribute("font", font)
if font_size != None: site_node.setAttribute("font_size", font_size)
return
def get_aux_windows(self):

View File

@ -68,13 +68,13 @@ class GuiGraphViewer (threading.Thread):
if len(result) == 1:
playerids.append(result[0][0])
if sitenos == []:
if not sitenos:
#Should probably pop up here.
print "No sites selected - defaulting to PokerStars"
sitenos = [2]
if playerids == []:
if not playerids:
print "No player ids found"
return

View File

@ -91,7 +91,7 @@ class HUD_main(object):
gtk.gdk.threads_enter()
try:
newlabel = gtk.Label(table.site + " - " + table_name)
newlabel = gtk.Label("%s - %s" % (table.site, table_name))
self.vb.add(newlabel)
newlabel.show()
self.main_window.resize_children()
@ -110,8 +110,8 @@ class HUD_main(object):
self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection)
self.hud_dict[table_name].stat_dict = stat_dict
self.hud_dict[table_name].cards = cards
for aw in self.hud_dict[table_name].aux_windows:
aw.update_data(new_hand_id, self.db_connection)
[aw.update_data(new_hand_id, self.db_connection) for aw in self.hud_dict[table_name].aux_windows]
gobject.idle_add(idle_func)
def update_HUD(self, new_hand_id, table_name, config):

View File

@ -174,11 +174,10 @@ class Hud:
self.main_window.move(x, y)
adj = self.adj_seats(self.hand, self.config)
loc = self.config.get_locations(self.table.site, self.max)
for i, w in enumerate(self.stat_windows):
if not type(w) == int: # how do we get pure ints in this list??
(x, y) = loc[adj[i]]
w.relocate(x, y)
# TODO: is stat_windows getting converted somewhere from a list to a dict, for no good reason?
for i, w in enumerate(self.stat_windows.itervalues()):
(x, y) = loc[adj[i]]
w.relocate(x, y)
return True
def on_button_press(self, widget, event):
@ -415,8 +414,9 @@ class Stat_Window:
self.window.set_transient_for(parent.main_window)
self.window.set_focus_on_map(False)
self.grid = gtk.Table(rows = game.rows, columns = game.cols, homogeneous = False)
self.window.add(self.grid)
grid = gtk.Table(rows = game.rows, columns = game.cols, homogeneous = False)
self.grid = grid
self.window.add(grid)
self.window.modify_bg(gtk.STATE_NORMAL, parent.backgroundcolor)
self.e_box = []
@ -440,10 +440,10 @@ class Stat_Window:
Stats.do_tip(e_box[r][c], 'stuff')
if usegtkframes:
self.grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
self.frame[r][c].add(e_box[r][c])
else:
self.grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
label[r].append( gtk.Label('xxx') )
if usegtkframes:

View File

@ -39,15 +39,19 @@ import Database
class Aux_Window:
def __init__(self, hud, params, config):
self.hud = hud
self.params = params
self.config = config
def update_data(self, *parms):
def update_data(self, *args):
pass
def update_gui(self, *parms):
def update_gui(self, *args):
pass
def create(self, *parms):
def create(self, *args):
pass
def relocate(self, *args):
pass
def save_layout(self, *args):
@ -321,6 +325,7 @@ class Flop_Mucked(Aux_Window):
self.config = config # configuration object for this aux window to use
self.params = params # dict aux params from config
self.positions = {} # dict of window positions
# self.rel_positions = {} # dict of window positions, relative to the table origin
self.displayed_cards = False
self.timer_on = False # bool = Ture if the timeout for removing the cards is on
self.card_images = self.get_card_images()
@ -350,6 +355,7 @@ class Flop_Mucked(Aux_Window):
self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[('B', 'H')])
self.eb[i].add(self.seen_cards[i])
self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y)
# self.rel_positions[i] = (int(x), int(y))
self.m_windows[i].move(self.positions[i][0], self.positions[i][1])
self.m_windows[i].set_opacity(float(self.params['opacity']))
self.m_windows[i].show_all()
@ -434,6 +440,7 @@ class Flop_Mucked(Aux_Window):
def configure_event_cb(self, widget, event, i, *args):
self.positions[i] = widget.get_position()
# self.rel_positions[i] = (self.positions[i][0] - self.hud.table.x, self.positions[i][1] - self.hud.table.y)
def expose_all(self):
for (i, cards) in self.hud.cards.iteritems():

View File

@ -219,7 +219,7 @@ def discover_nt(c):
else:
tw.site = "Unknown"
sys.stderr.write("Found unknown table = %s" % tw.title)
if not tw.site == "Unknown":
if tw.site != "Unknown":
eval("%s(tw)" % c.supported_sites[tw.site].decoder)
else:
tw.name = "Unknown"

View File

@ -23,6 +23,8 @@ from optparse import OptionParser
parser = OptionParser()
parser.add_option("-x", "--errorsToConsole", action="store_true",
help="If passed error output will go to the console rather than .")
parser.add_option("-d", "--databaseName", dest="dbname", default="fpdb",
help="Overrides the default database name")
(options, sys.argv) = parser.parse_args()
if not options.errorsToConsole:
@ -371,7 +373,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
def __init__(self):
self.threads=[]
self.db=None
self.config = Configuration.Config()
self.config = Configuration.Config(dbname=options.dbname)
self.load_profile()
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)

View File

@ -68,12 +68,10 @@ class Importer:
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")
if 'minPrint' not in self.settings:
#TODO: Is this value in the xml file?
self.settings['minPrint'] = 30
if 'handCount' not in self.settings:
#TODO: Is this value in the xml file?
self.settings['handCount'] = 0
self.settings.setdefault("minPrint", 30)
self.settings.setdefault("handCount", 0)
self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
self.fdb.do_connect(self.config)
@ -279,10 +277,10 @@ class Importer:
def import_fpdb_file(self, file, site):
starttime = time()
last_read_hand=0
last_read_hand = 0
loc = 0
if (file=="stdin"):
inputFile=sys.stdin
if file == "stdin":
inputFile = sys.stdin
else:
if os.path.exists(file):
inputFile = open(file, "rU")
@ -295,7 +293,7 @@ class Importer:
pass
# Read input file into class and close file
inputFile.seek(loc)
self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines())
self.lines = fpdb_simple.removeTrailingEOL(inputFile.readlines())
self.pos_in_file[file] = inputFile.tell()
inputFile.close()
@ -313,11 +311,11 @@ class Importer:
category=fpdb_simple.recogniseCategory(firstline)
startpos=0
stored=0 #counter
duplicates=0 #counter
partial=0 #counter
errors=0 #counter
startpos = 0
stored = 0 #counter
duplicates = 0 #counter
partial = 0 #counter
errors = 0 #counter
for i in xrange (len(self.lines)):
if (len(self.lines[i])<2): #Wierd way to detect for '\r\n' or '\n'
@ -339,50 +337,51 @@ class Importer:
self.hand=hand
try:
handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db
,self.fdb.cursor, self.siteIds[site], category, hand, self.config)
handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db
,self.fdb.cursor, site, category, hand, self.config)
self.fdb.db.commit()
stored+=1
stored += 1
if self.callHud:
#print "call to HUD here. handsId:",handsId
#pipe the Hands.id out to the HUD
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
except fpdb_simple.DuplicateError:
duplicates+=1
duplicates += 1
except (ValueError), fe:
errors+=1
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
except (fpdb_simple.FpdbError), fe:
errors+=1
errors += 1
self.printEmailErrorMessage(errors, file, hand)
self.fdb.db.rollback()
if (self.settings['failOnError']):
if self.settings['failOnError']:
self.fdb.db.commit() #dont remove this, in case hand processing was cancelled.
raise
if (self.settings['minPrint']!=0):
if ((stored+duplicates+errors)%self.settings['minPrint']==0):
if self.settings['minPrint']:
if not ((stored+duplicates+errors) % self.settings['minPrint']):
print "stored:", stored, "duplicates:", duplicates, "errors:", errors
if (self.settings['handCount']!=0):
if ((stored+duplicates+errors)>=self.settings['handCount']):
if (not self.settings['quiet']):
if 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, "errors:", errors, " time:", (time() - starttime)
sys.exit(0)
startpos=endpos
startpos = endpos
ttime = time() - starttime
print "\rTotal stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", ttime
if stored==0:
if duplicates>0:
for line_no in range(len(self.lines)):
if not stored:
if duplicates:
for line_no in xrange(len(self.lines)):
if self.lines[line_no].find("Game #")!=-1:
final_game_line=self.lines[line_no]
handsId=fpdb_simple.parseSiteHandNo(final_game_line)

View File

@ -60,7 +60,7 @@ def mainParser(backend, db, cursor, siteID, category, hand, config):
fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo)
hand=fpdb_simple.filterCrap(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)

View File

@ -384,18 +384,13 @@ def getLastInsertId(backend, conn, cursor):
#returns an array of the total money paid. intending to add rebuys/addons here
def calcPayin(count, buyin, fee):
result=[]
for i in xrange(count):
result.append (buyin+fee)
return result
return [buyin + fee for i in xrange(count)]
#end def calcPayin
def checkPositions(positions):
""" verify positions are valid """
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")
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")
### 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...
@ -495,12 +490,13 @@ def convertBlindBet(actionTypes, actionAmounts):
blinds=[]
bets=[]
for k in xrange(len(actionTypes[i][j])):
if (actionTypes[i][j][k]=="blind"):
if actionTypes[i][j][k] == "blind":
blinds.append((i,j,k))
if (len(blinds)>0 and actionTypes[i][j][k]=="bet"):
if blinds and actionTypes[i][j][k] == "bet":
# if (len(blinds)>0 and actionTypes[i][j][k]=="bet"):
bets.append((i,j,k))
if (len(bets)==1):
if len(bets) == 1:
blind_amount=actionAmounts[blinds[0][0]][blinds[0][1]][blinds[0][2]]
bet_amount=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]]
actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]]=bet_amount-blind_amount
@ -615,84 +611,80 @@ def filterAnteBlindFold(hand):
#end def filterAnteFold
def stripEOLspaces(str):
if str[-1] == ' ':
str = str[:-1]
if str[-1] == ' ':
str = str[:-1]
return str
return str.rstrip()
#removes useless lines as well as trailing spaces
def filterCrap(hand, isTourney):
#remove two trailing spaces at end of line
hand = [stripEOLspaces(line) for line in hand]
hand = [line.rstrip() for line in hand]
#print "hand after trailing space removal in filterCrap:",hand
#general variable position word filter/string filter
for i in xrange (len(hand)):
if (hand[i].startswith("Board [")):
if hand[i].startswith("Board ["):
hand[i] = False
elif (hand[i].find(" out of hand ")!=-1):
elif hand[i].find(" out of hand ")!=-1:
hand[i]=hand[i][:-56]
elif (hand[i].find("($0 in chips)") != -1):
elif "($0 in chips)" in hand[i]:
hand[i] = False
elif (hand[i]=="*** HOLE CARDS ***"):
elif hand[i]=="*** HOLE CARDS ***":
hand[i] = False
elif (hand[i].endswith("has been disconnected")):
elif hand[i].endswith("has been disconnected"):
hand[i] = False
elif (hand[i].endswith("has requested TIME")):
elif hand[i].endswith("has requested TIME"):
hand[i] = False
elif (hand[i].endswith("has returned")):
elif hand[i].endswith("has returned"):
hand[i] = False
elif (hand[i].endswith("will be allowed to play after the button")):
elif hand[i].endswith("will be allowed to play after the button"):
hand[i] = False
elif (hand[i].endswith("has timed out")):
elif hand[i].endswith("has timed out"):
hand[i] = False
elif (hand[i].endswith("has timed out while disconnected")):
elif hand[i].endswith("has timed out while disconnected"):
hand[i] = False
elif (hand[i].endswith("has timed out while being disconnected")):
elif hand[i].endswith("has timed out while being disconnected"):
hand[i] = False
elif (hand[i].endswith("is connected")):
elif hand[i].endswith("is connected"):
hand[i] = False
elif (hand[i].endswith("is disconnected")):
elif hand[i].endswith("is disconnected"):
hand[i] = False
elif (hand[i].find(" is low with [")!=-1):
elif hand[i].find(" is low with [")!=-1:
hand[i] = False
elif (hand[i].endswith(" mucks")):
hand[i] = False
elif (hand[i].endswith(": mucks hand")):
elif hand[i].endswith(": mucks hand"):
hand[i] = False
elif (hand[i]=="No low hand qualified"):
elif hand[i] == "No low hand qualified":
hand[i] = False
elif (hand[i]=="Pair on board - a double bet is allowed"):
elif hand[i] == "Pair on board - a double bet is allowed":
hand[i] = False
elif (hand[i].find(" shows ")!=-1 and hand[i].find("[")==-1):
elif " shows " in hand[i] and "[" not in hand[i]:
hand[i] = False
elif (hand[i].startswith("The button is in seat #")):
elif hand[i].startswith("The button is in seat #"):
hand[i] = False
#above is alphabetic, reorder below if bored
elif (hand[i].startswith("Time has expired")):
elif hand[i].startswith("Time has expired"):
hand[i] = False
elif (hand[i].endswith("has reconnected")):
elif hand[i].endswith("has reconnected"):
hand[i] = False
elif (hand[i].endswith("seconds left to act")):
elif hand[i].endswith("seconds left to act"):
hand[i] = False
elif (hand[i].endswith("seconds to reconnect")):
elif hand[i].endswith("seconds to reconnect"):
hand[i] = False
elif (hand[i].endswith("was removed from the table for failing to post")):
elif hand[i].endswith("was removed from the table for failing to post"):
hand[i] = False
elif (hand[i].find("joins the table at seat ")!=-1):
elif "joins the table at seat " in hand[i]:
hand[i] = False
elif (hand[i].endswith("leaves the table")):
hand[i] = False
elif (hand[i].find("is high with ")!=-1):
elif "is high with " in hand[i]:
hand[i] = False
elif (hand[i].endswith("doesn't show hand")):
elif hand[i].endswith("doesn't show hand"):
hand[i] = False
elif (hand[i].endswith("is being treated as all-in")):
elif hand[i].endswith("is being treated as all-in"):
hand[i] = False
elif (hand[i].find(" adds $")!=-1):
elif " adds $" in hand[i]:
hand[i] = False
elif (hand[i]=="Betting is capped"):
elif hand[i] == "Betting is capped":
hand[i] = False
elif (hand[i].find(" said, \"")!=-1):
hand[i] = False
@ -700,7 +692,8 @@ def filterCrap(hand, isTourney):
if isTourney and not hand[i] == False:
if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))):
hand[i] = False
elif (hand[i].endswith(": sits out")):
elif hand[i]:
if (hand[i].endswith(": sits out")):
hand[i] = False
elif (hand[i].endswith(" is sitting out")):
hand[i] = False
@ -712,25 +705,25 @@ def filterCrap(hand, isTourney):
#end filterCrap
#takes a poker float (including , for thousand seperator and converts it to an int
def float2int (string):
pos=string.find(",")
if (pos!=-1): #remove , the thousand seperator
def float2int(string):
pos = string.find(",")
if pos != -1: #remove , the thousand seperator
string = "%s%s" % (string[0:pos], string[pos+1:])
pos=string.find(".")
if (pos!=-1): #remove decimal point
pos = string.find(".")
if pos != -1: #remove decimal point
string = "%s%s" % (string[0:pos], string[pos+1:])
result = int(string)
if pos == -1: #no decimal point - was in full dollars - need to multiply with 100
result*=100
result *= 100
return result
#end def float2int
ActionLines = ( "calls $", ": calls ", "brings in for", "completes it to", "posts small blind",
"posts the small blind", "posts big blind", "posts the big blind",
"posts small & big blinds", "posts $", "posts a dead", "bets $",
": bets ", "raises")
": bets ", " raises")
#returns boolean whether the passed line is an action line
def isActionLine(line):
@ -741,7 +734,8 @@ def isActionLine(line):
elif (line.startswith("Uncalled bet")):
return True
return len( [ x for x in ActionLines if x in line]) > 0
return any(x for x in ActionLines if x in line)
# return bool([ x for x in ActionLines if x in line])
# ret = any(True for searchstr in ActionLines if searchstr in line)
# ret = len( [ x for x in ActionLines if line.find(x) > -1] ) > 0
# ret = any(searchstr in line for searchstr in ActionLines)
@ -771,7 +765,7 @@ WinLines = ( "wins the pot", "ties for the ", "wins side pot", "wins the low mai
"wins the high pot", "wins the high side pot", "wins the main pot", "wins the side pot", "collected" )
#returns boolean whether the passed line is a win line
def isWinLine(line):
return len( [ x for x in WinLines if x in line ] ) > 0
return any(x for x in WinLines if x in line)
#end def isWinLine
#returns the amount of cash/chips put into the put in the given action line
@ -833,10 +827,10 @@ def parseActionLine(base, isTourney, line, street, playerIDs, names, action_type
if actionNos[street][player][count]>=nextActionNo:
nextActionNo=actionNos[street][player][count]+1
line, allIn=goesAllInOnThisLine(line)
atype=parseActionType(line)
playerno=recognisePlayerNo(line, names, atype)
amount=parseActionAmount(line, atype, isTourney)
(line, allIn) = goesAllInOnThisLine(line)
atype = parseActionType(line)
playerno = recognisePlayerNo(line, names, atype)
amount = parseActionAmount(line, atype, isTourney)
action_types[street][playerno].append(atype)
allIns[street][playerno].append(allIn)
@ -859,41 +853,24 @@ def goesAllInOnThisLine(line):
#end def goesAllInOnThisLine
#returns the action type code (see table design) of the given action line
ActionTypes = { 'calls':"call", 'brings in for':"blind", 'completes it to':"bet", ' posts $':"blind",
' posts a dead ' : "blind", ' posts the small blind of $':"blind", ': posts big blind ':"blind",
' posts the big blind of $':"blind", ': posts small & big blinds $':"blind",
': posts small blind $':"blind",
' bets' : "bet", ' raises' : "bet"
}
def parseActionType(line):
if (line.startswith("Uncalled bet")):
return "unbet"
elif (line.endswith("folds")):
elif (line.endswith(" folds")):
return "fold"
elif (line.endswith("checks")):
elif (line.endswith(" checks")):
return "check"
elif (line.find("calls")!=-1):
return "call"
elif (line.find("brings in for")!=-1):
return "blind"
elif (line.find("completes it to")!=-1):
return "bet"
#todo: what if someone completes instead of bringing in?
elif (line.find(" posts $")!=-1):
return "blind"
elif (line.find(" posts a dead ")!=-1):
return "blind"
elif (line.find(": posts small blind ")!=-1):
return "blind"
elif (line.find(" posts the small blind of $")!=-1):
return "blind"
elif (line.find(": posts big blind ")!=-1):
return "blind"
elif (line.find(" posts the big blind of $")!=-1):
return "blind"
elif (line.find(": posts small & big blinds $")!=-1):
return "blind"
#todo: seperately record voluntary blind payments made to join table out of turn
elif (line.find("bets")!=-1):
return "bet"
elif (line.find("raises")!=-1):
return "bet"
else:
raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line)
for x in ActionTypes:
if x in line:
return ActionTypes[x]
raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line)
#end def parseActionType
#parses the ante out of the given line and checks which player paid it, updates antes accordingly.
@ -1025,12 +1002,12 @@ def parseFee(topline):
def parseHandStartTime(topline):
#convert x:13:35 to 0x:13:35
counter=0
while (True):
pos=topline.find(" "+str(counter)+":")
if (pos!=-1):
topline=topline[0:pos+1]+"0"+topline[pos+1:]
counter+=1
if counter==10: break
while counter < 10:
pos = topline.find(" %d:" % counter)
if pos != -1:
topline = "%s0%s" % (topline[0:pos+1], topline[pos+1:])
break
counter += 1
isUTC=False
if topline.find("UTC")!=-1:
@ -1058,64 +1035,58 @@ def parseHandStartTime(topline):
#end def parseHandStartTime
#parses the names out of the given lines and returns them as an array
def findName(line):
pos1 = line.find(":") + 2
pos2 = line.rfind("(") - 1
return unicode(line[pos1:pos2], "latin-1")
def parseNames(lines):
result = []
for i in xrange (len(lines)):
pos1=lines[i].find(":")+2
pos2=lines[i].rfind("(")-1
tmp=lines[i][pos1:pos2]
#print "parseNames, tmp original:",tmp
tmp=unicode(tmp,"latin-1")
#print "parseNames, tmp after unicode latin-1 conversion:",tmp
result.append(tmp)
return result
return [findName(line) for line in lines]
#end def parseNames
def parsePositions(hand, names):
positions = map(lambda x: -1, names)
positions = [-1 for i in names]
sb, bb = -1, -1
#find blinds
sb,bb=-1,-1
for i in xrange (len(hand)):
if (sb==-1 and hand[i].find("small blind")!=-1 and hand[i].find("dead small blind")==-1):
sb=hand[i]
#print "sb:",sb
if (bb==-1 and hand[i].find("big blind")!=-1 and hand[i].find("dead big blind")==-1):
bb=hand[i]
#print "bb:",bb
for line in hand:
if sb == -1 and "small blind" in line and "dead small blind" not in line:
sb = line
if bb == -1 and "big blind" in line and "dead big blind" not in line:
bb = line
#identify blinds
#print "parsePositions before recognising sb/bb. names:",names
sbExists=True
if (sb!=-1):
sb=recognisePlayerNo(sb, names, "bet")
sbExists = True
if sb != -1:
sb = recognisePlayerNo(sb, names, "bet")
else:
sbExists=False
if (bb!=-1):
bb=recognisePlayerNo(bb, names, "bet")
sbExists = False
if bb != -1:
bb = recognisePlayerNo(bb, names, "bet")
# print "sb = ", sb, "bb = ", bb
if bb == sb:
if bb == sb: # if big and small are same, then don't duplicate the small
sbExists = False
sb = -1
#write blinds into array
if (sbExists):
if sbExists:
positions[sb]="S"
positions[bb]="B"
#fill up rest of array
if (sbExists):
arraypos=sb-1
if sbExists:
arraypos = sb-1
else:
arraypos=bb-1
arraypos = bb-1
distFromBtn=0
while (arraypos>=0 and arraypos != bb):
while arraypos >= 0 and arraypos != bb:
#print "parsePositions first while, arraypos:",arraypos,"positions:",positions
positions[arraypos]=distFromBtn
arraypos-=1
distFromBtn+=1
positions[arraypos] = distFromBtn
arraypos -= 1
distFromBtn += 1
# eric - this takes into account dead seats between blinds
if sbExists:
@ -1139,11 +1110,10 @@ def parsePositions(hand, names):
arraypos-=1
distFromBtn+=1
for i in xrange (len(names)):
if positions[i]==-1:
print "parsePositions names:",names
print "result:",positions
raise FpdbError ("failed to read positions")
if any(p == -1 for p in positions):
print "parsePositions names:",names
print "result:",positions
raise FpdbError ("failed to read positions")
# print str(positions), "\n"
return positions
#end def parsePositions
@ -1184,16 +1154,17 @@ def parseTourneyNo(topline):
#parses a win/collect line. manipulates the passed array winnings, no explicit return
def parseWinLine(line, names, winnings, isTourney):
#print "parseWinLine: line:",line
for i in xrange(len(names)):
if (line.startswith(names[i].encode("latin-1"))): #found a winner
for i,n in enumerate(names):
n = n.encode("latin-1")
if line.startswith(n):
if isTourney:
pos1=line.rfind("collected ")+10
pos2=line.find(" ", pos1)
pos1 = line.rfind("collected ") + 10
pos2 = line.find(" ", pos1)
winnings[i]+=int(line[pos1:pos2])
else:
pos1=line.rfind("$")+1
pos2=line.find(" ", pos1)
winnings[i]+=float2int(line[pos1:pos2])
pos1 = line.rfind("$") + 1
pos2 = line.find(" ", pos1)
winnings[i] += float2int(line[pos1:pos2])
#end def parseWinLine
#returns the category (as per database) string for the given line
@ -1335,21 +1306,49 @@ def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon):
#end def recogniseTourneyTypeId
#returns the SQL ids of the names given in an array
# TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict
# { playername: id } instead of depending on it's relation to the positions list
# then this can be reduced in complexity a bit
def recognisePlayerIDs(cursor, names, site_id):
result = []
for i in xrange(len(names)):
cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],))
tmp=cursor.fetchall()
if (len(tmp)==0): #new player
cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id))
#print "Number of players rows inserted: %d" % cursor.rowcount
cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],))
tmp=cursor.fetchall()
#print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp
result.append(tmp[0][0])
return result
cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names)) # get all playerids by the names passed in
ids = dict(cursor.fetchall()) # convert to dict
if len(ids) != len(names):
notfound = [n for n in names if n not in ids] # make list of names not in database
if notfound: # insert them into database
cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound))
cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(notfound)) # get their new ids
tmp = dict(cursor.fetchall())
for n in tmp: # put them all into the same dict
ids[n] = tmp[n]
# return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB
return [ids[n] for n in names]
#end def recognisePlayerIDs
# Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input
# this version could also be improved upon using list comprehensions, etc
#def recognisePlayerIDs(cursor, names, site_id):
# result = []
# notfound = []
# cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names))
# tmp = dict(cursor.fetchall())
# for n in names:
# if n not in tmp:
# notfound.append(n)
# else:
# result.append(tmp[n])
# if notfound:
# cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound))
# cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound))
# tmp = cursor.fetchall()
# for n in tmp:
# result.append(n[0])
#
# return result
#recognises the name in the given line and returns its array position in the given array
def recognisePlayerNo(line, names, atype):
#print "recogniseplayerno, names:",names
@ -2161,7 +2160,7 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData):
except TypeError:
row=[]
if (len(row)==0):
if not row:
#print "new huddata row"
doInsert=True
row=[]
@ -2174,9 +2173,11 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData):
else:
doInsert=False
# This is making a copy of the original list, although i really don't see any reason it's being done?
newrow=[]
for i in xrange(len(row)):
newrow.append(row[i])
newrow.extend(row)
# for i in xrange(len(row)):
# newrow.append(row[i])
row=newrow
if base=="hold":