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

This commit is contained in:
Worros 2010-08-12 14:40:09 +08:00
commit 5c76ec77d6
16 changed files with 642 additions and 109 deletions

View File

@ -452,8 +452,8 @@ class Email:
self.fetchType = node.getAttribute("fetchType")
def __str__(self):
return " host = %s\n username = %s\n password = %s\n useSsl = %s\n folder = %s\n" \
% (self.host, self.username, self.password, self.useSsl, self.folder)
return " siteName=%s\n fetchType=%s\n host = %s\n username = %s\n password = %s\n useSsl = %s\n folder = %s\n" \
% (self.siteName, self.fetchType, self.host, self.username, self.password, self.useSsl, self.folder)
class HudUI:
def __init__(self, node):
@ -626,6 +626,7 @@ class Config:
self.db_selected = None # database the user would like to use
self.tv = None
self.general = General()
self.emails = {}
self.gui_cash_stats = GUICashStats()
for gen_node in doc.getElementsByTagName("general"):
@ -687,7 +688,8 @@ class Config:
for email_node in doc.getElementsByTagName("email"):
email = Email(node = email_node)
self.email = email
if email.siteName!="": #FIXME: Why on earth is this needed?
self.emails[email.siteName+"_"+email.fetchType]=email
for hui_node in doc.getElementsByTagName('hud_ui'):
hui = HudUI(node = hui_node)
@ -734,6 +736,12 @@ class Config:
if site_node.getAttribute("site_name") == site:
return site_node
def getEmailNode(self, siteName, fetchType):
for emailNode in self.doc.getElementsByTagName("email"):
if emailNode.getAttribute("siteName") == siteName and emailNode.getAttribute("fetchType") == fetchType:
return emailNode
#end def getEmailNode
def getGameNode(self,gameName):
"""returns DOM game node for a given game"""
for gameNode in self.doc.getElementsByTagName("game"):
@ -808,6 +816,15 @@ class Config:
else:
return(l)
def editEmail(self, siteName, fetchType, newEmail):
emailNode = self.getEmailNode(siteName, fetchType)
emailNode.setAttribute("host", newEmail.host)
emailNode.setAttribute("username", newEmail.username)
emailNode.setAttribute("password", newEmail.password)
emailNode.setAttribute("folder", newEmail.folder)
emailNode.setAttribute("useSsl", newEmail.useSsl)
#end def editEmail
def edit_layout(self, site_name, max, width = None, height = None,
fav_seat = None, locations = None):
site_node = self.get_site_node(site_name)

View File

@ -74,7 +74,7 @@ except ImportError:
use_numpy = False
DB_VERSION = 140
DB_VERSION = 142
# Variance created as sqlite has a bunch of undefined aggregate functions.
@ -140,7 +140,7 @@ class Database:
, {'tab':'TourneysPlayers', 'col':'playerId', 'drop':0}
#, {'tab':'TourneysPlayers', 'col':'tourneyId', 'drop':0} unique indexes not dropped
, {'tab':'TourneyTypes', 'col':'siteId', 'drop':0}
, {'tab':'Backings', 'col':'tourneysPlayerId', 'drop':0}
, {'tab':'Backings', 'col':'tourneysPlayersId', 'drop':0}
, {'tab':'Backings', 'col':'playerId', 'drop':0}
]
, [ # indexes for sqlite (list index 4)
@ -155,7 +155,7 @@ class Database:
, {'tab':'Tourneys', 'col':'tourneyTypeId', 'drop':1}
, {'tab':'TourneysPlayers', 'col':'playerId', 'drop':0}
, {'tab':'TourneyTypes', 'col':'siteId', 'drop':0}
, {'tab':'Backings', 'col':'tourneysPlayerId', 'drop':0}
, {'tab':'Backings', 'col':'tourneysPlayersId', 'drop':0}
, {'tab':'Backings', 'col':'playerId', 'drop':0}
]
]
@ -1442,17 +1442,41 @@ class Database:
h_start = self.hero_hudstart_def
if v_start is None:
v_start = self.villain_hudstart_def
if self.hero_ids == {}:
where = ""
where = "WHERE hp.tourneysPlayersId IS NULL"
else:
where = "where ( hp.playerId not in " + str(tuple(self.hero_ids.values())) \
where = "where ((( hp.playerId not in " + str(tuple(self.hero_ids.values())) \
+ " and h.startTime > '" + v_start + "')" \
+ " or ( hp.playerId in " + str(tuple(self.hero_ids.values())) \
+ " and h.startTime > '" + h_start + "')"
rebuild_sql = self.sql.query['rebuildHudCache'].replace('<where_clause>', where)
+ " and h.startTime > '" + h_start + "'))" \
+ " AND hp.tourneysPlayersId IS NULL)"
rebuild_sql_cash = self.sql.query['rebuildHudCache'].replace('<tourney_insert_clause>', "")
rebuild_sql_cash = rebuild_sql_cash.replace('<tourney_select_clause>', "")
rebuild_sql_cash = rebuild_sql_cash.replace('<tourney_join_clause>', "")
rebuild_sql_cash = rebuild_sql_cash.replace('<tourney_group_clause>', "")
rebuild_sql_cash = rebuild_sql_cash.replace('<where_clause>', where)
#print "rebuild_sql_cash:",rebuild_sql_cash
self.get_cursor().execute(self.sql.query['clearHudCache'])
self.get_cursor().execute(rebuild_sql)
self.get_cursor().execute(rebuild_sql_cash)
if self.hero_ids == {}:
where = "WHERE hp.tourneysPlayersId >= 0"
else:
where = "where ((( hp.playerId not in " + str(tuple(self.hero_ids.values())) \
+ " and h.startTime > '" + v_start + "')" \
+ " or ( hp.playerId in " + str(tuple(self.hero_ids.values())) \
+ " and h.startTime > '" + h_start + "'))" \
+ " AND hp.tourneysPlayersId >= 0)"
rebuild_sql_tourney = self.sql.query['rebuildHudCache'].replace('<tourney_insert_clause>', ",tourneyTypeId")
rebuild_sql_tourney = rebuild_sql_tourney.replace('<tourney_select_clause>', ",t.tourneyTypeId")
rebuild_sql_tourney = rebuild_sql_tourney.replace('<tourney_join_clause>', """INNER JOIN TourneysPlayers tp ON (tp.id = hp.tourneysPlayersId)
INNER JOIN Tourneys t ON (t.id = tp.tourneyId)""")
rebuild_sql_tourney = rebuild_sql_tourney.replace('<tourney_group_clause>', ",t.tourneyTypeId")
rebuild_sql_tourney = rebuild_sql_tourney.replace('<where_clause>', where)
#print "rebuild_sql_tourney:",rebuild_sql_tourney
self.get_cursor().execute(rebuild_sql_tourney)
self.commit()
print "Rebuild hudcache took %.1f seconds" % (time() - stime,)
except:
@ -2115,6 +2139,32 @@ class Database:
result = c.fetchall()
return result
#end def getTourneyTypesIds
def getTourneyInfo(self, siteName, tourneyNo):
c = self.get_cursor()
c.execute(self.sql.query['getTourneyInfo'], (siteName, tourneyNo))
columnNames=c.description
names=[]
for column in columnNames:
names.append(column[0])
data=c.fetchone()
return (names,data)
#end def getTourneyInfo
def getTourneyPlayerInfo(self, siteName, tourneyNo, playerName):
c = self.get_cursor()
c.execute(self.sql.query['getTourneyPlayerInfo'], (siteName, tourneyNo, playerName))
columnNames=c.description
names=[]
for column in columnNames:
names.append(column[0])
data=c.fetchone()
return (names,data)
#end def getTourneyPlayerInfo
#end class Database
# Class used to hold all the data needed to write a hand to the db

