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

This commit is contained in:
Eric Blade 2010-12-26 23:23:24 -05:00
commit 75026dbd30
8 changed files with 198 additions and 110 deletions

View File

@ -1,3 +1,9 @@
free-poker-tools (0.21~rc1) unstable; urgency=low
* First 0.21 release candidate
-- Mika Bostrom <bostik@iki.fi> Mon, 06 Dec 2010 17:30:54 +0200
free-poker-tools (0.20.906-1) unstable; urgency=low free-poker-tools (0.20.906-1) unstable; urgency=low
* New snapshot * New snapshot

View File

@ -11,9 +11,8 @@ Section: games
Priority: extra Priority: extra
Depends: ${python:Depends}, python-gtk2, python-matplotlib, Depends: ${python:Depends}, python-gtk2, python-matplotlib,
python-support, python-xlib, python-support, python-xlib,
mysql-server | postgresql | python-pysqlite2, python-pysqlite2
python-psycopg2 | python-mysqldb Suggests: wine, postgresql | mysql-server, python-psycopg2 | python-mysqldb
Suggests: wine
Description: free poker database with HUD Description: free poker database with HUD
FPDB is a statistics tool for online poker. It supports most sites FPDB is a statistics tool for online poker. It supports most sites
and several games. Most prominent feature is its heads-up display and several games. Most prominent feature is its heads-up display

View File

@ -60,11 +60,14 @@ import Configuration
# Other library modules # Other library modules
try: try:
import sqlalchemy.pool as pool import sqlalchemy.pool as pool
use_pool = True #use_pool = True
# Forcing to False so we can use connection.row_factory
use_pool = False
except ImportError: except ImportError:
log.info(_("Not using sqlalchemy connection pool.")) log.info(_("Not using sqlalchemy connection pool."))
use_pool = False use_pool = False
try: try:
from numpy import var from numpy import var
use_numpy = True use_numpy = True
@ -446,7 +449,8 @@ class Database:
self.db_path = database self.db_path = database
log.info(_("Connecting to SQLite: %(database)s") % {'database':self.db_path}) log.info(_("Connecting to SQLite: %(database)s") % {'database':self.db_path})
if os.path.exists(database) or create: if os.path.exists(database) or create:
self.connection = sqlite3.connect(self.db_path, detect_types=sqlite3.PARSE_DECLTYPES ) self.connection = sqlite3.connect(self.db_path, detect_types=sqlite3.PARSE_DECLTYPES)
self.connection.row_factory = sqlite3.Row
self.__connected = True self.__connected = True
sqlite3.register_converter("bool", lambda x: bool(int(x))) sqlite3.register_converter("bool", lambda x: bool(int(x)))
sqlite3.register_adapter(bool, lambda x: "1" if x else "0") sqlite3.register_adapter(bool, lambda x: "1" if x else "0")
@ -2094,7 +2098,7 @@ class Database:
if (game['type']=='ring'): line[0] = 1 # count ring hands if (game['type']=='ring'): line[0] = 1 # count ring hands
if (game['type']=='tour'): line[1] = 1 # count tour hands if (game['type']=='tour'): line[1] = 1 # count tour hands
if (game['type']=='ring'): line[2] = pdata[p]['totalProfit'] #sum of profit if (game['type']=='ring'): line[2] = pdata[p]['totalProfit'] #sum of profit
if (game['type']=='ring'): line[3] = float(Decimal(pdata[p]['totalProfit'])/Decimal(bigBet)) #sum of big bets won if (game['type']=='ring'): line[3] = 0 #float(Decimal(pdata[p]['totalProfit'])/Decimal(bigBet)) #sum of big bets won
line[4] = startTime line[4] = startTime
inserts.append(line) inserts.append(line)

View File

