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-20 00:27:08 +09:00
commit 444e780f29
14 changed files with 662 additions and 675 deletions

122
pyfpdb/Configuration.py Normal file → Executable file
View File

@ -32,6 +32,13 @@ import shutil
import xml.dom.minidom
from xml.dom.minidom import Node
def fix_tf(x):
if x == "1" or x == 1 or string.lower(x) == "true" or string.lower(x) == "t":
return True
if x == "0" or x == 0 or string.lower(x) == "false" or string.lower(x) == "f":
return False
return False
class Layout:
def __init__(self, node):
@ -205,9 +212,18 @@ class Import:
self.interval = node.getAttribute("interval")
self.callFpdbHud = node.getAttribute("callFpdbHud")
self.hhArchiveBase = node.getAttribute("hhArchiveBase")
if node.hasAttribute("saveActions"):
self.saveActions = fix_tf(node.getAttribute("saveActions"))
else:
self.saveActions = True
if node.hasAttribute("fastStoreHudCache"):
self.fastStoreHudCache = fix_tf(node.getAttribute("fastStoreHudCache"))
else:
self.fastStoreHudCache = False
def __str__(self):
return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s" % (self.interval, self.callFpdbHud, self.hhArchiveBase)
return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s\n saveActions = %s\n fastStoreHudCache = %s\n" \
% (self.interval, self.callFpdbHud, self.hhArchiveBase, self.saveActions, self.saveActions)
class Tv:
def __init__(self, node):
@ -391,9 +407,14 @@ class Config:
return layout_node
def get_location_node(self, layout_node, seat):
for location_node in layout_node.getElementsByTagName("location"):
if int( location_node.getAttribute("seat") ) == int( seat ):
return location_node
if seat == "common":
for location_node in layout_node.getElementsByTagName("location"):
if location_node.hasAttribute("common"):
return location_node
else:
for location_node in layout_node.getElementsByTagName("location"):
if int( location_node.getAttribute("seat") ) == int( seat ):
return location_node
def save(self, file = None):
if not file == None:
@ -420,29 +441,42 @@ class Config:
def edit_aux_layout(self, aux_name, max, width = None, height = None, locations = None):
aux_node = self.get_aux_node(aux_name)
layout_node = self.get_layout_node(aux_node, max)
if layout_node == None: return
for i in range(1, max + 1):
if layout_node == None:
print "aux node not found"
return
print "editing locations =", locations
for (i, pos) in locations.iteritems():
location_node = self.get_location_node(layout_node, i)
location_node.setAttribute("x", str( locations[i-1][0] ))
location_node.setAttribute("y", str( locations[i-1][1] ))
self.aux_windows[aux_name].layout[max].location[i] = ( locations[i-1][0], locations[i-1][1] )
location_node.setAttribute("x", str( locations[i][0] ))
location_node.setAttribute("y", str( locations[i][1] ))
if i == "common":
self.aux_windows[aux_name].layout[max].common = ( locations[i][0], locations[i][1] )
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'
db = {}
try:
db['db-databaseName'] = name
db['db-host'] = self.supported_databases[name].db_ip
db['db-user'] = self.supported_databases[name].db_user
db['db-password'] = self.supported_databases[name].db_pass
db['db-server'] = self.supported_databases[name].db_server
if string.lower(self.supported_databases[name].db_server) == 'mysql':
db['db-backend'] = 2
elif string.lower(self.supported_databases[name].db_server) == 'postgresql':
db['db-backend'] = 3
else: db['db-backend'] = None # this is big trouble
except:
pass
try: db['db-databaseName'] = name
except: pass
try: db['db-host'] = self.supported_databases[name].db_ip
except: pass
try: db['db-user'] = self.supported_databases[name].db_user
except: pass
try: db['db-password'] = self.supported_databases[name].db_pass
except: pass
try: db['db-server'] = self.supported_databases[name].db_server
except: pass
if string.lower(self.supported_databases[name].db_server) == 'mysql':
db['db-backend'] = 2
elif string.lower(self.supported_databases[name].db_server) == 'postgresql':
db['db-backend'] = 3
else: db['db-backend'] = None # this is big trouble
return db
def set_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None,
@ -464,26 +498,32 @@ class Config:
def get_tv_parameters(self):
tv = {}
try:
tv['combinedStealFold'] = self.tv.combinedStealFold
tv['combined2B3B'] = self.tv.combined2B3B
tv['combinedPostflop'] = self.tv.combinedPostflop
except: # Default tv parameters
tv['combinedStealFold'] = True
tv['combined2B3B'] = True
tv['combinedPostflop'] = True
try: tv['combinedStealFold'] = self.tv.combinedStealFold
except: tv['combinedStealFold'] = True
try: tv['combined2B3B'] = self.tv.combined2B3B
except: tv['combined2B3B'] = True
try: tv['combinedPostflop'] = self.tv.combinedPostflop
except: tv['combinedPostflop'] = True
return tv
def get_import_parameters(self):
imp = {}
try:
imp['callFpdbHud'] = self.imp.callFpdbHud
imp['interval'] = self.imp.interval
imp['hhArchiveBase'] = self.imp.hhArchiveBase
except: # Default params
imp['callFpdbHud'] = True
imp['interval'] = 10
imp['hhArchiveBase'] = "~/.fpdb/HandHistories/"
try: imp['callFpdbHud'] = self.imp.callFpdbHud
except: imp['callFpdbHud'] = True
try: imp['interval'] = self.imp.interval
except: imp['interval'] = 10
try: imp['hhArchiveBase'] = self.imp.hhArchiveBase
except: imp['hhArchiveBase'] = "~/.fpdb/HandHistories/"
try: imp['saveActions'] = self.imp.saveActions
except: imp['saveActions'] = True
try: imp['fastStoreHudCache'] = self.imp.fastStoreHudCache
except: imp['fastStoreHudCache'] = True
return imp
def get_default_paths(self, site = "PokerStars"):
@ -689,9 +729,9 @@ if __name__== "__main__":
print c.get_aux_parameters(mw)
print "mucked locations =", c.get_aux_locations('mucked', 9)
c.edit_aux_layout('mucked', 9, locations = [(487, 113), (555, 469), (572, 276), (522, 345),
(333, 354), (217, 341), (150, 273), (150, 169), (230, 115)])
print "mucked locations =", c.get_aux_locations('mucked', 9)
# c.edit_aux_layout('mucked', 9, locations = [(487, 113), (555, 469), (572, 276), (522, 345),
# (333, 354), (217, 341), (150, 273), (150, 169), (230, 115)])
# print "mucked locations =", c.get_aux_locations('mucked', 9)
for site in c.supported_sites.keys():
print "site = ", site,

