diff --git a/create-release.sh b/create-release.sh
index bdc4333a..9f28a7ac 100755
--- a/create-release.sh
+++ b/create-release.sh
@@ -29,8 +29,8 @@ cp -R regression-test fpdb-$1/
cp -R utils fpdb-$1/
cd fpdb-$1
-zip -r ../../fpdb-1.0_$1.zip *
-tar -cf - * | bzip2 >> ../../fpdb-1.0_$1.tar.bz2
+zip -r releases/fpdb-1.0_$1.zip *
+tar -cf - * | bzip2 >> releases/fpdb-1.0_$1.tar.bz2
cd ..
rm -r fpdb-$1
diff --git a/docs/tabledesign.html b/docs/tabledesign.html
index ce39d4bc..e148b9cf 100644
--- a/docs/tabledesign.html
+++ b/docs/tabledesign.html
@@ -312,11 +312,10 @@ The program itself is licensed under AGPLv3, see agpl-3.0.txt
Table HandsPlayers
-cardX: can be 1 through 20, one for each card. In holdem only 1-2 of these are used, in omaha 1-4, in stud/razz 1-7, in single draw games 1-10 is used and in badugi 1-16 (4*4) is used.
-For the draw games: the first 5 (badugi: 4) cards are the initial cards, the next 5 (badugi: 4) are after the first draw. If a player keeps some cards then those cards' spaces are filled with "k", short for "kept".
-Example 1: If a player gets 2-6 spades for his first five cards and decides to throw away the 4 and then gets a 7 of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 4, 5, 6, k, k, 7, k, k
-Example 2: If a player gets 2, 3, 5, 8, J of spades for his first five cards and decides to throw away the 2 and the 3 and then gets a Q and K of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 5, 8, J, Q, K, k, k, k
-Note that it will k in the space of which card was there previously, so in example 2 where the player kept the last 3 cards, the last 3 fields of the first draw (ie. card8-10Value) are replaced with k.
+cardX: can be 1 through 20, one for each card. In holdem only 1-2 of these are used, in omaha 1-4, in stud/razz 1-7, in single draw 1-10, in tripple draw all 20 and in badugi 1-16 (4*4).
+For the draw games: the first 5 (badugi: 4) cards are the initial cards, the next 5 (badugi: 4) are after the first draw, etc.
+Example 1: If a player gets 2-6 spades for his first five cards and decides to throw away the 4 and then gets a 7 of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 4, 5, 6, 2, 3, 5, 6, 7
+Example 2: If a player gets 2, 3, 5, 8, J of spades for his first five cards and decides to throw away the 2 and the 3 and then gets a Q and K of spades then the first 10 fields of cardXValue would be as follows: 2, 3, 5, 8, J, 5, 8, J, Q, K.
I did not separate this into an extra table because I felt the lost space is not sufficiently large. Also the benefit for searching is far less relevant.
@@ -370,6 +369,17 @@ Note that it will k in the space of which card was there previously, so in examp
char(1)
h=hearts, s=spades, d=diamonds, c=clubs, unknown/no card=x
+
+ cardXDiscarded
+ boolean
+ Whether the card was discarded (this only applies to draw games, X can be 1 through 15 since the final cards can obviously not be discarded).
+
+
+ DrawnX
+ smallint
+ X can be 1 through 3.
+ This field denotes how many cards the player has drawn on each draw.
+
winnings
int
diff --git a/pyfpdb/CliFpdb.py b/pyfpdb/CliFpdb.py
old mode 100644
new mode 100755
diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py
old mode 100644
new mode 100755
diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py
index 1a1196c5..19253ddc 100755
--- a/pyfpdb/EverleafToFpdb.py
+++ b/pyfpdb/EverleafToFpdb.py
@@ -70,15 +70,16 @@ class Everleaf(HandHistoryConverter):
self.sitename = "Everleaf"
self.setFileType("text")
self.rexx.setGameInfoRegex('.*Blinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+)')
- self.rexx.setSplitHandRegex('\n\n\n\n')
+ self.rexx.setSplitHandRegex('\n\n+')
self.rexx.setHandInfoRegex('.*#(?P[0-9]+)\n.*\nBlinds \$?(?P[.0-9]+)/\$?(?P[.0-9]+) (?P.*) - (?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+) - (?P [0-9]+):(?P[0-9]+):(?P[0-9]+)\nTable (?P[ a-zA-Z]+)\nSeat (?P[0-9]+)')
- self.rexx.setPlayerInfoRegex('Seat (?P[0-9]+): (?P.*) \( \$ (?P[.0-9]+) USD \)')
+ self.rexx.setPlayerInfoRegex('Seat (?P[0-9]+): (?P.*) \(\s+(\$ (?P[.0-9]+) USD|new player|All-in) \)')
self.rexx.setPostSbRegex('.*\n(?P.*): posts small blind \[\$? (?P[.0-9]+)')
self.rexx.setPostBbRegex('.*\n(?P.*): posts big blind \[\$? (?P[.0-9]+)')
# mct : what about posting small & big blinds simultaneously?
self.rexx.setHeroCardsRegex('.*\nDealt\sto\s(?P.*)\s\[ (?P\S\S), (?P\S\S) \]')
- self.rexx.setActionStepRegex('.*\n(?P.*) (?Pbets|checks|raises|calls|folds)(\s\[\$ (?P[.\d]+) USD\])?')
+ self.rexx.setActionStepRegex('.*\n(?P.*)(?P: bets| checks| raises| calls| folds)(\s\[\$ (?P[.\d]+) USD\])?')
self.rexx.setShowdownActionRegex('.*\n(?P.*) shows \[ (?P.*) \]')
+ self.rexx.setCollectPotRegex('.*\n(?P.*) wins \$ (?P[.\d]+) USD.*')
self.rexx.compileRegexes()
def readSupportedGames(self):
@@ -117,16 +118,38 @@ class Everleaf(HandHistoryConverter):
def readPlayerStacks(self, hand):
m = self.rexx.player_info_re.finditer(hand.string)
players = []
-
+ #print "\nReading stacks - players seen:"
for a in m:
+ #print a.group('PNAME')
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
def markStreets(self, hand):
# PREFLOP = ** Dealing down cards **
- m = re.search('(\*\* Dealing down cards \*\*\n)(?P.*?\n\*\*)?( Dealing Flop \*\* \[ (?P\S\S), (?P\S\S), (?P\S\S) \])?(?P.*?\*\*)?( Dealing Turn \*\* \[ (?P\S\S) \])?(?P.*?\*\*)?( Dealing River \*\* \[ (?P\S\S) \])?(?P.*)', hand.string,re.DOTALL)
-# for street in m.groupdict():
-# print "DEBUG: Street: %s\tspan: %s" %(street, str(m.span(street)))
+ # This re fails if, say, river is missing; then we don't get the ** that starts the river.
+ #m = re.search('(\*\* Dealing down cards \*\*\n)(?P.*?\n\*\*)?( Dealing Flop \*\* \[ (?P\S\S), (?P\S\S), (?P\S\S) \])?(?P.*?\*\*)?( Dealing Turn \*\* \[ (?P\S\S) \])?(?P.*?\*\*)?( Dealing River \*\* \[ (?P\S\S) \])?(?P.*)', hand.string,re.DOTALL)
+
+ m = re.search(r"\*\* Dealing down cards \*\*(?P.+(?=\*\* Dealing Flop \*\*)|.+)"
+ r"(\*\* Dealing Flop \*\* \[ \S\S, \S\S, \S\S \](?P.+(?=\*\* Dealing Turn \*\*)|.+))?"
+ r"(\*\* Dealing Turn \*\* \[ \S\S \](?P.+(?=\*\* Dealing River \*\*)|.+))?"
+ r"(\*\* Dealing River \*\* \[ \S\S \](?P.+))?", hand.string,re.DOTALL)
+ # that wasn't easy.
+
+
+ #m1 = re.search(r'(\*\* Dealing down cards \*\*)?(?P.*?\n\*\*)',hand.string,re.DOTALL)
+ #m2 = re.search(r'(\*\* Dealing Flop \*\*)?(?P.*\n\*\*)',hand.string,re.DOTALL)
+ #print hand.string
+ #print "m groups:\n",m.groupdict()
+ #print "m1 groups:\n",m1.groupdict()
+ #print "m2 groups:\n",m2.groupdict()
+ #(\*\* Dealing Flop \*\* \[ (?P\S\S), (?P\S\S), (?P\S\S) \](?P.*?)?)?
+ #(\*\* Dealing Turn \*\* \[ (?P\S\S) \](?P.*?))?
+ #(\*\* Dealing River \*\* \[ (?P\S\S) \](?P.*?))?', hand.string,re.DOTALL)
+
+
+ #for street in m.groupdict():
+ #print "DEBUG: Street: %s\tspan: %s" %(street, str(m.span(street)))
hand.streets = m
+ #sys.exit()
def readCommunityCards(self, hand):
# currently regex in wrong place pls fix my brain's fried
@@ -165,15 +188,19 @@ class Everleaf(HandHistoryConverter):
m = self.rexx.action_re.finditer(hand.streets.group(street))
hand.actions[street] = []
for action in m:
- if action.group('ATYPE') == 'raises':
+ if action.group('ATYPE') == ' raises':
hand.addRaiseTo( street, action.group('PNAME'), action.group('BET') )
- elif action.group('ATYPE') == 'calls':
+ elif action.group('ATYPE') == ' calls':
hand.addCall( street, action.group('PNAME'), action.group('BET') )
- elif action.group('ATYPE') == 'bets':
+ 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'))
else:
- #print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)
- hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE')]]
+ print "DEBUG: unimplemented readAction: %s %s" %(action.group('PNAME'),action.group('ATYPE'),)
+ #hand.actions[street] += [[action.group('PNAME'), action.group('ATYPE')]]
def readShowdownActions(self, hand):
@@ -184,13 +211,19 @@ class Everleaf(HandHistoryConverter):
print cards
hand.addHoleCards(cards, shows.group('PNAME'))
+ def readCollectPot(self,hand):
+ m = self.rexx.collect_pot_re.search(hand.string)
+ if m is not None:
+ hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
+ else:
+ print "WARNING: Unusual, no one collected; can happen if it's folded to big blind with a dead small blind."
def getRake(self, hand):
hand.rake = hand.totalpot * Decimal('0.05') # probably not quite right
if __name__ == "__main__":
c = Configuration.Config()
- e = Everleaf(c, "Speed_Kuala.txt")
+ e = Everleaf(c, "Speed_Kuala_full.txt")
e.processFile()
print str(e)
diff --git a/pyfpdb/FpdbSQLQueries.py b/pyfpdb/FpdbSQLQueries.py
index a3d918ac..6443c1ed 100644
--- a/pyfpdb/FpdbSQLQueries.py
+++ b/pyfpdb/FpdbSQLQueries.py
@@ -73,13 +73,13 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createSitesTable'] = """CREATE TABLE Sites (
- id SMALLINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
name varchar(32) NOT NULL,
currency char(3) NOT NULL)
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createSitesTable'] = """CREATE TABLE Sites (
- id SERIAL UNIQUE, PRIMARY KEY (id),
+ id SERIAL, PRIMARY KEY (id),
name varchar(32),
currency char(3))"""
elif(self.dbname == 'SQLite'):
@@ -92,7 +92,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createGametypesTable'] = """CREATE TABLE Gametypes (
- id SMALLINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
type char(4) NOT NULL,
base char(4) NOT NULL,
@@ -106,7 +106,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createGametypesTable'] = """CREATE TABLE Gametypes (
- id SERIAL UNIQUE, PRIMARY KEY (id),
+ id SERIAL, PRIMARY KEY (id),
siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id),
type char(4),
base char(4),
@@ -127,7 +127,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createPlayersTable'] = """CREATE TABLE Players (
- id INT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
name VARCHAR(32) CHARACTER SET utf8 NOT NULL,
siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
comment text,
@@ -135,7 +135,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createPlayersTable'] = """CREATE TABLE Players (
- id SERIAL UNIQUE, PRIMARY KEY (id),
+ id SERIAL, PRIMARY KEY (id),
name VARCHAR(32),
siteId INTEGER, FOREIGN KEY (siteId) REFERENCES Sites(id),
comment text,
@@ -150,7 +150,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createAutoratesTable'] = """CREATE TABLE Autorates (
- id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id),
gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
description varchar(50) NOT NULL,
@@ -160,7 +160,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createAutoratesTable'] = """CREATE TABLE Autorates (
- id BIGSERIAL UNIQUE, PRIMARY KEY (id),
+ id BIGSERIAL, PRIMARY KEY (id),
playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id),
gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
description varchar(50),
@@ -177,7 +177,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createHandsTable'] = """CREATE TABLE Hands (
- id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
tableName VARCHAR(20) NOT NULL,
siteHandNo BIGINT NOT NULL,
gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
@@ -190,7 +190,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createHandsTable'] = """CREATE TABLE Hands (
- id BIGSERIAL UNIQUE, PRIMARY KEY (id),
+ id BIGSERIAL, PRIMARY KEY (id),
tableName VARCHAR(20),
siteHandNo BIGINT,
gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
@@ -210,7 +210,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards (
- id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id),
card1Value smallint NOT NULL,
card1Suit char(1) NOT NULL,
@@ -225,7 +225,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards (
- id BIGSERIAL UNIQUE, PRIMARY KEY (id),
+ id BIGSERIAL, PRIMARY KEY (id),
handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id),
card1Value smallint,
card1Suit char(1),
@@ -247,7 +247,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
- id SMALLINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
buyin INT NOT NULL,
fee INT NOT NULL,
@@ -272,7 +272,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createTourneysTable'] = """CREATE TABLE Tourneys (
- id INT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
siteTourneyNo BIGINT NOT NULL,
entries INT NOT NULL,
@@ -283,7 +283,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createTourneysTable'] = """CREATE TABLE Tourneys (
- id SERIAL UNIQUE, PRIMARY KEY (id),
+ id SERIAL, PRIMARY KEY (id),
tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
siteTourneyNo BIGINT,
entries INT,
@@ -300,7 +300,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers (
- id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id),
playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id),
startCash INT NOT NULL,
@@ -332,7 +332,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createHandsPlayersTable'] = """CREATE TABLE HandsPlayers (
- id BIGSERIAL UNIQUE, PRIMARY KEY (id),
+ id BIGSERIAL, PRIMARY KEY (id),
handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id),
playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id),
startCash INT,
@@ -370,7 +370,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers (
- id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
tourneyId INT UNSIGNED NOT NULL, FOREIGN KEY (tourneyId) REFERENCES Tourneys(id),
playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id),
payinAmount INT NOT NULL,
@@ -381,7 +381,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createTourneysPlayersTable'] = """CREATE TABLE TourneysPlayers (
- id BIGSERIAL UNIQUE, PRIMARY KEY (id),
+ id BIGSERIAL, PRIMARY KEY (id),
tourneyId INT, FOREIGN KEY (tourneyId) REFERENCES Tourneys(id),
playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id),
payinAmount INT,
@@ -399,7 +399,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions (
- id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
handPlayerId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id),
street SMALLINT NOT NULL,
actionNo SMALLINT NOT NULL,
@@ -411,7 +411,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createHandsActionsTable'] = """CREATE TABLE HandsActions (
- id BIGSERIAL UNIQUE, PRIMARY KEY (id),
+ id BIGSERIAL, PRIMARY KEY (id),
handPlayerId BIGINT, FOREIGN KEY (handPlayerId) REFERENCES HandsPlayers(id),
street SMALLINT,
actionNo SMALLINT,
@@ -430,7 +430,7 @@ class FpdbSQLQueries:
if(self.dbname == 'MySQL InnoDB'):
self.query['createHudCacheTable'] = """CREATE TABLE HudCache (
- id BIGINT UNSIGNED UNIQUE AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
+ id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id),
activeSeats SMALLINT NOT NULL,
@@ -503,7 +503,7 @@ class FpdbSQLQueries:
ENGINE=INNODB"""
elif(self.dbname == 'PostgreSQL'):
self.query['createHudCacheTable'] = """CREATE TABLE HudCache (
- id BIGSERIAL UNIQUE, PRIMARY KEY (id),
+ id BIGSERIAL, PRIMARY KEY (id),
gametypeId INT, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id),
playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id),
activeSeats SMALLINT,
@@ -726,7 +726,72 @@ class FpdbSQLQueries:
on hprof2.gameTypeId = stats.gameTypeId
order by stats.base, stats.limittype, stats.bigBlind"""
elif(self.dbname == 'PostgreSQL'):
- self.query['playerStats'] = """ """
+ self.query['playerStats'] = """
+ SELECT stats.gametypeId
+ ,stats.base
+ ,stats.limitType
+ ,stats.name
+ ,(stats.bigBlind/100) as BigBlind
+ ,stats.n
+ ,stats.vpip
+ ,stats.pfr
+ ,stats.saw_f
+ ,stats.sawsd
+ ,stats.wtsdwsf
+ ,stats.wmsd
+ ,stats.FlAFq
+ ,stats.TuAFq
+ ,stats.RvAFq
+ ,stats.PFAFq
+ ,hprof2.sum_profit/100 as Net
+ ,(hprof2.sum_profit/stats.bigBlind)/(stats.n/100) as BBlPer100
+ FROM
+ (select gt.base
+ ,upper(gt.limitType) as limitType
+ ,s.name
+ ,gt.bigBlind
+ ,hc.gametypeId
+ ,sum(HDs) as n
+ ,round(100*sum(street0VPI)/sum(HDs)) as vpip
+ ,round(100*sum(street0Aggr)/sum(HDs)) as pfr
+ ,round(100*sum(street1Seen)/sum(HDs)) AS saw_f
+ ,round(100*sum(sawShowdown)/sum(HDs)) AS sawsd
+ ,round(100*sum(sawShowdown)/sum(street1Seen)) AS wtsdwsf
+ ,round(100*sum(wonAtSD)/sum(sawShowdown)) AS wmsd
+ ,round(100*sum(street1Aggr)/sum(street1Seen)) AS FlAFq
+ ,round(100*sum(street2Aggr)/sum(street2Seen)) AS TuAFq
+ ,round(100*sum(street3Aggr)/sum(street3Seen)) AS RvAFq
+ ,round(100*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr))
+ /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen))) AS PFAFq
+ from Gametypes gt
+ inner join Sites s on s.Id = gt.siteId
+ inner join HudCache hc on hc.gameTypeId = gt.Id
+ where hc.playerId in
+ group by gt.base
+ ,upper(gt.limitType)
+ ,s.name
+ ,gt.bigBlind
+ ,hc.gametypeId
+ ) stats
+ inner join
+ ( select hprof.gameTypeId, sum(hprof.profit) as sum_profit
+ from
+ (select hp.handId,
+ h.gameTypeId,
+ hp.winnings,
+ SUM(ha.amount) as costs,
+ hp.winnings - SUM(ha.amount) as profit
+ from HandsPlayers hp
+ inner join Hands h ON h.id = hp.handId
+ inner join HandsActions ha ON ha.handPlayerId = hp.id
+ where hp.playerId in
+ and hp.tourneysPlayersId IS NULL
+ group by hp.handId, h.gameTypeId, hp.position, hp.winnings
+ ) hprof
+ group by hprof.gameTypeId
+ ) hprof2
+ on hprof2.gameTypeId = stats.gameTypeId
+ order by stats.base, stats.limittype, stats.bigBlind"""
elif(self.dbname == 'SQLite'):
self.query['playerStats'] = """ """
diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py
index d50f6b6a..94732295 100644
--- a/pyfpdb/GuiGraphViewer.py
+++ b/pyfpdb/GuiGraphViewer.py
@@ -83,22 +83,24 @@ class GuiGraphViewer (threading.Thread):
self.ax.set_xlabel("Hands", fontsize = 12)
self.ax.set_ylabel("$", fontsize = 12)
self.ax.grid(color='g', linestyle=':', linewidth=0.2)
- #This line will crash if no hands exist in the query.
- text = "All Hands, " + sitename + str(name) + "\nProfit: $" + str(line[-1]) + "\nTotal Hands: " + str(len(line))
+ if(line == None):
+ #TODO: Do something useful like alert user
+ print "No hands returned by graph query"
+ else:
+ text = "All Hands, " + sitename + str(name) + "\nProfit: $" + str(line[-1]) + "\nTotal Hands: " + str(len(line))
- self.ax.annotate(text,
- xy=(10, -10),
- xycoords='axes points',
- horizontalalignment='left', verticalalignment='top',
- fontsize=10)
+ self.ax.annotate(text,
+ xy=(10, -10),
+ xycoords='axes points',
+ horizontalalignment='left', verticalalignment='top',
+ fontsize=10)
+ #Draw plot
+ self.ax.plot(line,)
- #Draw plot
- self.ax.plot(line,)
-
- self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea
- self.graphBox.add(self.canvas)
- self.canvas.show()
+ self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea
+ self.graphBox.add(self.canvas)
+ self.canvas.show()
#end of def showClicked
def getRingProfitGraph(self, name, site):
@@ -106,6 +108,9 @@ class GuiGraphViewer (threading.Thread):
#returns (HandId,Winnings,Costs,Profit)
winnings = self.db.cursor.fetchall()
+ if(winnings == ()):
+ return None
+
y=map(lambda x:float(x[3]), winnings)
line = cumsum(y)
return line/100
diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py
index 7d689228..c486a664 100644
--- a/pyfpdb/GuiPlayerStats.py
+++ b/pyfpdb/GuiPlayerStats.py
@@ -44,43 +44,44 @@ class GuiPlayerStats (threading.Thread):
# 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.execute(self.sql.query['getPlayerId'], (self.heroes[self.activesite],))
result = self.db.cursor.fetchall()
- pid = result[0][0]
- tmp = tmp.replace("", "(" + str(pid) + ")")
- self.cursor.execute(tmp)
- result = self.db.cursor.fetchall()
- cols = 18
- 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)
+ if not result == ():
+ pid = result[0][0]
+ tmp = tmp.replace("", "(" + str(pid) + ")")
+ self.cursor.execute(tmp)
+ result = self.db.cursor.fetchall()
+ cols = 18
+ 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 = ("GID", "base", "Style", "Site", "$BB", "Hands", "VPIP", "PFR", "saw_f", "sawsd", "wtsdwsf", "wmsd", "FlAFq", "TuAFq", "RvAFq", "PFAFq", "Net($)", "BB/100")
+ # Create header row
+ titles = ("GID", "base", "Style", "Site", "$BB", "Hands", "VPIP", "PFR", "saw_f", "sawsd", "wtsdwsf", "wmsd", "FlAFq", "TuAFq", "RvAFq", "PFAFq", "Net($)", "BB/100")
- 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)
- col +=1
+ 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)
+ col +=1
- for row in range(rows-1):
- for col in range(cols):
- if(row%2 == 0):
- bgcolor = "white"
- else:
- bgcolor = "lightgrey"
- eb = gtk.EventBox()
- eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
- l = gtk.Label(result[row-1][col])
- eb.add(l)
- self.stats_table.attach(eb, col, col+1, row+1, row+2)
- l.show()
- eb.show()
+ for row in range(rows-1):
+ for col in range(cols):
+ if(row%2 == 0):
+ bgcolor = "white"
+ else:
+ bgcolor = "lightgrey"
+ eb = gtk.EventBox()
+ eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
+ l = gtk.Label(result[row-1][col])
+ eb.add(l)
+ self.stats_table.attach(eb, col, col+1, row+1, row+2)
+ l.show()
+ eb.show()
def fillPlayerFrame(self, vbox):
diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py
index 06a59064..23f39db3 100644
--- a/pyfpdb/HandHistoryConverter.py
+++ b/pyfpdb/HandHistoryConverter.py
@@ -28,6 +28,41 @@ import operator
from xml.dom.minidom import Node
from pokereval import PokerEval
+#from pokerengine.pokercards import *
+# provides letter2name{}, letter2names{}, visible_card(), not_visible_card(), is_visible(), card_value(), class PokerCards
+# but it's probably not installed so here are the ones we may want:
+letter2name = {
+ 'A': 'Ace',
+ 'K': 'King',
+ 'Q': 'Queen',
+ 'J': 'Jack',
+ 'T': 'Ten',
+ '9': 'Nine',
+ '8': 'Eight',
+ '7': 'Seven',
+ '6': 'Six',
+ '5': 'Five',
+ '4': 'Four',
+ '3': 'Trey',
+ '2': 'Deuce'
+ }
+
+letter2names = {
+ 'A': 'Aces',
+ 'K': 'Kings',
+ 'Q': 'Queens',
+ 'J': 'Jacks',
+ 'T': 'Tens',
+ '9': 'Nines',
+ '8': 'Eights',
+ '7': 'Sevens',
+ '6': 'Sixes',
+ '5': 'Fives',
+ '4': 'Fours',
+ '3': 'Treys',
+ '2': 'Deuces'
+ }
+
class HandHistoryConverter:
eval = PokerEval()
def __init__(self, config, file, sitename):
@@ -67,6 +102,7 @@ class HandHistoryConverter:
self.gametype = self.determineGameType()
self.hands = self.splitFileIntoHands()
for hand in self.hands:
+ print "\nInput:\n"+hand.string
self.readHandInfo(hand)
self.readPlayerStacks(hand)
self.markStreets(hand)
@@ -76,17 +112,21 @@ class HandHistoryConverter:
self.readShowdownActions(hand)
# Read action (Note: no guarantee this is in hand order.
for street in hand.streets.groupdict():
- self.readAction(hand, street)
+ if hand.streets.group(street) is not None:
+ self.readAction(hand, street)
+
+ self.readCollectPot(hand)
# finalise it (total the pot)
hand.totalPot()
self.getRake(hand)
- if(hand.involved == True):
+ hand.printHand()
+ #if(hand.involved == True):
#self.writeHand("output file", hand)
- hand.printHand()
- else:
- pass #Don't write out observed hands
+ #hand.printHand()
+ #else:
+ #pass #Don't write out observed hands
#####
# These functions are parse actions that may be overridden by the inheriting class
@@ -124,6 +164,7 @@ class HandHistoryConverter:
def readBlinds(self, hand): abstract
def readHeroCards(self, hand): abstract
def readAction(self, hand, street): abstract
+ def readCollectPot(self, hand): abstract
# Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated
# so that an inheriting class can calculate it for the specific site if need be.
@@ -156,6 +197,7 @@ class HandHistoryConverter:
def splitFileIntoHands(self):
hands = []
+ self.obs.strip()
list = self.rexx.split_hand_re.split(self.obs)
list.pop() #Last entry is empty
for l in list:
@@ -177,66 +219,6 @@ class HandHistoryConverter:
except:
traceback.print_exc(file=sys.stderr)
- def writeHand(self, file, hand):
- """Write out parsed data"""
- print "DEBUG: *************************"
- print "DEBUG: Start of print hand"
- print "DEBUG: *************************"
-
- print "%s Game #%s: %s ($%s/$%s) - %s" %(hand.sitename, hand.handid, "XXXXhand.gametype", hand.sb, hand.bb, hand.starttime)
- print "Table '%s' %d-max Seat #%s is the button" %(hand.tablename, hand.maxseats, hand.buttonpos)
-
- for player in hand.players:
- print "Seat %s: %s ($%s)" %(player[0], player[1], player[2])
-
- if(hand.posted[0] == "FpdbNBP"):
- print "No small blind posted"
- else:
- print "%s: posts small blind $%s" %(hand.posted[0], hand.sb)
-
- #May be more than 1 bb posting
- print "%s: posts big blind $%s" %(hand.posted[1], hand.bb)
- if(len(hand.posted) > 2):
- # Need to loop on all remaining big blinds - lazy
- print "XXXXXXXXX FIXME XXXXXXXX"
-
- print "*** HOLE CARDS ***"
- print "Dealt to %s [%s %s]" %(hand.hero , hand.holecards[0], hand.holecards[1])
-
- for act in hand.actions['PREFLOP']:
- self.printActionLine(act, 0)
-
- if 'PREFLOP' in hand.actions:
- for act in hand.actions['PREFLOP']:
- print "PF action"
-
- if 'FLOP' in hand.actions:
- print "*** FLOP *** [%s %s %s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"))
- for act in hand.actions['FLOP']:
- self.printActionLine(act, 0)
-
- if 'TURN' in hand.actions:
- print "*** TURN *** [%s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"))
- for act in hand.actions['TURN']:
- self.printActionLine(act, 0)
-
- if 'RIVER' in hand.actions:
- print "*** RIVER *** [%s %s %s %s] [%s]" %(hand.streets.group("FLOP1"), hand.streets.group("FLOP2"), hand.streets.group("FLOP3"), hand.streets.group("TURN1"), hand.streets.group("RIVER1"))
- for act in hand.actions['RIVER']:
- self.printActionLine(act, 0)
-
- print "*** SUMMARY ***"
- print "XXXXXXXXXXXX Need sumary info XXXXXXXXXXX"
-
-
- def printActionLine(self, act, pot):
- if act[1] == 'folds' or act[1] == 'checks':
- print "%s: %s " %(act[0], act[1])
- if act[1] == 'calls':
- print "%s: %s $%s" %(act[0], act[1], act[2])
- if act[1] == 'raises':
- print "%s: %s $%s to XXXpottotalXXX" %(act[0], act[1], act[2])
-
#takes a poker float (including , for thousand seperator and converts it to an int
def float2int (self, string):
@@ -282,6 +264,7 @@ class Hand:
self.hero = "Hiro"
self.holecards = {} # dict from player names to lists of hole cards
self.board = {} # dict from street names to community cards
+ self.collected = {} # dict from player names to amounts collected
self.action = []
self.totalpot = None
@@ -296,8 +279,7 @@ class Hand:
def addPlayer(self, seat, name, chips):
"""seat, an int indicating the seat
name, the player name
- chips, the chips the player has at the start of the hand"""
- #self.players.append(name)
+ chips, the chips the player has at the start of the hand (can be None)"""
self.players.append([seat, name, chips])
self.holecards[name] = []
#self.startChips[name] = chips
@@ -324,7 +306,7 @@ class Hand:
def setCommunityCards(self, street, cards):
self.board[street] = [self.card(c) for c in cards]
- print self.board[street]
+ #print self.board[street]
def card(self,c):
"""upper case the ranks but not suits, 'atjqk' => 'ATJQK'"""
@@ -370,10 +352,25 @@ class Hand:
self.actions[street] += [[player, 'raises', amountBy, amountTo]]
def addBet(self, street, player=None, amount=0):
- self.bets[street][name].append(Decimal(amount))
- self.orderedBets[street].append(Decimal(amount))
+ self.bets[street][player].append(Decimal(amount))
+ #self.orderedBets[street].append(Decimal(amount))
self.actions[street] += [[player, 'bets', amount]]
-
+
+ def addFold(self, street, player):
+ self.actions[street] += [[player, 'folds']]
+
+ def addCheck(self, street, player):
+ self.actions[street] += [[player, 'checks']]
+
+ def addCollectPot(self,player, pot):
+ if player not in self.collected:
+ self.collected[player] = pot
+ else:
+ # possibly lines like "p collected $ from pot" appear during the showdown
+ # but they are usually unique in the summary.
+ print "%s collected pot more than once; avoidable by reading winnings only from summary lines?"
+
+
def totalPot(self):
"""If all bets and blinds have been added, totals up the total pot size
Known bug: doesn't take into account side pots"""
@@ -391,7 +388,7 @@ Known bug: doesn't take into account side pots"""
def printHand(self):
# PokerStars format.
- print "### DEBUG ###"
+ print "\n### Pseudo stars format ###"
print "%s Game #%s: %s ($%s/$%s) - %s" %(self.sitename, self.handid, "XXXXhand.gametype", self.sb, self.bb, self.starttime)
print "Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)
for player in self.players:
@@ -409,24 +406,25 @@ Known bug: doesn't take into account side pots"""
# What about big & small blinds?
print "*** HOLE CARDS ***"
- print "Dealt to %s [%s %s]" %(self.hero , self.holecards[self.hero][0], self.holecards[self.hero][1])
+ if self.involved:
+ print "Dealt to %s [%s]" %(self.hero , " ".join(self.holecards[self.hero]))
if 'PREFLOP' in self.actions:
for act in self.actions['PREFLOP']:
self.printActionLine(act)
if 'FLOP' in self.actions:
- print "*** FLOP *** [%s %s %s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"))
+ print "*** FLOP *** [%s]" %( " ".join(self.board['Flop']))
for act in self.actions['FLOP']:
self.printActionLine(act)
if 'TURN' in self.actions:
- print "*** TURN *** [%s %s %s] [%s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"))
+ print "*** TURN *** [%s] [%s]" %( " ".join(self.board['Flop']), " ".join(self.board['Turn']))
for act in self.actions['TURN']:
self.printActionLine(act)
if 'RIVER' in self.actions:
- print "*** RIVER *** [%s %s %s %s] [%s]" %(self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1"))
+ print "*** RIVER *** [%s] [%s]" %(" ".join(self.board['Flop']+self.board['Turn']), " ".join(self.board['River']) )
for act in self.actions['RIVER']:
self.printActionLine(act)
@@ -438,21 +436,42 @@ Known bug: doesn't take into account side pots"""
print "what do they show"
print "*** SUMMARY ***"
- print "Total pot $%s | Rake $%s)" % (self.totalpot, self.rake)
- print "Board [%s %s %s %s %s]" % (self.streets.group("FLOP1"), self.streets.group("FLOP2"), self.streets.group("FLOP3"), self.streets.group("TURN1"), self.streets.group("RIVER1"))
+ print "Total pot $%s | Rake $%.2f)" % (self.totalpot, self.rake) # TODO side pots
+ board = []
+ for s in self.board.values():
+ board += s
+ if board: # sometimes hand ends preflop without a board
+ print "Board [%s]" % (" ".join(board))
#print self.board
for player in self.players:
- if self.holecards[player[1]]: # empty list default is false
- hole = self.holecards[player[1]]
- #print self.board.values()
- board = []
- for s in self.board.values():
- board += s
- playerhand = self.bestHand('hi', board+hole)
- print "Seat %d: %s showed %s and won/lost with %s" % (player[0], player[1], hole, playerhand)
+ seatnum = player[0]
+ name = player[1]
+ if name in self.collected and self.holecards[name]:
+ # TODO: (bug) hero cards will always be 'shown' because they are known to us. Better to explicitly flag those who 'show' their cards.
+ print "Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]), self.collected[name])
+ elif name in self.collected:
+ print "Seat %d: %s collected ($%s)" % (seatnum, name, self.collected[name])
+ elif self.holecards[player[1]]:
+ print "Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]))
else:
- print "Seat %d: %s mucked or folded" % (player[0], player[1])
+ print "Seat %d: %s folded or mucked" % (seatnum, name)
+
+ print
+ # TODO:
+ # logic for side pots
+ # logic for which players get to showdown
+ # I'm just not sure we need to do this so heavily.. and if we do, it's probably better to use pokerlib
+ #if self.holecards[player[1]]: # empty list default is false
+ #hole = self.holecards[player[1]]
+ ##board = []
+ ##for s in self.board.values():
+ ##board += s
+ ##playerhand = self.bestHand('hi', board+hole)
+ ##print "Seat %d: %s showed %s and won/lost with %s" % (player[0], player[1], hole, playerhand)
+ #print "Seat %d: %s showed %s" % (player[0], player[1], hole)
+ #else:
+ #print "Seat %d: %s mucked or folded" % (player[0], player[1])
def printActionLine(self, act):
@@ -460,13 +479,13 @@ Known bug: doesn't take into account side pots"""
print "%s: %s " %(act[0], act[1])
if act[1] == 'calls':
print "%s: %s $%s" %(act[0], act[1], act[2])
+ if act[1] == 'bets':
+ print "%s: %s $%s" %(act[0], act[1], act[2])
if act[1] == 'raises':
print "%s: %s $%s to $%s" %(act[0], act[1], act[2], act[3])
- # going to use pokereval to figure out hands
+ # going to use pokereval to figure out hands at some point.
# these functions are copied from pokergame.py
- # im thinking perhaps its best to use all the functionality of pokergame instead
- # of reinventing the wheel
def bestHand(self, side, cards):
#if self.variant == "omaha" or self.variant == "omaha8":
#hand = self.serial2player[serial].hand.tolist(True)
@@ -477,38 +496,39 @@ Known bug: doesn't take into account side pots"""
print cards
return HandHistoryConverter.eval.best('hi', cards, [])
+ # from pokergame.py
def bestHandValue(self, side, serial):
(value, cards) = self.bestHand(side, serial)
return value
-
+ # from pokergame.py
+ # got rid of the _ for internationalisation
def readableHandValueLong(self, side, value, cards):
- cards = self.eval.card2string(cards)
if value == "NoPair":
if side == "low":
if cards[0][0] == '5':
- return _("The wheel")
+ return ("The wheel")
else:
return join(map(lambda card: card[0], cards), ", ")
else:
- return _("High card %(card)s") % { 'card' : _(letter2name[cards[0][0]]) }
+ return ("High card %(card)s") % { 'card' : (letter2name[cards[0][0]]) }
elif value == "OnePair":
- return _("A pair of %(card)s") % { 'card' : _(letter2names[cards[0][0]]) } + _(", %(card)s kicker") % { 'card' : _(letter2name[cards[2][0]]) }
+ return ("A pair of %(card)s") % { 'card' : (letter2names[cards[0][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[2][0]]) }
elif value == "TwoPair":
- return _("Two pairs %(card1)s and %(card2)s") % { 'card1' : _(letter2names[cards[0][0]]), 'card2' : _(letter2names[cards[2][0]]) } + _(", %(card)s kicker") % { 'card' : _(letter2name[cards[4][0]]) }
+ return ("Two pairs %(card1)s and %(card2)s") % { 'card1' : (letter2names[cards[0][0]]), 'card2' : _(letter2names[cards[2][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[4][0]]) }
elif value == "Trips":
- return _("Three of a kind %(card)s") % { 'card' : _(letter2names[cards[0][0]]) } + _(", %(card)s kicker") % { 'card' : _(letter2name[cards[3][0]]) }
+ return ("Three of a kind %(card)s") % { 'card' : (letter2names[cards[0][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[3][0]]) }
elif value == "Straight":
- return _("Straight %(card1)s to %(card2)s") % { 'card1' : _(letter2name[cards[0][0]]), 'card2' : _(letter2name[cards[4][0]]) }
+ return ("Straight %(card1)s to %(card2)s") % { 'card1' : (letter2name[cards[0][0]]), 'card2' : (letter2name[cards[4][0]]) }
elif value == "Flush":
- return _("Flush %(card)s high") % { 'card' : _(letter2name[cards[0][0]]) }
+ return ("Flush %(card)s high") % { 'card' : (letter2name[cards[0][0]]) }
elif value == "FlHouse":
- return _("%(card1)ss full of %(card2)ss") % { 'card1' : _(letter2name[cards[0][0]]), 'card2' : _(letter2name[cards[3][0]]) }
+ return ("%(card1)ss full of %(card2)ss") % { 'card1' : (letter2name[cards[0][0]]), 'card2' : (letter2name[cards[3][0]]) }
elif value == "Quads":
- return _("Four of a kind %(card)s") % { 'card' : _(letter2names[cards[0][0]]) } + _(", %(card)s kicker") % { 'card' : _(letter2name[cards[4][0]]) }
+ return _("Four of a kind %(card)s") % { 'card' : (letter2names[cards[0][0]]) } + (", %(card)s kicker") % { 'card' : (letter2name[cards[4][0]]) }
elif value == "StFlush":
if letter2name[cards[0][0]] == 'Ace':
- return _("Royal flush")
+ return ("Royal flush")
else:
- return _("Straight flush %(card)s high") % { 'card' : _(letter2name[cards[0][0]]) }
+ return ("Straight flush %(card)s high") % { 'card' : (letter2name[cards[0][0]]) }
return value
\ No newline at end of file
diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py
index 66655c9a..25aad085 100644
--- a/pyfpdb/Hud.py
+++ b/pyfpdb/Hud.py
@@ -134,6 +134,8 @@ class Hud:
(x, y) = loc[adj[i]]
if self.stat_windows.has_key(i):
self.stat_windows[i].relocate(x, y)
+
+ return True
def on_button_press(self, widget, event):
if event.button == 1:
@@ -152,6 +154,7 @@ class Hud:
def reposition_windows(self, *args):
self.update_table_position()
+ return True
def debug_stat_windows(self, *args):
print self.table, "\n", self.main_window.window.get_transient_for()
@@ -226,7 +229,7 @@ class Hud:
aux_params = config.get_aux_parameters(game_params['aux'])
self.aux_windows.append(eval("%s.%s(gtk.Window(), self, config, 'fpdb')" % (aux_params['module'], aux_params['class'])))
- gobject.timeout_add(0.5, self.update_table_position)
+ gobject.timeout_add(500, self.update_table_position)
def update(self, hand, config, stat_dict):
self.hand = hand # this is the last hand, so it is available later