154
pyfpdb/GuiImapFetcher.py Normal file
View File

@ -0,0 +1,154 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2010 Steffen Schaumburg
#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.
import threading
import pygtk
pygtk.require('2.0')
import gtk
from imaplib import IMAP4
from socket import gaierror
import ImapFetcher
class GuiImapFetcher (threading.Thread):
def __init__(self, config, db, sql, mainwin, debug=True):
self.config = config
self.db = db
self.mainVBox = gtk.VBox()
self.buttonsHBox = gtk.HBox()
self.mainVBox.pack_end(self.buttonsHBox, expand=False)
label=gtk.Label("To cancel just close this tab.")
self.buttonsHBox.add(label)
self.saveButton = gtk.Button("_Save")
self.saveButton.connect('clicked', self.saveClicked)
self.buttonsHBox.add(self.saveButton)
self.importAllButton = gtk.Button("_Import All")
self.importAllButton.connect('clicked', self.importAllClicked)
self.buttonsHBox.add(self.importAllButton)
self.statusLabel=gtk.Label("If you change the config you must save before importing")
self.mainVBox.pack_end(self.statusLabel, expand=False, padding=4)
self.passwords={}
self.displayConfig()
self.mainVBox.show_all()
#end def __init__
def saveClicked(self, widget, data=None):
row = self.rowVBox.get_children()
columns=row[0].get_children() #TODO: make save capable of handling multiple email entries - not relevant yet as only one entry is useful atm. The rest of this tab works fine for multiple entries though
siteName=columns[0].get_text()
fetchType=columns[1].get_text()
code=siteName+"_"+fetchType
for email in self.config.emails:
toSave=self.config.emails[email]
break
toSave.siteName=siteName
toSave.fetchType=fetchType
toSave.host=columns[2].get_text()
toSave.username=columns[3].get_text()
if columns[4].get_text()=="***":
toSave.password=self.passwords[code]
else:
toSave.password=columns[4].get_text()
toSave.folder=columns[5].get_text()
if columns[6].get_active() == 0:
toSave.useSsl="True"
else:
toSave.useSsl="False"
self.config.editEmail(siteName, fetchType, toSave)
self.config.save()
#def saveClicked
def importAllClicked(self, widget, data=None):
self.statusLabel.set_label("Starting import. Please wait.") #FIXME: why doesnt this one show?
for email in self.config.emails:
try:
result=ImapFetcher.run(self.config.emails[email], self.db)
self.statusLabel.set_label("Finished import without error.")
except IMAP4.error as error:
if str(error)=="[AUTHENTICATIONFAILED] Authentication failed.":
self.statusLabel.set_label("Login to mailserver failed: please check mailserver, username and password")
except gaierror as error:
if str(error)=="[Errno -2] Name or service not known":
self.statusLabel.set_label("Could not connect to mailserver: check mailserver and use SSL settings and internet connectivity")
#def importAllClicked
def get_vbox(self):
"""returns the vbox of this thread"""
return self.mainVBox
#end def get_vbox
def displayConfig(self):
box=gtk.HBox(homogeneous=True)
for text in ("Site", "Fetch Type", "Mailserver", "Username", "Password", "Mail Folder", "Use SSL"):
label=gtk.Label(text)
box.add(label)
self.mainVBox.pack_start(box, expand=False)
self.rowVBox = gtk.VBox()
self.mainVBox.add(self.rowVBox)
for email in self.config.emails:
config=self.config.emails[email]
box=gtk.HBox(homogeneous=True)
for field in (config.siteName, config.fetchType):
label=gtk.Label(field)
box.add(label)
for field in (config.host, config.username):
entry=gtk.Entry()
entry.set_text(field)
box.add(entry)
entry=gtk.Entry()
self.passwords[email]=config.password
entry.set_text("***")
box.add(entry)
entry=gtk.Entry()
entry.set_text(config.folder)
box.add(entry)
sslBox = gtk.combo_box_new_text()
sslBox.append_text("Yes")
sslBox.append_text("No")
sslBox.set_active(0)
box.add(sslBox)
#TODO: "run just this one" button
self.rowVBox.pack_start(box, expand=False)
#print
self.mainVBox.show_all()
#end def displayConfig
#end class GuiImapFetcher