View File

@ -213,7 +213,7 @@ if __name__ == '__main__':
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename", help="Input file in quiet mode", metavar="FILE")
parser.add_option("-q", "--quiet", action="store_false", dest="gui", default=True, help="don't start gui")
parser.add_option("-x", "--convert", dest="filtername", help="Conversion filter", default="passthrough")
(options, sys.argv) = parser.parse_args()
config = Configuration.Config()
@ -240,7 +240,7 @@ if __name__ == '__main__':
importer = fpdb_import.Importer(False,settings, config)
importer.setDropIndexes("auto")
importer.setFailOnError(True)
importer.addImportFile(options.filename)
importer.addImportFile(options.filename, filter=options.filtername)
importer.setCallHud(False)
importer.runImport()
importer.clearFileList()

View File

@ -123,7 +123,7 @@ class HUD_main(object):
gtk.gdk.threads_enter()
try:
self.hud_dict[table_name].update(new_hand_id, config)
map(lambda aw: aw.update_gui(new_hand_id), self.hud_dict[table_name].aux_windows)
[aw.update_gui(new_hand_id) for aw in self.hud_dict[table_name].aux_windows]
return False
finally:
gtk.gdk.threads_leave()
@ -172,8 +172,7 @@ class HUD_main(object):
if temp_key in self.hud_dict:
self.hud_dict[temp_key].stat_dict = stat_dict
self.hud_dict[temp_key].cards = cards
for aw in self.hud_dict[temp_key].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[temp_key].aux_windows]
self.update_HUD(new_hand_id, temp_key, self.config)
# Or create a new HUD

View File

