pull and merge from fpdboz
This commit is contained in:
@@ -197,6 +197,15 @@ class Aux_window:
|
||||
temp = temp + "%s" % self.layout[layout]
|
||||
return temp
|
||||
|
||||
class HHC:
|
||||
def __init__(self, node):
|
||||
self.site = node.getAttribute("site")
|
||||
self.converter = node.getAttribute("converter")
|
||||
|
||||
def __str__(self):
|
||||
return "%s:\t%s" % (self.site, self.converter)
|
||||
|
||||
|
||||
class Popup:
|
||||
def __init__(self, node):
|
||||
self.name = node.getAttribute("pu_name")
|
||||
@@ -277,6 +286,7 @@ class Config:
|
||||
self.supported_games = {}
|
||||
self.supported_databases = {}
|
||||
self.aux_windows = {}
|
||||
self.hhcs = {}
|
||||
self.popup_windows = {}
|
||||
|
||||
# s_sites = doc.getElementsByTagName("supported_sites")
|
||||
@@ -299,6 +309,11 @@ class Config:
|
||||
aw = Aux_window(node = aw_node)
|
||||
self.aux_windows[aw.name] = aw
|
||||
|
||||
# s_dbs = doc.getElementsByTagName("mucked_windows")
|
||||
for hhc_node in doc.getElementsByTagName("hhc"):
|
||||
hhc = HHC(node = hhc_node)
|
||||
self.hhcs[hhc.site] = hhc
|
||||
|
||||
# s_dbs = doc.getElementsByTagName("popup_windows")
|
||||
for pu_node in doc.getElementsByTagName("pu"):
|
||||
pu = Popup(node = pu_node)
|
||||
@@ -703,6 +718,11 @@ if __name__== "__main__":
|
||||
for w in c.aux_windows.keys():
|
||||
print c.aux_windows[w]
|
||||
print "----------- END AUX WINDOW FORMATS -----------"
|
||||
|
||||
print "\n----------- HAND HISTORY CONVERTERS -----------"
|
||||
for w in c.hhcs.keys():
|
||||
print c.hhcs[w]
|
||||
print "----------- END HAND HISTORY CONVERTERS -----------"
|
||||
|
||||
print "\n----------- POPUP WINDOW FORMATS -----------"
|
||||
for w in c.popup_windows.keys():
|
||||
|
||||
@@ -201,6 +201,9 @@ class Database:
|
||||
t_dict = {}
|
||||
for name, val in zip(colnames, row):
|
||||
t_dict[name.lower()] = val
|
||||
# print t_dict
|
||||
t_dict['screen_name'] = names[t_dict['player_id']]
|
||||
t_dict['seat'] = seats[t_dict['player_id']]
|
||||
stat_dict[t_dict['player_id']] = t_dict
|
||||
return stat_dict
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ from HandHistoryConverter import *
|
||||
class Everleaf(HandHistoryConverter):
|
||||
|
||||
# Static regexes
|
||||
re_SplitHands = re.compile(r"(\n\n\n+)")
|
||||
re_SplitHands = re.compile(r"\n\n\n+")
|
||||
re_TailSplitHands = re.compile(r"(\n\n\n+)")
|
||||
re_GameInfo = re.compile(ur"^(Blinds )?(?P<CURRENCY>\$| €|)(?P<SB>[.0-9]+)/(?:\$| €)?(?P<BB>[.0-9]+) (?P<LIMIT>NL|PL|) ?(?P<GAME>(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE)
|
||||
#re.compile(ur"^(Blinds )?(?P<CURRENCY>\$| €|)(?P<SB>[.0-9]+)/(?:\$| €)?(?P<BB>[.0-9]+) (?P<LIMIT>NL|PL|) (?P<GAME>(Hold\'em|Omaha|7 Card Stud))", re.MULTILINE)
|
||||
re_HandInfo = re.compile(ur".*#(?P<HID>[0-9]+)\n.*\n(Blinds )?(?:\$| €|)(?P<SB>[.0-9]+)/(?:\$| €|)(?P<BB>[.0-9]+) (?P<GAMETYPE>.*) - (?P<DATETIME>\d\d\d\d/\d\d/\d\d - \d\d:\d\d:\d\d)\nTable (?P<TABLE>.+$)", re.MULTILINE)
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#Copyright 2008 Steffen Jobbagy-Felso
|
||||
#This program is free software: you can redistribute it and/or modify
|
||||
#it under the terms of the GNU Affero General Public License as published by
|
||||
#the Free Software Foundation, version 3 of the License.
|
||||
#
|
||||
#This program is distributed in the hope that it will be useful,
|
||||
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#GNU General Public License for more details.
|
||||
#
|
||||
#You should have received a copy of the GNU Affero General Public License
|
||||
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#In the "official" distribution you can find the license in
|
||||
#agpl-3.0.txt in the docs folder of the package.
|
||||
|
||||
import threading
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
import os
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
from time import *
|
||||
#import pokereval
|
||||
|
||||
import Configuration
|
||||
import fpdb_db
|
||||
import FpdbSQLQueries
|
||||
|
||||
class Filters(threading.Thread):
|
||||
def __init__(self, db, settings, config, qdict, display = {},debug=True):
|
||||
self.debug=debug
|
||||
#print "start of GraphViewer constructor"
|
||||
self.db=db
|
||||
self.cursor=db.cursor
|
||||
self.settings=settings
|
||||
self.sql=qdict
|
||||
self.conf = config
|
||||
|
||||
self.sites = {}
|
||||
self.games = {}
|
||||
self.limits = {}
|
||||
self.siteid = {}
|
||||
self.heroes = {}
|
||||
|
||||
# For use in date ranges.
|
||||
self.start_date = gtk.Entry(max=12)
|
||||
self.end_date = gtk.Entry(max=12)
|
||||
self.start_date.set_property('editable', False)
|
||||
self.end_date.set_property('editable', False)
|
||||
|
||||
# Outer Packing box
|
||||
self.mainVBox = gtk.VBox(False, 0)
|
||||
|
||||
playerFrame = gtk.Frame("Hero:")
|
||||
playerFrame.set_label_align(0.0, 0.0)
|
||||
vbox = gtk.VBox(False, 0)
|
||||
|
||||
self.fillPlayerFrame(vbox)
|
||||
playerFrame.add(vbox)
|
||||
|
||||
sitesFrame = gtk.Frame("Sites:")
|
||||
sitesFrame.set_label_align(0.0, 0.0)
|
||||
vbox = gtk.VBox(False, 0)
|
||||
|
||||
self.fillSitesFrame(vbox)
|
||||
sitesFrame.add(vbox)
|
||||
|
||||
# Game types
|
||||
gamesFrame = gtk.Frame("Games:")
|
||||
gamesFrame.set_label_align(0.0, 0.0)
|
||||
gamesFrame.show()
|
||||
vbox = gtk.VBox(False, 0)
|
||||
|
||||
self.fillGamesFrame(vbox)
|
||||
gamesFrame.add(vbox)
|
||||
|
||||
# Limits
|
||||
limitsFrame = gtk.Frame("Limits:")
|
||||
limitsFrame.set_label_align(0.0, 0.0)
|
||||
limitsFrame.show()
|
||||
vbox = gtk.VBox(False, 0)
|
||||
|
||||
self.fillLimitsFrame(vbox)
|
||||
limitsFrame.add(vbox)
|
||||
|
||||
dateFrame = gtk.Frame("Date:")
|
||||
dateFrame.set_label_align(0.0, 0.0)
|
||||
dateFrame.show()
|
||||
vbox = gtk.VBox(False, 0)
|
||||
|
||||
self.fillDateFrame(vbox)
|
||||
dateFrame.add(vbox)
|
||||
|
||||
self.Button1=gtk.Button("Unamed 1")
|
||||
|
||||
self.Button2=gtk.Button("Unamed 2")
|
||||
#self.exportButton.connect("clicked", self.exportGraph, "show clicked")
|
||||
self.Button2.set_sensitive(False)
|
||||
|
||||
self.mainVBox.add(playerFrame)
|
||||
self.mainVBox.add(sitesFrame)
|
||||
self.mainVBox.add(gamesFrame)
|
||||
self.mainVBox.add(limitsFrame)
|
||||
self.mainVBox.add(dateFrame)
|
||||
self.mainVBox.add(self.Button1)
|
||||
self.mainVBox.add(self.Button2)
|
||||
|
||||
self.mainVBox.show_all()
|
||||
|
||||
# Should do this cleaner
|
||||
if display["Heroes"] == False:
|
||||
playerFrame.hide()
|
||||
if display["Sites"] == False:
|
||||
sitesFrame.hide()
|
||||
if display["Games"] == False:
|
||||
gamesFrame.hide()
|
||||
if display["Limits"] == False:
|
||||
limitsFrame.hide()
|
||||
if display["Dates"] == False:
|
||||
dateFrame.hide()
|
||||
if display["Button1"] == False:
|
||||
self.Button1.hide()
|
||||
if display["Button2"] == False:
|
||||
self.Button2.hide()
|
||||
|
||||
def get_vbox(self):
|
||||
"""returns the vbox of this thread"""
|
||||
return self.mainVBox
|
||||
#end def get_vbox
|
||||
|
||||
def getSites(self):
|
||||
return self.sites
|
||||
|
||||
def getSiteIds(self):
|
||||
return self.siteid
|
||||
|
||||
def getHeroes(self):
|
||||
return self.heroes
|
||||
|
||||
def getLimits(self):
|
||||
ltuple = []
|
||||
for l in self.limits:
|
||||
if self.limits[l] == True:
|
||||
ltuple.append(l)
|
||||
return ltuple
|
||||
|
||||
def getDates(self):
|
||||
return self.__get_dates()
|
||||
|
||||
def registerButton1Name(self, title):
|
||||
self.Button1.set_label(title)
|
||||
|
||||
def registerButton1Callback(self, callback):
|
||||
self.Button1.connect("clicked", callback, "clicked")
|
||||
|
||||
def registerButton2Name(self, title):
|
||||
self.Button2.set_label(title)
|
||||
|
||||
def registerButton2Callback(self, callback):
|
||||
self.Button2.connect("clicked", callback, "clicked")
|
||||
|
||||
def cardCallback(self, widget, data=None):
|
||||
print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
|
||||
|
||||
def createPlayerLine(self, hbox, site, player):
|
||||
label = gtk.Label(site +" id:")
|
||||
hbox.pack_start(label, False, False, 0)
|
||||
|
||||
pname = gtk.Entry()
|
||||
pname.set_text(player)
|
||||
pname.set_width_chars(20)
|
||||
hbox.pack_start(pname, False, True, 0)
|
||||
pname.connect("changed", self.__set_hero_name, site)
|
||||
#TODO: Look at GtkCompletion - to fill out usernames
|
||||
|
||||
self.__set_hero_name(pname, site)
|
||||
|
||||
def __set_hero_name(self, w, site):
|
||||
self.heroes[site] = w.get_text()
|
||||
# print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site])
|
||||
|
||||
def createSiteLine(self, hbox, site):
|
||||
cb = gtk.CheckButton(site)
|
||||
cb.connect('clicked', self.__set_site_select, site)
|
||||
cb.set_active(True)
|
||||
hbox.pack_start(cb, False, False, 0)
|
||||
|
||||
def createGameLine(self, hbox, game):
|
||||
cb = gtk.CheckButton(game)
|
||||
cb.connect('clicked', self.__set_game_select, game)
|
||||
hbox.pack_start(cb, False, False, 0)
|
||||
|
||||
def createLimitLine(self, hbox, limit):
|
||||
cb = gtk.CheckButton(str(limit))
|
||||
cb.connect('clicked', self.__set_limit_select, limit)
|
||||
hbox.pack_start(cb, False, False, 0)
|
||||
|
||||
def __set_site_select(self, w, site):
|
||||
print w.get_active()
|
||||
self.sites[site] = w.get_active()
|
||||
print "self.sites[%s] set to %s" %(site, self.sites[site])
|
||||
|
||||
def __set_game_select(self, w, game):
|
||||
print w.get_active()
|
||||
self.games[game] = w.get_active()
|
||||
print "self.games[%s] set to %s" %(game, self.games[game])
|
||||
|
||||
def __set_limit_select(self, w, limit):
|
||||
print w.get_active()
|
||||
self.limits[limit] = w.get_active()
|
||||
print "self.limit[%s] set to %s" %(limit, self.limits[limit])
|
||||
|
||||
def fillPlayerFrame(self, vbox):
|
||||
for site in self.conf.get_supported_sites():
|
||||
pathHBox = gtk.HBox(False, 0)
|
||||
vbox.pack_start(pathHBox, False, True, 0)
|
||||
|
||||
player = self.conf.supported_sites[site].screen_name
|
||||
self.createPlayerLine(pathHBox, site, player)
|
||||
|
||||
def fillSitesFrame(self, vbox):
|
||||
for site in self.conf.get_supported_sites():
|
||||
hbox = gtk.HBox(False, 0)
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
self.createSiteLine(hbox, site)
|
||||
#Get db site id for filtering later
|
||||
self.cursor.execute(self.sql.query['getSiteId'], (site,))
|
||||
result = self.db.cursor.fetchall()
|
||||
if len(result) == 1:
|
||||
self.siteid[site] = result[0][0]
|
||||
else:
|
||||
print "Either 0 or more than one site matched - EEK"
|
||||
|
||||
def fillGamesFrame(self, vbox):
|
||||
self.cursor.execute(self.sql.query['getGames'])
|
||||
result = self.db.cursor.fetchall()
|
||||
if len(result) >= 1:
|
||||
for line in result:
|
||||
hbox = gtk.HBox(False, 0)
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
self.createGameLine(hbox, line[0])
|
||||
else:
|
||||
print "INFO: No games returned from database"
|
||||
|
||||
def fillLimitsFrame(self, vbox):
|
||||
self.cursor.execute(self.sql.query['getLimits'])
|
||||
result = self.db.cursor.fetchall()
|
||||
if len(result) >= 1:
|
||||
for line in result:
|
||||
hbox = gtk.HBox(False, 0)
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
self.createLimitLine(hbox, line[0])
|
||||
else:
|
||||
print "INFO: No games returned from database"
|
||||
|
||||
def fillCardsFrame(self, vbox):
|
||||
hbox1 = gtk.HBox(True,0)
|
||||
hbox1.show()
|
||||
vbox.pack_start(hbox1, True, True, 0)
|
||||
|
||||
cards = [ "A", "K","Q","J","T","9","8","7","6","5","4","3","2" ]
|
||||
|
||||
for j in range(0, len(cards)):
|
||||
hbox1 = gtk.HBox(True,0)
|
||||
hbox1.show()
|
||||
vbox.pack_start(hbox1, True, True, 0)
|
||||
for i in range(0, len(cards)):
|
||||
if i < (j + 1):
|
||||
suit = "o"
|
||||
else:
|
||||
suit = "s"
|
||||
button = gtk.ToggleButton("%s%s%s" %(cards[i], cards[j], suit))
|
||||
button.connect("toggled", self.cardCallback, "%s%s%s" %(cards[i], cards[j], suit))
|
||||
hbox1.pack_start(button, True, True, 0)
|
||||
button.show()
|
||||
|
||||
def fillDateFrame(self, vbox):
|
||||
# Hat tip to Mika Bostrom - calendar code comes from PokerStats
|
||||
hbox = gtk.HBox()
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
|
||||
lbl_start = gtk.Label('From:')
|
||||
|
||||
btn_start = gtk.Button()
|
||||
btn_start.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
|
||||
btn_start.connect('clicked', self.__calendar_dialog, self.start_date)
|
||||
|
||||
hbox.pack_start(lbl_start, expand=False, padding=3)
|
||||
hbox.pack_start(btn_start, expand=False, padding=3)
|
||||
hbox.pack_start(self.start_date, expand=False, padding=2)
|
||||
|
||||
#New row for end date
|
||||
hbox = gtk.HBox()
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
|
||||
lbl_end = gtk.Label(' To:')
|
||||
btn_end = gtk.Button()
|
||||
btn_end.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
|
||||
btn_end.connect('clicked', self.__calendar_dialog, self.end_date)
|
||||
|
||||
btn_clear = gtk.Button(label=' Clear Dates ')
|
||||
btn_clear.connect('clicked', self.__clear_dates)
|
||||
|
||||
hbox.pack_start(lbl_end, expand=False, padding=3)
|
||||
hbox.pack_start(btn_end, expand=False, padding=3)
|
||||
hbox.pack_start(self.end_date, expand=False, padding=2)
|
||||
|
||||
hbox.pack_start(btn_clear, expand=False, padding=15)
|
||||
|
||||
def __calendar_dialog(self, widget, entry):
|
||||
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
d.set_title('Pick a date')
|
||||
|
||||
vb = gtk.VBox()
|
||||
cal = gtk.Calendar()
|
||||
vb.pack_start(cal, expand=False, padding=0)
|
||||
|
||||
btn = gtk.Button('Done')
|
||||
btn.connect('clicked', self.__get_date, cal, entry, d)
|
||||
|
||||
vb.pack_start(btn, expand=False, padding=4)
|
||||
|
||||
d.add(vb)
|
||||
d.set_position(gtk.WIN_POS_MOUSE)
|
||||
d.show_all()
|
||||
|
||||
def __clear_dates(self, w):
|
||||
self.start_date.set_text('')
|
||||
self.end_date.set_text('')
|
||||
|
||||
def __get_dates(self):
|
||||
t1 = self.start_date.get_text()
|
||||
t2 = self.end_date.get_text()
|
||||
|
||||
if t1 == '':
|
||||
t1 = '1970-01-01'
|
||||
if t2 == '':
|
||||
t2 = '2020-12-12'
|
||||
|
||||
return (t1, t2)
|
||||
|
||||
def __get_date(self, widget, calendar, entry, win):
|
||||
# year and day are correct, month is 0..11
|
||||
(year, month, day) = calendar.get_date()
|
||||
month += 1
|
||||
ds = '%04d-%02d-%02d' % (year, month, day)
|
||||
entry.set_text(ds)
|
||||
win.destroy()
|
||||
|
||||
def main(argv=None):
|
||||
"""main can also be called in the python interpreter, by supplying the command line as the argument."""
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
def destroy(*args): # call back for terminating the main eventloop
|
||||
gtk.main_quit()
|
||||
|
||||
parser = OptionParser()
|
||||
(options, sys.argv) = parser.parse_args(args = argv)
|
||||
|
||||
config = Configuration.Config()
|
||||
db = None
|
||||
|
||||
settings = {}
|
||||
|
||||
settings.update(config.get_db_parameters())
|
||||
settings.update(config.get_tv_parameters())
|
||||
settings.update(config.get_import_parameters())
|
||||
settings.update(config.get_default_paths())
|
||||
|
||||
db = fpdb_db.fpdb_db()
|
||||
db.connect(settings['db-backend'],
|
||||
settings['db-host'],
|
||||
settings['db-databaseName'],
|
||||
settings['db-user'],
|
||||
settings['db-password'])
|
||||
|
||||
qdict = FpdbSQLQueries.FpdbSQLQueries(db.get_backend_name())
|
||||
|
||||
i = Filters(db, settings, config, qdict)
|
||||
main_window = gtk.Window()
|
||||
main_window.connect('destroy', destroy)
|
||||
main_window.add(i.get_vbox())
|
||||
main_window.show()
|
||||
gtk.main()
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
|
||||
+11
-18
@@ -41,8 +41,8 @@ class FpdbSQLQueries:
|
||||
self.query['list_tables'] = """ """
|
||||
|
||||
##################################################################
|
||||
# Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax
|
||||
##################################################################
|
||||
# Drop Tables - MySQL, PostgreSQL and SQLite all share same syntax
|
||||
##################################################################
|
||||
|
||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
||||
self.query['drop_table'] = """DROP TABLE IF EXISTS """
|
||||
@@ -609,7 +609,7 @@ class FpdbSQLQueries:
|
||||
elif(self.dbname == 'SQLite'):
|
||||
self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
|
||||
|
||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'):
|
||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
||||
self.query['getRingProfitAllHandsPlayerIdSite'] = """
|
||||
SELECT hp.handId, hp.winnings, coalesce(hp.ante,0) + SUM(ha.amount)
|
||||
, hp.winnings - (coalesce(hp.ante,0) + SUM(ha.amount))
|
||||
@@ -617,28 +617,15 @@ class FpdbSQLQueries:
|
||||
INNER JOIN Players pl ON hp.playerId = pl.id
|
||||
INNER JOIN Hands h ON h.id = hp.handId
|
||||
INNER JOIN HandsActions ha ON ha.handPlayerId = hp.id
|
||||
INNER JOIN Gametypes g ON h.gametypeId = g.id
|
||||
where pl.id in <player_test>
|
||||
AND pl.siteId in <site_test>
|
||||
AND h.handStart > '<startdate_test>'
|
||||
AND h.handStart < '<enddate_test>'
|
||||
AND g.bigBlind in <limit_test>
|
||||
AND hp.tourneysPlayersId IS NULL
|
||||
GROUP BY hp.handId, hp.winnings, h.handStart, hp.ante
|
||||
ORDER BY h.handStart"""
|
||||
elif(self.dbname == 'SQLite'):
|
||||
#Probably doesn't work.
|
||||
self.query['getRingProfitAllHandsPlayerIdSite'] = """
|
||||
SELECT hp.handId, hp.winnings, SUM(ha.amount), hp.winnings - SUM(ha.amount)
|
||||
FROM HandsPlayers hp
|
||||
INNER JOIN Players pl ON hp.playerId = pl.id
|
||||
INNER JOIN Hands h ON h.id = hp.handId
|
||||
INNER JOIN HandsActions ha ON ha.handPlayerId = hp.id
|
||||
where pl.id in <player_test>
|
||||
AND pl.siteId in <site_test>
|
||||
AND h.handStart > '<startdate_test>'
|
||||
AND h.handStart < '<enddate_test>'
|
||||
AND hp.tourneysPlayersId IS NULL
|
||||
GROUP BY hp.handId, hp.winnings, h.handStart
|
||||
ORDER BY h.handStart"""
|
||||
|
||||
if(self.dbname == 'MySQL InnoDB'):
|
||||
self.query['playerStats'] = """
|
||||
@@ -1153,6 +1140,12 @@ class FpdbSQLQueries:
|
||||
and hprof2.PlPosition = stats.PlPosition)
|
||||
order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as signed)
|
||||
"""
|
||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
||||
self.query['getGames'] = """SELECT DISTINCT category from Gametypes"""
|
||||
|
||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
||||
self.query['getLimits'] = """SELECT DISTINCT bigBlind from Gametypes ORDER by bigBlind DESC"""
|
||||
|
||||
|
||||
if __name__== "__main__":
|
||||
from optparse import OptionParser
|
||||
|
||||
@@ -28,11 +28,13 @@ class Fulltilt(HandHistoryConverter):
|
||||
|
||||
# Static regexes
|
||||
re_GameInfo = re.compile('- (?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<LIMIT>(No Limit|Pot Limit|Limit))? (?P<GAME>(Hold\'em|Omaha Hi|Razz))')
|
||||
re_SplitHands = re.compile(r"(\n\n+)")
|
||||
re_SplitHands = re.compile(r"\n\n+")
|
||||
re_TailSplitHands = re.compile(r"(\n\n+)")
|
||||
re_HandInfo = re.compile('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[- a-zA-Z]+) (\((?P<TABLEATTRIBUTES>.+)\) )?- \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) (Ante \$(?P<ANTE>[.0-9]+) )?- (?P<GAMETYPE>[a-zA-Z\' ]+) - (?P<DATETIME>.*)')
|
||||
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE)
|
||||
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[.0-9]+)\)\n')
|
||||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
# NB: if we ever match "Full Tilt Poker" we should also match "FullTiltPoker", which PT Stud erroneously exports.
|
||||
|
||||
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True):
|
||||
"""\
|
||||
|
||||
Regular → Executable
+8
-10
@@ -66,10 +66,10 @@ class GuiBulkImport():
|
||||
self.importer.setDropIndexes(cb_model[cb_index][0])
|
||||
else:
|
||||
self.importer.setDropIndexes("auto")
|
||||
hhc=self.cbfilter.get_model()[self.cbfilter.get_active()][0]
|
||||
sitename = self.cbfilter.get_model()[self.cbfilter.get_active()][0]
|
||||
self.lab_info.set_text("Importing")
|
||||
|
||||
self.importer.addBulkImportImportFileOrDir(self.inputFile,filter=hhc)
|
||||
self.importer.addBulkImportImportFileOrDir(self.inputFile, site = sitename)
|
||||
self.importer.setCallHud(False)
|
||||
starttime = time()
|
||||
(stored, dups, partial, errs, ttime) = self.importer.runImport()
|
||||
@@ -175,11 +175,9 @@ class GuiBulkImport():
|
||||
|
||||
# ComboBox - filter
|
||||
self.cbfilter = gtk.combo_box_new_text()
|
||||
self.cbfilter.append_text("passthrough")
|
||||
self.cbfilter.append_text("BetfairToFpdb")
|
||||
self.cbfilter.append_text("EverleafToFpdb")
|
||||
self.cbfilter.append_text("FulltiltToFpdb")
|
||||
self.cbfilter.append_text("PokerStarsToFpdb")
|
||||
for w in self.config.hhcs:
|
||||
print w
|
||||
self.cbfilter.append_text(w)
|
||||
self.cbfilter.set_active(0)
|
||||
self.table.attach(self.cbfilter, 3, 4, 2, 3, xpadding = 10, ypadding = 0, yoptions=gtk.SHRINK)
|
||||
self.cbfilter.show()
|
||||
@@ -220,8 +218,8 @@ def main(argv=None):
|
||||
help="Input file in quiet mode")
|
||||
parser.add_option("-q", "--quiet", action="store_false", dest="gui", default=True,
|
||||
help="don't start gui; deprecated (just give a filename with -f).")
|
||||
parser.add_option("-c", "--convert", dest="filtername", default="passthrough", metavar="FILTER",
|
||||
help="Conversion filter (*passthrough, FullTiltToFpdb, PokerStarsToFpdb, EverleafToFpdb)")
|
||||
parser.add_option("-c", "--convert", dest="filtername", default="PokerStars", metavar="FILTER",
|
||||
help="Conversion filter (*Full Tilt Poker, PokerStars, Everleaf)")
|
||||
parser.add_option("-x", "--failOnError", action="store_true", default=False,
|
||||
help="If this option is passed it quits when it encounters any error")
|
||||
parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int",
|
||||
@@ -256,7 +254,7 @@ def main(argv=None):
|
||||
importer = fpdb_import.Importer(False,settings, config)
|
||||
importer.setDropIndexes("auto")
|
||||
importer.setFailOnError(options.failOnError)
|
||||
importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), filter=options.filtername)
|
||||
importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername)
|
||||
importer.setCallHud(False)
|
||||
importer.runImport()
|
||||
importer.clearFileList()
|
||||
|
||||
+95
-253
@@ -39,8 +39,83 @@ except:
|
||||
|
||||
import fpdb_import
|
||||
import fpdb_db
|
||||
import Filters
|
||||
|
||||
class GuiGraphViewer (threading.Thread):
|
||||
|
||||
def __init__(self, db, settings, querylist, config, debug=True):
|
||||
"""Constructor for GraphViewer"""
|
||||
self.debug=debug
|
||||
#print "start of GraphViewer constructor"
|
||||
self.db=db
|
||||
self.cursor=db.cursor
|
||||
self.settings=settings
|
||||
self.sql=querylist
|
||||
self.conf = config
|
||||
|
||||
filters_display = { "Heroes" : True,
|
||||
"Sites" : True,
|
||||
"Games" : True,
|
||||
"Limits" : True,
|
||||
"Dates" : True,
|
||||
"Button1" : True,
|
||||
"Button2" : True
|
||||
}
|
||||
|
||||
self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display)
|
||||
self.filters.registerButton1Name("Refresh Graph")
|
||||
self.filters.registerButton1Callback(self.generateGraph)
|
||||
self.filters.registerButton2Name("Export to File")
|
||||
self.filters.registerButton2Callback(self.exportGraph)
|
||||
|
||||
self.mainHBox = gtk.HBox(False, 0)
|
||||
self.mainHBox.show()
|
||||
|
||||
self.leftPanelBox = self.filters.get_vbox()
|
||||
self.graphBox = gtk.VBox(False, 0)
|
||||
|
||||
self.hpane = gtk.HPaned()
|
||||
self.hpane.pack1(self.leftPanelBox)
|
||||
self.hpane.pack2(self.graphBox)
|
||||
|
||||
self.mainHBox.add(self.hpane)
|
||||
|
||||
self.fig = None
|
||||
#self.exportButton.set_sensitive(False)
|
||||
|
||||
self.fig = Figure(figsize=(5,4), dpi=100)
|
||||
self.canvas = None
|
||||
|
||||
self.mainHBox.show_all()
|
||||
|
||||
#################################
|
||||
#
|
||||
# self.db.cursor.execute("""select UNIX_TIMESTAMP(handStart) as time, id from Hands ORDER BY time""")
|
||||
# THRESHOLD = 1800
|
||||
# hands = self.db.cursor.fetchall()
|
||||
#
|
||||
# times = map(lambda x:long(x[0]), hands)
|
||||
# handids = map(lambda x:int(x[1]), hands)
|
||||
# print "DEBUG: len(times) %s" %(len(times))
|
||||
# diffs = diff(times)
|
||||
# print "DEBUG: len(diffs) %s" %(len(diffs))
|
||||
# index = nonzero(diff(times) > THRESHOLD)
|
||||
# print "DEBUG: len(index[0]) %s" %(len(index[0]))
|
||||
# print "DEBUG: index %s" %(index)
|
||||
# print "DEBUG: index[0][0] %s" %(index[0][0])
|
||||
#
|
||||
# total = 0
|
||||
#
|
||||
# last_idx = 0
|
||||
# for i in range(len(index[0])):
|
||||
# print "Hands in session %4s: %4s Start: %s End: %s Total: %s" %(i, index[0][i] - last_idx, strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])), strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]])), times[index[0][i]] - times[last_idx])
|
||||
# total = total + (index[0][i] - last_idx)
|
||||
# last_idx = index[0][i] + 1
|
||||
#
|
||||
# print "Total: ", total
|
||||
#################################
|
||||
|
||||
|
||||
def get_vbox(self):
|
||||
"""returns the vbox of this thread"""
|
||||
return self.mainHBox
|
||||
@@ -59,11 +134,15 @@ class GuiGraphViewer (threading.Thread):
|
||||
sitenos = []
|
||||
playerids = []
|
||||
|
||||
sites = self.filters.getSites()
|
||||
heroes = self.filters.getHeroes()
|
||||
siteids = self.filters.getSiteIds()
|
||||
limits = self.filters.getLimits()
|
||||
# Which sites are selected?
|
||||
for site in self.sites:
|
||||
if self.sites[site] == True:
|
||||
sitenos.append(self.siteid[site])
|
||||
self.cursor.execute(self.sql.query['getPlayerId'], (self.heroes[site],))
|
||||
for site in sites:
|
||||
if sites[site] == True:
|
||||
sitenos.append(siteids[site])
|
||||
self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],))
|
||||
result = self.db.cursor.fetchall()
|
||||
if len(result) == 1:
|
||||
playerids.append(result[0][0])
|
||||
@@ -73,18 +152,20 @@ class GuiGraphViewer (threading.Thread):
|
||||
print "No sites selected - defaulting to PokerStars"
|
||||
sitenos = [2]
|
||||
|
||||
|
||||
if not playerids:
|
||||
print "No player ids found"
|
||||
return
|
||||
|
||||
if not limits:
|
||||
print "No limits found"
|
||||
return
|
||||
|
||||
#Set graph properties
|
||||
self.ax = self.fig.add_subplot(111)
|
||||
|
||||
#Get graph data from DB
|
||||
starttime = time()
|
||||
line = self.getRingProfitGraph(playerids, sitenos)
|
||||
line = self.getRingProfitGraph(playerids, sitenos, limits)
|
||||
print "Graph generated in: %s" %(time() - starttime)
|
||||
|
||||
self.ax.set_title("Profit graph for ring games")
|
||||
@@ -114,33 +195,32 @@ class GuiGraphViewer (threading.Thread):
|
||||
self.exportButton.set_sensitive(True)
|
||||
#end of def showClicked
|
||||
|
||||
def getRingProfitGraph(self, names, sites):
|
||||
def getRingProfitGraph(self, names, sites, limits):
|
||||
tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite']
|
||||
# print "DEBUG: getRingProfitGraph"
|
||||
start_date, end_date = self.__get_dates()
|
||||
|
||||
if start_date == '':
|
||||
start_date = '1970-01-01'
|
||||
if end_date == '':
|
||||
end_date = '2020-12-12'
|
||||
start_date, end_date = self.filters.getDates()
|
||||
|
||||
#Buggered if I can find a way to do this 'nicely' take a list of intergers and longs
|
||||
# and turn it into a tuple readale by sql.
|
||||
# [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
|
||||
nametest = str(tuple(names))
|
||||
sitetest = str(tuple(sites))
|
||||
limittest = str(tuple(limits))
|
||||
nametest = nametest.replace("L", "")
|
||||
nametest = nametest.replace(",)",")")
|
||||
sitetest = sitetest.replace(",)",")")
|
||||
limittest = limittest.replace("L", "")
|
||||
limittest = limittest.replace(",)",")")
|
||||
|
||||
#Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
|
||||
tmp = tmp.replace("<player_test>", nametest)
|
||||
tmp = tmp.replace("<site_test>", sitetest)
|
||||
tmp = tmp.replace("<startdate_test>", start_date)
|
||||
tmp = tmp.replace("<enddate_test>", end_date)
|
||||
tmp = tmp.replace("<limit_test>", limittest)
|
||||
|
||||
# print "DEBUG: sql query:"
|
||||
# print tmp
|
||||
#print "DEBUG: sql query:"
|
||||
#print tmp
|
||||
self.cursor.execute(tmp)
|
||||
#returns (HandId,Winnings,Costs,Profit)
|
||||
winnings = self.db.cursor.fetchall()
|
||||
@@ -153,136 +233,6 @@ class GuiGraphViewer (threading.Thread):
|
||||
return line/100
|
||||
#end of def getRingProfitGraph
|
||||
|
||||
def createPlayerLine(self, hbox, site, player):
|
||||
label = gtk.Label(site +" id:")
|
||||
hbox.pack_start(label, False, False, 0)
|
||||
label.show()
|
||||
|
||||
pname = gtk.Entry()
|
||||
pname.set_text(player)
|
||||
pname.set_width_chars(20)
|
||||
hbox.pack_start(pname, False, True, 0)
|
||||
pname.connect("changed", self.__set_hero_name, site)
|
||||
#TODO: Look at GtkCompletion - to fill out usernames
|
||||
pname.show()
|
||||
|
||||
self.__set_hero_name(pname, site)
|
||||
|
||||
def __set_hero_name(self, w, site):
|
||||
self.heroes[site] = w.get_text()
|
||||
# print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site])
|
||||
|
||||
def createSiteLine(self, hbox, site):
|
||||
cb = gtk.CheckButton(site)
|
||||
cb.connect('clicked', self.__set_site_select, site)
|
||||
hbox.pack_start(cb, False, False, 0)
|
||||
cb.show()
|
||||
|
||||
def __set_site_select(self, w, site):
|
||||
# This doesn't behave as intended - self.site only allows 1 site for the moment.
|
||||
print w.get_active()
|
||||
self.sites[site] = w.get_active()
|
||||
print "self.sites[%s] set to %s" %(site, self.sites[site])
|
||||
|
||||
def fillPlayerFrame(self, vbox):
|
||||
for site in self.conf.supported_sites.keys():
|
||||
pathHBox = gtk.HBox(False, 0)
|
||||
vbox.pack_start(pathHBox, False, True, 0)
|
||||
pathHBox.show()
|
||||
|
||||
player = self.conf.supported_sites[site].screen_name
|
||||
self.createPlayerLine(pathHBox, site, player)
|
||||
|
||||
def fillSitesFrame(self, vbox):
|
||||
for site in self.conf.supported_sites.keys():
|
||||
hbox = gtk.HBox(False, 0)
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
hbox.show()
|
||||
self.createSiteLine(hbox, site)
|
||||
#Get db site id for filtering later
|
||||
self.cursor.execute(self.sql.query['getSiteId'], (site,))
|
||||
result = self.db.cursor.fetchall()
|
||||
if len(result) == 1:
|
||||
self.siteid[site] = result[0][0]
|
||||
else:
|
||||
print "Either 0 or more than one site matched - EEK"
|
||||
|
||||
def fillDateFrame(self, vbox):
|
||||
# Hat tip to Mika Bostrom - calendar code comes from PokerStats
|
||||
hbox = gtk.HBox()
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
hbox.show()
|
||||
|
||||
lbl_start = gtk.Label('From:')
|
||||
lbl_start.show()
|
||||
|
||||
btn_start = gtk.Button()
|
||||
btn_start.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
|
||||
btn_start.connect('clicked', self.__calendar_dialog, self.start_date)
|
||||
btn_start.show()
|
||||
|
||||
hbox.pack_start(lbl_start, expand=False, padding=3)
|
||||
hbox.pack_start(btn_start, expand=False, padding=3)
|
||||
hbox.pack_start(self.start_date, expand=False, padding=2)
|
||||
self.start_date.show()
|
||||
|
||||
#New row for end date
|
||||
hbox = gtk.HBox()
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
hbox.show()
|
||||
|
||||
lbl_end = gtk.Label(' To:')
|
||||
lbl_end.show()
|
||||
btn_end = gtk.Button()
|
||||
btn_end.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
|
||||
btn_end.connect('clicked', self.__calendar_dialog, self.end_date)
|
||||
btn_end.show()
|
||||
|
||||
btn_clear = gtk.Button(label=' Clear Dates ')
|
||||
btn_clear.connect('clicked', self.__clear_dates)
|
||||
btn_clear.show()
|
||||
|
||||
hbox.pack_start(lbl_end, expand=False, padding=3)
|
||||
hbox.pack_start(btn_end, expand=False, padding=3)
|
||||
hbox.pack_start(self.end_date, expand=False, padding=2)
|
||||
self.end_date.show()
|
||||
|
||||
hbox.pack_start(btn_clear, expand=False, padding=15)
|
||||
|
||||
def __calendar_dialog(self, widget, entry):
|
||||
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
d.set_title('Pick a date')
|
||||
|
||||
vb = gtk.VBox()
|
||||
cal = gtk.Calendar()
|
||||
vb.pack_start(cal, expand=False, padding=0)
|
||||
|
||||
btn = gtk.Button('Done')
|
||||
btn.connect('clicked', self.__get_date, cal, entry, d)
|
||||
|
||||
vb.pack_start(btn, expand=False, padding=4)
|
||||
|
||||
d.add(vb)
|
||||
d.set_position(gtk.WIN_POS_MOUSE)
|
||||
d.show_all()
|
||||
|
||||
def __clear_dates(self, w):
|
||||
self.start_date.set_text('')
|
||||
self.end_date.set_text('')
|
||||
|
||||
def __get_dates(self):
|
||||
t1 = self.start_date.get_text()
|
||||
t2 = self.end_date.get_text()
|
||||
return (t1, t2)
|
||||
|
||||
def __get_date(self, widget, calendar, entry, win):
|
||||
# year and day are correct, month is 0..11
|
||||
(year, month, day) = calendar.get_date()
|
||||
month += 1
|
||||
ds = '%04d-%02d-%02d' % (year, month, day)
|
||||
entry.set_text(ds)
|
||||
win.destroy()
|
||||
|
||||
def exportGraph (self, widget, data):
|
||||
if self.fig is None:
|
||||
return # Might want to disable export button until something has been generated.
|
||||
@@ -303,112 +253,4 @@ class GuiGraphViewer (threading.Thread):
|
||||
#TODO: This asks for a directory but will take a filename and overwrite it.
|
||||
self.fig.savefig(self.exportDir, format="png")
|
||||
|
||||
def __init__(self, db, settings, querylist, config, debug=True):
|
||||
"""Constructor for GraphViewer"""
|
||||
self.debug=debug
|
||||
#print "start of GraphViewer constructor"
|
||||
self.db=db
|
||||
self.cursor=db.cursor
|
||||
self.settings=settings
|
||||
self.sql=querylist
|
||||
self.conf = config
|
||||
|
||||
self.sites = {}
|
||||
self.siteid = {}
|
||||
self.heroes = {}
|
||||
|
||||
# For use in date ranges.
|
||||
self.start_date = gtk.Entry(max=12)
|
||||
self.end_date = gtk.Entry(max=12)
|
||||
self.start_date.set_property('editable', False)
|
||||
self.end_date.set_property('editable', False)
|
||||
|
||||
self.mainHBox = gtk.HBox(False, 0)
|
||||
self.mainHBox.show()
|
||||
|
||||
self.leftPanelBox = gtk.VBox(False, 0)
|
||||
self.graphBox = gtk.VBox(False, 0)
|
||||
|
||||
self.hpane = gtk.HPaned()
|
||||
self.hpane.pack1(self.leftPanelBox)
|
||||
self.hpane.pack2(self.graphBox)
|
||||
self.hpane.show()
|
||||
|
||||
self.mainHBox.add(self.hpane)
|
||||
|
||||
playerFrame = gtk.Frame("Hero:")
|
||||
playerFrame.set_label_align(0.0, 0.0)
|
||||
playerFrame.show()
|
||||
vbox = gtk.VBox(False, 0)
|
||||
vbox.show()
|
||||
|
||||
self.fillPlayerFrame(vbox)
|
||||
playerFrame.add(vbox)
|
||||
|
||||
sitesFrame = gtk.Frame("Sites:")
|
||||
sitesFrame.set_label_align(0.0, 0.0)
|
||||
sitesFrame.show()
|
||||
vbox = gtk.VBox(False, 0)
|
||||
vbox.show()
|
||||
|
||||
self.fillSitesFrame(vbox)
|
||||
sitesFrame.add(vbox)
|
||||
|
||||
dateFrame = gtk.Frame("Date:")
|
||||
dateFrame.set_label_align(0.0, 0.0)
|
||||
dateFrame.show()
|
||||
vbox = gtk.VBox(False, 0)
|
||||
vbox.show()
|
||||
|
||||
self.fillDateFrame(vbox)
|
||||
dateFrame.add(vbox)
|
||||
|
||||
graphButton=gtk.Button("Generate Graph")
|
||||
graphButton.connect("clicked", self.generateGraph, "cliced data")
|
||||
graphButton.show()
|
||||
|
||||
self.fig = None
|
||||
self.exportButton=gtk.Button("Export to File")
|
||||
self.exportButton.connect("clicked", self.exportGraph, "show clicked")
|
||||
self.exportButton.set_sensitive(False)
|
||||
self.exportButton.show()
|
||||
|
||||
self.leftPanelBox.add(playerFrame)
|
||||
self.leftPanelBox.add(sitesFrame)
|
||||
self.leftPanelBox.add(dateFrame)
|
||||
self.leftPanelBox.add(graphButton)
|
||||
self.leftPanelBox.add(self.exportButton)
|
||||
|
||||
self.leftPanelBox.show()
|
||||
self.graphBox.show()
|
||||
|
||||
self.fig = Figure(figsize=(5,4), dpi=100)
|
||||
self.canvas = None
|
||||
|
||||
#################################
|
||||
#
|
||||
# self.db.cursor.execute("""select UNIX_TIMESTAMP(handStart) as time, id from Hands ORDER BY time""")
|
||||
# THRESHOLD = 1800
|
||||
# hands = self.db.cursor.fetchall()
|
||||
#
|
||||
# times = map(lambda x:long(x[0]), hands)
|
||||
# handids = map(lambda x:int(x[1]), hands)
|
||||
# print "DEBUG: len(times) %s" %(len(times))
|
||||
# diffs = diff(times)
|
||||
# print "DEBUG: len(diffs) %s" %(len(diffs))
|
||||
# index = nonzero(diff(times) > THRESHOLD)
|
||||
# print "DEBUG: len(index[0]) %s" %(len(index[0]))
|
||||
# print "DEBUG: index %s" %(index)
|
||||
# print "DEBUG: index[0][0] %s" %(index[0][0])
|
||||
#
|
||||
# total = 0
|
||||
#
|
||||
# last_idx = 0
|
||||
# for i in range(len(index[0])):
|
||||
# print "Hands in session %4s: %4s Start: %s End: %s Total: %s" %(i, index[0][i] - last_idx, strftime("%d/%m/%Y %H:%M", localtime(times[last_idx])), strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]])), times[index[0][i]] - times[last_idx])
|
||||
# total = total + (index[0][i] - last_idx)
|
||||
# last_idx = index[0][i] + 1
|
||||
#
|
||||
# print "Total: ", total
|
||||
#################################
|
||||
|
||||
|
||||
+107
-124
@@ -23,146 +23,43 @@ import os
|
||||
|
||||
import fpdb_import
|
||||
import fpdb_db
|
||||
import Filters
|
||||
import FpdbSQLQueries
|
||||
|
||||
class GuiPlayerStats (threading.Thread):
|
||||
def get_vbox(self):
|
||||
"""returns the vbox of this thread"""
|
||||
return self.main_hbox
|
||||
|
||||
def toggleCallback(self, widget, data=None):
|
||||
# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
|
||||
self.activesite = data
|
||||
print "DEBUG: activesite set to %s" %(self.activesite)
|
||||
|
||||
def refreshStats(self, widget, data):
|
||||
try: self.stats_table.destroy()
|
||||
except AttributeError: pass
|
||||
self.fillStatsFrame(self.stats_frame)
|
||||
|
||||
def fillStatsFrame(self, vbox):
|
||||
# Get currently active site and grab playerid
|
||||
tmp = self.sql.query['playerStats']
|
||||
|
||||
result = self.cursor.execute(self.sql.query['getPlayerId'], (self.heroes[self.activesite],))
|
||||
result = self.cursor.fetchall()
|
||||
if not result == ():
|
||||
pid = result[0][0]
|
||||
pid = result[0][0]
|
||||
tmp = tmp.replace("<player_test>", "(" + str(pid) + ")")
|
||||
self.cursor.execute(tmp)
|
||||
result = self.cursor.fetchall()
|
||||
cols = 16
|
||||
rows = len(result)+1 # +1 for title row
|
||||
self.stats_table = gtk.Table(rows, cols, False)
|
||||
self.stats_table.set_col_spacings(4)
|
||||
self.stats_table.show()
|
||||
vbox.add(self.stats_table)
|
||||
|
||||
# Create header row
|
||||
titles = ("Game", "Hands", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance")
|
||||
|
||||
col = 0
|
||||
row = 0
|
||||
for t in titles:
|
||||
l = gtk.Label(titles[col])
|
||||
l.show()
|
||||
self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK)
|
||||
col +=1
|
||||
|
||||
for row in range(rows-1):
|
||||
if(row%2 == 0):
|
||||
bgcolor = "white"
|
||||
else:
|
||||
bgcolor = "lightgrey"
|
||||
for col in range(cols):
|
||||
eb = gtk.EventBox()
|
||||
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
|
||||
if result[row][col]:
|
||||
l = gtk.Label(result[row][col])
|
||||
else:
|
||||
l = gtk.Label(' ')
|
||||
if col == 0:
|
||||
l.set_alignment(xalign=0.0, yalign=0.5)
|
||||
else:
|
||||
l.set_alignment(xalign=1.0, yalign=0.5)
|
||||
eb.add(l)
|
||||
self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK)
|
||||
l.show()
|
||||
eb.show()
|
||||
self.fdb.db.commit()
|
||||
#end def fillStatsFrame(self, vbox):
|
||||
|
||||
def fillPlayerFrame(self, vbox):
|
||||
for site in self.conf.supported_sites.keys():
|
||||
hbox = gtk.HBox(False, 0)
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
hbox.show()
|
||||
|
||||
player = self.conf.supported_sites[site].screen_name
|
||||
self.createPlayerLine(hbox, site, player)
|
||||
hbox = gtk.HBox(False, 0)
|
||||
button = gtk.Button("Refresh")
|
||||
button.connect("clicked", self.refreshStats, False)
|
||||
button.show()
|
||||
hbox.add(button)
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
hbox.show()
|
||||
|
||||
def createPlayerLine(self, hbox, site, player):
|
||||
if(self.buttongroup == None):
|
||||
button = gtk.RadioButton(None, site + " id:")
|
||||
button.set_active(True)
|
||||
self.buttongroup = button
|
||||
self.activesite = site
|
||||
else:
|
||||
button = gtk.RadioButton(self.buttongroup, site + " id:")
|
||||
hbox.pack_start(button, True, True, 0)
|
||||
button.connect("toggled", self.toggleCallback, site)
|
||||
button.show()
|
||||
|
||||
pname = gtk.Entry()
|
||||
pname.set_text(player)
|
||||
pname.set_width_chars(20)
|
||||
hbox.pack_start(pname, False, True, 0)
|
||||
pname.connect("changed", self.__set_hero_name, site)
|
||||
#TODO: Look at GtkCompletion - to fill out usernames
|
||||
pname.show()
|
||||
self.__set_hero_name(pname, site)
|
||||
|
||||
def __set_hero_name(self, w, site):
|
||||
self.heroes[site] = w.get_text()
|
||||
|
||||
def __init__(self, db, config, querylist, debug=True):
|
||||
self.debug=debug
|
||||
self.conf=config
|
||||
|
||||
# create new db connection to avoid conflicts with other threads
|
||||
self.fdb = fpdb_db.fpdb_db()
|
||||
self.fdb.do_connect(self.conf)
|
||||
self.cursor=self.fdb.cursor
|
||||
|
||||
self.db = fpdb_db.fpdb_db()
|
||||
self.db.do_connect(self.conf)
|
||||
self.cursor=self.db.cursor
|
||||
self.sql = querylist
|
||||
|
||||
self.activesite = None
|
||||
self.buttongroup = None
|
||||
settings = {}
|
||||
settings.update(config.get_db_parameters())
|
||||
settings.update(config.get_tv_parameters())
|
||||
settings.update(config.get_import_parameters())
|
||||
settings.update(config.get_default_paths())
|
||||
|
||||
filters_display = { "Heroes" : True,
|
||||
"Sites" : True,
|
||||
"Games" : False,
|
||||
"Limits" : False,
|
||||
"Dates" : False,
|
||||
"Button1" : False,
|
||||
"Button2" : False
|
||||
}
|
||||
|
||||
self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display)
|
||||
|
||||
self.heroes = {}
|
||||
self.stat_table = None
|
||||
self.stats_frame = None
|
||||
|
||||
self.main_hbox = gtk.HBox(False, 0)
|
||||
self.main_hbox.show()
|
||||
|
||||
playerFrame = gtk.Frame("Hero:")
|
||||
playerFrame.set_label_align(0.0, 0.0)
|
||||
playerFrame.show()
|
||||
vbox = gtk.VBox(False, 0)
|
||||
vbox.show()
|
||||
|
||||
self.fillPlayerFrame(vbox)
|
||||
playerFrame.add(vbox)
|
||||
|
||||
statsFrame = gtk.Frame("Stats:")
|
||||
statsFrame.set_label_align(0.0, 0.0)
|
||||
statsFrame.show()
|
||||
@@ -172,6 +69,92 @@ class GuiPlayerStats (threading.Thread):
|
||||
self.fillStatsFrame(self.stats_frame)
|
||||
statsFrame.add(self.stats_frame)
|
||||
|
||||
self.main_hbox.pack_start(playerFrame)
|
||||
self.main_hbox.pack_start(self.filters.get_vbox())
|
||||
self.main_hbox.pack_start(statsFrame)
|
||||
|
||||
def get_vbox(self):
|
||||
"""returns the vbox of this thread"""
|
||||
return self.main_hbox
|
||||
|
||||
def refreshStats(self, widget, data):
|
||||
try: self.stats_table.destroy()
|
||||
except AttributeError: pass
|
||||
self.fillStatsFrame(self.stats_frame)
|
||||
|
||||
def fillStatsFrame(self, vbox):
|
||||
sites = self.filters.getSites()
|
||||
heroes = self.filters.getHeroes()
|
||||
siteids = self.filters.getSiteIds()
|
||||
sitenos = []
|
||||
playerids = []
|
||||
|
||||
# Which sites are selected?
|
||||
for site in sites:
|
||||
if sites[site] == True:
|
||||
sitenos.append(siteids[site])
|
||||
self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],))
|
||||
result = self.db.cursor.fetchall()
|
||||
if len(result) == 1:
|
||||
playerids.append(result[0][0])
|
||||
|
||||
if not sitenos:
|
||||
#Should probably pop up here.
|
||||
print "No sites selected - defaulting to PokerStars"
|
||||
sitenos = [2]
|
||||
if not playerids:
|
||||
print "No player ids found"
|
||||
return
|
||||
|
||||
self.createStatsTable(vbox, playerids, sitenos)
|
||||
|
||||
def createStatsTable(self, vbox, playerids, sitenos):
|
||||
tmp = self.sql.query['playerStats']
|
||||
|
||||
nametest = str(tuple(playerids))
|
||||
nametest = nametest.replace("L", "")
|
||||
nametest = nametest.replace(",)",")")
|
||||
|
||||
tmp = tmp.replace("<player_test>", nametest)
|
||||
|
||||
self.cursor.execute(tmp)
|
||||
result = self.cursor.fetchall()
|
||||
cols = 16
|
||||
rows = len(result)+1 # +1 for title row
|
||||
self.stats_table = gtk.Table(rows, cols, False)
|
||||
self.stats_table.set_col_spacings(4)
|
||||
self.stats_table.show()
|
||||
vbox.add(self.stats_table)
|
||||
|
||||
# Create header row
|
||||
titles = ("Game", "Hands", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance")
|
||||
|
||||
col = 0
|
||||
row = 0
|
||||
for t in titles:
|
||||
l = gtk.Label(titles[col])
|
||||
l.show()
|
||||
self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK)
|
||||
col +=1
|
||||
|
||||
for row in range(rows-1):
|
||||
if(row%2 == 0):
|
||||
bgcolor = "white"
|
||||
else:
|
||||
bgcolor = "lightgrey"
|
||||
for col in range(cols):
|
||||
eb = gtk.EventBox()
|
||||
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
|
||||
if result[row][col]:
|
||||
l = gtk.Label(result[row][col])
|
||||
else:
|
||||
l = gtk.Label(' ')
|
||||
if col == 0:
|
||||
l.set_alignment(xalign=0.0, yalign=0.5)
|
||||
else:
|
||||
l.set_alignment(xalign=1.0, yalign=0.5)
|
||||
eb.add(l)
|
||||
self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK)
|
||||
l.show()
|
||||
eb.show()
|
||||
self.db.db.commit()
|
||||
#end def fillStatsFrame(self, vbox):
|
||||
|
||||
+112
-158
@@ -23,180 +23,43 @@ import os
|
||||
|
||||
import fpdb_import
|
||||
import fpdb_db
|
||||
import Filters
|
||||
import FpdbSQLQueries
|
||||
|
||||
class GuiPositionalStats (threading.Thread):
|
||||
def get_vbox(self):
|
||||
"""returns the vbox of this thread"""
|
||||
return self.main_hbox
|
||||
|
||||
def toggleCallback(self, widget, data=None):
|
||||
# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
|
||||
self.activesite = data
|
||||
print "DEBUG: activesite set to %s" %(self.activesite)
|
||||
|
||||
def cardCallback(self, widget, data=None):
|
||||
print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
|
||||
|
||||
def refreshStats(self, widget, data):
|
||||
try: self.stats_table.destroy()
|
||||
except AttributeError: pass
|
||||
self.fillStatsFrame(self.stats_frame)
|
||||
|
||||
def fillStatsFrame(self, vbox):
|
||||
# Get currently active site and grab playerid
|
||||
print "DEBUG: attempting to fill stats frame"
|
||||
tmp = self.sql.query['playerStatsByPosition']
|
||||
|
||||
result = self.cursor.execute(self.sql.query['getPlayerId'], (self.heroes[self.activesite],))
|
||||
result = self.cursor.fetchall()
|
||||
if not result == ():
|
||||
pid = result[0][0]
|
||||
pid = result[0][0]
|
||||
tmp = tmp.replace("<player_test>", "(" + str(pid) + ")")
|
||||
self.cursor.execute(tmp)
|
||||
result = self.cursor.fetchall()
|
||||
cols = 16
|
||||
rows = len(result)+1 # +1 for title row
|
||||
self.stats_table = gtk.Table(rows, cols, False)
|
||||
self.stats_table.set_col_spacings(4)
|
||||
self.stats_table.show()
|
||||
vbox.add(self.stats_table)
|
||||
|
||||
# Create header row
|
||||
titles = ("Game", "Position", "#", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance")
|
||||
|
||||
col = 0
|
||||
row = 0
|
||||
for t in titles:
|
||||
l = gtk.Label(titles[col])
|
||||
l.show()
|
||||
self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK)
|
||||
col +=1
|
||||
|
||||
for row in range(rows-1):
|
||||
if(row%2 == 0):
|
||||
bgcolor = "white"
|
||||
else:
|
||||
bgcolor = "lightgrey"
|
||||
for col in range(cols):
|
||||
eb = gtk.EventBox()
|
||||
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
|
||||
if result[row][col]:
|
||||
l = gtk.Label(result[row][col])
|
||||
else:
|
||||
l = gtk.Label(' ')
|
||||
if col == 0:
|
||||
l.set_alignment(xalign=0.0, yalign=0.5)
|
||||
else:
|
||||
l.set_alignment(xalign=1.0, yalign=0.5)
|
||||
eb.add(l)
|
||||
self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK)
|
||||
l.show()
|
||||
eb.show()
|
||||
self.fdb.db.commit()
|
||||
#end def fillStatsFrame(self, vbox):
|
||||
|
||||
def fillPlayerFrame(self, vbox):
|
||||
for site in self.conf.supported_sites.keys():
|
||||
hbox = gtk.HBox(False, 0)
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
hbox.show()
|
||||
|
||||
player = self.conf.supported_sites[site].screen_name
|
||||
self.createPlayerLine(hbox, site, player)
|
||||
hbox = gtk.HBox(False, 0)
|
||||
button = gtk.Button("Refresh")
|
||||
button.connect("clicked", self.refreshStats, False)
|
||||
button.show()
|
||||
hbox.add(button)
|
||||
vbox.pack_start(hbox, False, True, 0)
|
||||
hbox.show()
|
||||
|
||||
def fillCardsFrame(self, vbox):
|
||||
hbox1 = gtk.HBox(True,0)
|
||||
hbox1.show()
|
||||
vbox.pack_start(hbox1, True, True, 0)
|
||||
|
||||
cards = [ "A", "K","Q","J","T","9","8","7","6","5","4","3","2" ]
|
||||
|
||||
for j in range(0, len(cards)):
|
||||
hbox1 = gtk.HBox(True,0)
|
||||
hbox1.show()
|
||||
vbox.pack_start(hbox1, True, True, 0)
|
||||
for i in range(0, len(cards)):
|
||||
if i < (j + 1):
|
||||
suit = "o"
|
||||
else:
|
||||
suit = "s"
|
||||
button = gtk.ToggleButton("%s%s%s" %(cards[i], cards[j], suit))
|
||||
button.connect("toggled", self.cardCallback, "%s%s%s" %(cards[i], cards[j], suit))
|
||||
hbox1.pack_start(button, True, True, 0)
|
||||
button.show()
|
||||
|
||||
def createPlayerLine(self, hbox, site, player):
|
||||
if(self.buttongroup == None):
|
||||
button = gtk.RadioButton(None, site + " id:")
|
||||
button.set_active(True)
|
||||
self.buttongroup = button
|
||||
self.activesite = site
|
||||
else:
|
||||
button = gtk.RadioButton(self.buttongroup, site + " id:")
|
||||
hbox.pack_start(button, True, True, 0)
|
||||
button.connect("toggled", self.toggleCallback, site)
|
||||
button.show()
|
||||
|
||||
pname = gtk.Entry()
|
||||
pname.set_text(player)
|
||||
pname.set_width_chars(20)
|
||||
hbox.pack_start(pname, False, True, 0)
|
||||
pname.connect("changed", self.__set_hero_name, site)
|
||||
#TODO: Look at GtkCompletion - to fill out usernames
|
||||
pname.show()
|
||||
self.__set_hero_name(pname, site)
|
||||
|
||||
def __set_hero_name(self, w, site):
|
||||
self.heroes[site] = w.get_text()
|
||||
|
||||
def __init__(self, db, config, querylist, debug=True):
|
||||
self.debug=debug
|
||||
self.conf=config
|
||||
|
||||
# create new db connection to avoid conflicts with other threads
|
||||
self.fdb = fpdb_db.fpdb_db()
|
||||
self.fdb.do_connect(self.conf)
|
||||
self.cursor=self.fdb.cursor
|
||||
|
||||
self.db = fpdb_db.fpdb_db()
|
||||
self.db.do_connect(self.conf)
|
||||
self.cursor=self.db.cursor
|
||||
self.sql = querylist
|
||||
|
||||
self.activesite = None
|
||||
self.buttongroup = None
|
||||
settings = {}
|
||||
settings.update(config.get_db_parameters())
|
||||
settings.update(config.get_tv_parameters())
|
||||
settings.update(config.get_import_parameters())
|
||||
settings.update(config.get_default_paths())
|
||||
|
||||
filters_display = { "Heroes" : True,
|
||||
"Sites" : True,
|
||||
"Games" : False,
|
||||
"Limits" : False,
|
||||
"Dates" : False,
|
||||
"Button1" : False,
|
||||
"Button2" : False
|
||||
}
|
||||
|
||||
self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display)
|
||||
|
||||
self.heroes = {}
|
||||
self.stat_table = None
|
||||
self.stats_frame = None
|
||||
|
||||
self.main_hbox = gtk.HBox(False, 0)
|
||||
self.main_hbox.show()
|
||||
|
||||
playerFrame = gtk.Frame("Hero:")
|
||||
playerFrame.set_label_align(0.0, 0.0)
|
||||
playerFrame.show()
|
||||
vbox = gtk.VBox(False, 0)
|
||||
vbox.show()
|
||||
|
||||
self.fillPlayerFrame(vbox)
|
||||
playerFrame.add(vbox)
|
||||
|
||||
cardsFrame = gtk.Frame("Cards:")
|
||||
cardsFrame.set_label_align(0.0, 0.0)
|
||||
cardsFrame.show()
|
||||
vbox = gtk.VBox(False, 0)
|
||||
vbox.show()
|
||||
|
||||
self.fillCardsFrame(vbox)
|
||||
cardsFrame.add(vbox)
|
||||
|
||||
statsFrame = gtk.Frame("Stats:")
|
||||
statsFrame.set_label_align(0.0, 0.0)
|
||||
statsFrame.show()
|
||||
@@ -206,6 +69,97 @@ class GuiPositionalStats (threading.Thread):
|
||||
self.fillStatsFrame(self.stats_frame)
|
||||
statsFrame.add(self.stats_frame)
|
||||
|
||||
self.main_hbox.pack_start(playerFrame)
|
||||
self.main_hbox.pack_start(self.filters.get_vbox())
|
||||
self.main_hbox.pack_start(statsFrame)
|
||||
|
||||
def get_vbox(self):
|
||||
"""returns the vbox of this thread"""
|
||||
return self.main_hbox
|
||||
|
||||
def toggleCallback(self, widget, data=None):
|
||||
# print "%s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
|
||||
self.activesite = data
|
||||
print "DEBUG: activesite set to %s" %(self.activesite)
|
||||
|
||||
def refreshStats(self, widget, data):
|
||||
try: self.stats_table.destroy()
|
||||
except AttributeError: pass
|
||||
self.fillStatsFrame(self.stats_frame)
|
||||
|
||||
def fillStatsFrame(self, vbox):
|
||||
sites = self.filters.getSites()
|
||||
heroes = self.filters.getHeroes()
|
||||
siteids = self.filters.getSiteIds()
|
||||
sitenos = []
|
||||
playerids = []
|
||||
|
||||
# Which sites are selected?
|
||||
for site in sites:
|
||||
if sites[site] == True:
|
||||
sitenos.append(siteids[site])
|
||||
self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],))
|
||||
result = self.db.cursor.fetchall()
|
||||
if len(result) == 1:
|
||||
playerids.append(result[0][0])
|
||||
|
||||
if not sitenos:
|
||||
#Should probably pop up here.
|
||||
print "No sites selected - defaulting to PokerStars"
|
||||
sitenos = [2]
|
||||
if not playerids:
|
||||
print "No player ids found"
|
||||
return
|
||||
|
||||
self.createStatsTable(vbox, playerids, sitenos)
|
||||
|
||||
def createStatsTable(self, vbox, playerids, sitenos):
|
||||
tmp = self.sql.query['playerStatsByPosition']
|
||||
|
||||
nametest = str(tuple(playerids))
|
||||
nametest = nametest.replace("L", "")
|
||||
nametest = nametest.replace(",)",")")
|
||||
|
||||
tmp = tmp.replace("<player_test>", nametest)
|
||||
|
||||
self.cursor.execute(tmp)
|
||||
result = self.cursor.fetchall()
|
||||
cols = 16
|
||||
rows = len(result)+1 # +1 for title row
|
||||
self.stats_table = gtk.Table(rows, cols, False)
|
||||
self.stats_table.set_col_spacings(4)
|
||||
self.stats_table.show()
|
||||
vbox.add(self.stats_table)
|
||||
|
||||
# Create header row
|
||||
titles = ("Game", "Position", "#", "VPIP", "PFR", "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq", "PoFAFq", "Net($)", "BB/100", "$/hand", "Variance")
|
||||
|
||||
col = 0
|
||||
row = 0
|
||||
for t in titles:
|
||||
l = gtk.Label(titles[col])
|
||||
l.show()
|
||||
self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK)
|
||||
col +=1
|
||||
|
||||
for row in range(rows-1):
|
||||
if(row%2 == 0):
|
||||
bgcolor = "white"
|
||||
else:
|
||||
bgcolor = "lightgrey"
|
||||
for col in range(cols):
|
||||
eb = gtk.EventBox()
|
||||
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
|
||||
if result[row][col]:
|
||||
l = gtk.Label(result[row][col])
|
||||
else:
|
||||
l = gtk.Label(' ')
|
||||
if col == 0:
|
||||
l.set_alignment(xalign=0.0, yalign=0.5)
|
||||
else:
|
||||
l.set_alignment(xalign=1.0, yalign=0.5)
|
||||
eb.add(l)
|
||||
self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK)
|
||||
l.show()
|
||||
eb.show()
|
||||
self.db.db.commit()
|
||||
#end def fillStatsFrame(self, vbox):
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
screen_name="YOUR SCREEN NAME HERE"
|
||||
site_path="C:/Program Files/PokerStars/"
|
||||
HH_path="C:/Program Files/PokerStars/HandHistory/YOUR SCREEN NAME HERE/"
|
||||
decoder="pokerstars_decode_table"
|
||||
decoder="pokerstars_decode_table"
|
||||
converter="PokerStarsToFpdb"
|
||||
bgcolor="#000000"
|
||||
fgcolor="#FFFFFF"
|
||||
hudopacity="1.0"
|
||||
font="Sans"
|
||||
font_size="8"
|
||||
converter="passthrough"
|
||||
supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo">
|
||||
<layout max="8" width="792" height="546" fav_seat="0">
|
||||
<location seat="1" x="684" y="61"> </location>
|
||||
@@ -74,12 +74,12 @@
|
||||
site_path="C:/Program Files/Full Tilt Poker/"
|
||||
HH_path="C:/Program Files/Full Tilt Poker/HandHistory/YOUR SCREEN NAME HERE/"
|
||||
decoder="fulltilt_decode_table"
|
||||
converter="FulltiltToFpdb"
|
||||
bgcolor="#000000"
|
||||
fgcolor="#FFFFFF"
|
||||
hudopacity="1.0"
|
||||
font="Sans"
|
||||
font_size="8"
|
||||
converter="passthrough"
|
||||
supported_games="holdem,razz,omahahi,omahahilo,studhi,studhilo">
|
||||
<layout fav_seat="0" height="547" max="8" width="794">
|
||||
<location seat="1" x="640" y="64"> </location>
|
||||
@@ -123,7 +123,7 @@
|
||||
site_path=""
|
||||
HH_path=""
|
||||
decoder="everleaf_decode_table"
|
||||
converter="EverleafToFpdb"
|
||||
converter="EverleafToFpdb"
|
||||
supported_games="holdem">
|
||||
<layout fav_seat="0" height="547" max="8" width="794">
|
||||
<location seat="1" x="640" y="64"> </location>
|
||||
@@ -288,6 +288,12 @@
|
||||
</aw>
|
||||
</aux_windows>
|
||||
|
||||
<hhcs>
|
||||
<hhc site="PokerStars" converter="PokerStarsToFpdb"/>
|
||||
<hhc site="Full Tilt Poker" converter="FulltiltToFpdb"/>
|
||||
<hhc site="Everleaf" converter="EverleafToFpdb"/>
|
||||
</hhcs>
|
||||
|
||||
<supported_databases>
|
||||
<database db_name="fpdb" db_server="mysql" db_ip="localhost" db_user="fpdb" db_pass="YOUR MYSQL PASSWORD" db_type="fpdb"></database>
|
||||
</supported_databases>
|
||||
|
||||
@@ -112,7 +112,9 @@ class HandHistoryConverter():
|
||||
def start(self):
|
||||
"""process a hand at a time from the input specified by in_path.
|
||||
If in follow mode, wait for more data to turn up.
|
||||
Otherwise, finish at eof..."""
|
||||
Otherwise, finish at eof...
|
||||
|
||||
"""
|
||||
starttime = time.time()
|
||||
if not self.sanityCheck():
|
||||
print "Cowardly refusing to continue after failed sanity check"
|
||||
@@ -137,7 +139,11 @@ Otherwise, finish at eof..."""
|
||||
|
||||
def tailHands(self):
|
||||
"""Generator of handTexts from a tailed file:
|
||||
Tail the in_path file and yield handTexts separated by re_SplitHands"""
|
||||
Tail the in_path file and yield handTexts separated by re_SplitHands.
|
||||
This requires a regex that greedily groups and matches the 'splitter' between hands,
|
||||
which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
|
||||
|
||||
"""
|
||||
if self.in_path == '-': raise StopIteration
|
||||
interval = 1.0 # seconds to sleep between reads for new data
|
||||
fd = codecs.open(self.in_path,'r', self.codepage)
|
||||
@@ -161,7 +167,7 @@ Tail the in_path file and yield handTexts separated by re_SplitHands"""
|
||||
else:
|
||||
# yield hands
|
||||
data = data + newdata
|
||||
result = self.re_SplitHands.split(data)
|
||||
result = self.re_TailSplitHands.split(data)
|
||||
result = iter(result)
|
||||
data = ''
|
||||
# --x data (- is bit of splitter, x is paragraph) yield,...,keep
|
||||
|
||||
@@ -27,7 +27,8 @@ 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|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_SplitHands = re.compile('\n\n+')
|
||||
re_TailSplitHands = re.compile('(\n\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)
|
||||
re_PlayerInfo = re.compile('^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[.0-9]+) in chips\)', re.MULTILINE)
|
||||
@@ -72,7 +73,7 @@ follow : whether to tail -f the input"""
|
||||
["ring", "hold", "pl"],
|
||||
["ring", "hold", "fl"],
|
||||
["ring", "stud", "fl"],
|
||||
["ring", "draw", "fl"],
|
||||
#["ring", "draw", "fl"],
|
||||
["ring", "omaha", "pl"]
|
||||
]
|
||||
|
||||
|
||||
Executable
+329
@@ -0,0 +1,329 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2008, Carl Gherardi
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
########################################################################
|
||||
|
||||
import sys
|
||||
from HandHistoryConverter import *
|
||||
|
||||
|
||||
class UltimateBet(HandHistoryConverter):
|
||||
|
||||
# Static regexes
|
||||
re_GameInfo = re.compile("Stage #(?P<HID>[0-9]+):\s+\(?(?P<GAME>Hold\'em|Razz|Seven Card|Omaha|Omaha Hi/Lo|Badugi) (?P<LIMIT>No Limit|Normal|Pot Limit),? \(?(?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\) - (?P<DATETIME>.*$)", re.MULTILINE)
|
||||
re_SplitHands = re.compile('(\n\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)
|
||||
re_PlayerInfo = re.compile('^Seat (?P<SEAT>[0-9]+) - (?P<PNAME>.*) \(\$?(?P<CASH>[.0-9]+) in chips\)', re.MULTILINE)
|
||||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
# self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
|
||||
|
||||
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True):
|
||||
"""\
|
||||
in_path (default '-' = sys.stdin)
|
||||
out_path (default '-' = sys.stdout)
|
||||
follow : whether to tail -f the input"""
|
||||
HandHistoryConverter.__init__(self, in_path, out_path, sitename="UltimateBet", follow=follow)
|
||||
logging.info("Initialising UltimateBetconverter class")
|
||||
self.filetype = "text"
|
||||
self.codepage = "cp1252"
|
||||
if autostart:
|
||||
self.start()
|
||||
|
||||
|
||||
def compilePlayerRegexs(self, hand):
|
||||
players = set([player[1] for player in hand.players])
|
||||
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
|
||||
# we need to recompile the player regexs.
|
||||
self.compiledPlayers = players
|
||||
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
|
||||
logging.debug("player_re: " + player_re)
|
||||
self.re_PostSB = re.compile(r"^%s: posts small blind \$?(?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_PostBB = re.compile(r"^%s: posts big blind \$?(?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_Antes = re.compile(r"^%s - Ante \$?(?P<ANTE>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_BringIn = re.compile(r"^%s - Bring-In \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_PostBoth = re.compile(r"^%s: posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_HeroCards = re.compile(r"^Dealt to %s - Pocket (\[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE)
|
||||
self.re_Action = re.compile(r"^%s -(?P<ATYPE> Bets| Checks| raises| Calls| Folds)( \$(?P<BET>[.\d]+))?( to \$(?P<BETTO>[.\d]+))?( (?P<NODISCARDED>\d) cards?( \[(?P<DISCARDED>.+?)\])?)?" % player_re, re.MULTILINE)
|
||||
self.re_ShowdownAction = re.compile(r"^%s - Shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
|
||||
self.re_CollectPot = re.compile(r"Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*|)" % player_re, re.MULTILINE)
|
||||
self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE)
|
||||
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s \(.*\) showed \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
|
||||
|
||||
|
||||
def readSupportedGames(self):
|
||||
return [ ["ring", "stud", "fl"]
|
||||
]
|
||||
|
||||
def determineGameType(self, handText):
|
||||
info = {'type':'ring'}
|
||||
|
||||
m = self.re_GameInfo.search(handText)
|
||||
if not m:
|
||||
return None
|
||||
|
||||
mg = m.groupdict()
|
||||
|
||||
# translations from captured groups to our info strings
|
||||
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' }
|
||||
games = { # base, category
|
||||
"Hold'em" : ('hold','holdem'),
|
||||
'Omaha' : ('hold','omahahi'),
|
||||
'Omaha Hi/Lo' : ('hold','omahahilo'),
|
||||
'Razz' : ('stud','razz'),
|
||||
'7 Card Stud' : ('stud','studhi'),
|
||||
'Badugi' : ('draw','badugi')
|
||||
}
|
||||
currencies = { u'€':'EUR', '$':'USD', '':'T$' }
|
||||
if 'LIMIT' in mg:
|
||||
info['limitType'] = limits[mg['LIMIT']]
|
||||
if 'GAME' in mg:
|
||||
(info['base'], info['category']) = games[mg['GAME']]
|
||||
if 'SB' in mg:
|
||||
info['sb'] = mg['SB']
|
||||
if 'BB' in mg:
|
||||
info['bb'] = mg['BB']
|
||||
if 'CURRENCY' in mg:
|
||||
info['currency'] = currencies[mg['CURRENCY']]
|
||||
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def readHandInfo(self, hand):
|
||||
info = {}
|
||||
m = self.re_HandInfo.search(hand.handText,re.DOTALL)
|
||||
if m:
|
||||
info.update(m.groupdict())
|
||||
# TODO: Be less lazy and parse maxseats from the HandInfo regex
|
||||
if m.group('TABLEATTRIBUTES'):
|
||||
m2 = re.search("\s*(\d+)-max", m.group('TABLEATTRIBUTES'))
|
||||
hand.maxseats = int(m2.group(1))
|
||||
m = self.re_GameInfo.search(hand.handText)
|
||||
if m: info.update(m.groupdict())
|
||||
m = self.re_Button.search(hand.handText)
|
||||
if m: info.update(m.groupdict())
|
||||
# TODO : I rather like the idea of just having this dict as hand.info
|
||||
logging.debug("readHandInfo: %s" % info)
|
||||
for key in info:
|
||||
if key == 'DATETIME':
|
||||
#2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET]
|
||||
#2008/08/17 - 01:14:43 (ET)
|
||||
#2008/09/07 06:23:14 ET
|
||||
m2 = re.search("(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)", info[key])
|
||||
datetime = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'),m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S'))
|
||||
hand.starttime = time.strptime(datetime, "%Y/%m/%d %H:%M:%S")
|
||||
if key == 'HID':
|
||||
hand.handid = info[key]
|
||||
if key == 'TABLE':
|
||||
hand.tablename = info[key]
|
||||
if key == 'BUTTON':
|
||||
hand.buttonpos = info[key]
|
||||
|
||||
def readButton(self, hand):
|
||||
m = self.re_Button.search(hand.handText)
|
||||
if m:
|
||||
hand.buttonpos = int(m.group('BUTTON'))
|
||||
else:
|
||||
logging.info('readButton: not found')
|
||||
|
||||
def readPlayerStacks(self, hand):
|
||||
logging.debug("readPlayerStacks")
|
||||
m = self.re_PlayerInfo.finditer(hand.handText)
|
||||
players = []
|
||||
for a in m:
|
||||
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
|
||||
|
||||
def markStreets(self, hand):
|
||||
# PREFLOP = ** Dealing down cards **
|
||||
# This re fails if, say, river is missing; then we don't get the ** that starts the river.
|
||||
if hand.gametype['base'] in ("hold"):
|
||||
m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*)|.+)"
|
||||
r"(\*\*\* FLOP \*\*\*(?P<FLOP> \[\S\S \S\S \S\S\].+(?=\*\*\* TURN \*\*\*)|.+))?"
|
||||
r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* RIVER \*\*\*)|.+))?"
|
||||
r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?", hand.handText,re.DOTALL)
|
||||
elif hand.gametype['base'] in ("stud"):
|
||||
m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3rd STREET \*\*\*)|.+)"
|
||||
r"(\*\*\* 3rd STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4th STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 4th STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5th STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 5th STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6th STREET \*\*\*)|.+))?"
|
||||
r"(\*\*\* 6th STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* RIVER \*\*\*)|.+))?"
|
||||
r"(\*\*\* RIVER \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL)
|
||||
elif hand.gametype['base'] in ("draw"):
|
||||
m = re.search(r"(?P<PREDEAL>.+(?=\*\*\* DEALING HANDS \*\*\*)|.+)"
|
||||
r"(\*\*\* DEALING HANDS \*\*\*(?P<DEAL>.+(?=\*\*\* FIRST DRAW \*\*\*)|.+))?"
|
||||
r"(\*\*\* FIRST DRAW \*\*\*(?P<DRAWONE>.+(?=\*\*\* SECOND DRAW \*\*\*)|.+))?"
|
||||
r"(\*\*\* SECOND DRAW \*\*\*(?P<DRAWTWO>.+(?=\*\*\* THIRD DRAW \*\*\*)|.+))?"
|
||||
r"(\*\*\* THIRD DRAW \*\*\*(?P<DRAWTHREE>.+))?", hand.handText,re.DOTALL)
|
||||
hand.addStreets(m)
|
||||
|
||||
def readCommunityCards(self, hand, street): # street has been matched by markStreets, so exists in this hand
|
||||
if street in ('FLOP','TURN','RIVER'): # a list of streets which get dealt community cards (i.e. all but PREFLOP)
|
||||
#print "DEBUG readCommunityCards:", street, hand.streets.group(street)
|
||||
m = self.re_Board.search(hand.streets[street])
|
||||
hand.setCommunityCards(street, m.group('CARDS').split(' '))
|
||||
|
||||
def readAntes(self, hand):
|
||||
logging.debug("reading antes")
|
||||
m = self.re_Antes.finditer(hand.handText)
|
||||
for player in m:
|
||||
#~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE')))
|
||||
hand.addAnte(player.group('PNAME'), player.group('ANTE'))
|
||||
|
||||
def readBringIn(self, hand):
|
||||
m = self.re_BringIn.search(hand.handText,re.DOTALL)
|
||||
if m:
|
||||
#~ logging.debug("readBringIn: %s for %s" %(m.group('PNAME'), m.group('BRINGIN')))
|
||||
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
|
||||
|
||||
def readBlinds(self, hand):
|
||||
try:
|
||||
m = self.re_PostSB.search(hand.handText)
|
||||
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
|
||||
except: # no small blind
|
||||
hand.addBlind(None, None, None)
|
||||
for a in self.re_PostBB.finditer(hand.handText):
|
||||
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
|
||||
for a in self.re_PostBoth.finditer(hand.handText):
|
||||
hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB'))
|
||||
|
||||
def readHeroCards(self, hand):
|
||||
m = self.re_HeroCards.search(hand.handText)
|
||||
if(m == None):
|
||||
#Not involved in hand
|
||||
hand.involved = False
|
||||
else:
|
||||
hand.hero = m.group('PNAME')
|
||||
# "2c, qh" -> set(["2c","qc"])
|
||||
# Also works with Omaha hands.
|
||||
cards = m.group('NEWCARDS')
|
||||
cards = set(cards.split(' '))
|
||||
hand.addHoleCards(cards, m.group('PNAME'))
|
||||
|
||||
def readDrawCards(self, hand, street):
|
||||
logging.debug("readDrawCards")
|
||||
m = self.re_HeroCards.finditer(hand.streets[street])
|
||||
if m == None:
|
||||
hand.involved = False
|
||||
else:
|
||||
for player in m:
|
||||
hand.hero = player.group('PNAME') # Only really need to do this once
|
||||
newcards = player.group('NEWCARDS')
|
||||
oldcards = player.group('OLDCARDS')
|
||||
if newcards == None:
|
||||
newcards = set()
|
||||
else:
|
||||
newcards = set(newcards.split(' '))
|
||||
if oldcards == None:
|
||||
oldcards = set()
|
||||
else:
|
||||
oldcards = set(oldcards.split(' '))
|
||||
hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street)
|
||||
|
||||
|
||||
def readStudPlayerCards(self, hand, street):
|
||||
# See comments of reference implementation in FullTiltToFpdb.py
|
||||
logging.debug("readStudPlayerCards")
|
||||
m = self.re_HeroCards.finditer(hand.streets[street])
|
||||
for player in m:
|
||||
#~ logging.debug(player.groupdict())
|
||||
(pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS'))
|
||||
if oldcards:
|
||||
oldcards = [c.strip() for c in oldcards.split(' ')]
|
||||
if newcards:
|
||||
newcards = [c.strip() for c in newcards.split(' ')]
|
||||
if street=='ANTES':
|
||||
return
|
||||
elif street=='THIRD':
|
||||
# we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS'
|
||||
# hero: [xx][o]
|
||||
# others: [o]
|
||||
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards)
|
||||
elif street in ('FOURTH', 'FIFTH', 'SIXTH'):
|
||||
# 4th:
|
||||
# hero: [xxo] [o]
|
||||
# others: [o] [o]
|
||||
# 5th:
|
||||
# hero: [xxoo] [o]
|
||||
# others: [oo] [o]
|
||||
# 6th:
|
||||
# hero: [xxooo] [o]
|
||||
# others: [ooo] [o]
|
||||
hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards)
|
||||
# we may additionally want to check the earlier streets tally with what we have but lets trust it for now.
|
||||
elif street=='SEVENTH' and newcards:
|
||||
# hero: [xxoooo] [x]
|
||||
# others: not reported.
|
||||
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards)
|
||||
|
||||
def readAction(self, hand, street):
|
||||
m = self.re_Action.finditer(hand.streets[street])
|
||||
for action in m:
|
||||
if action.group('ATYPE') == ' Raises':
|
||||
hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') )
|
||||
elif action.group('ATYPE') == ' Calls':
|
||||
hand.addCall( street, action.group('PNAME'), action.group('BET') )
|
||||
elif action.group('ATYPE') == ' Bets':
|
||||
hand.addBet( street, action.group('PNAME'), action.group('BET') )
|
||||
elif action.group('ATYPE') == ' Folds':
|
||||
hand.addFold( street, action.group('PNAME'))
|
||||
elif action.group('ATYPE') == ' Checks':
|
||||
hand.addCheck( street, action.group('PNAME'))
|
||||
#elif action.group('ATYPE') == ' discards':
|
||||
# hand.addDiscard(street, action.group('PNAME'), action.group('NODISCARDED'), action.group('DISCARDED'))
|
||||
#elif action.group('ATYPE') == ' stands pat':
|
||||
# hand.addStandsPat( street, action.group('PNAME'))
|
||||
else:
|
||||
print "DEBUG: unimplemented readAction: '%s' '%s'" %(action.group('PNAME'),action.group('ATYPE'),)
|
||||
|
||||
|
||||
def readShowdownActions(self, hand):
|
||||
for shows in self.re_ShowdownAction.finditer(hand.handText):
|
||||
cards = shows.group('CARDS')
|
||||
cards = set(cards.split(' '))
|
||||
hand.addShownCards(cards, shows.group('PNAME'))
|
||||
|
||||
def readCollectPot(self,hand):
|
||||
for m in self.re_CollectPot.finditer(hand.handText):
|
||||
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
|
||||
|
||||
def readShownCards(self,hand):
|
||||
for m in self.re_ShownCards.finditer(hand.handText):
|
||||
if m.group('CARDS') is not None:
|
||||
cards = m.group('CARDS')
|
||||
cards = set(cards.split(' '))
|
||||
hand.addShownCards(cards=cards, player=m.group('PNAME'))
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = OptionParser()
|
||||
parser.add_option("-i", "--input", dest="ipath", help="parse input hand history", default="regression-test-files/pokerstars/HH20090226 Natalie V - $0.10-$0.20 - HORSE.txt")
|
||||
parser.add_option("-o", "--output", dest="opath", help="output translation to", default="-")
|
||||
parser.add_option("-f", "--follow", dest="follow", help="follow (tail -f) the input", action="store_true", default=False)
|
||||
parser.add_option("-q", "--quiet",
|
||||
action="store_const", const=logging.CRITICAL, dest="verbosity", default=logging.INFO)
|
||||
parser.add_option("-v", "--verbose",
|
||||
action="store_const", const=logging.INFO, dest="verbosity")
|
||||
parser.add_option("--vv",
|
||||
action="store_const", const=logging.DEBUG, dest="verbosity")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
LOG_FILENAME = './logging.out'
|
||||
logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity)
|
||||
|
||||
e = UltimateBet(in_path = options.ipath, out_path = options.opath, follow = options.follow)
|
||||
+2
-2
@@ -382,7 +382,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
||||
self.window.connect("destroy", self.destroy)
|
||||
self.window.set_title("Free Poker DB - v%s or higher" % (VERSION, ))
|
||||
self.window.set_border_width(1)
|
||||
self.window.set_size_request(1020,400)
|
||||
self.window.set_default_size(900,720)
|
||||
self.window.set_resizable(True)
|
||||
|
||||
self.menu_items = (
|
||||
@@ -450,7 +450,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
||||
|
||||
self.tab_main_help(None, None)
|
||||
|
||||
self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host)
|
||||
self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host))
|
||||
self.main_vbox.pack_end(self.status_bar, False, True, 0)
|
||||
self.status_bar.show()
|
||||
|
||||
|
||||
+52
-76
@@ -58,13 +58,14 @@ class Importer:
|
||||
self.cursor = None
|
||||
self.filelist = {}
|
||||
self.dirlist = {}
|
||||
self.siteIds = {}
|
||||
self.addToDirList = {}
|
||||
self.removeFromFileList = {} # to remove deleted files
|
||||
self.monitor = False
|
||||
self.updated = {} #Time last import was run {file:mtime}
|
||||
self.updated = {} #Time last import was run {file:mtime}
|
||||
self.lines = None
|
||||
self.faobs = None #File as one big string
|
||||
self.pos_in_file = {} # dict to remember how far we have read in the file
|
||||
self.faobs = None # File as one big string
|
||||
self.pos_in_file = {} # dict to remember how far we have read in the file
|
||||
#Set defaults
|
||||
self.callHud = self.config.get_import_parameters().get("callFpdbHud")
|
||||
|
||||
@@ -110,20 +111,32 @@ class Importer:
|
||||
def addImportFile(self, filename, site = "default", filter = "passthrough"):
|
||||
#TODO: test it is a valid file -> put that in config!!
|
||||
self.filelist[filename] = [site] + [filter]
|
||||
if site not in self.siteIds:
|
||||
# Get id from Sites table in DB
|
||||
self.fdb.cursor.execute(self.fdb.sql.query['getSiteId'], (site,))
|
||||
result = self.fdb.cursor.fetchall()
|
||||
if len(result) == 1:
|
||||
self.siteIds[site] = result[0][0]
|
||||
else:
|
||||
if len(result) == 0:
|
||||
print "[ERROR] Database ID for %s not found" % site
|
||||
else:
|
||||
print "[ERROR] More than 1 Database ID found for %s - Multiple currencies not implemented yet" % site
|
||||
|
||||
|
||||
# Called from GuiBulkImport to add a file or directory.
|
||||
def addBulkImportImportFileOrDir(self, inputPath,filter = "passthrough"):
|
||||
def addBulkImportImportFileOrDir(self, inputPath, site = "PokerStars"):
|
||||
"""Add a file or directory for bulk import"""
|
||||
|
||||
filter = self.config.hhcs[site].converter
|
||||
# Bulk import never monitors
|
||||
# if directory, add all files in it. Otherwise add single file.
|
||||
# TODO: only add sane files?
|
||||
if os.path.isdir(inputPath):
|
||||
for subdir in os.walk(inputPath):
|
||||
for file in subdir[2]:
|
||||
self.addImportFile(os.path.join(inputPath, subdir[0], file), site="default", filter=filter)
|
||||
self.addImportFile(os.path.join(inputPath, subdir[0], file), site=site, filter=filter)
|
||||
else:
|
||||
self.addImportFile(inputPath, site="default", filter=filter)
|
||||
self.addImportFile(inputPath, site=site, filter=filter)
|
||||
#Add a directory of files to filelist
|
||||
#Only one import directory per site supported.
|
||||
#dirlist is a hash of lists:
|
||||
@@ -194,7 +207,7 @@ class Importer:
|
||||
self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1])
|
||||
|
||||
for file in self.filelist:
|
||||
if os.path.exists(file):
|
||||
if os.path.exists(file):
|
||||
stat_info = os.stat(file)
|
||||
try:
|
||||
lastupdate = self.updated[file]
|
||||
@@ -214,8 +227,8 @@ class Importer:
|
||||
#self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
|
||||
else:
|
||||
removeFromFileList[file] = True
|
||||
self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList)
|
||||
|
||||
self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList)
|
||||
|
||||
for file in self.removeFromFileList:
|
||||
if file in self.filelist:
|
||||
del self.filelist[file]
|
||||
@@ -295,10 +308,9 @@ class Importer:
|
||||
print "TODO: implement importing tournament summaries"
|
||||
#self.faobs = readfile(inputFile)
|
||||
#self.parseTourneyHistory()
|
||||
return 0
|
||||
|
||||
site = fpdb_simple.recogniseSite(firstline)
|
||||
category = fpdb_simple.recogniseCategory(firstline)
|
||||
return (0,0,0,1,0)
|
||||
|
||||
category=fpdb_simple.recogniseCategory(firstline)
|
||||
|
||||
startpos = 0
|
||||
stored = 0 #counter
|
||||
@@ -306,61 +318,30 @@ class Importer:
|
||||
partial = 0 #counter
|
||||
errors = 0 #counter
|
||||
|
||||
for i in xrange (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method
|
||||
if len(self.lines[i]) < 2:
|
||||
endpos = i
|
||||
hand = self.lines[startpos:endpos]
|
||||
for i in xrange (len(self.lines)):
|
||||
if (len(self.lines[i])<2): #Wierd way to detect for '\r\n' or '\n'
|
||||
endpos=i
|
||||
hand=self.lines[startpos:endpos]
|
||||
|
||||
if len(hand[0]) < 2:
|
||||
hand = hand[1:]
|
||||
|
||||
cancelled=False
|
||||
damaged=False
|
||||
if (site=="ftp"):
|
||||
for i in range (len(hand)):
|
||||
if hand[i].endswith(" has been canceled"): #this is their typo. this is a typo, right?
|
||||
cancelled = True
|
||||
if (len(hand[0])<2):
|
||||
hand=hand[1:]
|
||||
|
||||
#FTP generates lines looking like:
|
||||
#Seat 1: IOS Seat 2: kashman59 (big blind) showed [8c 9d] and won ($3.25) with a pair of Eights
|
||||
#ie. Seat X multiple times on the same line in the summary section, when a new player sits down in the
|
||||
#middle of the hand.
|
||||
#TODO: Deal with this properly, either fix the file or make the parsing code work with this line.
|
||||
if "Seat" in hand[i]:
|
||||
mo = re.search(" Seat [0-9]+: ", hand[i])
|
||||
if mo:
|
||||
print "mo=", mo, "\nmo.start=", mo.start(),"\nhand[i]=",hand[i]
|
||||
hand.insert(i+1, hand[i][mo.start()+1:])
|
||||
hand[i] = hand[i][0:mo.start()]
|
||||
|
||||
if len(hand) < 3:
|
||||
|
||||
if (len(hand)<3):
|
||||
pass
|
||||
#todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work.
|
||||
elif hand[0].endswith(" (partial)"): #partial hand - do nothing
|
||||
partial += 1
|
||||
elif "Seat" not in hand[1] and "Seat" not in hand[2] and "Seat" not in hand[3]:
|
||||
partial += 1
|
||||
elif cancelled or damaged:
|
||||
partial += 1
|
||||
if damaged:
|
||||
print """
|
||||
DEBUG: Partial hand triggered by a line containing 'Seat X:' twice. This is a
|
||||
bug in the FTP software when a player sits down in the middle of a hand.
|
||||
Adding a newline after the player name will fix the issue
|
||||
"""
|
||||
print "File: %s" %(file)
|
||||
print "Line: %s" %(startpos)
|
||||
else: #normal processing
|
||||
isTourney = fpdb_simple.isTourney(hand[0])
|
||||
#TODO: This is ugly - we didn't actually find the start of the
|
||||
# hand with the outer loop so we test again...
|
||||
else:
|
||||
isTourney=fpdb_simple.isTourney(hand[0])
|
||||
if not isTourney:
|
||||
hand = fpdb_simple.filterAnteBlindFold(site,hand)
|
||||
hand = fpdb_simple.filterAnteBlindFold(hand)
|
||||
self.hand=hand
|
||||
|
||||
|
||||
try:
|
||||
handsId = fpdb_parse_logic.mainParser(self.settings['db-backend'], self.fdb.db
|
||||
,self.fdb.cursor, site, category, hand, self.config)
|
||||
,self.fdb.cursor, self.siteIds[site], category, hand, self.config)
|
||||
self.fdb.db.commit()
|
||||
|
||||
|
||||
stored += 1
|
||||
if self.callHud:
|
||||
#print "call to HUD here. handsId:",handsId
|
||||
@@ -368,10 +349,11 @@ class Importer:
|
||||
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
|
||||
except fpdb_simple.DuplicateError:
|
||||
duplicates += 1
|
||||
self.fdb.db.rollback()
|
||||
except (ValueError), fe:
|
||||
errors += 1
|
||||
self.printEmailErrorMessage(errors, file, hand)
|
||||
|
||||
|
||||
if (self.settings['failOnError']):
|
||||
self.fdb.db.commit() #dont remove this, in case hand processing was cancelled.
|
||||
raise
|
||||
@@ -381,26 +363,25 @@ class Importer:
|
||||
errors += 1
|
||||
self.printEmailErrorMessage(errors, file, hand)
|
||||
|
||||
#fe.printStackTrace() #todo: get stacktrace
|
||||
self.fdb.db.rollback()
|
||||
|
||||
|
||||
if self.settings['failOnError']:
|
||||
self.fdb.db.commit() #dont remove this, in case hand processing was cancelled.
|
||||
raise
|
||||
|
||||
|
||||
if self.settings['minPrint']:
|
||||
if not ((stored+duplicates+partial+errors) % self.settings['minPrint']):
|
||||
print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors
|
||||
if not ((stored+duplicates+errors) % self.settings['minPrint']):
|
||||
print "stored:", stored, "duplicates:", duplicates, "errors:", errors
|
||||
|
||||
if self.settings['handCount']:
|
||||
if ((stored+duplicates+partial+errors) >= self.settings['handCount']):
|
||||
if ((stored+duplicates+errors) >= self.settings['handCount']):
|
||||
if not self.settings['quiet']:
|
||||
print "quitting due to reaching the amount of hands to be imported"
|
||||
print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime)
|
||||
print "Total stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", (time() - starttime)
|
||||
sys.exit(0)
|
||||
startpos = endpos
|
||||
ttime = time() - starttime
|
||||
print "\rTotal stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", ttime
|
||||
print "\rTotal stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", ttime
|
||||
|
||||
if not stored:
|
||||
if duplicates:
|
||||
@@ -411,16 +392,11 @@ class Importer:
|
||||
else:
|
||||
print "failed to read a single hand from file:", inputFile
|
||||
handsId=0
|
||||
#todo: this will cause return of an unstored hand number if the last hand was error or partial
|
||||
#todo: this will cause return of an unstored hand number if the last hand was error
|
||||
self.fdb.db.commit()
|
||||
self.handsId=handsId
|
||||
return (stored, duplicates, partial, errors, ttime)
|
||||
|
||||
def parseTourneyHistory(self):
|
||||
print "Tourney history parser stub"
|
||||
#Find tournament boundaries.
|
||||
#print self.foabs
|
||||
|
||||
def printEmailErrorMessage(self, errors, filename, line):
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it."
|
||||
|
||||
+19
-26
@@ -21,11 +21,11 @@ import fpdb_simple
|
||||
import fpdb_save_to_db
|
||||
|
||||
#parses a holdem hand
|
||||
def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
def mainParser(backend, db, cursor, siteID, category, hand, config):
|
||||
category = fpdb_simple.recogniseCategory(hand[0])
|
||||
|
||||
|
||||
base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud"
|
||||
|
||||
|
||||
#part 0: create the empty arrays
|
||||
lineTypes = [] #char, valid values: header, name, cards, action, win, rake, ignore
|
||||
lineStreets = [] #char, valid values: (predeal, preflop, flop, turn, river)
|
||||
@@ -34,9 +34,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
|
||||
#part 1: read hand no and check for duplicate
|
||||
siteHandNo = fpdb_simple.parseSiteHandNo(hand[0])
|
||||
handStartTime = fpdb_simple.parseHandStartTime(hand[0], site)
|
||||
siteID = fpdb_simple.recogniseSiteID(cursor, site)
|
||||
#print "parse logic, siteID:",siteID,"site:",site
|
||||
handStartTime = fpdb_simple.parseHandStartTime(hand[0])
|
||||
|
||||
isTourney = fpdb_simple.isTourney(hand[0])
|
||||
smallBlindLine = 0
|
||||
@@ -46,11 +44,9 @@ def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
smallBlindLine = i
|
||||
break
|
||||
#print "small blind line:",smallBlindLine
|
||||
|
||||
|
||||
gametypeID = fpdb_simple.recogniseGametypeID(backend, db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney)
|
||||
if isTourney:
|
||||
if site != "ps":
|
||||
raise fpdb_simple.FpdbError("tourneys are only supported on PS right now")
|
||||
siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0])
|
||||
buyin = fpdb_simple.parseBuyin(hand[0])
|
||||
fee = fpdb_simple.parseFee(hand[0])
|
||||
@@ -61,10 +57,10 @@ def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0])
|
||||
|
||||
tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon)
|
||||
|
||||
|
||||
fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo)
|
||||
|
||||
hand = fpdb_simple.filterCrap(site, hand, isTourney)
|
||||
hand = fpdb_simple.filterCrap(hand, isTourney)
|
||||
|
||||
#part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street
|
||||
fpdb_simple.classifyLines(hand, category, lineTypes, lineStreets)
|
||||
@@ -74,10 +70,10 @@ def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
for i, line in enumerate(hand):
|
||||
if lineTypes[i] == "name":
|
||||
seatLines.append(line)
|
||||
|
||||
|
||||
names = fpdb_simple.parseNames(seatLines)
|
||||
playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID)
|
||||
tmp = fpdb_simple.parseCashesAndSeatNos(seatLines, site)
|
||||
tmp = fpdb_simple.parseCashesAndSeatNos(seatLines)
|
||||
startCashes = tmp['startCashes']
|
||||
seatNos = tmp['seatNos']
|
||||
|
||||
@@ -90,30 +86,27 @@ def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
#part 4: take appropriate action for each line based on linetype
|
||||
for i, line in enumerate(hand):
|
||||
if lineTypes[i] == "cards":
|
||||
fpdb_simple.parseCardLine(site, category, lineStreets[i], line, names, cardValues, cardSuits, boardValues, boardSuits)
|
||||
fpdb_simple.parseCardLine(category, lineStreets[i], line, names, cardValues, cardSuits, boardValues, boardSuits)
|
||||
#if category=="studhilo":
|
||||
# print "hand[i]:", hand[i]
|
||||
# print "cardValues:", cardValues
|
||||
# print "cardSuits:", cardSuits
|
||||
elif lineTypes[i] == "action":
|
||||
fpdb_simple.parseActionLine(site, base, isTourney, line, lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
|
||||
fpdb_simple.parseActionLine(base, isTourney, line, lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo)
|
||||
elif lineTypes[i] == "win":
|
||||
fpdb_simple.parseWinLine(line, site, names, winnings, isTourney)
|
||||
fpdb_simple.parseWinLine(line, names, winnings, isTourney)
|
||||
elif lineTypes[i] == "rake":
|
||||
totalRake = 0 if isTourney else fpdb_simple.parseRake(line)
|
||||
fpdb_simple.splitRake(winnings, rakes, totalRake)
|
||||
elif lineTypes[i]=="header" or lineTypes[i]=="rake" or lineTypes[i]=="name" or lineTypes[i]=="ignore":
|
||||
pass
|
||||
elif lineTypes[i]=="ante":
|
||||
fpdb_simple.parseAnteLine(line, site, isTourney, names, antes)
|
||||
fpdb_simple.parseAnteLine(line, isTourney, names, antes)
|
||||
elif lineTypes[i]=="table":
|
||||
tableResult=fpdb_simple.parseTableLine(site, base, line)
|
||||
tableResult=fpdb_simple.parseTableLine(base, line)
|
||||
else:
|
||||
raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i])
|
||||
|
||||
if site == "ftp":
|
||||
tableResult = fpdb_simple.parseTableLine(site, base, hand[0])
|
||||
|
||||
|
||||
maxSeats = tableResult['maxSeats']
|
||||
tableName = tableResult['tableName']
|
||||
#print "before part5, antes:", antes
|
||||
@@ -128,7 +121,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
|
||||
cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, ))
|
||||
limit_type = cursor.fetchone()[0]
|
||||
fpdb_simple.convert3B4B(site, category, limit_type, actionTypes, actionAmounts)
|
||||
fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts)
|
||||
|
||||
totalWinnings = sum(winnings)
|
||||
|
||||
@@ -141,7 +134,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes
|
||||
, allIns, actionTypeByNo, winnings, totalWinnings, None
|
||||
, actionTypes, actionAmounts, antes)
|
||||
|
||||
|
||||
if isTourney:
|
||||
ranks = map(lambda x: 0, names) # create an array of 0's equal to the length of names
|
||||
payin_amounts = fpdb_simple.calcPayin(len(names), buyin, fee)
|
||||
@@ -165,7 +158,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
, allIns, actionAmounts, actionNos, hudImportData, maxSeats
|
||||
, tableName, seatNos)
|
||||
else:
|
||||
raise fpdb_simple.FpdbError("unrecognised category") # it's impossible to get here, but w/e
|
||||
raise fpdb_simple.FpdbError("unrecognised category")
|
||||
else:
|
||||
if base == "hold":
|
||||
result = fpdb_save_to_db.ring_holdem_omaha(
|
||||
@@ -183,7 +176,7 @@ def mainParser(backend, db, cursor, site, category, hand, config):
|
||||
, actionAmounts, actionNos, hudImportData, maxSeats, tableName
|
||||
, seatNos)
|
||||
else:
|
||||
raise fpdb_simple.FpdbError ("unrecognised category") # also impossible to get here
|
||||
raise fpdb_simple.FpdbError ("unrecognised category")
|
||||
db.commit()
|
||||
return result
|
||||
#end def mainParser
|
||||
|
||||
@@ -32,8 +32,7 @@ saveActions = True # set this to False to avoid storing action data
|
||||
# Pros: speeds up imports
|
||||
# Cons: no action data is saved, so you need to keep the hand histories
|
||||
# variance not available on stats page
|
||||
# no graphs
|
||||
|
||||
# : No graphs
|
||||
#stores a stud/razz hand into the database
|
||||
def ring_stud(config, backend, db, cursor, base, category, site_hand_no, gametype_id, hand_start_time
|
||||
,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes
|
||||
|
||||
+61
-163
@@ -187,10 +187,10 @@ def prepareBulkImport(fdb):
|
||||
# mod to use tab_col for index name?
|
||||
try:
|
||||
fdb.cursor.execute( "drop index %s_%s_idx" % (idx['tab'],idx['col']) )
|
||||
print "drop index %s_%s_idx" % (idx['tab'],idx['col'])
|
||||
print "drop index %s_%s_idx" % (idx['tab'],idx['col'])
|
||||
#print "dropped pg index ", idx['tab'], idx['col']
|
||||
except:
|
||||
print "! failed drop index %s_%s_idx" % (idx['tab'],idx['col'])
|
||||
print "! failed drop index %s_%s_idx" % (idx['tab'],idx['col'])
|
||||
else:
|
||||
print "Only MySQL and Postgres supported so far"
|
||||
return -1
|
||||
@@ -392,10 +392,6 @@ def checkPositions(positions):
|
||||
""" verify positions are valid """
|
||||
if any(not (p == "B" or p == "S" or (p >= 0 and p <= 9)) for p in positions):
|
||||
raise FpdbError("invalid position '"+p+"' found in checkPositions")
|
||||
# for p in positions:
|
||||
# if not (p == "B" or p == "S" or (p >= 0 and p <= 9)):
|
||||
# raise FpdbError("invalid position '" + p + "' found in checkPositions")
|
||||
|
||||
### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB
|
||||
### eric - position 8 could be valid - if only one blind is posted, but there's still 10 people, ie a sitout is present, and the small is dead...
|
||||
|
||||
@@ -446,7 +442,7 @@ def classifyLines(hand, category, lineTypes, lineStreets):
|
||||
currentStreet=3
|
||||
elif line.startswith("*** 7") or line == "*** RIVER ***":
|
||||
lineTypes.append("ignore")
|
||||
currentStreet=4
|
||||
currentStreet=4
|
||||
elif isWinLine(line):
|
||||
lineTypes.append("win")
|
||||
elif line.startswith("Total pot ") and "Rake" in line:
|
||||
@@ -462,7 +458,7 @@ def classifyLines(hand, category, lineTypes, lineStreets):
|
||||
lineStreets.append(currentStreet)
|
||||
#end def classifyLines
|
||||
|
||||
def convert3B4B(site, category, limit_type, actionTypes, actionAmounts):
|
||||
def convert3B4B(category, limit_type, actionTypes, actionAmounts):
|
||||
"""calculates the actual bet amounts in the given amount array and changes it accordingly."""
|
||||
for i in xrange(len(actionTypes)):
|
||||
for j in xrange(len(actionTypes[i])):
|
||||
@@ -572,7 +568,7 @@ def fillCardArrays(player_count, base, category, card_values, card_suits):
|
||||
|
||||
#filters out a player that folded before paying ante or blinds. This should be called
|
||||
#before calling the actual hand parser. manipulates hand, no return.
|
||||
def filterAnteBlindFold(site,hand):
|
||||
def filterAnteBlindFold(hand):
|
||||
#todo: this'll only get rid of one ante folder, not multiple ones
|
||||
#todo: in tourneys this should not be removed but
|
||||
#print "start of filterAnteBlindFold"
|
||||
@@ -610,7 +606,7 @@ def stripEOLspaces(str):
|
||||
return str.rstrip()
|
||||
|
||||
#removes useless lines as well as trailing spaces
|
||||
def filterCrap(site, hand, isTourney):
|
||||
def filterCrap(hand, isTourney):
|
||||
#remove two trailing spaces at end of line
|
||||
hand = [line.rstrip() for line in hand]
|
||||
|
||||
@@ -643,18 +639,8 @@ def filterCrap(site, hand, isTourney):
|
||||
hand[i] = False
|
||||
elif hand[i].endswith("is disconnected"):
|
||||
hand[i] = False
|
||||
elif hand[i].endswith(" is feeling angry"):
|
||||
elif hand[i].find(" is low with [")!=-1:
|
||||
hand[i] = False
|
||||
elif hand[i].endswith(" is feeling confused"):
|
||||
hand[i] = False
|
||||
elif hand[i].endswith(" is feeling happy"):
|
||||
hand[i] = False
|
||||
elif hand[i].endswith(" is feeling normal"):
|
||||
hand[i] = False
|
||||
elif " is low with [" in hand[i]:
|
||||
hand[i] = False
|
||||
#elif (hand[i].find("-max Seat #")!=-1 and hand[i].find(" is the button")!=-1):
|
||||
# toRemove.append(hand[i])
|
||||
elif hand[i].endswith(" mucks"):
|
||||
hand[i] = False
|
||||
elif hand[i].endswith(": mucks hand"):
|
||||
@@ -680,13 +666,9 @@ def filterCrap(site, hand, isTourney):
|
||||
hand[i] = False
|
||||
elif "joins the table at seat " in hand[i]:
|
||||
hand[i] = False
|
||||
elif (hand[i].endswith(" sits down")):
|
||||
hand[i] = False
|
||||
elif (hand[i].endswith("leaves the table")):
|
||||
hand[i] = False
|
||||
elif (hand[i].endswith(" stands up")):
|
||||
hand[i] = False
|
||||
elif "is high with" in hand[i]:
|
||||
elif "is high with " in hand[i]:
|
||||
hand[i] = False
|
||||
elif hand[i].endswith("doesn't show hand"):
|
||||
hand[i] = False
|
||||
@@ -696,11 +678,9 @@ def filterCrap(site, hand, isTourney):
|
||||
hand[i] = False
|
||||
elif hand[i] == "Betting is capped":
|
||||
hand[i] = False
|
||||
#site specific variable position filter
|
||||
elif 'said, "' in hand[i]:
|
||||
hand[i] = False
|
||||
elif site == "ftp" and ":" in hand[i] and "Seat " not in hand[i] and ": Table" not in hand[i]: # FTP chat
|
||||
elif (hand[i].find(" said, \"")!=-1):
|
||||
hand[i] = False
|
||||
|
||||
if isTourney and not hand[i] == False:
|
||||
if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))):
|
||||
hand[i] = False
|
||||
@@ -781,7 +761,7 @@ def isWinLine(line):
|
||||
#end def isWinLine
|
||||
|
||||
#returns the amount of cash/chips put into the put in the given action line
|
||||
def parseActionAmount(line, atype, site, isTourney):
|
||||
def parseActionAmount(line, atype, isTourney):
|
||||
#if (line.endswith(" and is all-in")):
|
||||
# line=line[:-14]
|
||||
#elif (line.endswith(", and is all in")):
|
||||
@@ -795,19 +775,14 @@ def parseActionAmount(line, atype, site, isTourney):
|
||||
if atype == "fold" or atype == "check":
|
||||
amount = 0
|
||||
elif atype == "unbet":
|
||||
if site == "ftp":
|
||||
pos1 = line.find("$") + 1
|
||||
pos2 = line.find(" returned to")
|
||||
amount = float2int(line[pos1:pos2])
|
||||
elif site == "ps":
|
||||
pos1 = line.find("$") + 1
|
||||
if pos1 == 0:
|
||||
pos1 = line.find("(") + 1
|
||||
pos2 = line.find(")")
|
||||
amount = float2int(line[pos1:pos2])
|
||||
elif atype == "bet" and site == "ps" and line.find(": raises $")!=-1 and line.find("to $")!=-1:
|
||||
pos = line.find("to $")+4
|
||||
amount = float2int(line[pos:])
|
||||
pos1 = line.find("$") + 1
|
||||
if pos1 == 0:
|
||||
pos1 = line.find("(") + 1
|
||||
pos2 = line.find(")")
|
||||
amount = float2int(line[pos1:pos2])
|
||||
elif atype == "bet" and line.find(": raises $")!=-1 and line.find("to $")!=-1:
|
||||
pos=line.find("to $")+4
|
||||
amount=float2int(line[pos:])
|
||||
else:
|
||||
if not isTourney:
|
||||
pos = line.rfind("$")+1
|
||||
@@ -828,7 +803,7 @@ def parseActionAmount(line, atype, site, isTourney):
|
||||
#doesnt return anything, simply changes the passed arrays action_types and
|
||||
# action_amounts. For stud this expects numeric streets (3-7), for
|
||||
# holdem/omaha it expects predeal, preflop, flop, turn or river
|
||||
def parseActionLine(site, base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo):
|
||||
def parseActionLine(base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo):
|
||||
if street == "predeal" or street == "preflop":
|
||||
street = 0
|
||||
elif street == "flop":
|
||||
@@ -847,7 +822,7 @@ def parseActionLine(site, base, isTourney, line, street, playerIDs, names, actio
|
||||
(line, allIn) = goesAllInOnThisLine(line)
|
||||
atype = parseActionType(line)
|
||||
playerno = recognisePlayerNo(line, names, atype)
|
||||
amount = parseActionAmount(line, atype, site, isTourney)
|
||||
amount = parseActionAmount(line, atype, isTourney)
|
||||
|
||||
action_types[street][playerno].append(atype)
|
||||
allIns[street][playerno].append(allIn)
|
||||
@@ -899,7 +874,7 @@ def parseActionType(line):
|
||||
#end def parseActionType
|
||||
|
||||
#parses the ante out of the given line and checks which player paid it, updates antes accordingly.
|
||||
def parseAnteLine(line, site, isTourney, names, antes):
|
||||
def parseAnteLine(line, isTourney, names, antes):
|
||||
for i, name in enumerate(names):
|
||||
if line.startswith(name.encode("latin-1")):
|
||||
pos = line.rfind("$") + 1
|
||||
@@ -925,7 +900,7 @@ def parseBuyin(topline):
|
||||
|
||||
#parses a card line and changes the passed arrays accordingly
|
||||
#todo: reorganise this messy method
|
||||
def parseCardLine(site, category, street, line, names, cardValues, cardSuits, boardValues, boardSuits):
|
||||
def parseCardLine(category, street, line, names, cardValues, cardSuits, boardValues, boardSuits):
|
||||
if line.startswith("Dealt to") or " shows [" in line or "mucked [" in line:
|
||||
playerNo = recognisePlayerNo(line, names, "card") #anything but unbet will be ok for that string
|
||||
|
||||
@@ -999,7 +974,7 @@ def parseCardLine(site, category, street, line, names, cardValues, cardSuits, bo
|
||||
raise FpdbError ("unrecognised line:"+line)
|
||||
#end def parseCardLine
|
||||
|
||||
def parseCashesAndSeatNos(lines, site):
|
||||
def parseCashesAndSeatNos(lines):
|
||||
"""parses the startCashes and seatNos of each player out of the given lines and returns them as a dictionary of two arrays"""
|
||||
cashes = []
|
||||
seatNos = []
|
||||
@@ -1010,10 +985,7 @@ def parseCashesAndSeatNos(lines, site):
|
||||
pos1=lines[i].rfind("($")+2
|
||||
if pos1==1: #for tourneys - it's 1 instead of -1 due to adding 2 above
|
||||
pos1=lines[i].rfind("(")+1
|
||||
if (site=="ftp"):
|
||||
pos2=lines[i].rfind(")")
|
||||
elif (site=="ps"):
|
||||
pos2=lines[i].find(" in chips")
|
||||
pos2=lines[i].find(" in chips")
|
||||
cashes.append(float2int(lines[i][pos1:pos2]))
|
||||
return {'startCashes':cashes, 'seatNos':seatNos}
|
||||
#end def parseCashesAndSeatNos
|
||||
@@ -1027,7 +999,7 @@ def parseFee(topline):
|
||||
#end def parsefee
|
||||
|
||||
#returns a datetime object with the starttime indicated in the given topline
|
||||
def parseHandStartTime(topline, site):
|
||||
def parseHandStartTime(topline):
|
||||
#convert x:13:35 to 0x:13:35
|
||||
counter=0
|
||||
while counter < 10:
|
||||
@@ -1038,41 +1010,25 @@ def parseHandStartTime(topline, site):
|
||||
counter += 1
|
||||
|
||||
isUTC=False
|
||||
if site=="ftp":
|
||||
# Full Tilt Sit'n'Go
|
||||
# Full Tilt Poker Game #10311865543: $1 + $0.25 Sit & Go (78057629), Table 1 - 25/50 - No Limit Hold'em - 0:07:45 ET - 2009/01/29
|
||||
# Cash Game:
|
||||
# Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09
|
||||
# Full Tilt Poker Game #9468383505: Table Bike (deep 6) - $0.05/$0.10 - No Limit Hold'em - 5:09:36 ET - 2008/12/13
|
||||
pos = topline.find(" ", len(topline)-26)+1
|
||||
tmp = topline[pos:]
|
||||
|
||||
rexx = '(?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+) ET [\- ]+(?P<YEAR>[0-9]{4})\/(?P<MON>[0-9]{2})\/(?P<DAY>[0-9]{2})'
|
||||
m = re.search(rexx,tmp)
|
||||
result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
|
||||
elif site=="ps":
|
||||
if topline.find("UTC")!=-1:
|
||||
pos1 = topline.find("-")+2
|
||||
pos2 = topline.find("UTC")
|
||||
tmp=topline[pos1:pos2]
|
||||
isUTC=True
|
||||
else:
|
||||
tmp=topline
|
||||
#print "parsehandStartTime, tmp:", tmp
|
||||
pos = tmp.find("-")+2
|
||||
tmp = tmp[pos:]
|
||||
#Need to match either
|
||||
# 2008/09/07 06:23:14 ET or
|
||||
# 2008/08/17 - 01:14:43 (ET) or
|
||||
# 2008/11/12 9:33:31 CET [2008/11/12 3:33:31 ET]
|
||||
rexx = '(?P<YEAR>[0-9]{4})\/(?P<MON>[0-9]{2})\/(?P<DAY>[0-9]{2})[\- ]+(?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+)'
|
||||
m = re.search(rexx,tmp)
|
||||
#print "year:", int(m.group('YEAR')), "month", int(m.group('MON')), "day", int(m.group('DAY')), "hour", int(m.group('HR')), "minute", int(m.group('MIN')), "second", int(m.group('SEC'))
|
||||
result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
|
||||
if topline.find("UTC")!=-1:
|
||||
pos1 = topline.find("-")+2
|
||||
pos2 = topline.find("UTC")
|
||||
tmp=topline[pos1:pos2]
|
||||
isUTC=True
|
||||
else:
|
||||
raise FpdbError("invalid site in parseHandStartTime")
|
||||
tmp=topline
|
||||
#print "parsehandStartTime, tmp:", tmp
|
||||
pos = tmp.find("-")+2
|
||||
tmp = tmp[pos:]
|
||||
#Need to match either
|
||||
# 2008/09/07 06:23:14 ET or
|
||||
# 2008/08/17 - 01:14:43 (ET) or
|
||||
# 2008/11/12 9:33:31 CET [2008/11/12 3:33:31 ET]
|
||||
rexx = '(?P<YEAR>[0-9]{4})\/(?P<MON>[0-9]{2})\/(?P<DAY>[0-9]{2})[\- ]+(?P<HR>[0-9]+):(?P<MIN>[0-9]+):(?P<SEC>[0-9]+)'
|
||||
m = re.search(rexx,tmp)
|
||||
result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC')))
|
||||
|
||||
if (site=="ftp" or site=="ps") and not isUTC: #these use US ET
|
||||
if not isUTC: #these use US ET
|
||||
result+=datetime.timedelta(hours=5)
|
||||
|
||||
return result
|
||||
@@ -1109,7 +1065,7 @@ def parsePositions(hand, names):
|
||||
if bb != -1:
|
||||
bb = recognisePlayerNo(bb, names, "bet")
|
||||
|
||||
# print "sb = ", sb, "bb = ", bb
|
||||
# print "sb = ", sb, "bb = ", bb
|
||||
if bb == sb: # if big and small are same, then don't duplicate the small
|
||||
sbExists = False
|
||||
sb = -1
|
||||
@@ -1138,7 +1094,7 @@ 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"
|
||||
### RHH - Changed to set the null seats before BB to "9"
|
||||
if sbExists:
|
||||
i = sb-1
|
||||
else:
|
||||
@@ -1158,7 +1114,7 @@ def parsePositions(hand, names):
|
||||
print "parsePositions names:",names
|
||||
print "result:",positions
|
||||
raise FpdbError ("failed to read positions")
|
||||
# print str(positions), "\n"
|
||||
# print str(positions), "\n"
|
||||
return positions
|
||||
#end def parsePositions
|
||||
|
||||
@@ -1176,42 +1132,15 @@ def parseSiteHandNo(topline):
|
||||
return topline[pos1:pos2]
|
||||
#end def parseSiteHandNo
|
||||
|
||||
def parseTableLine(site, base, line):
|
||||
def parseTableLine(base, line):
|
||||
"""returns a dictionary with maxSeats and tableName"""
|
||||
if site=="ps":
|
||||
pos1=line.find('\'')+1
|
||||
pos2=line.find('\'', pos1)
|
||||
#print "table:",line[pos1:pos2]
|
||||
pos3=pos2+2
|
||||
pos4=line.find("-max")
|
||||
#print "seats:",line[pos3:pos4]
|
||||
return {'maxSeats':int(line[pos3:pos4]), 'tableName':line[pos1:pos2]}
|
||||
elif site=="ftp":
|
||||
pos1=line.find("Table ")+6
|
||||
pos2=line.find("-")-1
|
||||
if base=="hold":
|
||||
maxSeats=9
|
||||
elif base=="stud":
|
||||
maxSeats=8
|
||||
|
||||
if line.find("6 max")!=-1:
|
||||
maxSeats=6
|
||||
elif line.find("4 max")!=-1:
|
||||
maxSeats=4
|
||||
elif line.find("heads up")!=-1:
|
||||
maxSeats=2
|
||||
|
||||
tableName = line[pos1:pos2]
|
||||
for pattern in [' \(6 max\)', ' \(heads up\)', ' \(deep\)',
|
||||
' \(deep hu\)', ' \(deep 6\)', ' \(2\)',
|
||||
' \(edu\)', ' \(edu, 6 max\)', ' \(6\)',
|
||||
' \(speed\)',
|
||||
' no all-in', ' fast', ',', ' 50BB min', '\s+$']:
|
||||
tableName = re.sub(pattern, '', tableName)
|
||||
tableName = tableName.rstrip()
|
||||
return {'maxSeats':maxSeats, 'tableName':tableName}
|
||||
else:
|
||||
raise FpdbError("invalid site ID")
|
||||
pos1=line.find('\'')+1
|
||||
pos2=line.find('\'', pos1)
|
||||
#print "table:",line[pos1:pos2]
|
||||
pos3=pos2+2
|
||||
pos4=line.find("-max")
|
||||
#print "seats:",line[pos3:pos4]
|
||||
return {'maxSeats':int(line[pos3:pos4]), 'tableName':line[pos1:pos2]}
|
||||
#end def parseTableLine
|
||||
|
||||
#returns the hand no assigned by the poker site
|
||||
@@ -1223,24 +1152,18 @@ def parseTourneyNo(topline):
|
||||
#end def parseTourneyNo
|
||||
|
||||
#parses a win/collect line. manipulates the passed array winnings, no explicit return
|
||||
def parseWinLine(line, site, names, winnings, isTourney):
|
||||
def parseWinLine(line, names, winnings, isTourney):
|
||||
#print "parseWinLine: line:",line
|
||||
for i,n in enumerate(names):
|
||||
n = n.encode("latin-1")
|
||||
if line.startswith(n):
|
||||
if isTourney:
|
||||
pos1 = line.rfind("collected ") + 10
|
||||
if site == "ftp":
|
||||
pos2 = line.find(")", pos1)
|
||||
elif site == "ps":
|
||||
pos2 = line.find(" ", pos1)
|
||||
winnings[i] += int(line[pos1:pos2])
|
||||
pos2 = line.find(" ", pos1)
|
||||
winnings[i]+=int(line[pos1:pos2])
|
||||
else:
|
||||
pos1 = line.rfind("$") + 1
|
||||
if site == "ftp":
|
||||
pos2 = line.find(")", pos1)
|
||||
elif site == "ps":
|
||||
pos2 = line.find(" ", pos1)
|
||||
pos2 = line.find(" ", pos1)
|
||||
winnings[i] += float2int(line[pos1:pos2])
|
||||
#end def parseWinLine
|
||||
|
||||
@@ -1286,10 +1209,7 @@ def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, c
|
||||
pos1=pos2+2
|
||||
if isTourney:
|
||||
pos1-=1
|
||||
if (site_id==1): #ftp
|
||||
pos2=topline.find(" ", pos1)
|
||||
elif (site_id==2): #ps
|
||||
pos2=topline.find(")")
|
||||
pos2=topline.find(")")
|
||||
|
||||
if pos2<=pos1:
|
||||
pos2=topline.find(")", pos1)
|
||||
@@ -1472,28 +1392,6 @@ def recognisePlayerNo(line, names, atype):
|
||||
raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype)
|
||||
#end def recognisePlayerNo
|
||||
|
||||
#returns the site abbreviation for the given site
|
||||
def recogniseSite(line):
|
||||
if (line.startswith("Full Tilt Poker") or line.startswith("FullTiltPoker")):
|
||||
return "ftp"
|
||||
elif (line.startswith("PokerStars")):
|
||||
return "ps"
|
||||
else:
|
||||
raise FpdbError("failed to recognise site, line:"+line)
|
||||
#end def recogniseSite
|
||||
|
||||
#returns the ID of the given site
|
||||
def recogniseSiteID(cursor, site):
|
||||
if (site=="ftp"):
|
||||
return 1
|
||||
#cursor.execute("SELECT id FROM Sites WHERE name = ('Full Tilt Poker')")
|
||||
elif (site=="ps"):
|
||||
return 2
|
||||
#cursor.execute("SELECT id FROM Sites WHERE name = ('PokerStars')")
|
||||
else:
|
||||
raise FpdbError("invalid site in recogniseSiteID: "+site)
|
||||
return cursor.fetchall()[0][0]
|
||||
#end def recogniseSiteID
|
||||
|
||||
#removes trailing \n from the given array
|
||||
def removeTrailingEOL(arr):
|
||||
@@ -1810,7 +1708,7 @@ sure to also change the following storage method and table_viewer.prepare_data i
|
||||
myStreet0_3B4BDone = True
|
||||
|
||||
#steal calculations
|
||||
if base == "hold":
|
||||
if base=="hold":
|
||||
if len(player_ids)>=3: # no point otherwise # was 5, use 3 to match pokertracker definition
|
||||
if positions[player]==1:
|
||||
if firstPfRaiserId==player_ids[player] \
|
||||
@@ -2285,7 +2183,7 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData):
|
||||
except TypeError:
|
||||
row=[]
|
||||
|
||||
if not row:
|
||||
if not row:
|
||||
#print "new huddata row"
|
||||
doInsert=True
|
||||
row=[]
|
||||
|
||||
@@ -46,7 +46,7 @@ def testGameInfo():
|
||||
|
||||
|
||||
def testHandInfo():
|
||||
text = u""""PokerStars Game #20461877044: Hold'em No Limit ($1/$2) - 2008/09/16 18:58:01 ET"""
|
||||
text = u"""PokerStars Game #20461877044: Hold'em No Limit ($1/$2) - 2008/09/16 18:58:01 ET"""
|
||||
hhc = PokerStarsToFpdb.PokerStars(autostart=False)
|
||||
h = HoldemOmahaHand(None, "PokerStars", gametype, text, builtFrom = "Test")
|
||||
hhc.readHandInfo(h)
|
||||
@@ -78,4 +78,4 @@ Table 'Caia II' 6-max Seat #2 is the button"""
|
||||
assert h.buttonpos == '2' # TODO: should this be an int?
|
||||
assert h.starttime == (2008,11 , 15, 19, 22, 21, 5, 320, -1)
|
||||
|
||||
|
||||
|
||||
|
||||
+18
-19
@@ -16,25 +16,24 @@ def testPokerStarsHHDate():
|
||||
datetime.datetime(2008,9,7,11,23,14))
|
||||
)
|
||||
|
||||
#def testFullTiltHHDate(self):
|
||||
# sitngo1 = "Full Tilt Poker Game #10311865543: $1 + $0.25 Sit & Go (78057629), Table 1 - 25/50 - No Limit Hold'em - 0:07:45 ET - 2009/01/29"
|
||||
# cash1 = "Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09"
|
||||
# cash2 = "Full Tilt Poker Game #9468383505: Table Bike (deep 6) - $0.05/$0.10 - No Limit Hold'em - 5:09:36 ET - 2008/12/13"
|
||||
def testFullTiltHHDate():
|
||||
sitngo1 = "Full Tilt Poker Game #10311865543: $1 + $0.25 Sit & Go (78057629), Table 1 - 25/50 - No Limit Hold'em - 0:07:45 ET - 2009/01/29"
|
||||
cash1 = "Full Tilt Poker Game #9403951181: Table CR - tay - $0.05/$0.10 - No Limit Hold'em - 9:40:20 ET - 2008/12/09"
|
||||
cash2 = "Full Tilt Poker Game #9468383505: Table Bike (deep 6) - $0.05/$0.10 - No Limit Hold'em - 5:09:36 ET - 2008/12/13"
|
||||
|
||||
# result = fpdb_simple.parseHandStartTime(sitngo1,"ftp")
|
||||
# self.failUnless(result==datetime.datetime(2009,1,29,05,07,45),
|
||||
# "Date incorrect, expected: 2009-01-29 05:07:45 got: " + str(result))
|
||||
# result = fpdb_simple.parseHandStartTime(cash1,"ftp")
|
||||
# self.failUnless(result==datetime.datetime(2008,12,9,14,40,20),
|
||||
# "Date incorrect, expected: 2008-12-09 14:40:20 got: " + str(result))
|
||||
# result = fpdb_simple.parseHandStartTime(cash2,"ftp")
|
||||
# self.failUnless(result==datetime.datetime(2008,12,13,10,9,36),
|
||||
# "Date incorrect, expected: 2008-12-13 10:09:36 got: " + str(result))
|
||||
result = fpdb_simple.parseHandStartTime(sitngo1,"ftp")
|
||||
assert result==datetime.datetime(2009,1,29,05,07,45)
|
||||
result = fpdb_simple.parseHandStartTime(cash1,"ftp")
|
||||
assert result==datetime.datetime(2008,12,9,14,40,20)
|
||||
result = fpdb_simple.parseHandStartTime(cash2,"ftp")
|
||||
assert result==datetime.datetime(2008,12,13,10,9,36)
|
||||
|
||||
# def testTableDetection(self):
|
||||
# result = Tables.clean_title("French (deep)")
|
||||
# self.failUnless(result == "French", "French (deep) parsed incorrectly. Expected 'French' got: " + str(result))
|
||||
# result = ("French (deep) - $0.25/$0.50 - No Limit Hold'em - Logged In As xxxx")
|
||||
def testTableDetection():
|
||||
result = Tables.clean_title("French (deep)")
|
||||
assert result == "French"
|
||||
result = Tables.clean_title("French (deep) - $0.25/$0.50 - No Limit Hold'em - Logged In As xxxx")
|
||||
assert result == "French"
|
||||
|
||||
for (header, site, result) in tuples:
|
||||
yield checkDateParse, header, site, result
|
||||
|
||||
for (header, site, result) in tuples:
|
||||
yield checkDateParse, header, site, result
|
||||
|
||||
Reference in New Issue
Block a user