139
pyfpdb/GuiTourneyViewer.py Normal file
View File

@ -0,0 +1,139 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2010 Steffen Schaumburg
#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.
import threading
import pygtk
pygtk.require('2.0')
import gtk
class GuiTourneyViewer (threading.Thread):
def __init__(self, config, db, sql, mainwin, debug=True):
self.db = db
self.mainVBox = gtk.VBox()
self.interfaceHBox = gtk.HBox()
self.mainVBox.pack_start(self.interfaceHBox, expand=False)
self.siteBox = gtk.combo_box_new_text()
for site in config.supported_sites:
self.siteBox.append_text(site)
self.siteBox.set_active(0)
self.interfaceHBox.add(self.siteBox)
label=gtk.Label("Enter the tourney number you want to display:")
self.interfaceHBox.add(label)
self.entryTourney = gtk.Entry()
self.interfaceHBox.add(self.entryTourney)
self.displayButton = gtk.Button("_Display")
self.displayButton.connect('clicked', self.displayClicked)
self.interfaceHBox.add(self.displayButton)
self.entryPlayer = gtk.Entry()
self.interfaceHBox.add(self.entryPlayer)
self.playerButton = gtk.Button("Display _Player")
self.playerButton.connect('clicked', self.displayPlayerClicked)
self.interfaceHBox.add(self.playerButton)
self.table = gtk.Table(columns=10, rows=9)
self.mainVBox.add(self.table)
self.mainVBox.show_all()
#end def __init__
def displayClicked(self, widget, data=None):
if self.prepare(10, 9):
result=self.db.getTourneyInfo(self.siteName, self.tourneyNo)
if result[1] == None:
self.table.destroy()
self.errorLabel=gtk.Label("Tournament not found - please ensure you imported it and selected the correct site")
self.mainVBox.add(self.errorLabel)
else:
x=0
y=0
for i in range(1,len(result[0])):
if y==9:
x+=2
y=0
label=gtk.Label(result[0][i])
self.table.attach(label,x,x+1,y,y+1)
if result[1][i]==None:
label=gtk.Label("N/A")
else:
label=gtk.Label(result[1][i])
self.table.attach(label,x+1,x+2,y,y+1)
y+=1
self.mainVBox.show_all()
#def displayClicked
def displayPlayerClicked(self, widget, data=None):
if self.prepare(4, 5):
result=self.db.getTourneyPlayerInfo(self.siteName, self.tourneyNo, self.playerName)
if result[1] == None:
self.table.destroy()
self.errorLabel=gtk.Label("Player or tourney not found - please ensure you imported it and selected the correct site")
self.mainVBox.add(self.errorLabel)
else:
x=0
y=0
for i in range(1,len(result[0])):
if y==5:
x+=2
y=0
label=gtk.Label(result[0][i])
self.table.attach(label,x,x+1,y,y+1)
if result[1][i]==None:
label=gtk.Label("N/A")
else:
label=gtk.Label(result[1][i])
self.table.attach(label,x+1,x+2,y,y+1)
y+=1
self.mainVBox.show_all()
#def displayPlayerClicked
def get_vbox(self):
"""returns the vbox of this thread"""
return self.mainVBox
#end def get_vbox
def prepare(self, columns, rows):
try: self.errorLabel.destroy()
except: pass
try:
self.tourneyNo=int(self.entryTourney.get_text())
except ValueError:
self.errorLabel=gtk.Label("invalid entry in tourney number - must enter numbers only")
self.mainVBox.add(self.errorLabel)
return False
self.siteName=self.siteBox.get_active_text()
self.playerName=self.entryPlayer.get_text()
self.table.destroy()
self.table=gtk.Table(columns=columns, rows=rows)
self.mainVBox.add(self.table)
return True
#end def readInfo
#end class GuiTourneyViewer

View File