@ -504,7 +504,15 @@ Card ranks will be uppercased
if self.shown:
print >>fh, _("*** SHOW DOWN ***")
for name in self.shown:
print >>fh, _("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards[name]['PREFLOP'])))
# TODO: legacy importer can't handle only one holecard here, make sure there are 2 for holdem, 4 for omaha
# TOOD: If HoldHand subclass supports more than omahahi, omahahilo, holdem, add them here
numOfHoleCardsNeeded = None
if self.gametype['category'] in ('omahahi','omahahilo'):
numOfHoleCardsNeeded = 4
elif self.gametype['category'] in ('holdem'):
numOfHoleCardsNeeded = 2
if len(self.holecards[name]['PREFLOP']) == numOfHoleCardsNeeded:
print >>fh, _("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards[name]['PREFLOP'])))
# Current PS format has the lines:
# Uncalled bet ($111.25) returned to s0rrow

View File

@ -196,12 +196,12 @@ class Hud:
s.window.destroy()
self.stat_windows = {}
# also kill any aux windows
map(lambda m: m.destroy(), self.aux_windows)
[aux.destroy() for aux in self.aux_windows]
self.aux_windows = []
def reposition_windows(self, *args):
if self.stat_windows and len(self.stat_windows > 0):
map(lambda x: x.window.move(x.x, x.y), self.stat_windows)
if self.stat_windows != {} and len(self.stat_windows) > 0:
map(lambda x: x.window.move(x.x, x.y), self.stat_windows.itervalues())
return True
def debug_stat_windows(self, *args):
@ -216,6 +216,10 @@ class Hud:
new_loc = (loc[0] - self.table.x, loc[1] - self.table.y)
new_layout[self.stat_windows[sw].adj - 1] = new_loc
self.config.edit_layout(self.table.site, self.max, locations = new_layout)
# ask each aux to save its layout back to the config object
[aux.save_layout() for aux in self.aux_windows]
# save the config object back to the file
print "saving new xml file"
self.config.save()
def adj_seats(self, hand, config):
@ -346,6 +350,8 @@ class Hud:
style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE)
style |= win32con.WS_CLIPCHILDREN
win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style)
break
window.set_title(real_name)
class Stat_Window:
@ -570,6 +576,7 @@ class Popup_window:
style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE)
style |= win32con.WS_CLIPCHILDREN
win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style)
break
window.set_title(real_name)

View File

@ -49,6 +49,9 @@ class Aux_Window:
def create(self, *parms):
pass
def save_layout(self, *args):
pass
def destroy(self):
self.container.destroy()
@ -312,12 +315,13 @@ class Flop_Mucked(Aux_Window):
def __init__(self, hud, config, params):
self.hud = hud # hud object that this aux window supports
self.config = config # configuration object for this aux window to use
self.params = params # hash aux params from config
self.params = params # dict aux params from config
self.positions = {} # dict of window positions
self.displayed_cards = False
self.card_images = self.get_card_images()
def create(self):
adj = self.hud.adj_seats(0, self.config)
self.adj = self.hud.adj_seats(0, self.config)
loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max))
self.m_windows = {} # windows to put the card images in
@ -328,7 +332,7 @@ class Flop_Mucked(Aux_Window):
if i == 'common':
(x, y) = self.params['layout'][self.hud.max].common
else:
(x, y) = loc[adj[i]]
(x, y) = loc[self.adj[i]]
self.m_windows[i] = gtk.Window()
self.m_windows[i].set_decorated(False)
self.m_windows[i].set_property("skip-taskbar-hint", True)
@ -340,6 +344,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.m_windows[i].move(int(x) + self.hud.table.x, int(y) + self.hud.table.y)
self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y)
self.m_windows[i].set_opacity(float(self.params['opacity']))
self.m_windows[i].show_all()
self.m_windows[i].hide()
@ -350,11 +355,9 @@ class Flop_Mucked(Aux_Window):
def update_gui(self, new_hand_id):
"""Prepare and show the mucked cards."""
pos = {}
for i, w in self.m_windows.iteritems():
pos[i] = w.get_position() # I hate this. I don't know why I have to save position and then move back
self.hide_mucked_cards()
displayed_cards = False
if self.displayed_cards:
self.hide_mucked_cards()
self.displayed_cards = False
for (i, cards) in self.hud.cards.iteritems():
if self.has_cards(cards):
# scratch is a working pixbuf, used to assemble the image
@ -370,11 +373,12 @@ class Flop_Mucked(Aux_Window):
x = x + int(self.params['card_wd'])
self.seen_cards[i].set_from_pixbuf(scratch)
# self.m_windows[i].show_all()
self.m_windows[i].move(pos[i][0], pos[i][1]) # here is where I move back
self.m_windows[i].resize(1,1)
self.m_windows[i].present()
displayed_cards = True
self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back
self.displayed_cards = True
if displayed_cards and float(self.params['timeout']) > 0:
if self.displayed_cards and float(self.params['timeout']) > 0:
gobject.timeout_add(int(1000*float(self.params['timeout'])), self.hide_mucked_cards)
def destroy(self):
@ -385,8 +389,10 @@ class Flop_Mucked(Aux_Window):
def hide_mucked_cards(self):
"""Hide the mucked card windows."""
# this is the callback from the timeout
for w in self.m_windows.values():
for (i, w) in self.m_windows.iteritems():
self.positions[i] = w.get_position()
w.hide()
self.displayed_cards = False
return False # this tells the system to NOT run this timeout again
def button_press_cb(self, widget, event, *args):
@ -403,17 +409,16 @@ class Flop_Mucked(Aux_Window):
def save_layout(self, *args):
"""Save new layout back to the aux element in the config file."""
# similar to same method in stat_windows
new_layout = [(0, 0)] * self.hud.max
for (i, w) in self.m_windows.iteritems():
(x, y) = w.get_position()
new_loc = (x - self.hud.table.x, y - self.hud.table.y)
if i != "common":
new_layout[self.hud.stat_windows[int(i)].adj - 1] = new_loc
new_locs = {}
print "adj =", self.adj
for (i, pos) in self.positions.iteritems():
if i != 'common':
new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y)
else:
pass
self.config.edit_layout(self.table.site, self.max, locations = new_layout)
self.config.save()
new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y)
print "old locations =", self.params['layout'][self.hud.max]
print "saving locations =", new_locs
self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs)
if __name__== "__main__":

