diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py
new file mode 100755
index 00000000..4ecd69b0
--- /dev/null
+++ b/pyfpdb/Card.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+
+#Copyright 2008 Carl Gherardi
+#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 .
+#In the "official" distribution you can find the license in
+#agpl-3.0.txt in the docs folder of the package.
+
+
+
+
+def twoStartCards(value1, suit1, value2, suit2):
+ """ Function to convert 2 value,suit pairs into a Holdem style starting hand e.g. AQo
+ Hand is stored as an int 13 * x + y where (x+2) represents rank of 1st card and
+ (y+2) represents rank of second card (2=2 .. 14=Ace)
+ If x > y then pair is suited, if x < y then unsuited"""
+ if value1 < 2 or value2 < 2:
+ return(0)
+ if (suit1 == suit2 and value1 < value2) or (suit1 != suit2 and value2 > value1):
+ return(13 * (value2-2) + (value1-1))
+ else:
+ return(13 * (value1-2) + (value2-1))
+
+def twoStartCardString(card):
+ """ Function to convert an int representing 2 holdem hole cards (as created by twoStartCards)
+ into a string like AQo """
+ if card <= 0:
+ return 'xx'
+ else:
+ card -= 1
+ s = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
+ x = card/13
+ y = card - 13*x
+ if x == y: return(s[x] + s[y])
+ elif x > y: return(s[x] + s[y] + 's')
+ else: return(s[y] + s[x] + 'o')
+
+def cardFromValueSuit(value, suit):
+ """ 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As """
+ if suit == 'h': return(value-1)
+ elif suit == 'd': return(value+12)
+ elif suit == 'c': return(value+25)
+ elif suit == 's': return(value+38)
+ else: return(0)
+
+def valueSuitFromCard(card):
+ """ Function to convert a card stored in the database (int 0-52) into value
+ and suit like 9s, 4c etc """
+ if card < 0 or card > 52:
+ return('')
+ else:
+ return( ['', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', 'Th', 'Jh', 'Qh', 'Kh', 'Ah'
+ , '2d', '3d', '4d', '5d', '6d', '7d', '8d', '9d', 'Td', 'Jd', 'Qd', 'Kd', 'Ad'
+ , '2c', '3c', '4c', '5c', '6c', '7c', '8c', '9c', 'Tc', 'Jc', 'Qc', 'Kc', 'Ac'
+ , '2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', 'Ts', 'Js', 'Qs', 'Ks', 'As'
+ ][card] )
+
+
+
diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py
index 0e5c1547..0483da96 100644
--- a/pyfpdb/Database.py
+++ b/pyfpdb/Database.py
@@ -32,6 +32,7 @@ import traceback
# FreePokerTools modules
import Configuration
import SQL
+import Card
class Database:
def __init__(self, c, db_name, game):
@@ -78,6 +79,7 @@ class Database:
self.type = c.supported_databases[db_name].db_type
self.sql = SQL.Sql(game = game, type = self.type)
+ self.connection.rollback()
def close_connection(self):
self.connection.close()
@@ -122,11 +124,17 @@ class Database:
c = self.connection.cursor()
c.execute(self.sql.query['get_cards'], [hand])
colnames = [desc[0] for desc in c.description]
+ cardnames = ['card1', 'card2', 'card3', 'card4', 'card5', 'card6', 'card7']
for row in c.fetchall():
- s_dict = {}
- for name, val in zip(colnames, row):
- s_dict[name] = val
- cards[s_dict['seat_number']] = (self.convert_cards(s_dict))
+ cs = ['', '', '', '', '', '', '']
+ seat = -1
+ for col,name in enumerate(colnames):
+ if name in cardnames:
+ cs[cardnames.index(name)] = Card.valueSuitFromCard(row[col])
+ elif name == 'seat_number':
+ seat = row[col]
+ if seat != -1:
+ cards[seat] = ''.join(cs)
return cards
def get_common_cards(self, hand):
diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py
index d35d0817..3a5f0365 100644
--- a/pyfpdb/Filters.py
+++ b/pyfpdb/Filters.py
@@ -38,6 +38,7 @@ class Filters(threading.Thread):
self.settings=settings
self.sql=qdict
self.conf = config
+ self.display = display
self.sites = {}
self.games = {}
@@ -45,10 +46,12 @@ class Filters(threading.Thread):
self.seats = {}
self.siteid = {}
self.heroes = {}
+ self.boxes = {}
# text used on screen stored here so that it can be configured
- self.filterText = {'limitsall':'All', 'limitsnone':'None', 'limitsshow':'Show Limits'
- ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Seats'
+ self.filterText = {'limitsall':'All', 'limitsnone':'None', 'limitsshow':'Show _Limits'
+ ,'seatsbetween':'Between:', 'seatsand':'And:', 'seatsshow':'Show Number of _Players'
+ ,'limitstitle':'Limits:', 'seatstitle':'Number of Players:'
}
# For use in date ranges.
@@ -66,6 +69,7 @@ class Filters(threading.Thread):
self.fillPlayerFrame(vbox)
playerFrame.add(vbox)
+ self.boxes['player'] = vbox
sitesFrame = gtk.Frame("Sites:")
sitesFrame.set_label_align(0.0, 0.0)
@@ -73,6 +77,7 @@ class Filters(threading.Thread):
self.fillSitesFrame(vbox)
sitesFrame.add(vbox)
+ self.boxes['sites'] = vbox
# Game types
gamesFrame = gtk.Frame("Games:")
@@ -82,29 +87,29 @@ class Filters(threading.Thread):
self.fillGamesFrame(vbox)
gamesFrame.add(vbox)
+ self.boxes['games'] = vbox
# Limits
- limitsFrame = gtk.Frame("Limits:")
- limitsFrame.set_label_align(0.0, 0.0)
+ limitsFrame = gtk.Frame()
limitsFrame.show()
vbox = gtk.VBox(False, 0)
self.cbLimits = {}
self.cbNoLimits = None
self.cbAllLimits = None
- self.fillLimitsFrame(vbox, display)
+ self.fillLimitsFrame(vbox, self.display)
limitsFrame.add(vbox)
# Seats
- seatsFrame = gtk.Frame("Seats:")
- seatsFrame.set_label_align(0.0, 0.0)
+ seatsFrame = gtk.Frame()
seatsFrame.show()
vbox = gtk.VBox(False, 0)
self.sbSeats = {}
- self.fillSeatsFrame(vbox, display)
+ self.fillSeatsFrame(vbox, self.display)
seatsFrame.add(vbox)
+ # Date
dateFrame = gtk.Frame("Date:")
dateFrame.set_label_align(0.0, 0.0)
dateFrame.show()
@@ -112,11 +117,13 @@ class Filters(threading.Thread):
self.fillDateFrame(vbox)
dateFrame.add(vbox)
+ self.boxes['date'] = vbox
+ # Buttons
self.Button1=gtk.Button("Unnamed 1")
+ self.Button1.set_sensitive(False)
self.Button2=gtk.Button("Unnamed 2")
- #self.exportButton.connect("clicked", self.exportGraph, "show clicked")
self.Button2.set_sensitive(False)
self.mainVBox.add(playerFrame)
@@ -131,21 +138,21 @@ class Filters(threading.Thread):
self.mainVBox.show_all()
# Should do this cleaner
- if "Heroes" not in display or display["Heroes"] == False:
+ if "Heroes" not in self.display or self.display["Heroes"] == False:
playerFrame.hide()
- if "Sites" not in display or display["Sites"] == False:
+ if "Sites" not in self.display or self.display["Sites"] == False:
sitesFrame.hide()
- if "Games" not in display or display["Games"] == False:
+ if "Games" not in self.display or self.display["Games"] == False:
gamesFrame.hide()
- if "Limits" not in display or display["Limits"] == False:
+ if "Limits" not in self.display or self.display["Limits"] == False:
limitsFrame.hide()
- if "Seats" not in display or display["Seats"] == False:
+ if "Seats" not in self.display or self.display["Seats"] == False:
seatsFrame.hide()
- if "Dates" not in display or display["Dates"] == False:
+ if "Dates" not in self.display or self.display["Dates"] == False:
dateFrame.hide()
- if "Button1" not in display or display["Button1"] == False:
+ if "Button1" not in self.display or self.display["Button1"] == False:
self.Button1.hide()
- if "Button2" not in display or display["Button2"] == False:
+ if "Button2" not in self.display or self.display["Button2"] == False:
self.Button2.hide()
def get_vbox(self):
@@ -184,12 +191,14 @@ class Filters(threading.Thread):
def registerButton1Callback(self, callback):
self.Button1.connect("clicked", callback, "clicked")
+ self.Button1.set_sensitive(True)
def registerButton2Name(self, title):
self.Button2.set_label(title)
def registerButton2Callback(self, callback):
self.Button2.connect("clicked", callback, "clicked")
+ self.Button2.set_sensitive(True)
def cardCallback(self, widget, data=None):
print "DEBUG: %s was toggled %s" % (data, ("OFF", "ON")[widget.get_active()])
@@ -226,7 +235,7 @@ class Filters(threading.Thread):
cb = gtk.CheckButton(str(ltext))
cb.connect('clicked', self.__set_limit_select, limit)
hbox.pack_start(cb, False, False, 0)
- if limit != "None":
+ if limit != "none":
cb.set_active(True)
return(cb)
@@ -251,11 +260,11 @@ class Filters(threading.Thread):
else:
if self.cbAllLimits != None:
self.cbAllLimits.set_active(False)
- elif limit == "All":
+ elif limit == "all":
if self.limits[limit]:
for cb in self.cbLimits.values():
cb.set_active(True)
- elif limit == "None":
+ elif limit == "none":
if self.limits[limit]:
for cb in self.cbLimits.values():
cb.set_active(False)
@@ -298,38 +307,66 @@ class Filters(threading.Thread):
print "INFO: No games returned from database"
def fillLimitsFrame(self, vbox, display):
+ hbox = gtk.HBox(False, 0)
+ vbox.pack_start(hbox, False, False, 0)
+ lbl_title = gtk.Label(self.filterText['limitstitle'])
+ lbl_title.set_alignment(xalign=0.0, yalign=0.5)
+ hbox.pack_start(lbl_title, expand=True, padding=3)
+ showb = gtk.Button(label="hide", stock=None, use_underline=True)
+ showb.set_alignment(xalign=1.0, yalign=0.5)
+ showb.connect('clicked', self.__toggle_box, 'limits')
+ hbox.pack_start(showb, expand=False, padding=1)
+
+ vbox1 = gtk.VBox(False, 0)
+ vbox.pack_start(vbox1, False, False, 0)
+ self.boxes['limits'] = vbox1
+
self.cursor.execute(self.sql.query['getLimits'])
result = self.db.cursor.fetchall()
if len(result) >= 1:
hbox = gtk.HBox(True, 0)
- vbox.pack_start(hbox, False, False, 0)
- vbox1 = gtk.VBox(False, 0)
- hbox.pack_start(vbox1, False, False, 0)
+ vbox1.pack_start(hbox, False, False, 0)
vbox2 = gtk.VBox(False, 0)
hbox.pack_start(vbox2, False, False, 0)
+ vbox3 = gtk.VBox(False, 0)
+ hbox.pack_start(vbox3, False, False, 0)
for i, line in enumerate(result):
hbox = gtk.HBox(False, 0)
if i <= len(result)/2:
- vbox1.pack_start(hbox, False, False, 0)
- else:
vbox2.pack_start(hbox, False, False, 0)
+ else:
+ vbox3.pack_start(hbox, False, False, 0)
self.cbLimits[line[0]] = self.createLimitLine(hbox, line[0], line[0])
if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2:
hbox = gtk.HBox(False, 0)
- vbox.pack_start(hbox, False, True, 0)
+ vbox1.pack_start(hbox, False, True, 0)
self.cbAllLimits = self.createLimitLine(hbox, 'all', self.filterText['limitsall'])
hbox = gtk.HBox(False, 0)
- vbox.pack_start(hbox, False, True, 0)
+ vbox1.pack_start(hbox, False, True, 0)
self.cbNoLimits = self.createLimitLine(hbox, 'none', self.filterText['limitsnone'])
hbox = gtk.HBox(False, 0)
- vbox.pack_start(hbox, False, True, 0)
+ vbox1.pack_start(hbox, False, True, 0)
cb = self.createLimitLine(hbox, 'show', self.filterText['limitsshow'])
else:
print "INFO: No games returned from database"
def fillSeatsFrame(self, vbox, display):
hbox = gtk.HBox(False, 0)
- vbox.pack_start(hbox, False, True, 0)
+ vbox.pack_start(hbox, False, False, 0)
+ lbl_title = gtk.Label(self.filterText['seatstitle'])
+ lbl_title.set_alignment(xalign=0.0, yalign=0.5)
+ hbox.pack_start(lbl_title, expand=True, padding=3)
+ showb = gtk.Button(label="hide", stock=None, use_underline=True)
+ showb.set_alignment(xalign=1.0, yalign=0.5)
+ showb.connect('clicked', self.__toggle_box, 'seats')
+ hbox.pack_start(showb, expand=False, padding=1)
+
+ vbox1 = gtk.VBox(False, 0)
+ vbox.pack_start(vbox1, False, False, 0)
+ self.boxes['seats'] = vbox1
+
+ hbox = gtk.HBox(False, 0)
+ vbox1.pack_start(hbox, False, True, 0)
lbl_from = gtk.Label(self.filterText['seatsbetween'])
lbl_to = gtk.Label(self.filterText['seatsand'])
@@ -338,8 +375,6 @@ class Filters(threading.Thread):
adj2 = gtk.Adjustment(value=10, lower=2, upper=10, step_incr=1, page_incr=1, page_size=0)
sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0)
-
-
hbox.pack_start(lbl_from, expand=False, padding=3)
hbox.pack_start(sb1, False, False, 0)
hbox.pack_start(lbl_to, expand=False, padding=3)
@@ -347,7 +382,7 @@ class Filters(threading.Thread):
if "SeatSep" in display and display["SeatSep"] == True:
hbox = gtk.HBox(False, 0)
- vbox.pack_start(hbox, False, True, 0)
+ vbox1.pack_start(hbox, False, True, 0)
cb = gtk.CheckButton(self.filterText['seatsshow'])
cb.connect('clicked', self.__set_seat_select, 'show')
hbox.pack_start(cb, False, False, 0)
@@ -358,8 +393,6 @@ class Filters(threading.Thread):
self.sbSeats['from'] = sb1
self.sbSeats['to'] = sb2
-
-
def fillCardsFrame(self, vbox):
hbox1 = gtk.HBox(True,0)
hbox1.show()
@@ -414,6 +447,16 @@ class Filters(threading.Thread):
hbox.pack_start(btn_clear, expand=False, padding=15)
+ def __toggle_box(self, widget, entry):
+ if "Limits" not in self.display or self.display["Limits"] == False:
+ self.boxes[entry].hide()
+ elif self.boxes[entry].props.visible:
+ self.boxes[entry].hide()
+ widget.set_label("show")
+ else:
+ self.boxes[entry].show()
+ widget.set_label("hide")
+
def __calendar_dialog(self, widget, entry):
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
d.set_title('Pick a date')
diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py
index dd770106..422da934 100644
--- a/pyfpdb/FpdbSQLQueries.py
+++ b/pyfpdb/FpdbSQLQueries.py
@@ -183,37 +183,67 @@ class FpdbSQLQueries:
gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
handStart DATETIME NOT NULL,
importTime DATETIME NOT NULL,
- seats SMALLINT NOT NULL,
- maxSeats SMALLINT NOT NULL,
- vpi SMALLINT,
- street0Seen SMALLINT,
- street1Seen SMALLINT,
- street2Seen SMALLINT,
- street3Seen SMALLINT,
- street4Seen SMALLINT,
- sdSeen SMALLINT,
+ seats TINYINT NOT NULL,
+ maxSeats TINYINT NOT NULL,
+ boardcard1 smallint, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */
+ boardcard2 smallint,
+ boardcard3 smallint,
+ boardcard4 smallint,
+ boardcard5 smallint,
+ texture smallint,
+ playersVpi SMALLINT NOT NULL, /* num of players vpi */
+ playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */
+ playersAtStreet2 SMALLINT NOT NULL,
+ playersAtStreet3 SMALLINT NOT NULL,
+ playersAtStreet4 SMALLINT NOT NULL,
+ playersAtShowdown SMALLINT NOT NULL,
+ street0Raises TINYINT NOT NULL, /* num small bets paid to see flop/street4, including blind */
+ street1Raises TINYINT NOT NULL, /* num small bets paid to see turn/street5 */
+ street2Raises TINYINT NOT NULL, /* num big bets paid to see river/street6 */
+ street3Raises TINYINT NOT NULL, /* num big bets paid to see sd/street7 */
+ street4Raises TINYINT NOT NULL, /* num big bets paid to see showdown */
+ street1Pot INT, /* pot size at flop/street4 */
+ street2Pot INT, /* pot size at turn/street5 */
+ street3Pot INT, /* pot size at river/street6 */
+ street4Pot INT, /* pot size at sd/street7 */
+ showdownPot INT, /* pot size at sd/street7 */
comment TEXT,
commentTs DATETIME)
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createHandsTable'] = """CREATE TABLE Hands (
- id BIGSERIAL, PRIMARY KEY (id),
- tableName VARCHAR(20),
- siteHandNo BIGINT,
- gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
- handStart timestamp without time zone,
- importTime timestamp without time zone,
- seats SMALLINT,
- maxSeats SMALLINT,
- vpi SMALLINT,
- street0Seen SMALLINT,
- street1Seen SMALLINT,
- street2Seen SMALLINT,
- street3Seen SMALLINT,
- street4Seen SMALLINT,
- sdSeen SMALLINT,
- comment TEXT,
- commentTs timestamp without time zone)"""
+ id BIGSERIAL, PRIMARY KEY (id),
+ tableName VARCHAR(20) NOT NULL,
+ siteHandNo BIGINT NOT NULL,
+ gametypeId INT NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
+ handStart timestamp without time zone NOT NULL,
+ importTime timestamp without time zone NOT NULL,
+ seats SMALLINT NOT NULL,
+ maxSeats SMALLINT NOT NULL,
+ boardcard1 smallint, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */
+ boardcard2 smallint,
+ boardcard3 smallint,
+ boardcard4 smallint,
+ boardcard5 smallint,
+ texture smallint,
+ playersVpi SMALLINT NOT NULL, /* num of players vpi */
+ playersAtStreet1 SMALLINT NOT NULL, /* num of players seeing flop/street4 */
+ playersAtStreet2 SMALLINT NOT NULL,
+ playersAtStreet3 SMALLINT NOT NULL,
+ playersAtStreet4 SMALLINT NOT NULL,
+ playersAtShowdown SMALLINT NOT NULL,
+ street0Raises SMALLINT NOT NULL, /* num small bets paid to see flop/street4, including blind */
+ street1Raises SMALLINT NOT NULL, /* num small bets paid to see turn/street5 */
+ street2Raises SMALLINT NOT NULL, /* num big bets paid to see river/street6 */
+ street3Raises SMALLINT NOT NULL, /* num big bets paid to see sd/street7 */
+ street4Raises SMALLINT NOT NULL, /* num big bets paid to see showdown */
+ street1Pot INT, /* pot size at flop/street4 */
+ street2Pot INT, /* pot size at turn/street5 */
+ street3Pot INT, /* pot size at river/street6 */
+ street4Pot INT, /* pot size at sd/street7 */
+ showdownPot INT, /* pot size at sd/street7 */
+ comment TEXT,
+ commentTs timestamp without time zone)"""
elif(self.dbname == 'SQLite'):
self.query['createHandsTable'] = """ """
@@ -321,20 +351,13 @@ class FpdbSQLQueries:
position CHAR(1),
seatNo SMALLINT NOT NULL,
- card1Value smallint NOT NULL,
- card1Suit char(1) NOT NULL,
- card2Value smallint NOT NULL,
- card2Suit char(1) NOT NULL,
- card3Value smallint,
- card3Suit char(1),
- card4Value smallint,
- card4Suit char(1),
- card5Value smallint,
- card5Suit char(1),
- card6Value smallint,
- card6Suit char(1),
- card7Value smallint,
- card7Suit char(1),
+ card1 smallint NOT NULL, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */
+ card2 smallint NOT NULL,
+ card3 smallint,
+ card4 smallint,
+ card5 smallint,
+ card6 smallint,
+ card7 smallint,
startCards smallint,
ante INT,
@@ -416,7 +439,25 @@ class FpdbSQLQueries:
street3CheckCallRaiseDone BOOLEAN NOT NULL,
street4CheckCallRaiseChance BOOLEAN NOT NULL,
street4CheckCallRaiseDone BOOLEAN NOT NULL,
-
+
+ street0Calls TINYINT,
+ street1Calls TINYINT,
+ street2Calls TINYINT,
+ street3Calls TINYINT,
+ street4Calls TINYINT,
+ street0Bets TINYINT,
+ street1Bets TINYINT,
+ street2Bets TINYINT,
+ street3Bets TINYINT,
+ street4Bets TINYINT,
+ street0Raises TINYINT,
+ street1Raises TINYINT,
+ street2Raises TINYINT,
+ street3Raises TINYINT,
+ street4Raises TINYINT,
+
+ actionString VARCHAR(15),
+
FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id))
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
@@ -428,20 +469,13 @@ class FpdbSQLQueries:
position CHAR(1),
seatNo SMALLINT NOT NULL,
- card1Value smallint NOT NULL,
- card1Suit char(1) NOT NULL,
- card2Value smallint NOT NULL,
- card2Suit char(1) NOT NULL,
- card3Value smallint,
- card3Suit char(1),
- card4Value smallint,
- card4Suit char(1),
- card5Value smallint,
- card5Suit char(1),
- card6Value smallint,
- card6Suit char(1),
- card7Value smallint,
- card7Suit char(1),
+ card1 smallint NOT NULL, /* 0=none, 1-13=2-Ah 14-26=2-Ad 27-39=2-Ac 40-52=2-As */
+ card2 smallint NOT NULL,
+ card3 smallint,
+ card4 smallint,
+ card5 smallint,
+ card6 smallint,
+ card7 smallint,
startCards smallint,
ante INT,
@@ -524,6 +558,24 @@ class FpdbSQLQueries:
street4CheckCallRaiseChance BOOLEAN NOT NULL,
street4CheckCallRaiseDone BOOLEAN NOT NULL,
+ street0Calls SMALLINT,
+ street1Calls SMALLINT,
+ street2Calls SMALLINT,
+ street3Calls SMALLINT,
+ street4Calls SMALLINT,
+ street0Bets SMALLINT,
+ street1Bets SMALLINT,
+ street2Bets SMALLINT,
+ street3Bets SMALLINT,
+ street4Bets SMALLINT,
+ street0Raises SMALLINT,
+ street1Raises SMALLINT,
+ street2Raises SMALLINT,
+ street3Raises SMALLINT,
+ street4Raises SMALLINT,
+
+ actionString VARCHAR(15),
+
FOREIGN KEY (tourneysPlayersId) REFERENCES TourneysPlayers(id))"""
elif(self.dbname == 'SQLite'):
self.query['createHandsPlayersTable'] = """ """
@@ -674,7 +726,24 @@ class FpdbSQLQueries:
street3CheckCallRaiseChance INT NOT NULL,
street3CheckCallRaiseDone INT NOT NULL,
street4CheckCallRaiseChance INT NOT NULL,
- street4CheckCallRaiseDone INT NOT NULL)
+ street4CheckCallRaiseDone INT NOT NULL,
+
+ street0Calls INT,
+ street1Calls INT,
+ street2Calls INT,
+ street3Calls INT,
+ street4Calls INT,
+ street0Bets INT,
+ street1Bets INT,
+ street2Bets INT,
+ street3Bets INT,
+ street4Bets INT,
+ street0Raises INT,
+ street1Raises INT,
+ street2Raises INT,
+ street3Raises INT,
+ street4Raises INT)
+
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createHudCacheTable'] = """CREATE TABLE HudCache (
@@ -756,7 +825,24 @@ class FpdbSQLQueries:
street3CheckCallRaiseChance INT,
street3CheckCallRaiseDone INT,
street4CheckCallRaiseChance INT,
- street4CheckCallRaiseDone INT)"""
+ street4CheckCallRaiseDone INT,
+
+ street0Calls INT,
+ street1Calls INT,
+ street2Calls INT,
+ street3Calls INT,
+ street4Calls INT,
+ street0Bets INT,
+ street1Bets INT,
+ street2Bets INT,
+ street3Bets INT,
+ street4Bets INT,
+ street0Raises INT,
+ street1Raises INT,
+ street2Raises INT,
+ street3Raises INT,
+ street4Raises INT)
+ """
elif(self.dbname == 'SQLite'):
self.query['createHudCacheTable'] = """ """
@@ -867,6 +953,8 @@ class FpdbSQLQueries:
where hp.playerId in
and hp.tourneysPlayersId IS NULL
and h.seats
+
+
group by hgameTypeId
,hp.playerId
,gt.base
@@ -878,6 +966,8 @@ class FpdbSQLQueries:
,gt.base
,gt.category
+
+ ,maxbigblind desc
,upper(gt.limitType)
,s.name
"""
diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py
index 73cb981f..a7f3abf1 100644
--- a/pyfpdb/GuiPlayerStats.py
+++ b/pyfpdb/GuiPlayerStats.py
@@ -20,7 +20,9 @@ import pygtk
pygtk.require('2.0')
import gtk
import os
-
+from time import time, strftime
+
+import Card
import fpdb_import
import fpdb_db
import Filters
@@ -47,6 +49,10 @@ class GuiPlayerStats (threading.Thread):
settings.update(config.get_import_parameters())
settings.update(config.get_default_paths())
+ # text used on screen stored here so that it can be configured
+ self.filterText = {'handhead':'Hand Breakdown for all levels listed above'
+ }
+
filters_display = { "Heroes" : True,
"Sites" : True,
"Games" : False,
@@ -55,65 +61,93 @@ class GuiPlayerStats (threading.Thread):
"Seats" : True,
"SeatSep" : True,
"Dates" : False,
+ "Groups" : True,
"Button1" : True,
- "Button2" : False
+ "Button2" : True
}
self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display)
- self.filters.registerButton1Name("Refresh")
- self.filters.registerButton1Callback(self.refreshStats)
+ self.filters.registerButton1Name("_Filters")
+ self.filters.registerButton1Callback(self.showDetailFilter)
+ self.filters.registerButton2Name("_Refresh")
+ self.filters.registerButton2Callback(self.refreshStats)
- # TODO: these probably be a dict keyed on colAlias and the headings loop should use colAlias ...
- # This could be stored in config eventually, or maybe configured in this window somehow.
- # Each colAlias element is the name of a column returned by the sql
- # query (in lower case) and each colHeads element is the text to use as
- # the heading in the GUI. Both sequences should be the same length.
- # To miss columns out remove them from both tuples (the 1st 2 elements should always be included).
- # To change the heading just edit the second list element as required
- # If the first list element does not match a query column that pair is ignored
- self.colAlias = ( "game", "n", "avgseats", "vpip", "pfr", "pf3", "steals"
- , "saw_f", "sawsd", "wtsdwsf", "wmsd", "flafq", "tuafq", "rvafq"
- , "pofafq", "net", "bbper100", "rake", "variance"
- )
- self.colHeads = ( "Game", "Hds", "Seats", "VPIP", "PFR", "PF3", "Steals"
- , "Saw_F", "SawSD", "WtSDwsF", "W$SD", "FlAFq", "TuAFq", "RvAFq"
- , "PoFAFq", "Net($)", "BB/100", "Rake($)", "Variance"
- )
- self.colXAligns = ( 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
- , 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
- , 1.0, 1.0, 1.0, 1.0, 1.0
- )
- self.colFormats = ( "%s", "%d", "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f"
- , "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f", "%3.1f"
- , "%3.1f", "%6.2f", "%4.2f", "%6.2f", "%5.2f"
- )
+ # ToDo: store in config
+ # ToDo: create popup to adjust column config
+ # columns to display, keys match column name returned by sql, values in tuple are:
+ # is column displayed, column heading, xalignment, formatting
+ self.columns = [ ("game", True, "Game", 0.0, "%s")
+ , ("hand", False, "Hand", 0.0, "%s") # true not allowed for this line
+ , ("n", True, "Hds", 1.0, "%d")
+ , ("avgseats", True, "Seats", 1.0, "%3.1f")
+ , ("vpip", True, "VPIP", 1.0, "%3.1f")
+ , ("pfr", True, "PFR", 1.0, "%3.1f")
+ , ("pf3", True, "PF3", 1.0, "%3.1f")
+ , ("steals", True, "Steals", 1.0, "%3.1f")
+ , ("saw_f", True, "Saw_F", 1.0, "%3.1f")
+ , ("sawsd", True, "SawSD", 1.0, "%3.1f")
+ , ("wtsdwsf", True, "WtSDwsF", 1.0, "%3.1f")
+ , ("wmsd", True, "W$SD", 1.0, "%3.1f")
+ , ("flafq", True, "FlAFq", 1.0, "%3.1f")
+ , ("tuafq", True, "TuAFq", 1.0, "%3.1f")
+ , ("rvafq", True, "RvAFq", 1.0, "%3.1f")
+ , ("pofafq", False, "PoFAFq", 1.0, "%3.1f")
+ , ("net", True, "Net($)", 1.0, "%6.2f")
+ , ("bbper100", True, "BB/100", 1.0, "%4.2f")
+ , ("rake", True, "Rake($)", 1.0, "%6.2f")
+ , ("variance", True, "Variance", 1.0, "%5.2f")
+ ]
+
+ # Detail filters: This holds the data used in the popup window, extra values are
+ # added at the end of these lists during processing
+ # sql test, screen description, min, max
+ self.handtests = [ # already in filter class : ['h.seats', 'Number of Players', 2, 10]
+ ['h.maxSeats', 'Size of Table', 2, 10]
+ ,['h.playersVpi', 'Players who VPI', 0, 10]
+ ,['h.playersAtStreet1', 'Players at Flop', 0, 10]
+ ,['h.playersAtStreet2', 'Players at Turn', 0, 10]
+ ,['h.playersAtStreet3', 'Players at River', 0, 10]
+ ,['h.playersAtStreet4', 'Players at Street7', 0, 10]
+ ,['h.playersAtShowdown', 'Players at Showdown', 0, 10]
+ ,['h.street0Raises', 'Bets to See Flop', 0, 5]
+ ,['h.street1Raises', 'Bets to See Turn', 0, 5]
+ ,['h.street2Raises', 'Bets to See River', 0, 5]
+ ,['h.street3Raises', 'Bets to See Street7', 0, 5]
+ ,['h.street4Raises', 'Bets to See Showdown', 0, 5]
+ ]
- self.stat_table = None
self.stats_frame = None
+ self.stats_vbox = None
+ self.detailFilters = [] # the data used to enhance the sql select
self.main_hbox = gtk.HBox(False, 0)
self.main_hbox.show()
- statsFrame = gtk.Frame("Stats:")
- statsFrame.set_label_align(0.0, 0.0)
- statsFrame.show()
- self.stats_frame = gtk.VBox(False, 0)
+ self.stats_frame = gtk.Frame()
self.stats_frame.show()
- self.fillStatsFrame(self.stats_frame)
- statsFrame.add(self.stats_frame)
+ self.stats_vbox = gtk.VBox(False, 0)
+ self.stats_vbox.show()
+ self.stats_frame.add(self.stats_vbox)
+ self.fillStatsFrame(self.stats_vbox)
self.main_hbox.pack_start(self.filters.get_vbox())
- self.main_hbox.pack_start(statsFrame)
+ self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True)
+
+ # make sure Hand column is not displayed
+ [x for x in self.columns if x[0] == 'hand'][0][1] == False
def get_vbox(self):
"""returns the vbox of this thread"""
return self.main_hbox
def refreshStats(self, widget, data):
- try: self.stats_table.destroy()
+ try: self.stats_vbox.destroy()
except AttributeError: pass
- self.fillStatsFrame(self.stats_frame)
+ self.stats_vbox = gtk.VBox(False, 0)
+ self.stats_vbox.show()
+ self.stats_frame.add(self.stats_vbox)
+ self.fillStatsFrame(self.stats_vbox)
def fillStatsFrame(self, vbox):
sites = self.filters.getSites()
@@ -147,72 +181,137 @@ class GuiPlayerStats (threading.Thread):
self.createStatsTable(vbox, playerids, sitenos, limits, seats)
def createStatsTable(self, vbox, playerids, sitenos, limits, seats):
+ starttime = time()
+
+ # Display summary table at top of page
+ # 3rd parameter passes extra flags, currently includes:
+ # holecards - whether to display card breakdown (True/False)
+ flags = [False]
+ self.addTable(vbox, 'playerDetailedStats', flags, playerids, sitenos, limits, seats)
+
+ # Separator
+ sep = gtk.HSeparator()
+ vbox.pack_start(sep, expand=False, padding=3)
+ sep.show_now()
+ vbox.show_now()
+ heading = gtk.Label(self.filterText['handhead'])
+ heading.show()
+ vbox.pack_start(heading, expand=False, padding=3)
+
+ # Scrolled window for detailed table (display by hand)
+ swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
+ swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ swin.show()
+ vbox.pack_start(swin, expand=True, padding=3)
+
+ vbox1 = gtk.VBox(False, 0)
+ vbox1.show()
+ swin.add_with_viewport(vbox1)
+
+ # Detailed table
+ flags = [True]
+ self.addTable(vbox1, 'playerDetailedStats', flags, playerids, sitenos, limits, seats)
+
+ self.db.db.commit()
+ print "Stats page displayed in %4.2f seconds" % (time() - starttime)
+ #end def fillStatsFrame(self, vbox):
+
+ def addTable(self, vbox, query, flags, playerids, sitenos, limits, seats):
+ row = 0
+ sqlrow = 0
+ colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4
+ if not flags: holecards = False
+ else: holecards = flags[0]
+
+
self.stats_table = gtk.Table(1, 1, False)
self.stats_table.set_col_spacings(4)
self.stats_table.show()
- vbox.add(self.stats_table)
-
- # Create header row
- row = 0
- col = 0
- for t in self.colHeads:
- l = gtk.Label(self.colHeads[col])
- l.set_alignment(xalign=self.colXAligns[col], yalign=0.5)
- l.show()
- self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK)
- col +=1
-
- tmp = self.sql.query['playerDetailedStats']
- tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats)
+
+ tmp = self.sql.query[query]
+ tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats)
self.cursor.execute(tmp)
result = self.cursor.fetchall()
-
- #cols = 19
- rows = len(result) # +1 for title row
colnames = [desc[0].lower() for desc in self.cursor.description]
- col = 0
- for row in range(rows):
+ # pre-fetch some constant values:
+ cols_to_show = [x for x in self.columns if x[colshow]]
+ hgametypeid_idx = colnames.index('hgametypeid')
+
+ liststore = gtk.ListStore(*([str] * len(cols_to_show)))
+ view = gtk.TreeView(model=liststore)
+ view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
+ vbox.pack_start(view, expand=False, padding=3)
+ textcell = gtk.CellRendererText()
+ numcell = gtk.CellRendererText()
+ numcell.set_property('xalign', 1.0)
+ listcols = []
+
+ # Create header row eg column: ("game", True, "Game", 0.0, "%s")
+ for col, column in enumerate(cols_to_show):
+ if column[colalias] == 'game' and holecards:
+ s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading]
+ else:
+ s = column[colheading]
+ listcols.append(gtk.TreeViewColumn(s))
+ view.append_column(listcols[col])
+ if column[colformat] == '%s':
+ if col == 1 and holecards:
+ listcols[col].pack_start(textcell, expand=True)
+ else:
+ listcols[col].pack_start(textcell, expand=False)
+ listcols[col].add_attribute(textcell, 'text', col)
+ else:
+ listcols[col].pack_start(numcell, expand=False)
+ listcols[col].add_attribute(numcell, 'text', col)
+
+ rows = len(result) # +1 for title row
+
+ while sqlrow < rows:
+ treerow = []
if(row%2 == 0):
bgcolor = "white"
else:
bgcolor = "lightgrey"
- for col,colname in enumerate(self.colAlias):
- if colname in colnames:
- value = result[row][colnames.index(colname)]
+ for col,column in enumerate(cols_to_show):
+ if column[colalias] in colnames:
+ value = result[sqlrow][colnames.index(column[colalias])]
else:
- if colname == 'game':
- minbb = result[row][colnames.index('minbigblind')]
- maxbb = result[row][colnames.index('maxbigblind')]
- value = result[row][colnames.index('limittype')] + ' ' \
- + result[row][colnames.index('category')].title() + ' ' \
- + result[row][colnames.index('name')] + ' $'
- if 100 * int(minbb/100.0) != minbb:
- value += '%.2f' % (minbb/100.0)
+ if column[colalias] == 'game':
+ if holecards:
+ value = Card.twoStartCardString( result[sqlrow][hgametypeid_idx] )
else:
- value += '%.0f' % (minbb/100.0)
- if minbb != maxbb:
- if 100 * int(maxbb/100.0) != maxbb:
- value += ' - $' + '%.2f' % (maxbb/100.0)
+ minbb = result[sqlrow][colnames.index('minbigblind')]
+ maxbb = result[sqlrow][colnames.index('maxbigblind')]
+ value = result[sqlrow][colnames.index('limittype')] + ' ' \
+ + result[sqlrow][colnames.index('category')].title() + ' ' \
+ + result[sqlrow][colnames.index('name')] + ' $'
+ if 100 * int(minbb/100.0) != minbb:
+ value += '%.2f' % (minbb/100.0)
else:
- value += ' - $' + '%.0f' % (maxbb/100.0)
+ value += '%.0f' % (minbb/100.0)
+ if minbb != maxbb:
+ if 100 * int(maxbb/100.0) != maxbb:
+ value += ' - $' + '%.2f' % (maxbb/100.0)
+ else:
+ value += ' - $' + '%.0f' % (maxbb/100.0)
else:
continue
- eb = gtk.EventBox()
- eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
if value and value != -999:
- l = gtk.Label(self.colFormats[col] % value)
+ treerow.append(column[colformat] % value)
else:
- l = gtk.Label(' ')
- l.set_alignment(xalign=self.colXAligns[col], 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):
+ treerow.append(' ')
+ iter = liststore.append(treerow)
+ sqlrow += 1
+ row += 1
+ vbox.show_all()
+
+ #end def addTable(self, query, vars, playerids, sitenos, limits, seats):
+
+ def refineQuery(self, query, flags, playerids, sitenos, limits, seats):
+ if not flags: holecards = False
+ else: holecards = flags[0]
- def refineQuery(self, query, playerids, sitenos, limits, seats):
if playerids:
nametest = str(tuple(playerids))
nametest = nametest.replace("L", "")
@@ -238,20 +337,32 @@ class GuiPlayerStats (threading.Thread):
blindtest = str(tuple([x for x in limits if str(x).isdigit()]))
blindtest = blindtest.replace("L", "")
blindtest = blindtest.replace(",)",")")
- query = query.replace("", "gt.bigBlind in " + blindtest)
+ query = query.replace("", " and gt.bigBlind in " + blindtest + " ")
else:
- query = query.replace("", "gt.bigBlind = -1 ")
+ query = query.replace("", "")
- groupLevels = "show" not in str(limits)
- if groupLevels:
- query = query.replace("", "")
- query = query.replace("", "-1")
- query = query.replace("", "-1")
+ if holecards: # pinch level variables for hole card query
+ query = query.replace("", "hp.startcards")
+ query = query.replace("", ",hgameTypeId desc")
else:
- query = query.replace("", ",gt.bigBlind")
- query = query.replace("", "hc.gametypeId")
- query = query.replace("", "h.gameTypeId")
+ query = query.replace("", "")
+ groupLevels = "show" not in str(limits)
+ if groupLevels:
+ query = query.replace("", "-1")
+ else:
+ query = query.replace("", "h.gameTypeId")
+ # process self.detailFilters (a list of tuples)
+ flagtest = ''
+ #self.detailFilters = [('h.seats', 5, 6)] # for debug
+ if self.detailFilters:
+ for f in self.detailFilters:
+ if len(f) == 3:
+ # X between Y and Z
+ flagtest += ' and %s between %s and %s ' % (f[0], str(f[1]), str(f[2]))
+ query = query.replace("", flagtest)
+
+ # allow for differences in sql cast() function:
if self.db.backend == self.MYSQL_INNODB:
query = query.replace("", 'signed ')
else:
@@ -260,3 +371,70 @@ class GuiPlayerStats (threading.Thread):
#print "query =\n", query
return(query)
#end def refineQuery(self, query, playerids, sitenos, limits):
+
+ def showDetailFilter(self, widget, data):
+ detailDialog = gtk.Dialog(title="Detailed Filters", parent=self.main_window
+ ,flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
+ ,buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
+ gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
+
+ handbox = gtk.VBox(True, 0)
+ detailDialog.vbox.pack_start(handbox, False, False, 0)
+ handbox.show()
+
+ label = gtk.Label("Hand Filters:")
+ handbox.add(label)
+ label.show()
+
+ betweenFilters = []
+ for htest in self.handtests:
+ hbox = gtk.HBox(False, 0)
+ handbox.pack_start(hbox, False, False, 0)
+ hbox.show()
+
+ cb = gtk.CheckButton()
+ lbl_from = gtk.Label(htest[1])
+ lbl_from.set_alignment(xalign=0.0, yalign=0.5)
+ lbl_tween = gtk.Label('between')
+ lbl_to = gtk.Label('and')
+ adj1 = gtk.Adjustment(value=htest[2], lower=0, upper=10, step_incr=1, page_incr=1, page_size=0)
+ sb1 = gtk.SpinButton(adjustment=adj1, climb_rate=0.0, digits=0)
+ adj2 = gtk.Adjustment(value=htest[3], lower=2, upper=10, step_incr=1, page_incr=1, page_size=0)
+ sb2 = gtk.SpinButton(adjustment=adj2, climb_rate=0.0, digits=0)
+
+ for df in [x for x in self.detailFilters if x[0] == htest[0]]:
+ cb.set_active(True)
+
+ hbox.pack_start(cb, expand=False, padding=3)
+ hbox.pack_start(lbl_from, expand=True, padding=3)
+ hbox.pack_start(lbl_tween, expand=False, padding=3)
+ hbox.pack_start(sb1, False, False, 0)
+ hbox.pack_start(lbl_to, expand=False, padding=3)
+ hbox.pack_start(sb2, False, False, 0)
+
+ cb.show()
+ lbl_from.show()
+ lbl_tween.show()
+ sb1.show()
+ lbl_to.show()
+ sb2.show()
+
+ htest[4:7] = [cb,sb1,sb2]
+
+ response = detailDialog.run()
+
+ if response == gtk.RESPONSE_ACCEPT:
+ self.detailFilters = []
+ for ht in self.handtests:
+ if ht[4].get_active():
+ self.detailFilters.append( (ht[0], ht[5].get_value_as_int(), ht[6].get_value_as_int()) )
+ ht[2],ht[3] = ht[5].get_value_as_int(), ht[6].get_value_as_int()
+ print "detailFilters =", self.detailFilters
+ self.refreshStats(None, None)
+
+ detailDialog.destroy()
+
+
+
+
+
diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py
index 9eb42d0f..6d4c3241 100644
--- a/pyfpdb/SQL.py
+++ b/pyfpdb/SQL.py
@@ -349,13 +349,13 @@ class Sql:
select
seatNo AS seat_number,
name AS screen_name,
- card1Value, card1Suit,
- card2Value, card2Suit,
- card3Value, card3Suit,
- card4Value, card4Suit,
- card5Value, card5Suit,
- card6Value, card6Suit,
- card7Value, card7Suit
+ card1, /*card1Value, card1Suit, */
+ card2, /*card2Value, card2Suit, */
+ card3, /*card3Value, card3Suit, */
+ card4, /*card4Value, card4Suit, */
+ card5, /*card5Value, card5Suit, */
+ card6, /*card6Value, card6Suit, */
+ card7 /*card7Value, card7Suit */
from HandsPlayers, Players
where handID = %s and HandsPlayers.playerId = Players.id
order by seatNo
diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py
index f983b910..18344030 100644
--- a/pyfpdb/fpdb_save_to_db.py
+++ b/pyfpdb/fpdb_save_to_db.py
@@ -82,11 +82,11 @@ def ring_holdem_omaha(config, backend, db, cursor, base, category, site_hand_no,
t2 = time()
hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id
- ,hand_start_time, names, tableName, maxSeats)
+ ,hand_start_time, names, tableName, maxSeats, hudImportData)
t3 = time()
hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha(
backend, db, cursor, category, hands_id, player_ids, start_cashes
- , positions, card_values, card_suits, winnings, rakes, seatNos)
+ , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData)
t4 = time()
#print "ring holdem, backend=%d" % backend
if fastStoreHudCache:
diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py
index cd8a9e76..2b36cf01 100644
--- a/pyfpdb/fpdb_simple.py
+++ b/pyfpdb/fpdb_simple.py
@@ -20,6 +20,8 @@
import datetime
import time
import re
+
+import Card
PS = 1
FTP = 2
@@ -1448,14 +1450,29 @@ card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
#end def store_board_cards
def storeHands(backend, conn, cursor, site_hand_no, gametype_id
- ,hand_start_time, names, tableName, maxSeats):
-#stores into table hands
- cursor.execute ("INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats) VALUES (%s, %s, %s, %s, %s, %s, %s)", (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats))
- #todo: find a better way of doing this...
- #cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id))
- #return cursor.fetchall()[0][0]
+ ,hand_start_time, names, tableName, maxSeats, hudCache):
+#stores into table hands:
+ cursor.execute ("""INSERT INTO Hands
+ (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats
+ ,playersVpi, playersAtStreet1, playersAtStreet2
+ ,playersAtStreet3, playersAtStreet4, playersAtShowdown
+ ,street0Raises, street1Raises, street2Raises
+ ,street3Raises, street4Raises, street1Pot
+ ,street2Pot, street3Pot, street4Pot
+ ,showdownPot
+ )
+ VALUES
+ (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
+ """
+ , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats
+ ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2']
+ ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown']
+ ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises']
+ ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot']
+ ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot']
+ ,hudCache['showdownPot']
+ ))
return getLastInsertId(backend, conn, cursor)
- #return db.insert_id() # mysql only
#end def storeHands
def store_hands_players_holdem_omaha(backend, conn, cursor, category, hands_id, player_ids, start_cashes
@@ -1474,14 +1491,13 @@ def store_hands_players_holdem_omaha(backend, conn, cursor, category, hands_id,
if (category=="holdem"):
for i in xrange(len(player_ids)):
- x,y = card_values[i][0],card_values[i][1]
- if (card_suits[i][0] == card_suits[i][1] and x < y) or (card_suits[i][0] != card_suits[i][1] and x > y):
- x,y = y,x
- startCards = 13 * (x-2) + (y-2)
+ startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1])
+ card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0])
+ card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1])
cursor.execute ("""
INSERT INTO HandsPlayers
-(handId, playerId, startCash, position, activeSeats, tourneyTypeId,
- card1Value, card1Suit, card2Value, card2Suit, winnings, rake, seatNo, totalProfit,
+(handId, playerId, startCash, position, tourneyTypeId,
+ card1, card2, startCards, winnings, rake, seatNo, totalProfit,
street0VPI, street0Aggr, street0_3BChance, street0_3BDone,
street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown,
street1Aggr, street2Aggr, street3Aggr, street4Aggr,
@@ -1494,13 +1510,16 @@ INSERT INTO HandsPlayers
foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone,
foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone,
street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone,
- street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone
+ street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone,
+ street0Calls, street1Calls, street2Calls, street3Calls, street4Calls,
+ street0Bets, street1Bets, street2Bets, street3Bets, street4Bets
)
-VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
+VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
- %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
- (hands_id, player_ids[i], start_cashes[i], positions[i], len(player_ids), 1, # tourneytypeid
- card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1],
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
+ %s, %s, %s, %s, %s, %s, %s, %s)""",
+ (hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid
+ card1, card2, startCards,
winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i],
hudCache['street0VPI'][i], hudCache['street0Aggr'][i],
hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i],
@@ -1523,7 +1542,9 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i],
hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i],
hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i],
- hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i]
+ hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i],
+ hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], hudCache['street3Calls'][i], hudCache['street4Calls'][i],
+ hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], hudCache['street3Bets'][i], hudCache['street4Bets'][i]
) )
#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i]))
#result.append(cursor.fetchall()[0][0])
@@ -1531,8 +1552,8 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
elif (category=="omahahi" or category=="omahahilo"):
for i in xrange(len(player_ids)):
cursor.execute ("""INSERT INTO HandsPlayers
-(handId, playerId, startCash, position, activeSeats, tourneyTypeId,
- card1Value, card1Suit, card2Value, card2Suit,
+(handId, playerId, startCash, position, tourneyTypeId,
+ card1Value, card1Suit, card2Value, card2Suit,
card3Value, card3Suit, card4Value, card4Suit, winnings, rake, seatNo, totalProfit,
street0VPI, street0Aggr, street0_3BChance, street0_3BDone,
street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown,
@@ -1546,12 +1567,15 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
foldToStreet1CBChance, foldToStreet1CBDone, foldToStreet2CBChance, foldToStreet2CBDone,
foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, foldToStreet4CBDone,
street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone,
- street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone
+ street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone,
+ street0Calls, street1Calls, street2Calls, street3Calls, street4Calls,
+ street0Bets, street1Bets, street2Bets, street3Bets, street4Bets
)
-VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
+VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
- %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
- (hands_id, player_ids[i], start_cashes[i], positions[i], len(player_ids), 1, # tourneytypeid
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
+ %s, %s, %s, %s, %s, %s, %s, %s)""",
+ (hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid
card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1],
card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3],
winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i],
@@ -1576,7 +1600,9 @@ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i],
hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i],
hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i],
- hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i]
+ hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i],
+ hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], hudCache['street3Calls'][i], hudCache['street4Calls'][i],
+ hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], hudCache['street3Bets'][i], hudCache['street4Bets'][i]
) )
#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i]))
#result.append(cursor.fetchall()[0][0])
@@ -1705,6 +1731,41 @@ sure to also change the following storage method and table_viewer.prepare_data i
stealAttempted=[]
hudDataPositions=[]
+ street0Calls=[]
+ street1Calls=[]
+ street2Calls=[]
+ street3Calls=[]
+ street4Calls=[]
+ street0Bets=[]
+ street1Bets=[]
+ street2Bets=[]
+ street3Bets=[]
+ street4Bets=[]
+ #street0Raises=[]
+ #street1Raises=[]
+ #street2Raises=[]
+ #street3Raises=[]
+ #street4Raises=[]
+
+ # Summary figures for hand table:
+ result={}
+ result['playersVpi']=0
+ result['playersAtStreet1']=0
+ result['playersAtStreet2']=0
+ result['playersAtStreet3']=0
+ result['playersAtStreet4']=0
+ result['playersAtShowdown']=0
+ result['street0Raises']=0
+ result['street1Raises']=0
+ result['street2Raises']=0
+ result['street3Raises']=0
+ result['street4Raises']=0
+ result['street1Pot']=0
+ result['street2Pot']=0
+ result['street3Pot']=0
+ result['street4Pot']=0
+ result['showdownPot']=0
+
firstPfRaiseByNo=-1
firstPfRaiserId=-1
firstPfRaiserNo=-1
@@ -1776,6 +1837,21 @@ sure to also change the following storage method and table_viewer.prepare_data i
myWonAtSD=0.0
myStealAttemptChance=False
myStealAttempted=False
+ myStreet0Calls=0
+ myStreet1Calls=0
+ myStreet2Calls=0
+ myStreet3Calls=0
+ myStreet4Calls=0
+ myStreet0Bets=0
+ myStreet1Bets=0
+ myStreet2Bets=0
+ myStreet3Bets=0
+ myStreet4Bets=0
+ #myStreet0Raises=0
+ #myStreet1Raises=0
+ #myStreet2Raises=0
+ #myStreet3Raises=0
+ #myStreet4Raises=0
#calculate VPIP and PFR
street=0
@@ -1785,6 +1861,13 @@ sure to also change the following storage method and table_viewer.prepare_data i
myStreet0Aggr = True
if currentAction == "bet" or currentAction == "call":
myStreet0VPI = True
+
+ if myStreet0VPI:
+ result['playersVpi'] += 1
+ myStreet0Calls = action_types[street][player].count('call')
+ myStreet0Bets = action_types[street][player].count('bet')
+ # street0Raises = action_types[street][player].count('raise') bet count includes raises for now
+ result['street0Raises'] += myStreet0Bets
#PF3BChance and PF3B
pfFold=-1
@@ -1865,7 +1948,17 @@ sure to also change the following storage method and table_viewer.prepare_data i
mySawShowdown = True
if any(actiontype == "fold" for actiontype in action_types[4][player]):
mySawShowdown = False
-
+
+ if myStreet1Seen:
+ result['playersAtStreet1'] += 1
+ if myStreet2Seen:
+ result['playersAtStreet2'] += 1
+ if myStreet3Seen:
+ result['playersAtStreet3'] += 1
+ if myStreet4Seen:
+ result['playersAtStreet4'] += 1
+ if mySawShowdown:
+ result['playersAtShowdown'] += 1
#flop stuff
street=1
@@ -1873,6 +1966,11 @@ sure to also change the following storage method and table_viewer.prepare_data i
if any(actiontype == "bet" for actiontype in action_types[street][player]):
myStreet1Aggr = True
+ myStreet1Calls = action_types[street][player].count('call')
+ myStreet1Bets = action_types[street][player].count('bet')
+ # street1Raises = action_types[street][player].count('raise') bet count includes raises for now
+ result['street1Raises'] += myStreet1Bets
+
for otherPlayer in xrange(len(player_ids)):
if player==otherPlayer:
pass
@@ -1890,6 +1988,11 @@ sure to also change the following storage method and table_viewer.prepare_data i
if any(actiontype == "bet" for actiontype in action_types[street][player]):
myStreet2Aggr = True
+ myStreet2Calls = action_types[street][player].count('call')
+ myStreet2Bets = action_types[street][player].count('bet')
+ # street2Raises = action_types[street][player].count('raise') bet count includes raises for now
+ result['street2Raises'] += myStreet2Bets
+
for otherPlayer in xrange(len(player_ids)):
if player==otherPlayer:
pass
@@ -1907,6 +2010,11 @@ sure to also change the following storage method and table_viewer.prepare_data i
if any(actiontype == "bet" for actiontype in action_types[street][player]):
myStreet3Aggr = True
+ myStreet3Calls = action_types[street][player].count('call')
+ myStreet3Bets = action_types[street][player].count('bet')
+ # street3Raises = action_types[street][player].count('raise') bet count includes raises for now
+ result['street3Raises'] += myStreet3Bets
+
for otherPlayer in xrange(len(player_ids)):
if player==otherPlayer:
pass
@@ -1924,6 +2032,11 @@ sure to also change the following storage method and table_viewer.prepare_data i
if any(actiontype == "bet" for actiontype in action_types[street][player]):
myStreet4Aggr=True
+ myStreet4Calls = action_types[street][player].count('call')
+ myStreet4Bets = action_types[street][player].count('bet')
+ # street4Raises = action_types[street][player].count('raise') bet count includes raises for now
+ result['street4Raises'] += myStreet4Bets
+
for otherPlayer in xrange(len(player_ids)):
if player==otherPlayer:
pass
@@ -1989,9 +2102,25 @@ sure to also change the following storage method and table_viewer.prepare_data i
elif base=="stud":
#todo: stud positions and steals
pass
+
+ street0Calls.append(myStreet0Calls)
+ street1Calls.append(myStreet1Calls)
+ street2Calls.append(myStreet2Calls)
+ street3Calls.append(myStreet3Calls)
+ street4Calls.append(myStreet4Calls)
+ street0Bets.append(myStreet0Bets)
+ street1Bets.append(myStreet1Bets)
+ street2Bets.append(myStreet2Bets)
+ street3Bets.append(myStreet3Bets)
+ street4Bets.append(myStreet4Bets)
+ #street0Raises.append(myStreet0Raises)
+ #street1Raises.append(myStreet1Raises)
+ #street2Raises.append(myStreet2Raises)
+ #street3Raises.append(myStreet3Raises)
+ #street4Raises.append(myStreet4Raises)
#add each array to the to-be-returned dictionary
- result={'street0VPI':street0VPI}
+ result['street0VPI']=street0VPI
result['street0Aggr']=street0Aggr
result['street0_3BChance']=street0_3BChance
result['street0_3BDone']=street0_3BDone
@@ -2017,6 +2146,21 @@ sure to also change the following storage method and table_viewer.prepare_data i
result['wonAtSD']=wonAtSD
result['stealAttemptChance']=stealAttemptChance
result['stealAttempted']=stealAttempted
+ result['street0Calls']=street0Calls
+ result['street1Calls']=street1Calls
+ result['street2Calls']=street2Calls
+ result['street3Calls']=street3Calls
+ result['street4Calls']=street4Calls
+ result['street0Bets']=street0Bets
+ result['street1Bets']=street1Bets
+ result['street2Bets']=street2Bets
+ result['street3Bets']=street3Bets
+ result['street4Bets']=street4Bets
+ #result['street0Raises']=street0Raises
+ #result['street1Raises']=street1Raises
+ #result['street2Raises']=street2Raises
+ #result['street3Raises']=street3Raises
+ #result['street4Raises']=street4Raises
#now the various steal values
foldBbToStealChance=[]