@ -252,48 +252,45 @@ Left-Drag to Move"
</layout>
</site>
<site enabled="False"
site_name="Everleaf"
table_finder="Everleaf.exe"
screen_name="YOUR SCREEN NAME HERE"
site_path=""
HH_path=""
decoder="everleaf_decode_table"
<site HH_path="C:\Users\WindowsUserName\Documents\EverleafSiteName\HandHistory\PlayerName"
bgcolor="#000000"
converter="EverleafToFpdb"
supported_games="holdem">
<layout fav_seat="0" height="547" max="8" width="794">
<location seat="1" x="640" y="64"> </location>
<location seat="2" x="650" y="230"> </location>
<location seat="3" x="650" y="385"> </location>
<location seat="4" x="588" y="425"> </location>
<location seat="5" x="92" y="425"> </location>
<location seat="6" x="0" y="373"> </location>
<location seat="7" x="0" y="223"> </location>
<location seat="8" x="25" y="50"> </location>
decoder="everleaf_decode_table"
enabled="False"
fgcolor="#EEEEEE"
hudopacity="0.75"
screen_name="PlayerName"
site_name="Everleaf"
site_path="C:\Users\WindowsUserName\AppData\Roaming\EverleafSiteName\"
supported_games="holdem,omahahi,omahahilo"
table_finder="Poker.exe">
<layout fav_seat="0" height="546" max="6" width="792">
<location seat="0" x="0" y="0"> </location>
<location seat="1" x="586" y="109"> </location>
<location seat="2" x="605" y="283"> </location>
<location seat="3" x="544" y="383"> </location>
<location seat="4" x="67" y="383"> </location>
<location seat="5" x="5" y="284"> </location>
<location seat="6" x="61" y="111"> </location>
</layout>
<layout fav_seat="0" height="547" max="6" width="794">
<location seat="1" x="640" y="58"> </location>
<location seat="2" x="654" y="288"> </location>
<location seat="3" x="615" y="424"> </location>
<location seat="4" x="70" y="421"> </location>
<location seat="5" x="0" y="280"> </location>
<location seat="6" x="70" y="58"> </location>
<layout fav_seat="0" height="546" max="10" width="792">
<location seat="0" x="182" y="69"> </location>
<location seat="1" x="456" y="74"> </location>
<location seat="2" x="630" y="81"> </location>
<location seat="3" x="637" y="208"> </location>
<location seat="4" x="629" y="347"> </location>
<location seat="5" x="412" y="377"> </location>
<location seat="6" x="232" y="377"> </location>
<location seat="7" x="21" y="349"> </location>
<location seat="8" x="4" y="208"> </location>
<location seat="9" x="7" y="88"> </location>
<location seat="10" x="196" y="69"> </location>
</layout>
<layout fav_seat="0" height="547" max="2" width="794">
<layout fav_seat="0" height="546" max="2" width="792">
<location seat="1" x="651" y="288"> </location>
<location seat="2" x="10" y="288"> </location>
</layout>
<layout fav_seat="0" height="547" max="9" width="794">
<location seat="1" x="634" y="38"> </location>
<location seat="2" x="667" y="184"> </location>
<location seat="3" x="667" y="321"> </location>
<location seat="4" x="667" y="445"> </location>
<location seat="5" x="337" y="459"> </location>
<location seat="6" x="0" y="400"> </location>
<location seat="7" x="0" y="322"> </location>
<location seat="8" x="0" y="181"> </location>
<location seat="9" x="70" y="53"> </location>
</layout>
</site>
<site enabled="False"
@ -589,6 +586,8 @@ Left-Drag to Move"
<pu_stat pu_stat_name="playername"> </pu_stat>
<pu_stat pu_stat_name="totalprofit"> </pu_stat>
<pu_stat pu_stat_name="profit100"> </pu_stat>
<pu_stat pu_stat_name="bbper100"> </pu_stat>
<pu_stat pu_stat_name="BBper100"> </pu_stat>
<pu_stat pu_stat_name="n"> </pu_stat>
<pu_stat pu_stat_name="vpip"> </pu_stat>
<pu_stat pu_stat_name="pfr"> </pu_stat>

View File

@ -79,13 +79,13 @@ class Hand(object):
self.fee = None # the Database code is looking for this one .. ?
self.level = None
self.mixed = None
self.speed = None
self.isRebuy = None
self.isAddOn = None
self.isKO = None
self.speed = "Normal"
self.isRebuy = False
self.isAddOn = False
self.isKO = False
self.koBounty = None
self.isMatrix = None
self.isShootout = None
self.isMatrix = False
self.isShootout = False
self.added = None
self.addedCurrency = None
self.tourneyComment = None
@ -683,9 +683,15 @@ class HoldemOmahaHand(Hand):
hhc.readPlayerStacks(self)
hhc.compilePlayerRegexs(self)
hhc.markStreets(self)
if self.cancelled:
return
hhc.readBlinds(self)
try: hhc.readBlinds(self)
except:
print "*** Parse error reading blinds (check compilePlayerRegexs as a likely culprit)", self
return
hhc.readAntes(self)
hhc.readButton(self)
hhc.readHeroCards(self)

View File