View File

@ -24,9 +24,9 @@ from HandHistoryConverter import *
# PokerStars HH Format
class PokerStars(HandHistoryConverter):
# Static regexes
re_GameInfo = re.compile("PokerStars Game #(?P<HID>[0-9]+):\s+(HORSE)? \(?(?P<GAME>Hold\'em|Razz|7 Card Stud|Omaha Hi/Lo|Badugi) (?P<LIMIT>No Limit|Limit|Pot Limit),? \(?(?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\) - (?P<DATETIME>.*$)", re.MULTILINE)
re_GameInfo = re.compile("PokerStars Game #(?P<HID>[0-9]+):\s+(HORSE)? \(?(?P<GAME>Hold\'em|Razz|7 Card Stud|Omaha|Omaha Hi/Lo|Badugi) (?P<LIMIT>No Limit|Limit|Pot Limit),? \(?(?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\) - (?P<DATETIME>.*$)", re.MULTILINE)
re_SplitHands = re.compile('\n\n+')
re_HandInfo = re.compile("^Table \'(?P<TABLE>[- a-zA-Z]+)\'(?P<TABLEATTRIBUTES>.+?$)?", re.MULTILINE)
re_Button = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE)
@ -80,7 +80,7 @@ follow : whether to tail -f the input"""
info = {'type':'ring'}
m = self.re_GameInfo.search(handText)
if not m:
if not m:
return None
mg = m.groupdict()
@ -89,7 +89,7 @@ follow : whether to tail -f the input"""
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' }
games = { # base, category
"Hold'em" : ('hold','holdem'),
'Omaha Hi' : ('hold','omahahi'),
'Omaha' : ('hold','omahahi'),
'Omaha Hi/Lo' : ('hold','omahahilo'),
'Razz' : ('stud','razz'),
'7 Card Stud' : ('stud','studhi'),

View File

@ -81,23 +81,13 @@ class fpdb:
def display_tab(self, new_tab_name):
"""displays the indicated tab"""
#print "start of display_tab, len(self.tab_names):",len(self.tab_names)
tab_no=-1
#if len(self.tab_names)>1:
for i in range(len(self.tab_names)):
#print "display_tab, new_tab_name:",new_tab_name," self.tab_names[i]:", self.tab_names[i]
if (new_tab_name==self.tab_names[i]):
tab_no=i
#self.tab_buttons[i].set_active(False)
#else:
# tab_no=0
tab_no = -1
for i, name in enumerate(self.tab_names):
if name == new_tab_name:
tab_no = i
break
#current_tab_no=-1
for i in range(len(self.tab_names)):
if self.current_tab==self.tabs[i]:
#self.tab_buttons[i].set_active(False)
pass
if tab_no==-1:
if tab_no == -1:
raise fpdb_simple.FpdbError("invalid tab_no")
else:
self.main_vbox.remove(self.current_tab)
@ -199,12 +189,13 @@ class fpdb:
def dia_recreate_tables(self, widget, data):
"""Dialogue that asks user to confirm that he wants to delete and recreate the tables"""
self.obtain_global_lock()
dia_confirm=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING,
dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING,
buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables")
diastring=("Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted.")
diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted."
dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted
response=dia_confirm.run()
response = dia_confirm.run()
dia_confirm.destroy()
if response == gtk.RESPONSE_YES:
self.db.recreate_tables()

View File

@ -23,12 +23,12 @@ import FpdbSQLQueries
class fpdb_db:
def __init__(self):
"""Simple constructor, doesnt really do anything"""
self.db=None
self.cursor=None
self.sql = {}
self.MYSQL_INNODB=2
self.PGSQL=3
self.SQLITE=4
self.db = None
self.cursor = None
self.sql = {}
self.MYSQL_INNODB = 2
self.PGSQL = 3
self.SQLITE = 4
#end def __init__
def do_connect(self, config=None):
@ -37,10 +37,7 @@ class fpdb_db:
raise FpdbError('Configuration not defined')
self.settings = {}
if (os.sep=="/"):
self.settings['os']="linuxmac"
else:
self.settings['os']="windows"
self.settings['os'] = "linuxmac" if os.name != "nt" else "windows"
self.settings.update(config.get_db_parameters())
self.connect(self.settings['db-backend'],

View File

@ -51,22 +51,22 @@ class Importer:
def __init__(self, caller, settings, config):
"""Constructor"""
self.settings=settings
self.caller=caller
self.config = config
self.fdb = None
self.cursor = None
self.filelist = {}
self.dirlist = {}
self.settings = settings
self.caller = caller
self.config = config
self.fdb = None
self.cursor = None
self.filelist = {}
self.dirlist = {}
self.addToDirList = {}
self.removeFromFileList = {} # to remove deleted files
self.monitor = False
self.updated = {} #Time last import was run {file:mtime}
self.lines = None
self.faobs = None #File as one big string
self.monitor = False
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
#Set defaults
self.callHud = self.config.get_import_parameters().get("callFpdbHud")
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
@ -188,24 +188,26 @@ class Importer:
self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1])
for file in self.filelist:
stat_info = os.stat(file)
try:
lastupdate = self.updated[file]
if stat_info.st_mtime > lastupdate:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
if os.path.exists(file):
stat_info = os.stat(file)
try:
lastupdate = self.updated[file]
if stat_info.st_mtime > lastupdate:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
self.updated[file] = time()
except:
self.updated[file] = time()
except:
self.updated[file] = time()
# If modified in the last minute run an immediate import.
# This codepath only runs first time the file is found.
if os.path.isdir(file) or (time() - stat_info.st_mtime) < 60:
# TODO attach a HHC thread to the file
# TODO import the output of the HHC thread -- this needs to wait for the HHC to block?
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
# If modified in the last minute run an immediate import.
# This codepath only runs first time the file is found.
if os.path.isdir(file) or (time() - stat_info.st_mtime) < 60:
# TODO attach a HHC thread to the file
# TODO import the output of the HHC thread -- this needs to wait for the HHC to block?
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
# TODO we also test if directory, why?
#if os.path.isdir(file):
#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)
for file in self.removeFromFileList:
@ -251,7 +253,6 @@ class Importer:
print "Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter)
return
#This will barf if conv.getStatus != True
return (stored, duplicates, partial, errors, ttime)
@ -284,7 +285,13 @@ class Importer:
print "DEBUG: import_fpdb_file: failed on self.lines[0]: '%s' '%s' '%s' '%s' " %( file, site, self.lines, loc)
return (0,0,0,1,0)
# site=fpdb_simple.recogniseSite(firstline)
if firstline.find("Tournament Summary")!=-1:
print "TODO: implement importing tournament summaries"
#self.faobs = readfile(inputFile)
#self.parseTourneyHistory()
return 0
site=fpdb_simple.recogniseSite(firstline)
category=fpdb_simple.recogniseCategory(firstline)
startpos=0
@ -315,7 +322,7 @@ class Importer:
try:
handsId=fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db
,self.fdb.cursor, category, hand)
,self.fdb.cursor, site, category, hand, self.config)
self.fdb.db.commit()
stored+=1

