Merge branch 'master' of git://git.assembla.com/fpdb-eric

This commit is contained in:
grindi 2009-09-23 13:05:00 +04:00
commit e0df04e6c6
11 changed files with 271 additions and 257 deletions

View File

@ -24,6 +24,7 @@ Handles HUD configuration files.
########################################################################
# Standard Library modules
from __future__ import with_statement
import os
import sys
import inspect
@ -316,8 +317,8 @@ class Config:
# Parse even if there was no real config file found and we are using the example
# If using the example, we'll edit it later
log.info("Reading configuration file %s" % file)
try:
log.info("Reading configuration file %s" % (file))
doc = xml.dom.minidom.parse(file)
except:
log.error("Error parsing %s. See error log file." % (file))
@ -353,20 +354,22 @@ class Config:
for db_node in doc.getElementsByTagName("database"):
try:
db = Database(node = db_node)
except:
raise FpdbError("Unable to create database object")
else:
if db.db_name in self.supported_databases:
raise FpdbError("Database names must be unique")
# If there is only one Database node, or none are marked default, the first is selected
if len(self.supported_databases) == 0:
# If there is only one Database node, or none are marked
# default, use first
if not self.supported_databases:
self.db_selected = db.db_name
self.supported_databases[db.db_name] = db
if db.db_selected:
self.db_selected = db.db_name
except:
raise
if dbname and dbname in self.supported_databases:
self.db_selected = dbname
# s_dbs = doc.getElementsByTagName("mucked_windows")
for aw_node in doc.getElementsByTagName("aw"):
aw = Aux_window(node = aw_node)
@ -442,12 +445,11 @@ class Config:
def read_default_conf(self, file):
parms = {}
fh = open(file, "r")
for line in fh:
line = string.strip(line)
(key, value) = line.split('=')
parms[key] = value
fh.close
with open(file, "r") as fh:
for line in fh:
line = string.strip(line)
(key, value) = line.split('=')
parms[key] = value
return parms
def find_example_config(self):
@ -496,14 +498,12 @@ class Config:
def save(self, file = None):
if file != None:
f = open(file, 'w')
self.doc.writexml(f)
f.close()
with open(file, 'w') as f:
self.doc.writexml(f)
else:
shutil.move(self.file, self.file+".backup")
f = open(self.file, 'w')
self.doc.writexml(f)
f.close
with open(self.file, 'w') as f:
self.doc.writexml(f)
def edit_layout(self, site_name, max, width = None, height = None,
fav_seat = None, locations = None):
@ -535,6 +535,7 @@ class Config:
def get_db_parameters(self):
db = {}
name = self.db_selected
# TODO: What's up with all the exception handling here?!
try: db['db-databaseName'] = name
except: pass

View File

@ -181,7 +181,7 @@ class Database:
# create index indexname on tablename (col);
def __init__(self, c, db_name = None, game = None, sql = None): # db_name and game not used any more
def __init__(self, c, sql = None):
log.info("Creating Database instance, sql = %s" % sql)
self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
self.fdb.do_connect(c)
@ -201,7 +201,7 @@ class Database:
# where possible avoid creating new SQL instance by using the global one passed in
if sql == None:
if sql is None:
self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server'])
else:
self.sql = sql
@ -370,23 +370,20 @@ class Database:
def init_hud_stat_vars(self, hud_days):
"""Initialise variables used by Hud to fetch stats."""
self.hand_1day_ago = 1
try:
# self.hand_1day_ago used to fetch stats for current session (i.e. if hud_style = 'S')
self.hand_1day_ago = 1
c = self.get_cursor()
c.execute(self.sql.query['get_hand_1day_ago'])
row = c.fetchone()
except: # TODO: what error is a database error?!
err = traceback.extract_tb(sys.exc_info()[2])[-1]
print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
else:
if row and row[0]:
self.hand_1day_ago = row[0]
#print "hand 1day ago =", self.hand_1day_ago
# self.date_ndays_ago used if hud_style = 'T'
self.hand_1_day_ago = row[0]
d = timedelta(days=hud_days)
now = datetime.utcnow() - d
self.date_ndays_ago = "d%02d%02d%02d" % (now.year-2000, now.month, now.day)
except:
err = traceback.extract_tb(sys.exc_info()[2])[-1]
print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
self.date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day)
def init_player_hud_stat_vars(self, playerid):
# not sure if this is workable, to be continued ...

4
pyfpdb/FulltiltToFpdb.py Executable file → Normal file
View File