@ -441,6 +441,7 @@ or None if we fail to get the info """
pass
else:
print "unable to read file with any codec in list!", self.in_path
self.obs = ""
elif self.filetype == "xml":
doc = xml.dom.minidom.parse(filename)
self.doc = doc

View File

@ -33,16 +33,16 @@ def run(config, db):
#print "start of IS.run"
server=None
#try:
#print "useSSL",config.email.useSsl,"host",config.email.host
if config.email.useSsl:
server = IMAP4_SSL(config.email.host)
#print "useSSL",config.useSsl,"host",config.host
if config.useSsl:
server = IMAP4_SSL(config.host)
else:
server = IMAP4(config.email.host)
response = server.login(config.email.username, config.email.password) #TODO catch authentication error
server = IMAP4(config.host)
response = server.login(config.username, config.password) #TODO catch authentication error
print "response to logging in:",response
#print "server.list():",server.list() #prints list of folders
response = server.select(config.email.folder)
response = server.select(config.folder)
#print "response to selecting INBOX:",response
if response[0]!="OK":
raise error #TODO: show error message

View File

@ -219,6 +219,9 @@ class PartyPoker(HandHistoryConverter):
info['type'] = 'ring'
if info['type'] == 'ring':
if (m_sb is None) or (m_bb is None):
return None
else:
info['sb'] = m_sb.group('RINGSB')
info['bb'] = m_bb.group('RINGBB')
info['currency'] = currencies[mg['CURRENCY']]

View File

@ -137,21 +137,21 @@ class Sql:
if db_server == 'mysql':
self.query['createBackingsTable'] = """CREATE TABLE Backings (
id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
tourneysPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (tourneysPlayerId) REFERENCES TourneysPlayers(id),
tourneysPlayersId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id),
playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id),
buyInPercentage FLOAT UNSIGNED NOT NULL,
payOffPercentage FLOAT UNSIGNED NOT NULL) ENGINE=INNODB"""
elif db_server == 'postgresql':
self.query['createBackingsTable'] = """CREATE TABLE Backings (
id BIGSERIAL, PRIMARY KEY (id),
tourneysPlayerId INT NOT NULL, FOREIGN KEY (tourneysPlayerId) REFERENCES TourneysPlayers(id),
tourneysPlayersId INT NOT NULL, FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id),
playerId INT NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id),
buyInPercentage FLOAT NOT NULL,
payOffPercentage FLOAT NOT NULL)"""
elif db_server == 'sqlite':
self.query['createBackingsTable'] = """CREATE TABLE Backings (
id INTEGER PRIMARY KEY,
tourneysPlayerId INT NOT NULL,
tourneysPlayersId INT NOT NULL,
playerId INT NOT NULL,
buyInPercentage REAL UNSIGNED NOT NULL,
payOffPercentage REAL UNSIGNED NOT NULL)"""
@ -918,7 +918,7 @@ class Sql:
commentTs timestamp without time zone)"""
elif db_server == 'sqlite':
self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers (
id INT PRIMARY KEY,
id INTEGER PRIMARY KEY,
tourneyId INT,
playerId INT,
rank INT,
@ -963,7 +963,7 @@ class Sql:
commentTs timestamp without time zone)"""
elif db_server == 'sqlite':
self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions (
id INT PRIMARY KEY,
id INTEGER PRIMARY KEY,
handsPlayerId BIGINT,
street SMALLINT,
actionNo SMALLINT,
@ -1336,8 +1336,6 @@ class Sql:
and (p.siteId = %s or %s = -1)
"""
self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
self.query['get_stats_from_hand'] = """
SELECT hc.playerId AS player_id,
hp.seatNo AS seat,
@ -2010,8 +2008,6 @@ class Sql:
self.query['getPlayerIdBySite'] = """SELECT id from Players where name = %s AND siteId = %s"""
# used in *Filters:
self.query['getSiteId'] = """SELECT id from Sites where name = %s"""
self.query['getGames'] = """SELECT DISTINCT category from Gametypes"""
#self.query['getLimits'] = already defined further up
self.query['getLimits2'] = """SELECT DISTINCT type, limitType, bigBlind
from Gametypes
@ -2781,6 +2777,8 @@ class Sql:
order by stats.category, stats.limitType, stats.bigBlindDesc desc
<orderbyseats>, cast(stats.PlPosition as signed)
"""
elif db_server == 'sqlite':
self.query['playerStatsByPosition'] = ""#TODO
else: # assume postgresql
self.query['playerStatsByPosition'] = """
select /* stats from hudcache */
@ -2951,7 +2949,7 @@ class Sql:
INNER JOIN Players p on (p.Id = hp.playerId)
WHERE hp.playerId in <player_test>
AND date_format(h.startTime, '%Y-%m-%d') <datestest>
AND gt.type is 'ring'
AND gt.type LIKE 'ring'
ORDER by time"""
elif db_server == 'postgresql':
self.query['sessionStats'] = """
@ -2963,7 +2961,7 @@ class Sql:
INNER JOIN Players p on (p.Id = hp.playerId)
WHERE hp.playerId in <player_test>
AND h.startTime <datestest>
AND gt.type is 'ring'
AND gt.type LIKE 'ring'
ORDER by time"""
elif db_server == 'sqlite':
self.query['sessionStats'] = """
@ -2992,7 +2990,7 @@ class Sql:
,playerId
,activeSeats
,position
,tourneyTypeId
<tourney_insert_clause>
,styleKey
,HDs
,wonWhenSeenStreet1
@ -3082,7 +3080,7 @@ class Sql:
when hp.position = '9' then 'E'
else 'E'
end AS hc_position
,t.tourneyTypeId
<tourney_select_clause>
,date_format(h.startTime, 'd%y%m%d')
,count(1)
,sum(wonWhenSeenStreet1)
@ -3156,14 +3154,13 @@ class Sql:
,sum(hp.street4Raises)
FROM HandsPlayers hp
INNER JOIN Hands h ON (h.id = hp.handId)
INNER JOIN TourneysPlayers tp ON (tp.id = hp.tourneysPlayersId)
INNER JOIN Tourneys t ON (t.id = tp.tourneyId)
<tourney_join_clause>
<where_clause>
GROUP BY h.gametypeId
,hp.playerId
,h.seats
,hc_position
,t.tourneyTypeId
<tourney_group_clause>
,date_format(h.startTime, 'd%y%m%d')
"""
elif db_server == 'postgresql':
@ -3173,7 +3170,7 @@ class Sql:
,playerId
,activeSeats
,position
,tourneyTypeId
<tourney_insert_clause>
,styleKey
,HDs
,wonWhenSeenStreet1
@ -3263,7 +3260,7 @@ class Sql:
when hp.position = '9' then 'E'
else 'E'
end AS hc_position
,t.tourneyTypeId
<tourney_select_clause>
,'d' || to_char(h.startTime, 'YYMMDD')
,count(1)
,sum(wonWhenSeenStreet1)
@ -3337,14 +3334,13 @@ class Sql:
,sum(CAST(hp.street4Raises as integer))
FROM HandsPlayers hp
INNER JOIN Hands h ON (h.id = hp.handId)
INNER JOIN TourneysPlayers tp ON (tp.id = hp.tourneysPlayersId)
INNER JOIN Tourneys t ON (t.id = tp.tourneyId)
<tourney_join_clause>
<where_clause>
GROUP BY h.gametypeId
,hp.playerId
,h.seats
,hc_position
,t.tourneyTypeId
<tourney_group_clause>
,to_char(h.startTime, 'YYMMDD')
"""
else: # assume sqlite
@ -3354,7 +3350,7 @@ class Sql:
,playerId
,activeSeats
,position
,tourneyTypeId
<tourney_insert_clause>
,styleKey
,HDs
,wonWhenSeenStreet1
@ -3444,7 +3440,7 @@ class Sql:
when hp.position = '9' then 'E'
else 'E'
end AS hc_position
,t.tourneyTypeId
<tourney_select_clause>
,'d' || substr(strftime('%Y%m%d', h.startTime),3,7)
,count(1)
,sum(wonWhenSeenStreet1)
@ -3518,14 +3514,13 @@ class Sql:
,sum(CAST(hp.street4Raises as integer))
FROM HandsPlayers hp
INNER JOIN Hands h ON (h.id = hp.handId)
INNER JOIN TourneysPlayers tp ON (tp.id = hp.tourneysPlayersId)
INNER JOIN Tourneys t ON (t.id = tp.tourneyId)
<tourney_join_clause>
<where_clause>
GROUP BY h.gametypeId
,hp.playerId
,h.seats
,hc_position
,t.tourneyTypeId
<tourney_group_clause>
,'d' || substr(strftime('%Y%m%d', h.startTime),3,7)
"""
@ -3812,6 +3807,22 @@ class Sql:
WHERE tt.siteId=%s AND t.siteTourneyNo=%s
"""
self.query['getTourneyInfo'] = """SELECT tt.*, t.*
FROM Tourneys t
INNER JOIN TourneyTypes tt ON (t.tourneyTypeId = tt.id)
INNER JOIN Sites s ON (tt.siteId = s.id)
WHERE s.name=%s AND t.siteTourneyNo=%s
"""
self.query['getTourneyPlayerInfo'] = """SELECT tp.*
FROM Tourneys t
INNER JOIN TourneyTypes tt ON (t.tourneyTypeId = tt.id)
INNER JOIN Sites s ON (tt.siteId = s.id)
INNER JOIN TourneysPlayers tp ON (tp.tourneyId = t.id)
INNER JOIN Players p ON (p.id = tp.playerId)
WHERE s.name=%s AND t.siteTourneyNo=%s AND p.name=%s
"""
self.query['insertTourney'] = """INSERT INTO Tourneys
(tourneyTypeId, siteTourneyNo, entries, prizepool,
startTime, endTime, tourneyName, matrixIdProcessed,

View File

@ -770,10 +770,10 @@ def ffreq1(stat_dict, player):
)
except:
return (stat,
'%3.1f' % (0) + '%',
'ff1=%3.1f' % (0) + '%',
'ff_1=%3.1f' % (0) + '%',
'(%d/%d)' % (0, 0),
'NA',
'ff1=NA',
'ff_1=NA',
'(0/0)',
'% fold frequency flop/4th'
)

View File

@ -103,9 +103,10 @@ import GuiPrefs
import GuiLogView
#import GuiDatabase
import GuiBulkImport
import ImapFetcher
import GuiImapFetcher
import GuiRingPlayerStats
import GuiTourneyPlayerStats
import GuiTourneyViewer
import GuiPositionalStats
import GuiAutoImport
import GuiGraphViewer
@ -785,7 +786,7 @@ class fpdb:
<menu action="import">
<menuitem action="sethharchive"/>
<menuitem action="bulkimp"/>
<menuitem action="imapsummaries"/>
<menuitem action="imapimport"/>
<menuitem action="autoimp"/>
</menu>
<menu action="viewers">
@ -794,6 +795,7 @@ class fpdb:
<menuitem action="graphs"/>
<menuitem action="ringplayerstats"/>
<menuitem action="tourneyplayerstats"/>
<menuitem action="tourneyviewer"/>
<menuitem action="posnstats"/>
<menuitem action="sessionstats"/>
</menu>
@ -826,13 +828,14 @@ class fpdb:
('import', None, '_Import'),
('sethharchive', None, '_Set HandHistory Archive Directory', None, 'Set HandHistory Archive Directory', self.select_hhArchiveBase),
('bulkimp', None, '_Bulk Import', '<control>B', 'Bulk Import', self.tab_bulk_import),
('imapsummaries', None, '_Import Tourney Summaries through eMail/IMAP', '<control>I', 'Auto Import and HUD', self.import_imap_summaries),
('imapimport', None, '_Import through eMail/IMAP', '<control>I', 'Import through eMail/IMAP', self.tab_imap_import),
('viewers', None, '_Viewers'),
('autoimp', None, '_Auto Import and HUD', '<control>A', 'Auto Import and HUD', self.tab_auto_import),
('hudConfigurator', None, '_HUD Configurator', '<control>H', 'HUD Configurator', self.diaHudConfigurator),
('graphs', None, '_Graphs', '<control>G', 'Graphs', self.tabGraphViewer),
('ringplayerstats', None, 'Ring _Player Stats (tabulated view)', '<control>P', 'Ring Player Stats (tabulated view)', self.tab_ring_player_stats),
('tourneyplayerstats', None, '_Tourney Player Stats (tabulated view, mysql only)', '<control>T', 'Tourney Player Stats (tabulated view, mysql only)', self.tab_tourney_player_stats),
('tourneyviewer', None, 'Tourney _Viewer', None, 'Tourney Viewer)', self.tab_tourney_viewer_stats),
('posnstats', None, 'P_ositional Stats (tabulated view)', '<control>O', 'Positional Stats (tabulated view)', self.tab_positional_stats),
('sessionstats', None, 'Session Stats', None, 'Session Stats', self.tab_session_stats),
('database', None, '_Database'),
@ -857,10 +860,6 @@ class fpdb:
return menubar
#end def get_menu
def import_imap_summaries(self, widget, data=None):
result=ImapFetcher.run(self.config, self.db)
#print "import imap summaries result:", result
#end def import_imap_summaries
def load_profile(self, create_db = False):
"""Loads profile from the provided path name."""
@ -1021,6 +1020,13 @@ class fpdb:
bulk_tab=new_import_thread.get_vbox()
self.add_and_display_tab(bulk_tab, "Bulk Import")
def tab_imap_import(self, widget, data=None):
new_thread = GuiImapFetcher.GuiImapFetcher(self.config, self.db, self.sql, self.window)
self.threads.append(new_thread)
tab=new_thread.get_vbox()
self.add_and_display_tab(tab, "IMAP Import")
#end def tab_import_imap_summaries
def tab_ring_player_stats(self, widget, data=None):
new_ps_thread = GuiRingPlayerStats.GuiRingPlayerStats(self.config, self.sql, self.window)
self.threads.append(new_ps_thread)
@ -1033,6 +1039,12 @@ class fpdb:
ps_tab=new_ps_thread.get_vbox()
self.add_and_display_tab(ps_tab, "Tourney Player Stats")
def tab_tourney_viewer_stats(self, widget, data=None):
new_thread = GuiTourneyViewer.GuiTourneyViewer(self.config, self.db, self.sql, self.window)
self.threads.append(new_thread)
tab=new_thread.get_vbox()
self.add_and_display_tab(tab, "Tourney Viewer")
def tab_positional_stats(self, widget, data=None):
new_ps_thread = GuiPositionalStats.GuiPositionalStats(self.config, self.sql)
self.threads.append(new_ps_thread)

View File

@ -0,0 +1,41 @@
***** Hand History For Game 9423586142 *****
0.01/0.02 Texas Hold'em Game Table (NL) - Mon Jul 12 13:38:32 EDT 2010
Table 20BB Min Speed #1775757 (Real Money) -- Seat 1 is the button
Total number of players : 9/9
Seat 1: Player1 ($0.95)
Seat 2: Player2 ($0.57)
Seat 3: Player3 ($0.86)
Seat 4: Player4 ($1.71)
Seat 5: Player5 ($1.76)
Seat 6: Player6 ($0.44)
Seat 7: Player7 ($0.76)
Seat 8: Player8 ($0.68)
Seat 9: Player9 ($0.38)
Player2 posts small blind (0.01)
Player3 posts big blind (0.02)
** Dealing down cards **
Dealt to Player5 [ Tc, 9d ]
Player5 folds
Player6 calls (0.02)
Player8 folds
Player9 folds
Player1 folds
Player2 calls (0.01)
Player3 raises 0.06 to 0.08
Player6 calls (0.06)
Player2 folds
** Dealing Flop ** : [ 5s, 7h, 6h ]
Player3 bets (0.13)
Player6 folds
** Summary **
Main Pot: $0.18 Rake: $0
Board: [ 5s 7h 6h ]
Player1 balance $0.95, didn't bet (folded)
Player2 balance $0.55, lost $0.02 (folded)
Player3 balance $0.96, bet $0.21, collected $0.31, net +$0.1
Player4 balance $1.71, sits out
Player5 balance $1.76, didn't bet (folded)
Player6 balance $0.36, lost $0.08 (folded)
Player7 balance $0.76, sits out
Player8 balance $0.68, didn't bet (folded)
Player9 balance $0.38, didn't bet (folded)

View File

@ -0,0 +1,63 @@
Game #9485557849 starts.
#Game No : 9485557849
***** Hand History for Game 9485557849 *****
$0.80 USD NL Texas Hold'em - Saturday, July 31, 13:52:16 EDT 2010
Table 20BB Min Speed #1770998 (Real Money)
Seat 1 is the button
Total number of players : 4/9
Seat 3: FErki84 ( $1.64 USD )
Seat 5: Vandercasses ( $0.01 USD )
Seat 9: jeremyho888 ( $1.02 USD )
Seat 1: sergeodem ( $1.20 USD )
FErki84 posts small blind [$0.01 USD].
Vandercasses posts big blind [$0.01 USD].
** Dealing down cards **
Dealt to FErki84 [ 8h Kc ]
jeremyho888 folds
sergeodem calls [$0.02 USD]
FErki84 calls [$0.01 USD]
** Dealing Flop ** [ Td, 7c, 9h ]
FErki84 checks
sergeodem checks
** Dealing Turn ** [ 3h ]
FErki84 checks
sergeodem checks
** Dealing River ** [ Jc ]
FErki84 bets [$0.04 USD]
sergeodem folds
FErki84 shows [ 8h, Kc ]a straight, Seven to Jack.
Vandercasses doesn't show [ Ts, Jd ]two pairs, Jacks and Tens.
FErki84 wins $0.06 USD from the side pot 1 with a straight, Seven to Jack.
FErki84 wins $0.03 USD from the main pot with a straight, Seven to Jack.
Vandercasses has left the table.
Game #9498788316 starts.
#Game No : 9498788316
***** Hand History for Game 9498788316 *****
$1.60 USD NL Texas Hold'em - Wednesday, August 04, 15:02:33 EDT 2010
Table 20BB Min #1847547 (No DP) (Real Money)
Seat 2 is the button
Total number of players : 5/6
Seat 5: CepguTbIu999 ( $1.60 USD )
Seat 1: Daytona_955 ( $2.45 USD )
Seat 4: FErki84 ( $2.18 USD )
Seat 2: anjl2009 ( $2.80 USD )
Seat 3: lukeman2 ( $0.01 USD )
lukeman2 posts small blind [$0.01 USD].
FErki84 posts big blind [$0.04 USD].
** Dealing down cards **
Dealt to FErki84 [ 6s 2c ]
CepguTbIu999 folds
Daytona_955 folds
anjl2009 folds
** Dealing Flop ** [ 9d, Ah, 3h ]
** Dealing Turn ** [ Js ]
** Dealing River ** [ Kc ]
lukeman2 shows [ 5h, 5s ]a pair of Fives.
FErki84 shows [ 6s, 2c ]high card Ace.
FErki84 wins $0.03 USD from the side pot 1 with high card, Ace.
lukeman2 wins $0.02 USD from the main pot with a pair of Fives.
lukeman2 has left the table.

View File

@ -0,0 +1,37 @@
***** Hand History For Game 9336845949 *****
30/60 Tourney Texas Hold'em Game Table (NL) (STT Tournament #52792286) - Sun Jun 13 12:21:39 EDT 2010
Table 174827 (Real Money) -- Seat 6 is the button
Total number of players : 6/6
Seat 1: Player1 (1520)
Seat 2: Player2 (1540)
Seat 3: Player3 (2120)
Seat 4: Player4 (2460)
Seat 5: Player5 (2600)
Seat 6: Player6 (1760)
Player1 posts small blind (30)
Player2 posts big blind (60)
** Dealing down cards **
Dealt to Player5 [ Jc, Js ]
Player3 folds
Player4 folds
Player6 folds
Player1 calls (210)
Player2 folds
** Dealing Flop ** : [ 4h, 7d, 5c ]
Player1 checks
Player1 calls (450)
** Dealing Turn ** : [ Kd ]
Player1 checks
Player1 calls (830)
Player1 is all-In.
** Dealing River ** : [ Jd ]
Creating Main Pot with 3100 with Player1
** Summary **
Main Pot: 3100
Board: [ 4h 7d 5c Kd Jd ]
Player1 balance 0, lost 1520 [ Ks 6c ] [ a pair of kings -- Ks,Kd,Jd,7d,6c ]
Player2 balance 1480, lost 60 (folded)
Player3 balance 2120, didn't bet (folded)
Player4 balance 2460, didn't bet (folded)
Player5 balance 4180, bet 1520, collected 3100, net +1580 [ Jc Js ] [ three of a kind, jacks -- Kd,Jc,Js,Jd,7d ]
Player6 balance 1760, didn't bet (folded)