@ -31,6 +31,9 @@ import gtk
import math import math
import gobject import gobject
import pprint
pp = pprint.PrettyPrinter(indent=4)
class GuiReplayer: class GuiReplayer:
def __init__(self, config, querylist, mainwin, options = None, debug=True): def __init__(self, config, querylist, mainwin, options = None, debug=True):
@ -100,30 +103,16 @@ class GuiReplayer:
self.replayBox.pack_start(self.area) self.replayBox.pack_start(self.area)
self.MyHand = self.importhand() gobject.timeout_add(1000,self.draw_action)
self.maxseats=self.MyHand.maxseats self.MyHand = self.importhand()
self.table = Table(self.area, self.MyHand).table
if self.MyHand.gametype['currency']=="USD": #TODO: check if there are others .. if self.MyHand.gametype['currency']=="USD": #TODO: check if there are others ..
self.currency="$" self.currency="$"
elif self.MyHand.gametype['currency']=="EUR": elif self.MyHand.gametype['currency']=="EUR":
self.currency="" self.currency=""
self.table={} #create table with positions, player names, status (live/folded), stacks and chips on table
for i in range(0,self.maxseats): # radius: 200, center: 250,250
x= int (round(250+200*math.cos(2*i*math.pi/self.maxseats)))
y= int (round(250+200*math.sin(2*i*math.pi/self.maxseats)))
try:
self.table[i]={"name":self.MyHand.players[i][1],"stack":Decimal(self.MyHand.players[i][2]),"x":x,"y":y,"chips":0,"status":"live"} #save coordinates of each player
try:
self.table[i]['holecards']=self.MyHand.holecards["PREFLOP"][self.MyHand.players[i][1]][1]+' '+self.MyHand.holecards["PREFLOP"][self.MyHand.players[i][1]][2]
print "holecards: ",self.table[i]['holecards']
except:
self.table[i]['holecards']=''
except IndexError: #if seat is empty
print "seat ",i+1," out of ",self.maxseats," empty"
self.actions=[] #create list with all actions self.actions=[] #create list with all actions
if isinstance(self.MyHand, HoldemOmahaHand): if isinstance(self.MyHand, HoldemOmahaHand):
@ -133,7 +122,6 @@ class GuiReplayer:
self.action_number=0 self.action_number=0
self.action_level=0 self.action_level=0
self.pot=0 self.pot=0
gobject.timeout_add(1000,self.draw_action)
def area_expose(self, area, event): def area_expose(self, area, event):
@ -249,7 +237,7 @@ class GuiReplayer:
be replaced by a function to select a hand from the db in the not so distant future. be replaced by a function to select a hand from the db in the not so distant future.
This code has been shamelessly stolen from Carl This code has been shamelessly stolen from Carl
""" """
if True: if False:
settings = {} settings = {}
settings.update(self.conf.get_db_parameters()) settings.update(self.conf.get_db_parameters())
settings.update(self.conf.get_import_parameters()) settings.update(self.conf.get_import_parameters())
@ -276,7 +264,7 @@ class GuiReplayer:
# for the Hand.__init__ # for the Hand.__init__
####### Shift this section in Database.py for all to use ###### ####### Shift this section in Database.py for all to use ######
handid = 40 handid = 1
q = self.sql.query['get_gameinfo_from_hid'] q = self.sql.query['get_gameinfo_from_hid']
q = q.replace('%s', self.sql.query['placeholder']) q = q.replace('%s', self.sql.query['placeholder'])
@ -295,10 +283,74 @@ class GuiReplayer:
print "DEBUG: Create stud hand here" print "DEBUG: Create stud hand here"
elif gametype['base'] == 'draw': elif gametype['base'] == 'draw':
print "DEBUG: Create draw hand here" print "DEBUG: Create draw hand here"
return h
def temp(self): def temp(self):
pass pass
class Table:
def __init__(self, darea, hand):
self.darea = darea
self.hand = hand
self.players = []
#self.pixmap = gtk.gdk.Pixmap(darea, width, height, depth=-1)
# tmp var while refactoring
self.table = {}
i = 0
for seat, name, chips in hand.players:
self.players.append(Player(hand, name, chips, seat))
self.table[i] = self.players[i].get_hash()
i += 1
pp.pprint(self.table)
def draw(self):
draw_players()
draw_pot()
draw_community_cards()
class Player:
def __init__(self, hand, name, stack, seat):
self.status = 'live'
self.stack = Decimal(stack)
self.chips = 0
self.seat = seat
self.name = name
self.holecards = hand.join_holecards(name)
self.x = int (round(250+200*math.cos(2*self.seat*math.pi/hand.maxseats)))
self.y = int (round(250+200*math.sin(2*self.seat*math.pi/hand.maxseats)))
def get_hash(self):
return { 'chips': 0,
'holecards': self.holecards,
'name': self.name,
'stack': self.stack,
'status': self.status,
'x': self.x,
'y': self.y,
}
def draw(self):
draw_name()
draw_stack()
draw_cards()
class Pot:
def __init__(self, hand):
self.total = 0.0
def draw(self):
pass
class CommunityCards:
def __init__(self, hand):
self.pixbuf = self.gen_pixbuf_from_file(PATH_TO_THE_FILE)
def draw(self):
pass
def main(argv=None): def main(argv=None):
"""main can also be called in the python interpreter, by supplying the command line as the argument.""" """main can also be called in the python interpreter, by supplying the command line as the argument."""
if argv is None: if argv is None:

View File

@ -52,7 +52,7 @@ onlinehelp = {'Game':_('Type of Game'),
'PF3':_('% Pre Flop Re-Raise / 3Bet'), 'PF3':_('% Pre Flop Re-Raise / 3Bet'),
'AggFac':_('Aggression Factor\n'), 'AggFac':_('Aggression Factor\n'),
'AggFreq':_('Aggression Frequency\nBet or Raise vs Fold'), 'AggFreq':_('Aggression Frequency\nBet or Raise vs Fold'),
'ContBet':_('Continuation Bet on the flop'), 'ContBet':_('Continuation Bet post-flop'),
'RFI':_('% Raise First In\% Raise when first to bet'), 'RFI':_('% Raise First In\% Raise when first to bet'),
'Steals':_('% First to raise pre-flop\nand steal blinds'), 'Steals':_('% First to raise pre-flop\nand steal blinds'),
'Saw_F':_('% Saw Flop vs hands dealt'), 'Saw_F':_('% Saw Flop vs hands dealt'),

View File

@ -289,104 +289,131 @@ db: a connected Database object"""
hp.seatno, hp.seatno,
round(hp.winnings / 100.0,2) as winnings, round(hp.winnings / 100.0,2) as winnings,
p.name, p.name,
round(hp.startcash / 100.0,2) as chips, round(hp.startCash / 100.0,2) as chips,
hp.card1,hp.card2, hp.card1,hp.card2,hp.card3,hp.card4,
hp.position hp.position
FROM FROM
HandsPlayers as hp, HandsPlayers as hp,
Players as p Players as p
WHERE WHERE
hp.handId = %s hp.handId = %s
and p.id = hp.playerid and p.id = hp.playerId
ORDER BY
hp.seatno
""" """
q = q.replace('%s', db.sql.query['placeholder']) q = q.replace('%s', db.sql.query['placeholder'])
# PlayerStacks # PlayerStacks
c.execute(q, (handId,)) c.execute(q, (handId,))
for (seat, winnings, name, chips, card1,card2, position) in c.fetchall(): for (seat, winnings, name, chips, card1, card2, card3, card4, position) in c.fetchall():
print "DEBUG: seat: '%s'\tname: '%s'\tchips: '%s'" % (seat, name, chips) #print "DEBUG: addPlayer(%s, %s, %s)" %(seat,name,str(chips))
self.addPlayer(seat,name,str(chips)) self.addPlayer(seat,name,str(chips))
#if card1 and card2: #print "DEBUG: card1: %s" % card1
# self.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)), name, dealt=True) # map() should work, but is returning integers... FIXME later
#if winnings > 0: #cardlist = map(Card.valueSuitFromCard, [card1, card2, card3, card4])
# self.addCollectPot(name, winnings) cardlist = [Card.valueSuitFromCard(card1), Card.valueSuitFromCard(card2), Card.valueSuitFromCard(card3), Card.valueSuitFromCard(card4)]
#if position == 'B': #print "DEUBG: cardlist: '%s'" % cardlist
# self.buttonpos = seat if cardlist[0] == '':
pass
elif self.gametype['category'] == 'holdem':
self.addHoleCards('PREFLOP', name, closed=cardlist[0:2], shown=False, mucked=False, dealt=True)
elif self.gametype['category'] == 'omaha':
self.addHoleCards('PREFLOP', name, closed=cardlist, shown=False, mucked=False, dealt=True)
if winnings > 0:
self.addCollectPot(name, str(winnings))
if position == 'B':
self.buttonpos = seat
# HandInfo : HID, TABLE # HandInfo
# BUTTON - why is this treated specially in Hand? q = """SELECT *
# answer: it is written out in hand histories FROM Hands
# still, I think we should record all the active seat positions in a seat_order array WHERE id = %s
#c.execute("""SELECT """
# h.sitehandno as hid, q = q.replace('%s', db.sql.query['placeholder'])
# h.tablename as table, c.execute(q, (handId,))
# h.startTime as startTime
# FROM # NOTE: This relies on row_factory = sqlite3.Row (set in connect() params)
# Hands as h # Need to find MySQL and Postgres equivalents
# WHERE h.id = %(handid)s # MySQL maybe: cursorclass=MySQLdb.cursors.DictCursor
# """, {'handid':handid}) res = c.fetchone()
#res = c.fetchone() self.tablename = res['tableName']
#h.handid = res[0] self.handid = res['siteHandNo']
#h.tablename = res[1] self.startTime = datetime.datetime.strptime(res['startTime'], "%Y-%m-%d %H:%M:%S+00:00")
#h.startTime = res[2] # automatically a datetime #res['tourneyId']
#gametypeId
#res['importTime'] # Don't really care about this
#res['seats']
self.maxseats = res['maxSeats']
#res['rush']
cards = map(Card.valueSuitFromCard, [res['boardcard1'], res['boardcard2'], res['boardcard3'], res['boardcard4'], res['boardcard5']])
#print "DEBUG: res['boardcard1']: %s" % res['boardcard1']
#print "DEBUG: cards: %s" % cards
if cards[0]:
self.setCommunityCards('FLOP', cards[0:3])
if cards[3]:
self.setCommunityCards('TURN', [cards[3]])
if cards[4]:
self.setCommunityCards('RIVER', [cards[4]])
# playersVpi | playersAtStreet1 | playersAtStreet2 | playersAtStreet3 |
# playersAtStreet4 | playersAtShowdown | street0Raises | street1Raises |
# street2Raises | street3Raises | street4Raises | street1Pot | street2Pot |
# street3Pot | street4Pot | showdownPot | comment | commentTs | texture
#cards = map(Card.valueSuitFromCard, res[11:16] ) # Actions
#if cards[0]: q = """SELECT
# h.setCommunityCards('FLOP', cards[0:3]) ha.actionNo,
#if cards[3]: p.name,
# h.setCommunityCards('TURN', [cards[3]]) ha.street,
#if cards[4]: ha.actionId,
# h.setCommunityCards('RIVER', [cards[4]]) ha.allIn,
#[Card.valueSuitFromCard(x) for x in cards] round(ha.amount / 100.0,2) as bet
FROM
HandsActions as ha,
HandsPlayers as hp,
Players as p,
Hands as h
WHERE
h.id = %s
and ha.handsPlayerId = hp.id
and hp.playerId = p.id
AND h.id = hp.handId
ORDER BY
ha.id ASC
; """
q = q.replace('%s', db.sql.query['placeholder'])
c.execute(q, (handId,))
for row in c.fetchall():
name = row['name']
street = row['street']
act = row['actionId']
# allin True/False if row['allIn'] == 0
bet = row['bet']
street = self.allStreets[int(street)+1]
#print "DEBUG: name: '%s' street: '%s' act: '%s' bet: '%s'" %(name, street, act, bet)
if act == 2: # Small Blind
print "DEBUG: addBlind(%s, 'small blind', %s" %(name, str(bet))
self.addBlind(name, 'small blind', str(bet))
elif act == 4: # Big Blind
self.addBlind(name, 'big blind', str(bet))
elif act == 6: # Call
self.addCall(street, name, str(bet))
elif act == 8: # Bet
self.addBet(street, name, str(bet))
elif act == 10: # Fold
self.addFold(street, name)
elif act == 11: # Check
self.addCheck(street, name)
else:
print "DEBUG: unknown action: '%s'" % act
self.totalPot()
# actions self.rake = self.totalpot - self.totalcollected
#c.execute("""SELECT self.writeHand()
# (ha.street,ha.actionno) as actnum,
# p.name,
# ha.street,
# ha.action,
# ha.allin,
# round(ha.amount / 100.0,2)
# FROM
# handsplayers as hp,
# handsactions as ha,
# players as p
# WHERE
# hp.handid = %(handid)s
# and ha.handsplayerid = hp.id
# and p.id = hp.playerid
# ORDER BY
# ha.street,ha.actionno
# """, {'handid':handid})
#res = c.fetchall()
#for (actnum,player, streetnum, act, allin, amount) in res:
# act=act.strip()
# street = h.allStreets[streetnum+1]
# if act==u'blind':
# h.addBlind(player, 'big blind', amount)
# # TODO: The type of blind is not recorded in the DB.
# # TODO: preflop street name anomalies in Hand
# elif act==u'fold':
# h.addFold(street,player)
# elif act==u'call':
# h.addCall(street,player,amount)
# elif act==u'bet':
# h.addBet(street,player,amount)
# elif act==u'check':
# h.addCheck(street,player)
# elif act==u'unbet':
# pass
# else:
# print act, player, streetnum, allin, amount
# # TODO : other actions
#hhc.readShowdownActions(self) #hhc.readShowdownActions(self)
#hc.readShownCards(self) #hc.readShownCards(self)
#h.totalPot()
#h.rake = h.totalpot - h.totalcollected
def addPlayer(self, seat, name, chips): def addPlayer(self, seat, name, chips):
@ -980,7 +1007,7 @@ class HoldemOmahaHand(Hand):
log.debug(self.actions['PREFLOP']) log.debug(self.actions['PREFLOP'])
for player in [x for x in self.players if x[1] in players_who_act_preflop]: for player in [x for x in self.players if x[1] in players_who_act_preflop]:
#Only print stacks of players who do something preflop #Only print stacks of players who do something preflop
print >>fh, ("Seat %s: %s ($%s in chips) " %(player[0], player[1], player[2])) print >>fh, ("Seat %s: %s ($%.2f in chips) " %(player[0], player[1], float(player[2])))
if self.actions['BLINDSANTES']: if self.actions['BLINDSANTES']:
for act in self.actions['BLINDSANTES']: for act in self.actions['BLINDSANTES']:

View File

@ -2246,7 +2246,7 @@ class Sql:
(sum(cast(hp.street1Calls as <signed>integer))+ sum(cast(hp.street2Calls as <signed>integer))+ sum(cast(hp.street3Calls as <signed>integer))+ sum(cast(hp.street4Calls as <signed>integer))) + (sum(cast(hp.street1Calls as <signed>integer))+ sum(cast(hp.street2Calls as <signed>integer))+ sum(cast(hp.street3Calls as <signed>integer))+ sum(cast(hp.street4Calls as <signed>integer))) +
(sum(cast(hp.street1Aggr as <signed>integer)) + sum(cast(hp.street2Aggr as <signed>integer)) + sum(cast(hp.street3Aggr as <signed>integer)) + sum(cast(hp.street4Aggr as <signed>integer))) ) (sum(cast(hp.street1Aggr as <signed>integer)) + sum(cast(hp.street2Aggr as <signed>integer)) + sum(cast(hp.street3Aggr as <signed>integer)) + sum(cast(hp.street4Aggr as <signed>integer))) )
AS aggfrq AS aggfrq
,100.0*(sum(cast(hp.street1CBDone as <signed>integer)) + sum(cast(hp.street2CBDone as <signed>integer)) + sum(cast(hp.street2CBDone as <signed>integer)) + sum(cast(hp.street4CBDone as <signed>integer))) ,100.0*(sum(cast(hp.street1CBDone as <signed>integer)) + sum(cast(hp.street2CBDone as <signed>integer)) + sum(cast(hp.street3CBDone as <signed>integer)) + sum(cast(hp.street4CBDone as <signed>integer)))
/ (sum(cast(hp.street1CBChance as <signed>integer))+ sum(cast(hp.street2CBChance as <signed>integer))+ sum(cast(hp.street3CBChance as <signed>integer))+ sum(cast(hp.street4CBChance as <signed>integer))) / (sum(cast(hp.street1CBChance as <signed>integer))+ sum(cast(hp.street2CBChance as <signed>integer))+ sum(cast(hp.street3CBChance as <signed>integer))+ sum(cast(hp.street4CBChance as <signed>integer)))
AS conbet AS conbet
,sum(hp.totalProfit)/100.0 AS net ,sum(hp.totalProfit)/100.0 AS net
@ -2367,7 +2367,7 @@ class Sql:
(sum(cast(hp.street1Calls as <signed>integer))+ sum(cast(hp.street2Calls as <signed>integer))+ sum(cast(hp.street3Calls as <signed>integer))+ sum(cast(hp.street4Calls as <signed>integer))) + (sum(cast(hp.street1Calls as <signed>integer))+ sum(cast(hp.street2Calls as <signed>integer))+ sum(cast(hp.street3Calls as <signed>integer))+ sum(cast(hp.street4Calls as <signed>integer))) +
(sum(cast(hp.street1Aggr as <signed>integer)) + sum(cast(hp.street2Aggr as <signed>integer)) + sum(cast(hp.street3Aggr as <signed>integer)) + sum(cast(hp.street4Aggr as <signed>integer))) ) (sum(cast(hp.street1Aggr as <signed>integer)) + sum(cast(hp.street2Aggr as <signed>integer)) + sum(cast(hp.street3Aggr as <signed>integer)) + sum(cast(hp.street4Aggr as <signed>integer))) )
AS aggfrq AS aggfrq
,100.0*(sum(cast(hp.street1CBDone as <signed>integer)) + sum(cast(hp.street2CBDone as <signed>integer)) + sum(cast(hp.street2CBDone as <signed>integer)) + sum(cast(hp.street4CBDone as <signed>integer))) ,100.0*(sum(cast(hp.street1CBDone as <signed>integer)) + sum(cast(hp.street2CBDone as <signed>integer)) + sum(cast(hp.street3CBDone as <signed>integer)) + sum(cast(hp.street4CBDone as <signed>integer)))
/ (sum(cast(hp.street1CBChance as <signed>integer))+ sum(cast(hp.street2CBChance as <signed>integer))+ sum(cast(hp.street3CBChance as <signed>integer))+ sum(cast(hp.street4CBChance as <signed>integer))) / (sum(cast(hp.street1CBChance as <signed>integer))+ sum(cast(hp.street2CBChance as <signed>integer))+ sum(cast(hp.street3CBChance as <signed>integer))+ sum(cast(hp.street4CBChance as <signed>integer)))
AS conbet AS conbet
,sum(hp.totalProfit)/100.0 AS net ,sum(hp.totalProfit)/100.0 AS net
@ -2489,7 +2489,7 @@ class Sql:
(sum(cast(hp.street1Calls as <signed>integer))+ sum(cast(hp.street2Calls as <signed>integer))+ sum(cast(hp.street3Calls as <signed>integer))+ sum(cast(hp.street4Calls as <signed>integer))) + (sum(cast(hp.street1Calls as <signed>integer))+ sum(cast(hp.street2Calls as <signed>integer))+ sum(cast(hp.street3Calls as <signed>integer))+ sum(cast(hp.street4Calls as <signed>integer))) +
(sum(cast(hp.street1Aggr as <signed>integer)) + sum(cast(hp.street2Aggr as <signed>integer)) + sum(cast(hp.street3Aggr as <signed>integer)) + sum(cast(hp.street4Aggr as <signed>integer))) ) (sum(cast(hp.street1Aggr as <signed>integer)) + sum(cast(hp.street2Aggr as <signed>integer)) + sum(cast(hp.street3Aggr as <signed>integer)) + sum(cast(hp.street4Aggr as <signed>integer))) )
AS aggfrq AS aggfrq
,100.0*(sum(cast(hp.street1CBDone as <signed>integer)) + sum(cast(hp.street2CBDone as <signed>integer)) + sum(cast(hp.street2CBDone as <signed>integer)) + sum(cast(hp.street4CBDone as <signed>integer))) ,100.0*(sum(cast(hp.street1CBDone as <signed>integer)) + sum(cast(hp.street2CBDone as <signed>integer)) + sum(cast(hp.street3CBDone as <signed>integer)) + sum(cast(hp.street4CBDone as <signed>integer)))
/ (sum(cast(hp.street1CBChance as <signed>integer))+ sum(cast(hp.street2CBChance as <signed>integer))+ sum(cast(hp.street3CBChance as <signed>integer))+ sum(cast(hp.street4CBChance as <signed>integer))) / (sum(cast(hp.street1CBChance as <signed>integer))+ sum(cast(hp.street2CBChance as <signed>integer))+ sum(cast(hp.street3CBChance as <signed>integer))+ sum(cast(hp.street4CBChance as <signed>integer)))
AS conbet AS conbet
,sum(hp.totalProfit)/100.0 AS net ,sum(hp.totalProfit)/100.0 AS net

View File

@ -624,4 +624,4 @@ class ProgressBar:
if __name__ == "__main__": if __name__ == "__main__":
print _("CLI for fpdb_import is now available as CliFpdb.py") print _("CLI for importing hands is GuiBulkImport.py")