View File

@ -21,46 +21,45 @@ import fpdb_simple
import fpdb_save_to_db
#parses a holdem hand
def mainParser(backend, db, cursor, category, hand):
category=fpdb_simple.recogniseCategory(hand[0])
if (category=="holdem" or category=="omahahi" or category=="omahahilo"):
base="hold"
else:
base="stud"
def mainParser(backend, db, cursor, 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)
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=[],[],[],[],[],[],[],[],[],[],[],[],[]
#part 1: read hand no and check for duplicate
siteHandNo=fpdb_simple.parseSiteHandNo(hand[0])
handStartTime=fpdb_simple.parseHandStartTime(hand[0])
siteID=fpdb_simple.recogniseSiteID()
siteHandNo = fpdb_simple.parseSiteHandNo(hand[0])
handStartTime = fpdb_simple.parseHandStartTime(hand[0])
siteID = fpdb_simple.recogniseSiteID()
#print "parse logic, siteID:",siteID,"site:",site
isTourney=fpdb_simple.isTourney(hand[0])
smallBlindLine=0
for i in range(len(hand)):
if 'posts small blind' in hand[i] or 'posts the small blind' in hand[i]:
if hand[i][-2:] == "$0":
continue
smallBlindLine=i
#print "found small blind line:",smallBlindLine
isTourney = fpdb_simple.isTourney(hand[0])
smallBlindLine = 0
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
#print "small blind line:",smallBlindLine
gametypeID=fpdb_simple.recogniseGametypeID(backend, db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney)
if isTourney:
siteTourneyNo=fpdb_simple.parseTourneyNo(hand[0])
buyin=fpdb_simple.parseBuyin(hand[0])
fee=fpdb_simple.parseFee(hand[0])
entries=-1 #todo: parse this
prizepool=-1 #todo: parse this
knockout=0
tourneyStartTime=handStartTime #todo: read tourney start time
rebuyOrAddon=fpdb_simple.isRebuyOrAddon(hand[0])
tourneyTypeId=fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon)
gametypeID = fpdb_simple.recogniseGametypeID(backend, db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney)
if isTourney:
siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0])
buyin = fpdb_simple.parseBuyin(hand[0])
fee = fpdb_simple.parseFee(hand[0])
entries = -1 #todo: parse this
prizepool = -1 #todo: parse this
knockout = 0
tourneyStartTime= handStartTime #todo: read tourney start time
rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0])
tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon)
fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo)
#part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street
@ -68,94 +67,90 @@ def mainParser(backend, db, cursor, category, hand):
#part 3: read basic player info
#3a read player names, startcashes
for i in range (len(hand)): #todo: use maxseats+1 here.
if (lineTypes[i]=="name"):
seatLines.append(hand[i])
names=fpdb_simple.parseNames(seatLines)
playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID)
tmp=fpdb_simple.parseCashesAndSeatNos(seatLines)
startCashes=tmp['startCashes']
seatNos=tmp['seatNos']
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)
startCashes = tmp['startCashes']
seatNos = tmp['seatNos']
fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
#3b read positions
if base=="hold":
positions = fpdb_simple.parsePositions (hand, names)
if base == "hold":
positions = fpdb_simple.parsePositions(hand, names)
#part 4: take appropriate action for each line based on linetype
for i in range(len(hand)):
if (lineTypes[i]=="cards"):
fpdb_simple.parseCardLine (category, lineStreets[i], hand[i], names, cardValues, cardSuits, boardValues, boardSuits)
for i, line in enumerate(hand):
if lineTypes[i] == "cards":
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, hand[i], lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
elif (lineTypes[i]=="win"):
fpdb_simple.parseWinLine (hand[i], names, winnings, isTourney)
elif (lineTypes[i]=="rake"):
if isTourney:
totalRake=0
else:
totalRake=fpdb_simple.parseRake(hand[i])
elif lineTypes[i] == "action":
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"):
fpdb_simple.parseAnteLine(hand[i], isTourney, names, antes)
elif (lineTypes[i]=="table"):
tableResult=fpdb_simple.parseTableLine(base, hand[i])
elif lineTypes[i]=="ante":
fpdb_simple.parseAnteLine(line, isTourney, names, antes)
elif lineTypes[i]=="table":
tableResult=fpdb_simple.parseTableLine(base, line)
else:
raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i])
maxSeats=tableResult['maxSeats']
tableName=tableResult['tableName']
maxSeats = tableResult['maxSeats']
tableName = tableResult['tableName']
#print "before part5, antes:", antes
#part 5: final preparations, then call fpdb_save_to_db.* with
# the arrays as they are - that file will fill them.
fpdb_simple.convertCardValues(cardValues)
if base=="hold":
if base == "hold":
fpdb_simple.convertCardValuesBoard(boardValues)
fpdb_simple.convertBlindBet(actionTypes, actionAmounts)
fpdb_simple.checkPositions(positions)
cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, ))
limit_type=cursor.fetchone()[0]
limit_type = cursor.fetchone()[0]
fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts)
totalWinnings=0
for i in range(len(winnings)):
totalWinnings+=winnings[i]
totalWinnings = sum(winnings)
if base=="hold":
hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes
# if hold'em, use positions and not antes, if stud do not use positions, use antes
if base == "hold":
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
hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes
, allIns, actionTypeByNo, winnings, totalWinnings, None
, actionTypes, actionAmounts, antes)
if isTourney:
ranks=[]
for i in range (len(names)):
ranks.append(0)
payin_amounts=fpdb_simple.calcPayin(len(names), buyin, fee)
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)
if base=="hold":
if base == "hold":
result = fpdb_save_to_db.tourney_holdem_omaha(
backend, db, cursor, base, category, siteTourneyNo, buyin
config, backend, db, cursor, base, category, siteTourneyNo, buyin
, fee, knockout, entries, prizepool, tourneyStartTime
, payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo
, gametypeID, handStartTime, names, playerIDs, startCashes
, positions, cardValues, cardSuits, boardValues, boardSuits
, winnings, rakes, actionTypes, allIns, actionAmounts
, actionNos, hudImportData, maxSeats, tableName, seatNos)
elif base=="stud":
elif base == "stud":
result = fpdb_save_to_db.tourney_stud(
backend, db, cursor, base, category, siteTourneyNo
config, backend, db, cursor, base, category, siteTourneyNo
, buyin, fee, knockout, entries, prizepool, tourneyStartTime
, payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo
, gametypeID, handStartTime, names, playerIDs, startCashes
@ -163,19 +158,19 @@ def mainParser(backend, db, cursor, category, hand):
, allIns, actionAmounts, actionNos, hudImportData, maxSeats
, tableName, seatNos)
else:
raise fpdb_simple.FpdbError ("unrecognised category")
raise fpdb_simple.FpdbError("unrecognised category")
else:
if base=="hold":
if base == "hold":
result = fpdb_save_to_db.ring_holdem_omaha(
backend, db, cursor, base, category, siteHandNo
config, backend, db, cursor, base, category, siteHandNo
, gametypeID, handStartTime, names, playerIDs
, startCashes, positions, cardValues, cardSuits
, boardValues, boardSuits, winnings, rakes
, actionTypes, allIns, actionAmounts, actionNos
, hudImportData, maxSeats, tableName, seatNos)
elif base=="stud":
elif base == "stud":
result = fpdb_save_to_db.ring_stud(
backend, db, cursor, base, category, siteHandNo, gametypeID
config, backend, db, cursor, base, category, siteHandNo, gametypeID
, handStartTime, names, playerIDs, startCashes, antes
, cardValues, cardSuits, winnings, rakes, actionTypes, allIns
, actionAmounts, actionNos, hudImportData, maxSeats, tableName

View File

@ -22,29 +22,35 @@ from time import time
import fpdb_simple
MYSQL_INNODB=2
PGSQL=3
SQLITE=4
MYSQL_INNODB = 2
PGSQL = 3
SQLITE = 4
fastStoreHudCache=False # set this to True to test the new storeHudCache routine
fastStoreHudCache = True # set this to True to test the new storeHudCache routine
saveActions=True # set this to False to avoid storing action data
saveActions = False # 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
#stores a stud/razz hand into the database
def ring_stud(backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time
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
,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName
,seatNos):
import_options = config.get_import_parameters()
saveActions = True if import_options['saveActions'] == 'True' else False
fastStoreHudCache = True if import_options['fastStoreHudCache'] == 'True' else False
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
hands_id=fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
,hand_start_time, names, tableName, maxSeats)
#print "before calling store_hands_players_stud, antes:", antes
hands_players_ids=fpdb_simple.store_hands_players_stud(backend, db, cursor, hands_id, player_ids
hands_players_ids = fpdb_simple.store_hands_players_stud(backend, db, cursor, hands_id, player_ids
,start_cashes, antes, card_values
,card_suits, winnings, rakes, seatNos)
@ -56,21 +62,26 @@ def ring_stud(backend, db, cursor, base, category, site_hand_no, gametype_id, ha
return hands_id
#end def ring_stud
def ring_holdem_omaha(backend, db, cursor, base, category, site_hand_no, gametype_id
def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no, gametype_id
,hand_start_time, names, player_ids, start_cashes, positions, card_values
,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns
,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos):
"""stores a holdem/omaha hand into the database"""
import_options = config.get_import_parameters()
saveActions = True if import_options['saveActions'] == 'True' else False
fastStoreHudCache = True if import_options['fastStoreHudCache'] == 'True' else False
t0 = time()
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
t1 = time()
fpdb_simple.fill_board_cards(board_values, board_suits)
t2 = time()
hands_id=fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
,hand_start_time, names, tableName, maxSeats)
t3 = time()
hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha(
hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha(
backend, db, cursor, category, hands_id, player_ids, start_cashes
, positions, card_values, card_suits, winnings, rakes, seatNos)
t4 = time()
@ -89,7 +100,7 @@ def ring_holdem_omaha(backend, db, cursor, base, category, site_hand_no, gametyp
return hands_id
#end def ring_holdem_omaha
def tourney_holdem_omaha(backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout
def tourney_holdem_omaha(config, backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout
,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId
,siteId #end of tourney specific params
,site_hand_no, gametype_id, hand_start_time, names, player_ids
@ -97,16 +108,21 @@ def tourney_holdem_omaha(backend, db, cursor, base, category, siteTourneyNo, buy
,board_suits, winnings, rakes, action_types, allIns, action_amounts
,actionNos, hudImportData, maxSeats, tableName, seatNos):
"""stores a tourney holdem/omaha hand into the database"""
import_options = config.get_import_parameters()
saveActions = True if import_options['saveActions'] == 'True' else False
fastStoreHudCache = True if import_options['fastStoreHudCache'] == 'True' else False
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
fpdb_simple.fill_board_cards(board_values, board_suits)
tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start)
tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings)
tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start)
tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings)
hands_id=fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
,hand_start_time, names, tableName, maxSeats)
hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha_tourney(
hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha_tourney(
backend, db, cursor, category, hands_id, player_ids, start_cashes, positions
, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids)
@ -123,21 +139,26 @@ def tourney_holdem_omaha(backend, db, cursor, base, category, siteTourneyNo, buy
return hands_id
#end def tourney_holdem_omaha
def tourney_stud(backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries
def tourney_stud(config, backend, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries
,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId
,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes
,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts
,actionNos, hudImportData, maxSeats, tableName, seatNos):
#stores a tourney stud/razz hand into the database
import_options = config.get_import_parameters()
saveActions = True if import_options['saveActions'] == 'True' else False
fastStoreHudCache = True if import_options['fastStoreHudCache'] == 'True' else False
fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits)
tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime)
tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime)
tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings)
tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings)
hands_id=fpdb_simple.storeHands(backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats)
hands_id = fpdb_simple.storeHands(backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats)
hands_players_ids=fpdb_simple.store_hands_players_stud_tourney(backend, db, cursor, hands_id
hands_players_ids = fpdb_simple.store_hands_players_stud_tourney(backend, db, cursor, hands_id
, playerIds, startCashes, antes, cardValues, cardSuits
, winnings, rakes, seatNos, tourneys_players_ids)

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,10 @@ from Hand import *
import py
#regression-test-files/stars/badugi/ring-fl-badugi.txt
# s0rrow: start $30.00 end: $22.65 total: ($7.35)
# s0rrow: input: $30.00 end: $22.65 total: ($7.35)
#regression-test-files/stars/plo/PLO-6max.txt
# s0rrow: input: $18.35 end: $0 total: ($18.35)
# Notes: last hand #25975302416 s0rrow aifp against 2 players
gametype = {'type':'ring', 'base':'draw', 'category':'badugi', 'limitType':'fl', 'sb':'0.25', 'bb':'0.50','currency':'USD'}
text = ""
@ -30,7 +33,10 @@ def testGameInfo():
{'type':'ring', 'base':'hold', 'category':'omahahilo', 'limitType':'fl', 'sb':'2', 'bb':'4','currency':'USD'}),
(u"PokerStars Game #25923772706: Badugi Limit ($0.25/$0.50) - 2009/03/13 16:40:58 ET",
{'type':'ring', 'base':'draw', 'category':'badugi', 'limitType':'fl', 'sb':'0.25', 'bb':'0.50','currency':'USD'})
{'type':'ring', 'base':'draw', 'category':'badugi', 'limitType':'fl', 'sb':'0.25', 'bb':'0.50','currency':'USD'}),
(u"PokerStars Game #25974627364: Omaha Pot Limit ($0.05/$0.10) - 2009/03/15 0:29:00 ET",
{'type':'ring', 'base':'hold', 'category':'omahahi', 'limitType':'pl', 'sb':'0.05', 'bb':'0.10','currency':'USD'})
)
for (header, info) in pairs:
yield checkGameInfo, hhc, header, info