@ -656,7 +656,9 @@ class Fulltilt(HandHistoryConverter):
heroName = n.group('HERO_NAME')
tourney.hero = heroName
# Is this really useful ?
if (tourney.finishPositions[heroName] != Decimal(n.group('HERO_FINISHING_POS'))):
if heroName not in tourney.finishPositions:
print heroName, "not found in tourney.finishPositions ..."
elif (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'))
return True

View File

@ -60,6 +60,11 @@ class GuiBulkImport():
return True
def load_clicked(self, widget, data=None):
stored = None
dups = None
partial = None
errs = None
ttime = None
# Does the lock acquisition need to be more sophisticated for multiple dirs?
# (see comment above about what to do if pipe already open)
if self.settings['global_lock'].acquire(False): # returns false immediately if lock not acquired
@ -101,13 +106,13 @@ class GuiBulkImport():
self.importer.addBulkImportImportFileOrDir(self.inputFile, site = sitename)
self.importer.setCallHud(False)
starttime = time()
try:
(stored, dups, partial, errs, ttime) = self.importer.runImport()
except:
print "*** EXCEPTION DURING BULKIMPORT!!!"
raise Exceptions.FpdbError
finally:
gobject.source_remove(self.timer)
# try:
(stored, dups, partial, errs, ttime) = self.importer.runImport()
# except:
# print "*** EXCEPTION DURING BULKIMPORT!!!"
# raise Exceptions.FpdbError
# finally:
gobject.source_remove(self.timer)
ttime = time() - starttime
if ttime == 0:

View File

@ -32,7 +32,7 @@ try:
from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar
from numpy import arange, cumsum
from pylab import *
except:
except ImportError:
print """Failed to load libs for graphing, graphing will not function. Please in
stall numpy and matplotlib if you want to use graphs."""
print """This is of no consequence for other parts of the program, e.g. import

View File

@ -160,7 +160,7 @@ class HUD_main(object):
# be passed to HUDs for use in the gui thread. HUD objects should not
# need their own access to the database, but should open their own
# if it is required.
self.db_connection = Database.Database(self.config, self.db_name, 'temp')
self.db_connection = Database.Database(self.config)
self.db_connection.init_hud_stat_vars(hud_days)
tourny_finder = re.compile('(\d+) (\d+)')

View File

@ -334,11 +334,16 @@ class Hud:
self.update_table_position()
for s in self.stat_dict:
statd = self.stat_dict[s]
try:
statd = self.stat_dict[s]
except KeyError:
print "KeyError at the start of the for loop in update in hud_main. How this can possibly happen is totally beyond my comprehension. Your HUD may be about to get really weird. -Eric"
print "(btw, the key was ", s, " and statd is...", statd
continue
try:
self.stat_windows[statd['seat']].player_id = statd['player_id']
#self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id']
except: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here
except KeyError: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here
self.max = 10
self.create(hand, config, self.stat_dict, self.cards)
self.stat_windows[statd['seat']].player_id = statd['player_id']
@ -374,6 +379,7 @@ class Stat_Window:
# This handles all callbacks from button presses on the event boxes in
# the stat windows. There is a bit of an ugly kludge to separate single-
# and double-clicks.
self.window.show_all()
if event.button == 3: # right button event
newpopup = Popup_window(self.window, self)
@ -388,7 +394,6 @@ class Stat_Window:
if event.button == 1: # left button event
# TODO: make position saving save sizes as well?
self.window.show_all()
if event.state & gtk.gdk.SHIFT_MASK:
self.window.begin_resize_drag(gtk.gdk.WINDOW_EDGE_SOUTH_EAST, event.button, int(event.x_root), int(event.y_root), event.time)
else:

View File

@ -21,19 +21,18 @@ import re
import sys
import logging
from time import time, strftime
from Exceptions import *
use_pool = False
try:
import sqlalchemy.pool as pool
use_pool = True
except:
except ImportError:
logging.info("Not using sqlalchemy connection pool.")
use_pool = False
import fpdb_simple
import FpdbSQLQueries
from Exceptions import *
class fpdb_db:
MYSQL_INNODB = 2
@ -67,12 +66,12 @@ class fpdb_db:
"""Connects a database with the given parameters"""
if backend is None:
raise FpdbError('Database backend not defined')
self.backend=backend
self.host=host
self.user=user
self.password=password
self.database=database
if backend==fpdb_db.MYSQL_INNODB:
self.backend = backend
self.host = host
self.user = user
self.password = password
self.database = database
if backend == fpdb_db.MYSQL_INNODB:
import MySQLdb
if use_pool:
MySQLdb = pool.manage(MySQLdb, pool_size=5)
@ -113,7 +112,7 @@ class fpdb_db:
msg = "PostgreSQL connection to database (%s) user (%s) failed." % (database, user)
print msg
raise FpdbError(msg)
elif backend==fpdb_db.SQLITE:
elif backend == fpdb_db.SQLITE:
logging.info("Connecting to SQLite:%(database)s" % {'database':database})
import sqlite3
if use_pool:
@ -125,20 +124,20 @@ class fpdb_db:
sqlite3.register_adapter(bool, lambda x: "1" if x else "0")
else:
raise FpdbError("unrecognised database backend:"+backend)
self.cursor=self.db.cursor()
self.cursor = self.db.cursor()
# Set up query dictionary as early in the connection process as we can.
self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())
self.cursor.execute(self.sql.query['set tx level'])
self.wrongDbVersion=False
self.wrongDbVersion = False
try:
self.cursor.execute("SELECT * FROM Settings")
settings=self.cursor.fetchone()
if settings[0]!=118:
settings = self.cursor.fetchone()
if settings[0] != 118:
print "outdated or too new database version - please recreate tables"
self.wrongDbVersion=True
self.wrongDbVersion = True
except:# _mysql_exceptions.ProgrammingError:
if database != ":memory:": print "failed to read settings table - please recreate tables"
self.wrongDbVersion=True
self.wrongDbVersion = True
#end def connect
def disconnect(self, due_to_error=False):

View File

@ -49,22 +49,20 @@ log = logging.getLogger('importer')
# database interface modules
try:
import MySQLdb
mysqlLibFound=True
log.debug("Import module: MySQLdb")
except:
log.debug("Import module: MySQLdb not found")
except ImportError:
log.debug("Import database module: MySQLdb not found")
else:
mysqlLibFound = True
try:
import psycopg2
pgsqlLibFound=True
except ImportError:
log.debug("Import database module: psycopg2 not found")
else:
import psycopg2.extensions
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
log.debug("Import module: psycopg2")
except:
log.debug("Import module: psycopg2 not found")
class Importer:
def __init__(self, caller, settings, config, sql = None):
"""Constructor"""
self.settings = settings

View File

@ -18,46 +18,63 @@
#parses an in-memory fpdb hand history and calls db routine to store it
import sys
import fpdb_simple
import Database
from time import time, strftime
from Exceptions import *
import fpdb_simple
import Database
#parses a holdem hand
def mainParser(settings, siteID, category, hand, config, db = None, writeq = None):
""" mainParser for Holdem Hands """
t0 = time()
#print "mainparser"
backend = settings['db-backend']
# Ideally db connection is passed in, if not use sql list if passed in, otherwise start from scratch
# Ideally db connection is passed in, if not use sql list if passed in,
# otherwise start from scratch
if db == None:
db = Database.Database(c = config, sql = None)
category = fpdb_simple.recogniseCategory(hand[0])
base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud"
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)
cardValues, cardSuits, boardValues, boardSuits, antes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo, seatLines, winnings, rakes=[],[],[],[],[],[],[],[],[],[],[],[],[]
# lineTypes valid values: header, name, cards, action, win, rake, ignore
# lineStreets valid values: predeal, preflop, flop, turn, river
lineTypes = []
lineStreets = []
cardValues = []
cardSuits = []
boardValues = []
boardSuits = []
antes = []
allIns = []
actionAmounts = []
actionNos = []
actionTypes = []
actionTypeByNo = []
seatLines = []
winnings = []
rakes = []
#part 1: read hand no and check for duplicate
siteHandNo = fpdb_simple.parseSiteHandNo(hand[0])
#print "siteHandNo =", siteHandNo
handStartTime = fpdb_simple.parseHandStartTime(hand[0])
handStartTime = fpdb_simple.parseHandStartTime(hand[0])
isTourney = fpdb_simple.isTourney(hand[0])
smallBlindLine = 0
smallBlindLine = None
for i, line in enumerate(hand):
if 'posts small blind' in line or 'posts the small blind' in line:
if line[-2:] == "$0": continue
smallBlindLine = i
break
else:
smallBlindLine = 0
# If we did not find a small blind line, what happens?
# if we leave it at None, it errors two lines down.
gametypeID = fpdb_simple.recogniseGametypeID(backend, db, db.get_cursor(), hand[0], hand[smallBlindLine], siteID, category, isTourney)
gametypeID = fpdb_simple.recogniseGametypeID(backend, db, db.get_cursor(),
hand[0], hand[smallBlindLine],
siteID, category, isTourney)
if isTourney:
siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0])
buyin = fpdb_simple.parseBuyin(hand[0])
@ -68,8 +85,14 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non
tourneyStartTime= handStartTime #todo: read tourney start time
rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0])
## 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)
# 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:
siteTourneyNo = -1
buyin = -1
@ -100,7 +123,9 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non
startCashes = tmp['startCashes']
seatNos = tmp['seatNos']
fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes,
winnings, rakes, actionTypes, allIns,
actionAmounts, actionNos, actionTypeByNo)
#3b read positions
if base == "hold":
@ -109,27 +134,32 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non
#part 4: take appropriate action for each line based on linetype
for i, line in enumerate(hand):
if lineTypes[i] == "cards":
fpdb_simple.parseCardLine(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(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, 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":
elif (lineTypes[i] == "header" or lineTypes[i] == "rake" or
lineTypes[i] == "name" or lineTypes[i] == "ignore"):
pass
elif lineTypes[i]=="ante":
elif lineTypes[i] == "ante":
fpdb_simple.parseAnteLine(line, isTourney, names, antes)
elif lineTypes[i]=="table":
elif lineTypes[i] == "table":
tableResult=fpdb_simple.parseTableLine(base, line)
else:
raise FpdbError("unrecognised lineType:"+lineTypes[i])
raise FpdbError("unrecognised lineType:" + lineTypes[i])
maxSeats = tableResult['maxSeats']
tableName = tableResult['tableName']
#print "before part5, antes:", antes
@ -152,26 +182,34 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non
# if hold'em, use positions and not antes, if stud do not use positions, use antes
# this is used for handsplayers inserts, so still needed even if hudcache update is being skipped
if base == "hold":
hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes
, allIns, actionTypeByNo, winnings, totalWinnings, positions
, actionTypes, actionAmounts, None)
hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base,
category, actionTypes,
allIns, actionTypeByNo,
winnings,
totalWinnings,
positions, actionTypes,
actionAmounts, None)
else:
hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes
, allIns, actionTypeByNo, winnings, totalWinnings, None
, actionTypes, actionAmounts, antes)
hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base,
category, actionTypes,
allIns, actionTypeByNo,
winnings,
totalWinnings, None,
actionTypes,
actionAmounts, antes)
#print "parse: hand data prepared" # only reads up to here apart from inserting new players
try:
db.commit() # need to commit new players as different db connection used
# for other writes. maybe this will change maybe not ...
except:
except: # TODO: this really needs to be narrowed down
print "parse: error during commit: " + str(sys.exc_value)
# HERE's an ugly kludge to keep from failing when positions is undef
# We'll fix this by getting rid of the legacy importer. REB
try:
if positions: pass
except:
if positions:
pass
except NameError:
positions = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# save data structures in a HandToWrite instance and then insert into database:
htw = Database.HandToWrite()

View File

@ -53,8 +53,9 @@ def checkPositions(positions):
### 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...
#classifies each line for further processing in later code. Manipulates the passed arrays.
def classifyLines(hand, category, lineTypes, lineStreets):
""" makes a list of classifications for each line for further processing
manipulates passed arrays """
currentStreet = "predeal"
done = False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats)
for i, line in enumerate(hand):
@ -114,61 +115,59 @@ def classifyLines(hand, category, lineTypes, lineStreets):
else:
raise FpdbError("unrecognised linetype in:"+hand[i])
lineStreets.append(currentStreet)
#end def classifyLines
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])):
bets=[]
bets = []
for k in xrange(len(actionTypes[i][j])):
if (actionTypes[i][j][k]=="bet"):
if (actionTypes[i][j][k] == "bet"):
bets.append((i,j,k))
if (len(bets)>=2):
#print "len(bets) 2 or higher, need to correct it. bets:",bets,"len:",len(bets)
for betNo in reversed(xrange (1,len(bets))):
amount2=actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]]
amount1=actionAmounts[bets[betNo-1][0]][bets[betNo-1][1]][bets[betNo-1][2]]
actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]]=amount2-amount1
#print "actionAmounts postConvert",actionAmounts
#end def convert3B4B(actionTypes, actionAmounts)
amount2 = actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]]
amount1 = actionAmounts[bets[betNo-1][0]][bets[betNo-1][1]][bets[betNo-1][2]]
actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]] = amount2 - amount1
#Corrects the bet amount if the player had to pay blinds
def convertBlindBet(actionTypes, actionAmounts):
i=0#setting street to pre-flop
""" Corrects the bet amount if the player had to pay blinds """
i = 0#setting street to pre-flop
for j in xrange(len(actionTypes[i])):#playerloop
blinds=[]
bets=[]
blinds = []
bets = []
for k in xrange(len(actionTypes[i][j])):
if actionTypes[i][j][k] == "blind":
blinds.append((i,j,k))
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:
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
#end def convertBlindBet
actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] = bet_amount - blind_amount
#converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details
#todo: make this use convertCardValuesBoard
def convertCardValues(arr):
map(convertCardValuesBoard, arr)
#end def convertCardValues
# a 0-card is one in a stud game that we did not see or was not shown
card_map = { 0: 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14}
card_map = { 0: 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8,
"9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14}
#converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details
def convertCardValuesBoard(arr):
""" converts the strings in the given array to ints
(changes the passed array, no returning). see table design for
conversion details """
for i in xrange(len(arr)):
arr[i] = card_map[arr[i]]
#end def convertCardValuesBoard
#this creates the 2D/3D arrays. manipulates the passed arrays instead of returning.
def createArrays(category, seats, card_values, card_suits, antes, winnings, rakes, action_types, allIns, action_amounts, actionNos, actionTypeByNo):
def createArrays(category, seats, card_values, card_suits, antes, winnings,
rakes, action_types, allIns, action_amounts, actionNos,
actionTypeByNo):
""" this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. """
for i in xrange(seats):#create second dimension arrays
card_values.append( [] )
card_suits.append( [] )
@ -176,7 +175,8 @@ def createArrays(category, seats, card_values, card_suits, antes, winnings, rake
winnings.append(0)
rakes.append(0)
streetCount = 4 if category == "holdem" or category == "omahahi" or category == "omahahilo" else 5
streetCount = 4 if (category == "holdem" or category == "omahahi" or
category == "omahahilo") else 5
for i in xrange(streetCount): #build the first dimension array, for streets
action_types.append([])
@ -184,14 +184,14 @@ def createArrays(category, seats, card_values, card_suits, antes, winnings, rake
action_amounts.append([])
actionNos.append([])
actionTypeByNo.append([])
for j in xrange (seats): #second dimension arrays: players
for j in xrange(seats): # second dimension arrays: players
action_types[i].append([])
allIns[i].append([])
action_amounts[i].append([])
actionNos[i].append([])
# if (category=="holdem" or category=="omahahi" or category=="omahahilo"):
# pass
if category=="razz" or category=="studhi" or category=="studhilo":#need to fill card arrays.
if category == "razz" or category == "studhi" or category == "studhilo": #need to fill card arrays.
for i in xrange(seats):
for j in xrange(7):
card_values[i].append(0)
@ -201,25 +201,24 @@ def createArrays(category, seats, card_values, card_suits, antes, winnings, rake
#end def createArrays
def fill_board_cards(board_values, board_suits):
#fill up the two board card arrays
while (len(board_values)<5):
""" fill up the two board card arrays """
while len(board_values) < 5:
board_values.append(0)
board_suits.append("x")
#end def fill_board_cards
def fillCardArrays(player_count, base, category, card_values, card_suits):
"""fills up the two card arrays"""
if (category=="holdem"):
if category == "holdem":
cardCount = 2
elif (category=="omahahi" or category=="omahahilo"):
elif category == "omahahi" or category == "omahahilo":
cardCount = 4
elif base=="stud":
elif base == "stud":
cardCount = 7
else:
raise FpdbError("invalid category:", category)
for i in xrange(player_count):
while (len(card_values[i]) < cardCount):
while len(card_values[i]) < cardCount:
card_values[i].append(0)
card_suits[i].append("x")
#end def fillCardArrays
@ -230,12 +229,12 @@ 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"
pre3rd=[]
pre3rd = []
for i, line in enumerate(hand):
if line.startswith("*** 3") or line.startswith("*** HOLE"):
pre3rd = hand[0:i]
foldeeName=None
foldeeName = None
for line in pre3rd:
if line.endswith("folds") or line.endswith("is sitting out") or line.endswith(" stands up"): #found ante fold or timeout
pos = line.find(" folds")
@ -251,26 +250,25 @@ def filterAnteBlindFold(hand):
pos2 = line.find(" (")
foldeeName = line[pos1:pos2]
if foldeeName!=None:
if foldeeName is not None:
#print "filterAnteBlindFold, foldeeName:",foldeeName
for i, line in enumerate(hand):
if foldeeName in line:
hand[i] = None
return [line for line in hand if line]
#end def filterAnteFold
def stripEOLspaces(str):
return str.rstrip()
#removes useless lines as well as trailing spaces
def filterCrap(hand, isTourney):
#remove two trailing spaces at end of line
""" removes useless lines as well as trailing spaces """
#remove trailing spaces at end of line
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)):
for i in xrange(len(hand)):
if hand[i].startswith("Board ["):
hand[i] = False
elif hand[i].find(" out of hand ")!=-1:
@ -347,15 +345,16 @@ def filterCrap(hand, isTourney):
hand[i] = False
elif (hand[i].endswith(" is sitting out")):
hand[i] = False
hand = [line for line in hand if line] # python docs say this is identical to filter(None, list)
# python docs say this is identical to filter(None, list)
# which removes all false items from the passed list (hand)
hand = [line for line in hand if line]
#print "done with filterCrap, hand:", hand
return hand
#end filterCrap
#takes a poker float (including , for thousand seperator and converts it to an int
def float2int(string):
""" takes a poker float (including , for thousand seperator) and
converts it to an int """
# Note that this automagically assumes US style currency formatters
pos = string.find(",")
if pos != -1: #remove , the thousand seperator
string = "%s%s" % (string[0:pos], string[pos+1:])
@ -368,56 +367,46 @@ def float2int(string):
if pos == -1: #no decimal point - was in full dollars - need to multiply with 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")
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")
#returns boolean whether the passed line is an action line
def isActionLine(line):
if (line.endswith("folds")):
if line.endswith("folds"):
return True
elif (line.endswith("checks")):
elif line.endswith("checks"):
return True
elif (line.startswith("Uncalled bet")):
elif line.startswith("Uncalled bet"):
return True
# searches for each member of ActionLines being in line, returns true
# on first match .. neat func
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)
#end def isActionLine
#returns whether this is a duplicate
def isAlreadyInDB(db, gametypeID, siteHandNo):
#print "isAlreadyInDB gtid,shand:",gametypeID, siteHandNo
c = db.get_cursor()
c.execute( db.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo))
c.execute(db.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo))
result = c.fetchall()
if (len(result)>=1):
if len(result) >= 1:
raise DuplicateError ("dupl")
#end isAlreadyInDB
def isRebuyOrAddon(topline):
"""isRebuyOrAddon not implemented yet"""
return False
#end def isRebuyOrAddon
#returns whether the passed topline indicates a tournament or not
def isTourney(topline):
return "Tournament" in topline
#end def isTourney
WinLines = ( "wins the pot", "ties for the ", "wins side pot", "wins the low main pot", "wins the high main pot",
"wins the low",
"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):
""" returns boolean whether the passed line is a win line """
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
def parseActionAmount(line, atype, isTourney):
@ -426,7 +415,8 @@ def parseActionAmount(line, atype, isTourney):
#elif (line.endswith(", and is all in")):
# line=line[:-15]
if line.endswith(", and is capped"):#ideally we should recognise this as an all-in if category is capXl
#ideally we should recognise this as an all-in if category is capXl
if line.endswith(", and is capped"):
line=line[:-15]
if line.endswith(" and is capped"):
line=line[:-14]
@ -439,9 +429,9 @@ def parseActionAmount(line, atype, isTourney):
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:])
elif atype == "bet" and ": raises $" in line and "to $" in line:
pos = line.find("to $")+4
amount = float2int(line[pos:])
else:
if not isTourney:
pos = line.rfind("$")+1
@ -489,7 +479,6 @@ def parseActionLine(base, isTourney, line, street, playerIDs, names, action_type
actionNos[street][playerno].append(nextActionNo)
tmp=(playerIDs[playerno], atype)
actionTypeByNo[street].append(tmp)
#end def parseActionLine
def goesAllInOnThisLine(line):
"""returns whether the player went all-in on this line and removes the all-in text from the line."""
@ -501,7 +490,6 @@ def goesAllInOnThisLine(line):
line = line[:-15]
isAllIn = True
return (line, isAllIn)
#end def goesAllInOnThisLine
#returns the action type code (see table design) of the given action line
ActionTypes = { 'brings in for' :"blind",
@ -530,7 +518,6 @@ def parseActionType(line):
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.
def parseAnteLine(line, isTourney, names, antes):
@ -547,15 +534,12 @@ def parseAnteLine(line, isTourney, names, antes):
pos1 = line.rfind("ante") + 5
pos2 = line.find(" ", pos1)
antes[i] += int(line[pos1:pos2])
#print "parseAnteLine line: ", line, "antes[i]", antes[i], "antes", antes
#end def parseAntes
#returns the buyin of a tourney in cents
def parseBuyin(topline):
pos1 = topline.find("$")+1
pos2 = topline.find("+")
return float2int(topline[pos1:pos2])
#end def parseBuyin
#parses a card line and changes the passed arrays accordingly
#todo: reorganise this messy method
@ -568,8 +552,9 @@ def parseCardLine(category, street, line, names, cardValues, cardSuits, boardVal
for i in (pos, pos+3):
cardValues[playerNo].append(line[i:i+1])
cardSuits[playerNo].append(line[i+1:i+2])
if len(cardValues[playerNo]) !=2:
if cardValues[playerNo][0]==cardValues[playerNo][2] and cardSuits[playerNo][1]==cardSuits[playerNo][3]: #two tests will do
if len(cardValues[playerNo]) != 2:
if (cardValues[playerNo][0] == cardValues[playerNo][2] and
cardSuits[playerNo][1] == cardSuits[playerNo][3]):
cardValues[playerNo]=cardValues[playerNo][0:2]
cardSuits[playerNo]=cardSuits[playerNo][0:2]
else:
@ -580,13 +565,14 @@ def parseCardLine(category, street, line, names, cardValues, cardSuits, boardVal
cardValues[playerNo].append(line[i:i+1])
cardSuits[playerNo].append(line[i+1:i+2])
if (len(cardValues[playerNo])!=4):
if cardValues[playerNo][0]==cardValues[playerNo][4] and cardSuits[playerNo][3]==cardSuits[playerNo][7]: #two tests will do
cardValues[playerNo]=cardValues[playerNo][0:4]
cardSuits[playerNo]=cardSuits[playerNo][0:4]
if (cardValues[playerNo][0] == cardValues[playerNo][4] and
cardSuits[playerNo][3] == cardSuits[playerNo][7]): #two tests will do
cardValues[playerNo] = cardValues[playerNo][0:4]
cardSuits[playerNo] = cardSuits[playerNo][0:4]
else:
print "line:",line,"cardValues[playerNo]:",cardValues[playerNo]
raise FpdbError("read too many/too few holecards in parseCardLine")
elif category=="razz" or category=="studhi" or category=="studhilo":
elif category == "razz" or category == "studhi" or category == "studhilo":
if "shows" not in line and "mucked" not in line:
#print "parseCardLine(in stud if), street:", street
if line[pos+2]=="]": #-> not (hero and 3rd street)
@ -631,7 +617,6 @@ def parseCardLine(category, street, line, names, cardValues, cardSuits, boardVal
#print boardValues
else:
raise FpdbError ("unrecognised line:"+line)
#end def parseCardLine
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"""
@ -647,7 +632,6 @@ def parseCashesAndSeatNos(lines):
pos2=lines[i].find(" in chips")
cashes.append(float2int(lines[i][pos1:pos2]))
return {'startCashes':cashes, 'seatNos':seatNos}
#end def parseCashesAndSeatNos
#returns the buyin of a tourney in cents
def parseFee(topline):
@ -655,7 +639,6 @@ def parseFee(topline):
pos1=topline.find("$",pos1)+1
pos2=topline.find(" ", pos1)
return float2int(topline[pos1:pos2])
#end def parsefee
#returns a datetime object with the starttime indicated in the given topline
def parseHandStartTime(topline):
@ -688,10 +671,9 @@ def parseHandStartTime(topline):
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 not isUTC: #these use US ET
result+=datetime.timedelta(hours=5)
result += datetime.timedelta(hours=5)
return result
#end def parseHandStartTime
#parses the names out of the given lines and returns them as an array
def findName(line):
@ -701,13 +683,11 @@ def findName(line):
def parseNames(lines):
return [findName(line) for line in lines]
#end def parseNames
def parsePositions(hand, names):
positions = [-1 for i in names]
sb, bb = -1, -1
#find blinds
for line in hand:
if sb == -1 and "small blind" in line and "dead small blind" not in line:
sb = line
@ -735,10 +715,7 @@ def parsePositions(hand, names):
positions[bb]="B"
#fill up rest of array
if sbExists:
arraypos = sb-1
else:
arraypos = bb-1
arraypos = sb - 1 if sbExists else bb - 1
distFromBtn=0
while arraypos >= 0 and arraypos != bb:
@ -753,21 +730,19 @@ def parsePositions(hand, names):
while positions[i] < 0 and i != sb:
positions[i] = 9
i -= 1
### RHH - Changed to set the null seats before BB to "9"
if sbExists:
i = sb-1
else:
i = bb-1
### RHH - Changed to set the null seats before BB to "9"
i = sb - 1 if sbExists else bb - 1
while positions[i] < 0:
positions[i]=9
i-=1
arraypos=len(names)-1
if (bb!=0 or (bb==0 and sbExists==False) or (bb == 1 and sb != arraypos) ):
while (arraypos>bb and arraypos > sb):
positions[arraypos]=distFromBtn
arraypos-=1
distFromBtn+=1
while (arraypos > bb and arraypos > sb):
positions[arraypos] = distFromBtn
arraypos -= 1
distFromBtn += 1
if any(p == -1 for p in positions):
print "parsePositions names:",names
@ -775,21 +750,18 @@ def parsePositions(hand, names):
raise FpdbError ("failed to read positions")
# print str(positions), "\n"
return positions
#end def parsePositions
#simply parses the rake amount and returns it as an int
def parseRake(line):
pos=line.find("Rake")+6
rake=float2int(line[pos:])
pos = line.find("Rake")+6
rake = float2int(line[pos:])
return rake
#end def parseRake
def parseSiteHandNo(topline):
"""returns the hand no assigned by the poker site"""
pos1=topline.find("#")+1
pos2=topline.find(":")
pos1 = topline.find("#")+1
pos2 = topline.find(":")
return topline[pos1:pos2]
#end def parseSiteHandNo
def parseTableLine(base, line):
"""returns a dictionary with maxSeats and tableName"""
@ -804,11 +776,10 @@ def parseTableLine(base, line):
#returns the hand no assigned by the poker site
def parseTourneyNo(topline):
pos1=topline.find("Tournament #")+12
pos2=topline.find(",", pos1)
pos1 = topline.find("Tournament #")+12
pos2 = topline.find(",", pos1)
#print "parseTourneyNo pos1:",pos1," pos2:",pos2, " result:",topline[pos1:pos2]
return topline[pos1:pos2]
#end def parseTourneyNo
#parses a win/collect line. manipulates the passed array winnings, no explicit return
def parseWinLine(line, names, winnings, isTourney):
@ -819,12 +790,11 @@ def parseWinLine(line, names, winnings, isTourney):
if isTourney:
pos1 = line.rfind("collected ") + 10
pos2 = line.find(" ", pos1)
winnings[i]+=int(line[pos1:pos2])
winnings[i] += int(line[pos1:pos2])
else:
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
def recogniseCategory(line):
@ -844,7 +814,6 @@ def recogniseCategory(line):
return "studhilo"
else:
raise FpdbError("failed to recognise category, line:"+line)
#end def recogniseCategory
#returns the int for the gametype_id for the given line
def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, category, isTourney):#todo: this method is messy
@ -853,50 +822,50 @@ def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, c
#note: the below variable names small_bet and big_bet are misleading, in NL/PL they mean small/big blind
if isTourney:
type="tour"
pos1=topline.find("(")+1
if (topline[pos1]=="H" or topline[pos1]=="O" or topline[pos1]=="R" or topline[pos1]=="S" or topline[pos1+2]=="C"):
pos1=topline.find("(", pos1)+1
pos2=topline.find("/", pos1)
small_bet=int(topline[pos1:pos2])
type = "tour"
pos1 = topline.find("(")+1
if(topline[pos1] == "H" or topline[pos1] == "O" or
topline[pos1] == "R" or topline[pos1]=="S" or
topline[pos1+2] == "C"):
pos1 = topline.find("(", pos1)+1
pos2 = topline.find("/", pos1)
small_bet = int(topline[pos1:pos2])
else:
type="ring"
pos1=topline.find("$")+1
pos2=topline.find("/$")
small_bet=float2int(topline[pos1:pos2])
type = "ring"
pos1 = topline.find("$")+1
pos2 = topline.find("/$")
small_bet = float2int(topline[pos1:pos2])
pos1=pos2+2
pos1 = pos2+2
if isTourney:
pos1-=1
pos2=topline.find(")")
pos1 -= 1
pos2 = topline.find(")")
if pos2<=pos1:
pos2=topline.find(")", pos1)
if pos2 <= pos1:
pos2 = topline.find(")", pos1)
if isTourney:
big_bet=int(topline[pos1:pos2])
big_bet = int(topline[pos1:pos2])
else:
big_bet=float2int(topline[pos1:pos2])
big_bet = float2int(topline[pos1:pos2])
if (topline.find("No Limit")!=-1):
limit_type="nl"
if (topline.find("Cap No")!=-1):
limit_type="cn"
elif (topline.find("Pot Limit")!=-1):
limit_type="pl"
if (topline.find("Cap Pot")!=-1):
limit_type="cp"
if 'No Limit' in topline:
limit_type = "nl" if 'Cap No' not in topline else "cn"
elif 'Pot Limit' in topline:
limit_type = "pl" if 'Cap Pot' not in topline else "cp"
else:
limit_type="fl"
limit_type = "fl"
#print "recogniseGametypeID small_bet/blind:",small_bet,"big bet/blind:", big_bet,"limit type:",limit_type
if (limit_type=="fl"):
cursor.execute ( db.sql.query['getGametypeFL']
, (site_id, type, category, limit_type, small_bet, big_bet))
if limit_type == "fl":
cursor.execute(db.sql.query['getGametypeFL'], (site_id, type, category,
limit_type, small_bet,
big_bet))
else:
cursor.execute ( db.sql.query['getGametypeNL']
, (site_id, type, category, limit_type, small_bet, big_bet))
result=cursor.fetchone()
cursor.execute(db.sql.query['getGametypeNL'], (site_id, type, category,
limit_type, small_bet,
big_bet))
result = cursor.fetchone()
#print "recgt1 result=",result
#ret=result[0]
#print "recgt1 ret=",ret