Merge from ray, minor conflicts
This commit is contained in:
commit
79ca83c95a
|
@ -88,12 +88,32 @@ class Site:
|
|||
self.font_size = node.getAttribute("font_size")
|
||||
self.use_frames = node.getAttribute("use_frames")
|
||||
self.enabled = fix_tf(node.getAttribute("enabled"), default = True)
|
||||
self.xpad = node.getAttribute("xpad")
|
||||
self.ypad = node.getAttribute("ypad")
|
||||
self.layout = {}
|
||||
|
||||
for layout_node in node.getElementsByTagName('layout'):
|
||||
lo = Layout(layout_node)
|
||||
self.layout[lo.max] = lo
|
||||
|
||||
# Site defaults
|
||||
if self.xpad == "": self.xpad = 1
|
||||
else: self.xpad = int(self.xpad)
|
||||
|
||||
if self.ypad == "": self.ypad = 0
|
||||
else: self.ypad = int(self.ypad)
|
||||
|
||||
if self.font_size == "": self.font_size = 7
|
||||
else: self.font_size = int(self.font_size)
|
||||
|
||||
if self.hudopacity == "": self.hudopacity = 1.0
|
||||
else: self.hudopacity = float(self.hudopacity)
|
||||
|
||||
if self.use_frames == "": self.use_frames = False
|
||||
if self.font == "": self.font = "Sans"
|
||||
if self.hudbgcolor == "": self.hudbgcolor = "000000"
|
||||
if self.hudfgcolor == "": self.hudfgcolor = "FFFFFF"
|
||||
|
||||
def __str__(self):
|
||||
temp = "Site = " + self.site_name + "\n"
|
||||
for key in dir(self):
|
||||
|
@ -119,9 +139,16 @@ class Stat:
|
|||
class Game:
|
||||
def __init__(self, node):
|
||||
self.game_name = node.getAttribute("game_name")
|
||||
self.db = node.getAttribute("db")
|
||||
self.rows = int( node.getAttribute("rows") )
|
||||
self.cols = int( node.getAttribute("cols") )
|
||||
self.xpad = node.getAttribute("xpad")
|
||||
self.ypad = node.getAttribute("ypad")
|
||||
|
||||
# Defaults
|
||||
if self.xpad == "": self.xpad = 1
|
||||
else: self.xpad = int(self.xpad)
|
||||
if self.ypad == "": self.ypad = 0
|
||||
else: self.ypad = int(self.ypad)
|
||||
|
||||
aux_text = node.getAttribute("aux")
|
||||
aux_list = aux_text.split(',')
|
||||
|
@ -146,9 +173,10 @@ class Game:
|
|||
|
||||
def __str__(self):
|
||||
temp = "Game = " + self.game_name + "\n"
|
||||
temp = temp + " db = %s\n" % self.db
|
||||
temp = temp + " rows = %d\n" % self.rows
|
||||
temp = temp + " cols = %d\n" % self.cols
|
||||
temp = temp + " xpad = %d\n" % self.xpad
|
||||
temp = temp + " ypad = %d\n" % self.ypad
|
||||
temp = temp + " aux = %s\n" % self.aux
|
||||
|
||||
for stat in self.stats.keys():
|
||||
|
@ -633,6 +661,8 @@ class Config:
|
|||
parms["font"] = self.supported_sites[site].font
|
||||
parms["font_size"] = self.supported_sites[site].font_size
|
||||
parms["enabled"] = self.supported_sites[site].enabled
|
||||
parms["xpad"] = self.supported_sites[site].xpad
|
||||
parms["ypad"] = self.supported_sites[site].ypad
|
||||
return parms
|
||||
|
||||
def set_site_parameters(self, site_name, converter = None, decoder = None,
|
||||
|
@ -683,9 +713,10 @@ class Config:
|
|||
param = {}
|
||||
if self.supported_games.has_key(name):
|
||||
param['game_name'] = self.supported_games[name].game_name
|
||||
param['db'] = self.supported_games[name].db
|
||||
param['rows'] = self.supported_games[name].rows
|
||||
param['cols'] = self.supported_games[name].cols
|
||||
param['xpad'] = self.supported_games[name].xpad
|
||||
param['ypad'] = self.supported_games[name].ypad
|
||||
param['aux'] = self.supported_games[name].aux
|
||||
return param
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ import SQL
|
|||
import Card
|
||||
|
||||
class Database:
|
||||
def __init__(self, c, db_name, game):
|
||||
def __init__(self, c, db_name = None, game = None, sql = None): # db_name and game not used any more
|
||||
print "\ncreating Database instance, sql =", sql
|
||||
self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
|
||||
self.fdb.do_connect(c)
|
||||
self.connection = self.fdb.db
|
||||
|
@ -48,7 +49,12 @@ class Database:
|
|||
self.import_options = c.get_import_parameters()
|
||||
self.type = db_params['db-type']
|
||||
self.backend = db_params['db-backend']
|
||||
self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-server'])
|
||||
self.db_server = db_params['db-server']
|
||||
# where possible avoid creating new SQL instance by using the global one passed in
|
||||
if sql == None:
|
||||
self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server'])
|
||||
else:
|
||||
self.sql = sql
|
||||
self.connection.rollback()
|
||||
|
||||
# To add to config:
|
||||
|
@ -81,6 +87,8 @@ class Database:
|
|||
#row = cur.fetchone()
|
||||
self.saveActions = False if self.import_options['saveActions'] == False else True
|
||||
|
||||
def do_connect(self, c):
|
||||
self.fdb.do_connect(c)
|
||||
|
||||
def commit(self):
|
||||
self.fdb.db.commit()
|
||||
|
@ -88,6 +96,19 @@ class Database:
|
|||
def close_connection(self):
|
||||
self.connection.close()
|
||||
|
||||
def disconnect(self, due_to_error=False):
|
||||
"""Disconnects the DB (rolls back if param is true, otherwise commits"""
|
||||
self.fdb.disconnect(due_to_error)
|
||||
|
||||
def reconnect(self, due_to_error=False):
|
||||
"""Reconnects the DB"""
|
||||
self.fdb.reconnect(due_to_error=False)
|
||||
|
||||
def get_backend_name(self):
|
||||
"""Reconnects the DB"""
|
||||
return self.fdb.get_backend_name()
|
||||
|
||||
|
||||
def get_table_name(self, hand_id):
|
||||
c = self.connection.cursor()
|
||||
c.execute(self.sql.query['get_table_name'], (hand_id, ))
|
||||
|
@ -138,12 +159,8 @@ class Database:
|
|||
cards = {}
|
||||
c = self.connection.cursor()
|
||||
c.execute(self.sql.query['get_common_cards'], [hand])
|
||||
colnames = [desc[0] for desc in c.description]
|
||||
for row in c.fetchall():
|
||||
s_dict = {}
|
||||
for name, val in zip(colnames, row):
|
||||
s_dict[name] = val
|
||||
cards['common'] = (self.convert_cards(s_dict))
|
||||
# row = c.fetchone()
|
||||
cards['common'] = c.fetchone()
|
||||
return cards
|
||||
|
||||
def convert_cards(self, d):
|
||||
|
@ -285,7 +302,8 @@ class Database:
|
|||
fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits)
|
||||
|
||||
hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id
|
||||
,hand_start_time, names, tableName, maxSeats, hudImportData)
|
||||
,hand_start_time, names, tableName, maxSeats, hudImportData
|
||||
,(None, None, None, None, None), (None, None, None, None, None))
|
||||
|
||||
#print "before calling store_hands_players_stud, antes:", antes
|
||||
hands_players_ids = fpdb_simple.store_hands_players_stud(self.backend, db, cursor, hands_id, player_ids
|
||||
|
@ -326,7 +344,6 @@ class Database:
|
|||
if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop':
|
||||
fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData)
|
||||
t5 = time()
|
||||
fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits)
|
||||
t6 = time()
|
||||
if self.saveActions:
|
||||
fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos)
|
||||
|
@ -361,8 +378,6 @@ class Database:
|
|||
if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop':
|
||||
fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData)
|
||||
|
||||
fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits)
|
||||
|
||||
if self.saveActions:
|
||||
fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos)
|
||||
return hands_id
|
||||
|
|
|
@ -30,12 +30,11 @@ import fpdb_db
|
|||
import FpdbSQLQueries
|
||||
|
||||
class Filters(threading.Thread):
|
||||
def __init__(self, db, settings, config, qdict, display = {},debug=True):
|
||||
def __init__(self, db, config, qdict, display = {}, debug=True):
|
||||
self.debug=debug
|
||||
#print "start of GraphViewer constructor"
|
||||
self.db=db
|
||||
self.cursor=db.cursor
|
||||
self.settings=settings
|
||||
self.sql=qdict
|
||||
self.conf = config
|
||||
self.display = display
|
||||
|
@ -235,7 +234,7 @@ class Filters(threading.Thread):
|
|||
|
||||
def __set_hero_name(self, w, site):
|
||||
self.heroes[site] = w.get_text()
|
||||
# print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site])
|
||||
# print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site])
|
||||
|
||||
def createSiteLine(self, hbox, site):
|
||||
cb = gtk.CheckButton(site)
|
||||
|
@ -556,23 +555,12 @@ def main(argv=None):
|
|||
config = Configuration.Config()
|
||||
db = None
|
||||
|
||||
settings = {}
|
||||
|
||||
settings.update(config.get_db_parameters())
|
||||
settings.update(config.get_tv_parameters())
|
||||
settings.update(config.get_import_parameters())
|
||||
settings.update(config.get_default_paths())
|
||||
|
||||
db = fpdb_db.fpdb_db()
|
||||
db.connect(settings['db-backend'],
|
||||
settings['db-host'],
|
||||
settings['db-databaseName'],
|
||||
settings['db-user'],
|
||||
settings['db-password'])
|
||||
db.do_connect(config)
|
||||
|
||||
qdict = FpdbSQLQueries.FpdbSQLQueries(db.get_backend_name())
|
||||
|
||||
i = Filters(db, settings, config, qdict)
|
||||
i = Filters(db, config, qdict)
|
||||
main_window = gtk.Window()
|
||||
main_window.connect('destroy', destroy)
|
||||
main_window.add(i.get_vbox())
|
||||
|
|
|
@ -282,43 +282,6 @@ class FpdbSQLQueries:
|
|||
FOREIGN KEY(gametypeId) REFERENCES Gametypes(id) ON DELETE CASCADE)"""
|
||||
|
||||
|
||||
################################
|
||||
# Create BoardCards
|
||||
################################
|
||||
|
||||
if(self.dbname == 'MySQL InnoDB'):
|
||||
self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards (
|
||||
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,
|
||||
card2Value smallint NOT NULL,
|
||||
card2Suit char(1) NOT NULL,
|
||||
card3Value smallint NOT NULL,
|
||||
card3Suit char(1) NOT NULL,
|
||||
card4Value smallint NOT NULL,
|
||||
card4Suit char(1) NOT NULL,
|
||||
card5Value smallint NOT NULL,
|
||||
card5Suit char(1) NOT NULL)
|
||||
ENGINE=INNODB"""
|
||||
elif(self.dbname == 'PostgreSQL'):
|
||||
self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards (
|
||||
id BIGSERIAL, PRIMARY KEY (id),
|
||||
handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id),
|
||||
card1Value smallint,
|
||||
card1Suit char(1),
|
||||
card2Value smallint,
|
||||
card2Suit char(1),
|
||||
card3Value smallint,
|
||||
card3Suit char(1),
|
||||
card4Value smallint,
|
||||
card4Suit char(1),
|
||||
card5Value smallint,
|
||||
card5Suit char(1))"""
|
||||
elif(self.dbname == 'SQLite'):
|
||||
self.query['createBoardCardsTable'] = """ """
|
||||
|
||||
|
||||
################################
|
||||
# Create TourneyTypes
|
||||
################################
|
||||
|
@ -1598,136 +1561,6 @@ class FpdbSQLQueries:
|
|||
elif(self.dbname == 'SQLite'):
|
||||
self.query['playerStatsByPosition'] = """ """
|
||||
|
||||
if(self.dbname == 'MySQL InnoDB'):
|
||||
self.query['playerStatsByPositionAndHoleCards'] = """
|
||||
SELECT
|
||||
concat(upper(stats.limitType), ' '
|
||||
,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' '
|
||||
,stats.name, ' $'
|
||||
,cast(trim(leading ' ' from
|
||||
case when stats.bigBlind < 100 then format(stats.bigBlind/100.0,2)
|
||||
else format(stats.bigBlind/100.0,0)
|
||||
end ) as char)
|
||||
) AS Game
|
||||
,case when stats.PlPosition = -2 then 'BB'
|
||||
when stats.PlPosition = -1 then 'SB'
|
||||
when stats.PlPosition = 0 then 'Btn'
|
||||
when stats.PlPosition = 1 then 'CO'
|
||||
when stats.PlPosition = 2 then 'MP'
|
||||
when stats.PlPosition = 5 then 'EP'
|
||||
else '??'
|
||||
end AS PlPosition
|
||||
/*,stats.n*/,hprof2.n
|
||||
/*,stats.vpip*/,0
|
||||
/*,stats.pfr*/,0
|
||||
/*,stats.saw_f*/,0
|
||||
/*,stats.sawsd*/,0
|
||||
/*,stats.wtsdwsf*/,0
|
||||
/*,stats.wmsd*/,0
|
||||
/*,stats.FlAFq*/,0
|
||||
/*,stats.TuAFq*/,0
|
||||
/*,stats.RvAFq*/,0
|
||||
/*,stats.PoFAFq*/,0
|
||||
/* if you have handsactions data the next 3 fields should give same answer as
|
||||
following 3 commented out fields */
|
||||
/*,stats.Net
|
||||
,stats.BBper100
|
||||
,stats.Profitperhand*/
|
||||
,format(hprof2.sum_profit/100.0,2) AS Net
|
||||
/*,format((hprof2.sum_profit/(stats.bigBlind+0.0)) / (stats.n/100.0),2)*/,0
|
||||
AS BBlPer100
|
||||
,hprof2.profitperhand AS Profitperhand
|
||||
,format(hprof2.variance,2) AS Variance
|
||||
FROM
|
||||
(select /* stats from hudcache */
|
||||
gt.base
|
||||
,gt.category
|
||||
,upper(gt.limitType) as limitType
|
||||
,s.name
|
||||
,gt.bigBlind
|
||||
,hc.gametypeId
|
||||
,case when hc.position = 'B' then -2
|
||||
when hc.position = 'S' then -1
|
||||
when hc.position = 'D' then 0
|
||||
when hc.position = 'C' then 1
|
||||
when hc.position = 'M' then 2
|
||||
when hc.position = 'E' then 5
|
||||
else 9
|
||||
end as PlPosition
|
||||
,sum(HDs) AS n
|
||||
,format(100.0*sum(street0VPI)/sum(HDs),1) AS vpip
|
||||
,format(100.0*sum(street0Aggr)/sum(HDs),1) AS pfr
|
||||
,format(100.0*sum(street1Seen)/sum(HDs),1) AS saw_f
|
||||
,format(100.0*sum(sawShowdown)/sum(HDs),1) AS sawsd
|
||||
,case when sum(street1Seen) = 0 then '-'
|
||||
else format(100.0*sum(sawShowdown)/sum(street1Seen),1)
|
||||
end AS wtsdwsf
|
||||
,case when sum(sawShowdown) = 0 then '-'
|
||||
end AS wtsdwsf
|
||||
,case when sum(sawShowdown) = 0 then '-'
|
||||
else format(100.0*sum(wonAtSD)/sum(sawShowdown),1)
|
||||
end AS wmsd
|
||||
,case when sum(street1Seen) = 0 then '-'
|
||||
else format(100.0*sum(street1Aggr)/sum(street1Seen),1)
|
||||
end AS FlAFq
|
||||
,case when sum(street2Seen) = 0 then '-'
|
||||
else format(100.0*sum(street2Aggr)/sum(street2Seen),1)
|
||||
end AS TuAFq
|
||||
,case when sum(street3Seen) = 0 then '-'
|
||||
else format(100.0*sum(street3Aggr)/sum(street3Seen),1)
|
||||
end AS RvAFq
|
||||
,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-'
|
||||
else format(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr))
|
||||
/(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),1)
|
||||
end AS PoFAFq
|
||||
,format(sum(totalProfit)/100.0,2) AS Net
|
||||
,format((sum(totalProfit)/(gt.bigBlind+0.0)) / (sum(HDs)/100.0),2)
|
||||
AS BBper100
|
||||
,format( (sum(totalProfit)/100.0) / sum(HDs), 4) AS Profitperhand
|
||||
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 <player_test>
|
||||
# use <gametype_test> here ?
|
||||
group by gt.base
|
||||
,gt.category
|
||||
,upper(gt.limitType)
|
||||
,s.name
|
||||
,gt.bigBlind
|
||||
,hc.gametypeId
|
||||
,PlPosition
|
||||
) stats
|
||||
inner join
|
||||
( select # profit from handsplayers/handsactions
|
||||
hprof.gameTypeId,
|
||||
case when hprof.position = 'B' then -2
|
||||
when hprof.position = 'S' then -1
|
||||
when hprof.position in ('3','4') then 2
|
||||
when hprof.position in ('6','7') then 5
|
||||
else hprof.position
|
||||
end as PlPosition,
|
||||
sum(hprof.profit) as sum_profit,
|
||||
avg(hprof.profit/100.0) as profitperhand,
|
||||
variance(hprof.profit/100.0) as variance,
|
||||
count(*) as n
|
||||
from
|
||||
(select hp.handId, h.gameTypeId, hp.position, 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
|
||||
left join HandsActions ha ON ha.handsPlayerId = hp.id
|
||||
where hp.playerId in <player_test>
|
||||
# use <gametype_test> here ?
|
||||
and hp.tourneysPlayersId IS NULL
|
||||
and ((hp.card1Value = <first_card> and hp.card2Value = <second_card>) or (hp.card1Value = <second_card> and hp.card2Value = <first_card>))
|
||||
group by hp.handId, h.gameTypeId, hp.position, hp.winnings
|
||||
) hprof
|
||||
group by hprof.gameTypeId, PlPosition
|
||||
) hprof2
|
||||
on ( hprof2.gameTypeId = stats.gameTypeId
|
||||
and hprof2.PlPosition = stats.PlPosition)
|
||||
order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as signed)
|
||||
"""
|
||||
if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL') or (self.dbname == 'SQLite'):
|
||||
self.query['getGames'] = """SELECT DISTINCT category from Gametypes"""
|
||||
|
||||
|
|
|
@ -43,14 +43,14 @@ import Filters
|
|||
|
||||
class GuiGraphViewer (threading.Thread):
|
||||
|
||||
def __init__(self, db, settings, querylist, config, debug=True):
|
||||
def __init__(self, querylist, config, debug=True):
|
||||
"""Constructor for GraphViewer"""
|
||||
self.debug=debug
|
||||
#print "start of GraphViewer constructor"
|
||||
self.db=db
|
||||
self.cursor=db.cursor
|
||||
self.settings=settings
|
||||
self.sql=querylist
|
||||
self.db = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
|
||||
self.db.do_connect(config)
|
||||
|
||||
self.sql = querylist
|
||||
self.conf = config
|
||||
|
||||
filters_display = { "Heroes" : True,
|
||||
|
@ -63,7 +63,7 @@ class GuiGraphViewer (threading.Thread):
|
|||
"Button2" : True
|
||||
}
|
||||
|
||||
self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display)
|
||||
self.filters = Filters.Filters(self.db, config, querylist, display = filters_display)
|
||||
self.filters.registerButton1Name("Refresh Graph")
|
||||
self.filters.registerButton1Callback(self.generateGraph)
|
||||
self.filters.registerButton2Name("Export to File")
|
||||
|
@ -146,7 +146,7 @@ class GuiGraphViewer (threading.Thread):
|
|||
for site in sites:
|
||||
if sites[site] == True:
|
||||
sitenos.append(siteids[site])
|
||||
self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],))
|
||||
self.db.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],))
|
||||
result = self.db.cursor.fetchall()
|
||||
if len(result) == 1:
|
||||
playerids.append(result[0][0])
|
||||
|
@ -226,7 +226,7 @@ class GuiGraphViewer (threading.Thread):
|
|||
|
||||
#print "DEBUG: sql query:"
|
||||
#print tmp
|
||||
self.cursor.execute(tmp)
|
||||
self.db.cursor.execute(tmp)
|
||||
#returns (HandId,Winnings,Costs,Profit)
|
||||
winnings = self.db.cursor.fetchall()
|
||||
self.db.db.rollback()
|
||||
|
|
|
@ -66,7 +66,7 @@ class GuiPlayerStats (threading.Thread):
|
|||
"Button2" : True
|
||||
}
|
||||
|
||||
self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display)
|
||||
self.filters = Filters.Filters(self.db, config, querylist, display = filters_display)
|
||||
self.filters.registerButton1Name("_Filters")
|
||||
self.filters.registerButton1Callback(self.showDetailFilter)
|
||||
self.filters.registerButton2Name("_Refresh")
|
||||
|
@ -227,11 +227,6 @@ class GuiPlayerStats (threading.Thread):
|
|||
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()
|
||||
|
||||
tmp = self.sql.query[query]
|
||||
tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats, groups, dates)
|
||||
self.cursor.execute(tmp)
|
||||
|
@ -279,10 +274,6 @@ class GuiPlayerStats (threading.Thread):
|
|||
|
||||
while sqlrow < rows:
|
||||
treerow = []
|
||||
if(row%2 == 0):
|
||||
bgcolor = "white"
|
||||
else:
|
||||
bgcolor = "lightgrey"
|
||||
for col,column in enumerate(cols_to_show):
|
||||
if column[colalias] in colnames:
|
||||
value = result[sqlrow][colnames.index(column[colalias])]
|
||||
|
|
|
@ -20,6 +20,7 @@ import pygtk
|
|||
pygtk.require('2.0')
|
||||
import gtk
|
||||
import os
|
||||
from time import time, strftime
|
||||
|
||||
import fpdb_import
|
||||
import fpdb_db
|
||||
|
@ -58,21 +59,50 @@ class GuiPositionalStats (threading.Thread):
|
|||
"Button2" : False
|
||||
}
|
||||
|
||||
self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display)
|
||||
self.filters = Filters.Filters(self.db, config, querylist, display = filters_display)
|
||||
self.filters.registerButton1Name("Refresh")
|
||||
self.filters.registerButton1Callback(self.refreshStats)
|
||||
|
||||
# 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
|
||||
, ["plposition", False, "Posn", 1.0, "%s"] # true not allowed for this line (set in code)
|
||||
, ["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"]
|
||||
, ["bb100xr", True, "bbxr/100", 1.0, "%4.2f"]
|
||||
, ["variance", True, "Variance", 1.0, "%5.2f"]
|
||||
]
|
||||
|
||||
self.stat_table = None
|
||||
self.stats_frame = None
|
||||
self.stats_vbox = None
|
||||
|
||||
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.set_label_align(0.0, 0.0)
|
||||
self.stats_frame.show()
|
||||
self.stats_vbox = gtk.VBox(False, 0)
|
||||
self.stats_vbox.show()
|
||||
|
||||
# This could be stored in config eventually, or maybe configured in this window somehow.
|
||||
# Each posncols element is the name of a column returned by the sql
|
||||
|
@ -90,11 +120,11 @@ class GuiPositionalStats (threading.Thread):
|
|||
, "PoFAFq", "Net($)", "bb/100", "$/hand", "Variance", "Hds"
|
||||
)
|
||||
|
||||
self.fillStatsFrame(self.stats_frame)
|
||||
statsFrame.add(self.stats_frame)
|
||||
self.fillStatsFrame(self.stats_vbox)
|
||||
self.stats_frame.add(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)
|
||||
|
||||
|
||||
def get_vbox(self):
|
||||
|
@ -107,9 +137,12 @@ class GuiPositionalStats (threading.Thread):
|
|||
print "DEBUG: activesite set to %s" %(self.activesite)
|
||||
|
||||
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()
|
||||
|
@ -144,66 +177,104 @@ class GuiPositionalStats (threading.Thread):
|
|||
self.createStatsTable(vbox, playerids, sitenos, limits, seats, dates)
|
||||
|
||||
def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates):
|
||||
self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required
|
||||
self.stats_table.set_col_spacings(4)
|
||||
self.stats_table.show()
|
||||
vbox.add(self.stats_table)
|
||||
|
||||
starttime = time()
|
||||
colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4
|
||||
row = 0
|
||||
col = 0
|
||||
for t in self.posnheads:
|
||||
l = gtk.Label(self.posnheads[col])
|
||||
l.show()
|
||||
self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK)
|
||||
col +=1
|
||||
|
||||
tmp = self.sql.query['playerStatsByPosition']
|
||||
tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats, dates)
|
||||
self.cursor.execute(tmp)
|
||||
result = self.cursor.fetchall()
|
||||
colnames = [desc[0].lower() for desc in self.cursor.description]
|
||||
|
||||
liststore = gtk.ListStore(*([str] * len(colnames)))
|
||||
view = gtk.TreeView(model=liststore)
|
||||
view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
|
||||
vbox.pack_start(view, expand=False, padding=3)
|
||||
# left-aligned cells:
|
||||
textcell = gtk.CellRendererText()
|
||||
# centred cells:
|
||||
textcell50 = gtk.CellRendererText()
|
||||
textcell50.set_property('xalign', 0.5)
|
||||
# right-aligned cells:
|
||||
numcell = gtk.CellRendererText()
|
||||
numcell.set_property('xalign', 1.0)
|
||||
listcols = []
|
||||
|
||||
for t in self.posnheads:
|
||||
listcols.append(gtk.TreeViewColumn(self.posnheads[col]))
|
||||
view.append_column(listcols[col])
|
||||
if col == 0:
|
||||
listcols[col].pack_start(textcell, expand=True)
|
||||
listcols[col].add_attribute(textcell, 'text', col)
|
||||
listcols[col].set_expand(True)
|
||||
elif col in (1, 2):
|
||||
listcols[col].pack_start(textcell50, expand=True)
|
||||
listcols[col].add_attribute(textcell50, 'text', col)
|
||||
listcols[col].set_expand(True)
|
||||
else:
|
||||
listcols[col].pack_start(numcell, expand=True)
|
||||
listcols[col].add_attribute(numcell, 'text', col)
|
||||
listcols[col].set_expand(True)
|
||||
col +=1
|
||||
|
||||
# Code below to be used when full column data structures implemented like in player stats:
|
||||
|
||||
# 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 column[colxalign] == 0.0:
|
||||
# listcols[col].pack_start(textcell, expand=True)
|
||||
# listcols[col].add_attribute(textcell, 'text', col)
|
||||
# else:
|
||||
# listcols[col].pack_start(textcell50, expand=True)
|
||||
# listcols[col].add_attribute(textcell50, 'text', col)
|
||||
# listcols[col].set_expand(True)
|
||||
# else:
|
||||
# listcols[col].pack_start(numcell, expand=True)
|
||||
# listcols[col].add_attribute(numcell, 'text', col)
|
||||
# listcols[col].set_expand(True)
|
||||
# #listcols[col].set_alignment(column[colxalign]) # no effect?
|
||||
|
||||
rows = len(result)
|
||||
colnames = [desc[0].lower() for desc in self.cursor.description]
|
||||
|
||||
last_game,last_seats,sqlrow = "","",0
|
||||
while sqlrow < rows:
|
||||
if(row%2 == 0):
|
||||
bgcolor = "white"
|
||||
else:
|
||||
bgcolor = "lightgrey"
|
||||
rowprinted=0
|
||||
treerow = []
|
||||
avgcol = colnames.index('avgseats')
|
||||
for col,colname in enumerate(self.posncols):
|
||||
if colname in colnames:
|
||||
sqlcol = colnames.index(colname)
|
||||
else:
|
||||
continue
|
||||
eb = gtk.EventBox()
|
||||
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
|
||||
# print blank row between levels:
|
||||
if result[sqlrow][sqlcol]:
|
||||
if sqlrow == 0:
|
||||
l = gtk.Label(result[sqlrow][sqlcol])
|
||||
value = result[sqlrow][sqlcol]
|
||||
rowprinted=1
|
||||
elif result[sqlrow][0] != last_game:
|
||||
l = gtk.Label(' ')
|
||||
value = ' '
|
||||
elif 'show' in seats and seats['show'] and result[sqlrow][avgcol] != last_seats:
|
||||
l = gtk.Label(' ')
|
||||
value = ' '
|
||||
else:
|
||||
l = gtk.Label(result[sqlrow][sqlcol])
|
||||
value = result[sqlrow][sqlcol]
|
||||
rowprinted=1
|
||||
else:
|
||||
l = gtk.Label(' ')
|
||||
if col == 0:
|
||||
l.set_alignment(xalign=0.0, yalign=0.5)
|
||||
elif col == 1:
|
||||
l.set_alignment(xalign=0.5, yalign=0.5)
|
||||
value = ' '
|
||||
if value and value != -999:
|
||||
treerow.append(value)
|
||||
else:
|
||||
l.set_alignment(xalign=1.0, yalign=0.5)
|
||||
eb.add(l)
|
||||
self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK)
|
||||
l.show()
|
||||
eb.show()
|
||||
treerow.append(' ')
|
||||
iter = liststore.append(treerow)
|
||||
last_game = result[sqlrow][0]
|
||||
last_seats = result[sqlrow][avgcol]
|
||||
if rowprinted:
|
||||
|
@ -220,50 +291,36 @@ class GuiPositionalStats (threading.Thread):
|
|||
|
||||
# blank row between main stats and totals:
|
||||
col = 0
|
||||
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(' ')
|
||||
eb.add(l)
|
||||
self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK)
|
||||
l.show()
|
||||
eb.show()
|
||||
treerow = [' ' for x in self.posncols]
|
||||
iter = liststore.append(treerow)
|
||||
row = row + 1
|
||||
|
||||
for sqlrow in range(rows):
|
||||
if(row%2 == 0):
|
||||
bgcolor = "white"
|
||||
else:
|
||||
bgcolor = "lightgrey"
|
||||
treerow = []
|
||||
for col,colname in enumerate(self.posncols):
|
||||
if colname in colnames:
|
||||
sqlcol = colnames.index(colname)
|
||||
elif colname != "plposition":
|
||||
continue
|
||||
eb = gtk.EventBox()
|
||||
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor))
|
||||
if colname == 'plposition':
|
||||
l = gtk.Label('Totals')
|
||||
value = 'Totals'
|
||||
elif result[sqlrow][sqlcol]:
|
||||
l = gtk.Label(result[sqlrow][sqlcol])
|
||||
value = result[sqlrow][sqlcol]
|
||||
else:
|
||||
l = gtk.Label(' ')
|
||||
if col == 0:
|
||||
l.set_alignment(xalign=0.0, yalign=0.5)
|
||||
elif col == 1:
|
||||
l.set_alignment(xalign=0.5, yalign=0.5)
|
||||
value = ' '
|
||||
if value and value != -999:
|
||||
treerow.append(value)
|
||||
else:
|
||||
l.set_alignment(xalign=1.0, yalign=0.5)
|
||||
eb.add(l)
|
||||
self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK)
|
||||
l.show()
|
||||
eb.show()
|
||||
treerow.append(' ')
|
||||
iter = liststore.append(treerow)
|
||||
row = row + 1
|
||||
vbox.show_all()
|
||||
|
||||
self.db.db.rollback()
|
||||
print "Positional Stats page displayed in %4.2f seconds" % (time() - starttime)
|
||||
#end def fillStatsFrame(self, vbox):
|
||||
|
||||
def refineQuery(self, query, playerids, sitenos, limits, seats, dates):
|
||||
|
|
412
pyfpdb/Hand.py
412
pyfpdb/Hand.py
|
@ -15,6 +15,8 @@
|
|||
#In the "official" distribution you can find the license in
|
||||
#agpl-3.0.txt in the docs folder of the package.
|
||||
|
||||
# TODO: get writehand() encoding correct
|
||||
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
|
@ -26,12 +28,20 @@ import operator
|
|||
import time,datetime
|
||||
from copy import deepcopy
|
||||
from Exceptions import *
|
||||
import pprint
|
||||
import DerivedStats
|
||||
import Card
|
||||
|
||||
class Hand:
|
||||
|
||||
###############################################################3
|
||||
# Class Variables
|
||||
UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'}
|
||||
LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'}
|
||||
SYMBOL = {'USD': '$', 'EUR': u'E', 'T$': '', 'play': ''}
|
||||
MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose' : 'HOSE'}
|
||||
|
||||
|
||||
def __init__(self, sitename, gametype, handText, builtFrom = "HHC"):
|
||||
self.sitename = sitename
|
||||
self.stats = DerivedStats.DerivedStats(self)
|
||||
|
@ -44,6 +54,10 @@ class Hand:
|
|||
self.maxseats = 10
|
||||
self.counted_seats = 0
|
||||
self.buttonpos = 0
|
||||
self.tourNo = None
|
||||
self.buyin = None
|
||||
self.level = None
|
||||
self.mixed = None
|
||||
self.seating = []
|
||||
self.players = []
|
||||
self.posted = []
|
||||
|
@ -55,17 +69,19 @@ class Hand:
|
|||
self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']]
|
||||
self.board = {} # dict from street names to community cards
|
||||
self.holecards = {}
|
||||
self.discards = {}
|
||||
for street in self.allStreets:
|
||||
self.streets[street] = "" # portions of the handText, filled by markStreets()
|
||||
self.actions[street] = []
|
||||
for street in self.actionStreets:
|
||||
self.bets[street] = {}
|
||||
self.lastBet[street] = 0
|
||||
self.actions[street] = []
|
||||
self.board[street] = []
|
||||
for street in self.holeStreets:
|
||||
self.holecards[street] = {} # dict from player names to holecards
|
||||
|
||||
self.discards[street] = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards
|
||||
# Collections indexed by player names
|
||||
# self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards
|
||||
self.discards = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards
|
||||
self.stacks = {}
|
||||
self.collected = [] #list of ?
|
||||
self.collectees = {} # dict from player names to amounts collected (?)
|
||||
|
@ -74,6 +90,7 @@ class Hand:
|
|||
self.folded = set()
|
||||
self.dealt = set() # 'dealt to' line to be printed
|
||||
self.shown = set() # cards were shown
|
||||
self.mucked = set() # cards were mucked at showdown
|
||||
|
||||
# self.action = []
|
||||
# Things to do with money
|
||||
|
@ -83,10 +100,77 @@ class Hand:
|
|||
self.rake = None
|
||||
|
||||
def __str__(self):
|
||||
vars = ( ("BB", self.bb),
|
||||
("SB", self.sb),
|
||||
("BUTTONPOS", self.buttonpos),
|
||||
("HAND NO.", self.handid),
|
||||
("SITE", self.sitename),
|
||||
("TABLE NAME", self.tablename),
|
||||
("HERO", self.hero),
|
||||
("MAXSEATS", self.maxseats),
|
||||
("TOURNAMENT NO", self.tourNo),
|
||||
("BUYIN", self.buyin),
|
||||
("LEVEL", self.level),
|
||||
("MIXED", self.mixed),
|
||||
("LASTBET", self.lastBet),
|
||||
("ACTION STREETS", self.actionStreets),
|
||||
("STREETS", self.streets),
|
||||
("ALL STREETS", self.allStreets),
|
||||
("COMMUNITY STREETS", self.communityStreets),
|
||||
("HOLE STREETS", self.holeStreets),
|
||||
("COUNTED SEATS", self.counted_seats),
|
||||
("DEALT", self.dealt),
|
||||
("SHOWN", self.shown),
|
||||
("MUCKED", self.mucked),
|
||||
("TOTAL POT", self.totalpot),
|
||||
("TOTAL COLLECTED", self.totalcollected),
|
||||
("RAKE", self.rake),
|
||||
("START TIME", self.starttime),
|
||||
)
|
||||
|
||||
structs = ( ("PLAYERS", self.players),
|
||||
("STACKS", self.stacks),
|
||||
("POSTED", self.posted),
|
||||
("POT", self.pot),
|
||||
("SEATING", self.seating),
|
||||
("GAMETYPE", self.gametype),
|
||||
("ACTION", self.actions),
|
||||
("COLLECTEES", self.collectees),
|
||||
("BETS", self.bets),
|
||||
("BOARD", self.board),
|
||||
("DISCARDS", self.discards),
|
||||
("HOLECARDS", self.holecards),
|
||||
)
|
||||
str = ''
|
||||
str = str + "Hand Object for %s at %s" % (self.handid, self.sitename)
|
||||
for (name, var) in vars:
|
||||
str = str + "\n%s = " % name + pprint.pformat(var)
|
||||
|
||||
for (name, struct) in structs:
|
||||
str = str + "\n%s =\n" % name + pprint.pformat(struct, 4)
|
||||
return str
|
||||
|
||||
def addHoleCards(self, street, player, open=[], closed=[], shown=False, mucked=False, dealt=False):
|
||||
"""\
|
||||
Assigns observed holecards to a player.
|
||||
cards list of card bigrams e.g. ['2h','Jc']
|
||||
player (string) name of player
|
||||
shown whether they were revealed at showdown
|
||||
mucked whether they were mucked at showdown
|
||||
dealt whether they were seen in a 'dealt to' line
|
||||
"""
|
||||
# logging.debug("addHoleCards %s %s" % (open + closed, player))
|
||||
try:
|
||||
self.checkPlayerExists(player)
|
||||
except FpdbParseError, e:
|
||||
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||
return
|
||||
|
||||
if dealt: self.dealt.add(player)
|
||||
if shown: self.shown.add(player)
|
||||
if mucked: self.mucked.add(player)
|
||||
|
||||
self.holecards[street][player] = [open, closed]
|
||||
|
||||
def insert(self, db):
|
||||
""" Function to insert Hand into database
|
||||
Should not commit, and do minimal selects. Callers may want to cache commits
|
||||
|
@ -178,10 +262,10 @@ If a player has None chips he won't be added."""
|
|||
self.players.append([seat, name, chips])
|
||||
self.stacks[name] = Decimal(chips)
|
||||
self.pot.addPlayer(name)
|
||||
for street in self.allStreets:
|
||||
for street in self.actionStreets:
|
||||
self.bets[street][name] = []
|
||||
#self.holecards[name] = {} # dict from street names.
|
||||
self.discards[name] = {} # dict from street names.
|
||||
#self.discards[name] = {} # dict from street names.
|
||||
|
||||
|
||||
def addStreets(self, match):
|
||||
|
@ -202,7 +286,7 @@ If a player has None chips he won't be added."""
|
|||
def setCommunityCards(self, street, cards):
|
||||
logging.debug("setCommunityCards %s %s" %(street, cards))
|
||||
self.board[street] = [self.card(c) for c in cards]
|
||||
print "DEBUG: self.board: %s" % self.board
|
||||
# print "DEBUG: self.board: %s" % self.board
|
||||
|
||||
def card(self,c):
|
||||
"""upper case the ranks but not suits, 'atjqk' => 'ATJQK'"""
|
||||
|
@ -367,6 +451,20 @@ Add a raise on [street] by [player] to [amountTo]
|
|||
self.collectees[player] += Decimal(pot)
|
||||
|
||||
|
||||
def addShownCards(self, cards, player, holeandboard=None, shown=True, mucked=False):
|
||||
"""\
|
||||
For when a player shows cards for any reason (for showdown or out of choice).
|
||||
Card ranks will be uppercased
|
||||
"""
|
||||
logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
|
||||
if cards is not None:
|
||||
self.addHoleCards(cards,player,shown, mucked)
|
||||
elif holeandboard is not None:
|
||||
holeandboard = set([self.card(c) for c in holeandboard])
|
||||
board = set([c for s in self.board.values() for c in s])
|
||||
self.addHoleCards(holeandboard.difference(board),player,shown, mucked)
|
||||
|
||||
|
||||
def totalPot(self):
|
||||
"""If all bets and blinds have been added, totals up the total pot size"""
|
||||
|
||||
|
@ -410,7 +508,6 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
|||
|
||||
logging.debug("gametype: %s" %(self.gametype))
|
||||
retstring = "%s %s" %(gs[self.gametype['category']], ls[self.gametype['limitType']])
|
||||
|
||||
return retstring
|
||||
|
||||
|
||||
|
@ -447,6 +544,33 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
|||
elif act[1] == 'stands pat':
|
||||
return ("%s: stands pat" %(act[0]))
|
||||
|
||||
def getStakesAsString(self):
|
||||
retstring = "%s%s/%s%s" % (self.SYMBOL[self.gametype['currency']], self.sb, self.SYMBOL[self.gametype['currency']], self.bb)
|
||||
return retstring
|
||||
|
||||
def writeGameLine(self):
|
||||
# print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')))
|
||||
game_string = "PokerStars Game #%s: " % self.handid
|
||||
if self.tourNo != None:
|
||||
game_string = game_string + "Tournament #%s, %s %s - Level %s (%s) - " % (self.tourNo,
|
||||
self.buyin, self.getGameTypeAsString(), self.level, self.getStakesAsString())
|
||||
elif self.mixed != None:
|
||||
game_string = game_string + " %s (%s, %s) - " % (self.MS[self.mixed],
|
||||
self.getGameTypeAsString(), self.getStakesAsString())
|
||||
else:
|
||||
game_string = game_string + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString())
|
||||
game_string = game_string + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET')
|
||||
return game_string
|
||||
|
||||
|
||||
def writeTableLine(self):
|
||||
table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats)
|
||||
if self.gametype['currency'] == 'play':
|
||||
table_string = table_string + " (Play Money)"
|
||||
if self.buttonpos != None:
|
||||
table_string = table_string + " Seat #%s is the button" % self.buttonpos
|
||||
return table_string
|
||||
|
||||
|
||||
class HoldemOmahaHand(Hand):
|
||||
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None):
|
||||
|
@ -494,45 +618,12 @@ class HoldemOmahaHand(Hand):
|
|||
pass
|
||||
|
||||
|
||||
def addHoleCards(self, cards, player, shown=False, dealt=False):
|
||||
"""\
|
||||
Assigns observed holecards to a player.
|
||||
cards list of card bigrams e.g. ['2h','Jc']
|
||||
player (string) name of player
|
||||
shown whether they were revealed at showdown
|
||||
dealt whether they were seen in a 'dealt to' line
|
||||
"""
|
||||
logging.debug("addHoleCards %s %s" % (cards, player))
|
||||
try:
|
||||
self.checkPlayerExists(player)
|
||||
except FpdbParseError, e:
|
||||
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||
return
|
||||
|
||||
cardset = set((self.card(c) for c in cards))
|
||||
if len(cardset) == 0:
|
||||
return
|
||||
if dealt:
|
||||
self.dealt.add(player)
|
||||
if shown:
|
||||
self.shown.add(player)
|
||||
if player in self.holecards['PREFLOP']:
|
||||
self.holecards['PREFLOP'][player].update(cardset)
|
||||
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
|
||||
if player == self.hero: # we have hero's cards just update shown/mucked
|
||||
if shown: self.shown.add(player)
|
||||
if mucked: self.mucked.add(player)
|
||||
else:
|
||||
self.holecards['PREFLOP'][player] = cardset
|
||||
|
||||
def addShownCards(self, cards, player, holeandboard=None):
|
||||
"""\
|
||||
For when a player shows cards for any reason (for showdown or out of choice).
|
||||
Card ranks will be uppercased
|
||||
"""
|
||||
logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
|
||||
if cards is not None:
|
||||
self.addHoleCards(cards,player,shown=True)
|
||||
elif holeandboard is not None:
|
||||
holeandboard = set([self.card(c) for c in holeandboard])
|
||||
board = set([c for s in self.board.values() for c in s])
|
||||
self.addHoleCards(holeandboard.difference(board),player,shown=True)
|
||||
self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt)
|
||||
|
||||
|
||||
def writeHTMLHand(self, fh=sys.__stdout__):
|
||||
|
@ -632,8 +723,11 @@ Card ranks will be uppercased
|
|||
|
||||
def writeHand(self, fh=sys.__stdout__):
|
||||
# PokerStars format.
|
||||
print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')))
|
||||
print >>fh, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||
# print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')))
|
||||
print >>fh, self.writeGameLine()
|
||||
print >>fh, self.writeTableLine()
|
||||
|
||||
# print >>fh, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||
|
||||
players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']]))
|
||||
logging.debug(self.actions['PREFLOP'])
|
||||
|
@ -647,10 +741,10 @@ Card ranks will be uppercased
|
|||
|
||||
print >>fh, ("*** HOLE CARDS ***")
|
||||
for player in self.dealt:
|
||||
print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player])))
|
||||
print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player][1])))
|
||||
if self.hero == "":
|
||||
for player in self.shown.difference(self.dealt):
|
||||
print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player])))
|
||||
print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player][1])))
|
||||
|
||||
if self.actions['PREFLOP']:
|
||||
for act in self.actions['PREFLOP']:
|
||||
|
@ -689,7 +783,7 @@ Card ranks will be uppercased
|
|||
elif self.gametype['category'] in ('holdem'):
|
||||
numOfHoleCardsNeeded = 2
|
||||
if len(self.holecards['PREFLOP'][name]) == numOfHoleCardsNeeded:
|
||||
print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards['PREFLOP'][name])))
|
||||
print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards['PREFLOP'][name][1])))
|
||||
|
||||
# Current PS format has the lines:
|
||||
# Uncalled bet ($111.25) returned to s0rrow
|
||||
|
@ -716,7 +810,7 @@ Card ranks will be uppercased
|
|||
seatnum = player[0]
|
||||
name = player[1]
|
||||
if name in self.collectees and name in self.shown:
|
||||
print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]), self.collectees[name]))
|
||||
print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]), self.collectees[name]))
|
||||
elif name in self.collectees:
|
||||
print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
|
||||
#~ elif name in self.shown:
|
||||
|
@ -725,7 +819,9 @@ Card ranks will be uppercased
|
|||
print >>fh, ("Seat %d: %s folded" % (seatnum, name))
|
||||
else:
|
||||
if name in self.shown:
|
||||
print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards['PREFLOP'][name])))
|
||||
print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1])))
|
||||
elif name in self.mucked:
|
||||
print >>fh, ("Seat %d: %s mucked [%s] " % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1])))
|
||||
else:
|
||||
print >>fh, ("Seat %d: %s mucked" % (seatnum, name))
|
||||
|
||||
|
@ -736,8 +832,10 @@ class DrawHand(Hand):
|
|||
if gametype['base'] != 'draw':
|
||||
pass # or indeed don't pass and complain instead
|
||||
self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
|
||||
self.allStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
|
||||
self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
|
||||
self.actionStreets = ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE']
|
||||
self.communityStreets = []
|
||||
Hand.__init__(self, sitename, gametype, handText)
|
||||
self.sb = gametype['sb']
|
||||
self.bb = gametype['bb']
|
||||
|
@ -749,12 +847,13 @@ class DrawHand(Hand):
|
|||
hhc.markStreets(self)
|
||||
hhc.readBlinds(self)
|
||||
hhc.readButton(self)
|
||||
hhc.readHeroCards(self)
|
||||
hhc.readShowdownActions(self)
|
||||
# Read actions in street order
|
||||
for street in self.streetList:
|
||||
if self.streets[street]:
|
||||
# hhc.readCommunityCards(self, street)
|
||||
hhc.readDrawCards(self, street)
|
||||
# hhc.readDrawCards(self, street)
|
||||
hhc.readAction(self, street)
|
||||
hhc.readCollectPot(self)
|
||||
hhc.readShownCards(self)
|
||||
|
@ -790,25 +889,33 @@ class DrawHand(Hand):
|
|||
#print "DEBUG: self.posted: %s" %(self.posted)
|
||||
|
||||
|
||||
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
|
||||
if player == self.hero: # we have hero's cards just update shown/mucked
|
||||
if shown: self.shown.add(player)
|
||||
if mucked: self.mucked.add(player)
|
||||
else:
|
||||
# TODO: Probably better to find the last street with action and add the hole cards to that street
|
||||
self.addHoleCards('DRAWTHREE', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt)
|
||||
|
||||
def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False):
|
||||
"""\
|
||||
Assigns observed holecards to a player.
|
||||
cards list of card bigrams e.g. ['2h','Jc']
|
||||
player (string) name of player
|
||||
"""
|
||||
try:
|
||||
self.checkPlayerExists(player)
|
||||
# if shown and len(cardset) > 0:
|
||||
# self.shown.add(player)
|
||||
self.holecards[player][street] = (newcards,oldcards)
|
||||
except FpdbParseError, e:
|
||||
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||
|
||||
# def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False):
|
||||
# """\
|
||||
#Assigns observed holecards to a player.
|
||||
#cards list of card bigrams e.g. ['2h','Jc']
|
||||
#player (string) name of player
|
||||
#"""
|
||||
# try:
|
||||
# self.checkPlayerExists(player)
|
||||
## if shown and len(cardset) > 0:
|
||||
## self.shown.add(player)
|
||||
# self.holecards[street][player] = (newcards,oldcards)
|
||||
# except FpdbParseError, e:
|
||||
# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||
|
||||
|
||||
def discardDrawHoleCards(self, cards, player, street):
|
||||
logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street))
|
||||
self.discards[player][street] = set([cards])
|
||||
self.discards[street][player] = set([cards])
|
||||
|
||||
|
||||
def addDiscard(self, street, player, num, cards):
|
||||
|
@ -821,12 +928,12 @@ player (string) name of player
|
|||
self.actions[street].append(act)
|
||||
|
||||
|
||||
def addShownCards(self, cards, player, holeandboard=None):
|
||||
"""\
|
||||
For when a player shows cards for any reason (for showdown or out of choice).
|
||||
Card ranks will be uppercased
|
||||
"""
|
||||
logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
|
||||
# def addShownCards(self, cards, player, holeandboard=None, shown=False, mucked=False):
|
||||
# """\
|
||||
#For when a player shows cards for any reason (for showdown or out of choice).
|
||||
#Card ranks will be uppercased
|
||||
#"""
|
||||
# logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
|
||||
# if cards is not None:
|
||||
# self.shown.add(player)
|
||||
# self.addHoleCards(cards,player)
|
||||
|
@ -836,10 +943,39 @@ Card ranks will be uppercased
|
|||
# self.addHoleCards(holeandboard.difference(board),player,shown=True)
|
||||
|
||||
|
||||
# def addHoleCards(self, cards, player, shown, mucked, dealt=False):
|
||||
# """\
|
||||
#Assigns observed holecards to a player.
|
||||
#cards list of card bigrams e.g. ['2h','Jc']
|
||||
#player (string) name of player
|
||||
#shown whether they were revealed at showdown
|
||||
#mucked whether they were mucked at showdown
|
||||
#dealt whether they were seen in a 'dealt to' line
|
||||
#"""
|
||||
## I think this only gets called for shown cards.
|
||||
# logging.debug("addHoleCards %s %s" % (cards, player))
|
||||
# try:
|
||||
# self.checkPlayerExists(player)
|
||||
# except FpdbParseError, e:
|
||||
# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||
# return
|
||||
#
|
||||
# if dealt:
|
||||
# self.dealt.add(player)
|
||||
# if shown:
|
||||
# self.shown.add(player)
|
||||
# if mucked:
|
||||
# self.mucked.add(player)
|
||||
# if player != self.hero: #skip hero, we know his cards
|
||||
# print "player, cards =", player, cards
|
||||
# self.holecards[self.holeStreets[-1]][player] = (cards, set([]))
|
||||
|
||||
def writeHand(self, fh=sys.__stdout__):
|
||||
# PokerStars format.
|
||||
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d %H:%M:%S ET', self.starttime)))
|
||||
print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||
# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d %H:%M:%S ET', self.starttime)))
|
||||
print >>fh, self.writeGameLine()
|
||||
# print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||
print >>fh, self.writeTableLine()
|
||||
|
||||
players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']]))
|
||||
|
||||
|
@ -865,8 +1001,8 @@ Card ranks will be uppercased
|
|||
for act in self.actions['DRAWONE']:
|
||||
print >>fh, self.actionString(act)
|
||||
if act[0] == self.hero and act[1] == 'discards':
|
||||
(nc,oc) = self.holecards[act[0]]['DRAWONE']
|
||||
dc = self.discards[act[0]]['DRAWONE']
|
||||
(nc,oc) = self.holecards['DRAWONE'][act[0]]
|
||||
dc = self.discards['DRAWONE'][act[0]]
|
||||
kc = oc - dc
|
||||
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
|
||||
|
||||
|
@ -875,8 +1011,8 @@ Card ranks will be uppercased
|
|||
for act in self.actions['DRAWTWO']:
|
||||
print >>fh, self.actionString(act)
|
||||
if act[0] == self.hero and act[1] == 'discards':
|
||||
(nc,oc) = self.holecards[act[0]]['DRAWTWO']
|
||||
dc = self.discards[act[0]]['DRAWTWO']
|
||||
(nc,oc) = self.holecards['DRAWTWO'][act[0]]
|
||||
dc = self.discards['DRAWTWO'][act[0]]
|
||||
kc = oc - dc
|
||||
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
|
||||
|
||||
|
@ -885,8 +1021,8 @@ Card ranks will be uppercased
|
|||
for act in self.actions['DRAWTHREE']:
|
||||
print >>fh, self.actionString(act)
|
||||
if act[0] == self.hero and act[1] == 'discards':
|
||||
(nc,oc) = self.holecards[act[0]]['DRAWTHREE']
|
||||
dc = self.discards[act[0]]['DRAWTHREE']
|
||||
(nc,oc) = self.holecards['DRAWTHREE'][act[0]]
|
||||
dc = self.discards['DRAWTHREE'][act[0]]
|
||||
kc = oc - dc
|
||||
print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc)))
|
||||
|
||||
|
@ -916,6 +1052,11 @@ class StudHand(Hand):
|
|||
def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"):
|
||||
if gametype['base'] != 'stud':
|
||||
pass # or indeed don't pass and complain instead
|
||||
|
||||
self.allStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH']
|
||||
self.communityStreets = []
|
||||
self.actionStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH']
|
||||
|
||||
self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order
|
||||
self.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH']
|
||||
Hand.__init__(self, sitename, gametype, handText)
|
||||
|
@ -931,21 +1072,35 @@ class StudHand(Hand):
|
|||
hhc.markStreets(self)
|
||||
hhc.readAntes(self)
|
||||
hhc.readBringIn(self)
|
||||
hhc.readHeroCards(self)
|
||||
#hhc.readShowdownActions(self) # not done yet
|
||||
# Read actions in street order
|
||||
for street in self.streetList:
|
||||
if self.streets[street]:
|
||||
logging.debug(street)
|
||||
logging.debug(self.streets[street])
|
||||
hhc.readStudPlayerCards(self, street)
|
||||
# hhc.readStudPlayerCards(self, street)
|
||||
hhc.readAction(self, street)
|
||||
hhc.readCollectPot(self)
|
||||
#hhc.readShownCards(self) # not done yet
|
||||
hhc.readShownCards(self) # not done yet
|
||||
self.totalPot() # finalise it (total the pot)
|
||||
hhc.getRake(self)
|
||||
elif builtFrom == "DB":
|
||||
self.select("dummy") # Will need a handId
|
||||
|
||||
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
|
||||
if player == self.hero: # we have hero's cards just update shown/mucked
|
||||
if shown: self.shown.add(player)
|
||||
if mucked: self.mucked.add(player)
|
||||
else:
|
||||
# self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt)
|
||||
self.addHoleCards('THIRD', player, open=[cards[2]], closed=cards[0:2], shown=shown, mucked=mucked)
|
||||
self.addHoleCards('FOURTH', player, open=[cards[3]], closed=[], shown=shown, mucked=mucked)
|
||||
self.addHoleCards('FIFTH', player, open=[cards[4]], closed=[], shown=shown, mucked=mucked)
|
||||
self.addHoleCards('SIXTH', player, open=[cards[5]], closed=[], shown=shown, mucked=mucked)
|
||||
self.addHoleCards('SEVENTH', player, open=[], closed=[cards[6]], shown=shown, mucked=mucked)
|
||||
|
||||
|
||||
def addPlayerCards(self, player, street, open=[], closed=[]):
|
||||
"""\
|
||||
Assigns observed cards to a player.
|
||||
|
@ -957,12 +1112,47 @@ closed likewise, but known only to player
|
|||
logging.debug("addPlayerCards %s, o%s x%s" % (player, open, closed))
|
||||
try:
|
||||
self.checkPlayerExists(player)
|
||||
self.holecards[player][street] = (open, closed)
|
||||
self.holecards[street][player] = (open, closed)
|
||||
# cards = set([self.card(c) for c in cards])
|
||||
# self.holecards[player].update(cards)
|
||||
except FpdbParseError, e:
|
||||
print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||
|
||||
# def addHoleCards(self, cards, player, shown, mucked, dealt=False):
|
||||
# """\
|
||||
#Assigns observed holecards to a player.
|
||||
#cards list of card bigrams e.g. ['2h','Jc']
|
||||
#player (string) name of player
|
||||
#shown whether they were revealed at showdown
|
||||
#mucked whether they were mucked at showdown
|
||||
#dealt whether they were seen in a 'dealt to' line
|
||||
#"""
|
||||
##
|
||||
## For stud games we just need to do the routine setting of shown/mucked/etc
|
||||
## and then update the cards 'THIRD' and 'SEVENTH'
|
||||
# logging.debug("addHoleCards %s %s" % (cards, player))
|
||||
# try:
|
||||
# self.checkPlayerExists(player)
|
||||
# except FpdbParseError, e:
|
||||
# print "[ERROR] Tried to add holecards for unknown player: %s" % (player,)
|
||||
# return
|
||||
#
|
||||
# if dealt:
|
||||
# self.dealt.add(player)
|
||||
# if shown:
|
||||
# self.shown.add(player)
|
||||
# if mucked:
|
||||
# self.mucked.add(player)
|
||||
# if player == self.hero:
|
||||
# if len(cards) > 2:
|
||||
# self.holecards['THIRD'][player] = ([cards[0:3]], [])
|
||||
# if len(cards) > 6:
|
||||
# self.holecards['SEVENTH'][player] = ([cards[6]], [])
|
||||
# else:
|
||||
# if len(cards) > 2:
|
||||
# self.holecards['THIRD'][player] = ([cards[0]], cards[1:3])
|
||||
# if len(cards) > 6:
|
||||
# self.holecards['SEVENTH'][player] = ([], [cards[6]])
|
||||
# TODO: def addComplete(self, player, amount):
|
||||
def addComplete(self, street, player, amountTo):
|
||||
# assert street=='THIRD'
|
||||
|
@ -995,11 +1185,19 @@ Add a complete on [street] by [player] to [amountTo]
|
|||
self.lastBet['THIRD'] = Decimal(bringin)
|
||||
self.pot.addMoney(player, Decimal(bringin))
|
||||
|
||||
|
||||
def writeHand(self, fh=sys.__stdout__):
|
||||
# PokerStars format.
|
||||
# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime)))
|
||||
print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')))
|
||||
print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||
|
||||
# TODO:
|
||||
# Hole cards are not currently correctly written. Currently the down cards for non-heros
|
||||
# are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix
|
||||
# but mind got boggled, will try again.
|
||||
# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET')))
|
||||
print >>fh, self.writeGameLine()
|
||||
print >>fh, self.writeTableLine()
|
||||
# print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos))
|
||||
|
||||
players_who_post_antes = set([x[0] for x in self.actions['ANTES']])
|
||||
|
||||
|
@ -1015,8 +1213,8 @@ Add a complete on [street] by [player] to [amountTo]
|
|||
dealt = 0
|
||||
#~ print >>fh, _("*** 3RD STREET ***")
|
||||
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
|
||||
if 'THIRD' in self.holecards[player]:
|
||||
(open, closed) = self.holecards[player]['THIRD']
|
||||
if self.holecards['THIRD'].has_key(player):
|
||||
(open, closed) = self.holecards['THIRD'][player]
|
||||
dealt+=1
|
||||
if dealt==1:
|
||||
print >>fh, _("*** 3RD STREET ***")
|
||||
|
@ -1029,12 +1227,12 @@ Add a complete on [street] by [player] to [amountTo]
|
|||
dealt = 0
|
||||
#~ print >>fh, _("*** 4TH STREET ***")
|
||||
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
|
||||
if 'FOURTH' in self.holecards[player]:
|
||||
if player in self.holecards['FOURTH']:
|
||||
old = []
|
||||
(o,c) = self.holecards[player]['THIRD']
|
||||
(o,c) = self.holecards['THIRD'][player]
|
||||
if o:old.extend(o)
|
||||
if c:old.extend(c)
|
||||
new = self.holecards[player]['FOURTH'][0]
|
||||
new = self.holecards['FOURTH'][player][0]
|
||||
dealt+=1
|
||||
if dealt==1:
|
||||
print >>fh, _("*** 4TH STREET ***")
|
||||
|
@ -1046,13 +1244,13 @@ Add a complete on [street] by [player] to [amountTo]
|
|||
dealt = 0
|
||||
#~ print >>fh, _("*** 5TH STREET ***")
|
||||
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
|
||||
if 'FIFTH' in self.holecards[player]:
|
||||
if self.holecards['FIFTH'].has_key(player):
|
||||
old = []
|
||||
for street in ('THIRD','FOURTH'):
|
||||
(o,c) = self.holecards[player][street]
|
||||
(o,c) = self.holecards[street][player]
|
||||
if o:old.extend(o)
|
||||
if c:old.extend(c)
|
||||
new = self.holecards[player]['FIFTH'][0]
|
||||
new = self.holecards['FIFTH'][player][0]
|
||||
dealt+=1
|
||||
if dealt==1:
|
||||
print >>fh, _("*** 5TH STREET ***")
|
||||
|
@ -1064,13 +1262,13 @@ Add a complete on [street] by [player] to [amountTo]
|
|||
dealt = 0
|
||||
#~ print >>fh, _("*** 6TH STREET ***")
|
||||
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
|
||||
if 'SIXTH' in self.holecards[player]:
|
||||
if self.holecards['SIXTH'].has_key(player):
|
||||
old = []
|
||||
for street in ('THIRD','FOURTH','FIFTH'):
|
||||
(o,c) = self.holecards[player][street]
|
||||
(o,c) = self.holecards[street][player]
|
||||
if o:old.extend(o)
|
||||
if c:old.extend(c)
|
||||
new = self.holecards[player]['SIXTH'][0]
|
||||
new = self.holecards['SIXTH'][player][0]
|
||||
dealt += 1
|
||||
if dealt == 1:
|
||||
print >>fh, _("*** 6TH STREET ***")
|
||||
|
@ -1085,13 +1283,13 @@ Add a complete on [street] by [player] to [amountTo]
|
|||
# i.e. are all but one players folded; is there an allin showdown; and all that.
|
||||
print >>fh, _("*** 7TH STREET ***")
|
||||
for player in [x[1] for x in self.players if x[1] in players_who_post_antes]:
|
||||
if 'SEVENTH' in self.holecards[player]:
|
||||
if self.holecards['SEVENTH'].has_key(player):
|
||||
old = []
|
||||
for street in ('THIRD','FOURTH','FIFTH','SIXTH'):
|
||||
(o,c) = self.holecards[player][street]
|
||||
(o,c) = self.holecards[street][player]
|
||||
if o:old.extend(o)
|
||||
if c:old.extend(c)
|
||||
new = self.holecards[player]['SEVENTH'][0]
|
||||
new = self.holecards['SEVENTH'][player][0]
|
||||
if new:
|
||||
print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "")
|
||||
for act in self.actions['SEVENTH']:
|
||||
|
@ -1130,11 +1328,13 @@ Add a complete on [street] by [player] to [amountTo]
|
|||
seatnum = player[0]
|
||||
name = player[1]
|
||||
if name in self.collectees and name in self.shown:
|
||||
print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]), self.collectees[name]))
|
||||
print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, self.join_holecards(name), self.collectees[name]))
|
||||
elif name in self.collectees:
|
||||
print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name]))
|
||||
elif name in self.shown:
|
||||
print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name])))
|
||||
print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, self.join_holecards(name)))
|
||||
elif name in self.mucked:
|
||||
print >>fh, _("Seat %d: %s mucked [%s]" % (seatnum, name, self.join_holecards(name)))
|
||||
elif name in self.folded:
|
||||
print >>fh, _("Seat %d: %s folded" % (seatnum, name))
|
||||
else:
|
||||
|
@ -1143,6 +1343,12 @@ Add a complete on [street] by [player] to [amountTo]
|
|||
print >>fh, "\n\n"
|
||||
|
||||
|
||||
def join_holecards(self, player):
|
||||
holecards = []
|
||||
for street in self.holeStreets:
|
||||
if self.holecards[street].has_key(player):
|
||||
holecards = holecards + self.holecards[street][player][0]
|
||||
return " ".join(holecards)
|
||||
|
||||
class Pot(object):
|
||||
|
||||
|
|
|
@ -197,6 +197,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py.
|
|||
logging.info("Unsupported game type: %s" % gametype)
|
||||
|
||||
if hand:
|
||||
# print hand
|
||||
hand.writeHand(self.out_fh)
|
||||
else:
|
||||
logging.info("Unsupported game type: %s" % gametype)
|
||||
|
|
|
@ -34,10 +34,13 @@ import gobject
|
|||
|
||||
# FreePokerTools modules
|
||||
from Mucked import Aux_Window
|
||||
from Mucked import Seat_Window
|
||||
from Mucked import Aux_Seats
|
||||
|
||||
class Hello(Aux_Window):
|
||||
"""A 'Hello World' Aux_Window demo."""
|
||||
def create(self):
|
||||
print "creating Hello"
|
||||
# This demo simply creates a label in a window.
|
||||
self.container = gtk.Window()
|
||||
self.container.add(gtk.Label("Hello World"))
|
||||
|
@ -99,15 +102,18 @@ class Hello_plus(Aux_Window):
|
|||
# hands played that was updated in the "update_data()" function.
|
||||
self.label.set_text("Hello %s\nYou have played %d hands\n on %s." % (self.hero, self.hands_played, self.site))
|
||||
|
||||
class Hello_Menu(Aux_Window):
|
||||
"""A 'Hello World' Aux_Window demo."""
|
||||
def create(self):
|
||||
# This demo puts a menu item on the HUD mainwindow.
|
||||
self.item = gtk.MenuItem('Print cards')
|
||||
self.hud.menu.append(self.item)
|
||||
self.item.connect("activate", self.print_cards)
|
||||
self.item.show()
|
||||
class Hello_Seats(Aux_Seats):
|
||||
"""A 'Hello World' Seat_Window demo."""
|
||||
|
||||
def print_cards(self, *args):
|
||||
# callback for the menu item
|
||||
print "cards =", self.hud.cards
|
||||
def create_contents(self, container, i):
|
||||
container.label = gtk.Label("empty")
|
||||
container.add(container.label)
|
||||
container.show_all()
|
||||
|
||||
def update_contents(self, container, i):
|
||||
if i == "common": return
|
||||
id = self.get_id_from_seat(i)
|
||||
if id == None:
|
||||
container.label.set_text("empty")
|
||||
else:
|
||||
container.label.set_text("player = %s" % self.hud.stat_dict[id]['screen_name'])
|
||||
|
|
|
@ -339,30 +339,30 @@ class Hud:
|
|||
Stats.do_tip(window.e_box[r][c], tip)
|
||||
|
||||
def topify_window(self, window):
|
||||
"""Set the specified gtk window to stayontop in MS Windows."""
|
||||
|
||||
def windowEnumerationHandler(hwnd, resultList):
|
||||
'''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
||||
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
||||
|
||||
unique_name = 'unique name for finding this window'
|
||||
real_name = window.get_title()
|
||||
window.set_title(unique_name)
|
||||
tl_windows = []
|
||||
win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
|
||||
|
||||
for w in tl_windows:
|
||||
if w[1] == unique_name:
|
||||
# """Set the specified gtk window to stayontop in MS Windows."""
|
||||
#
|
||||
# def windowEnumerationHandler(hwnd, resultList):
|
||||
# '''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
||||
# resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
||||
# unique_name = 'unique name for finding this window'
|
||||
# real_name = window.get_title()
|
||||
# window.set_title(unique_name)
|
||||
# tl_windows = []
|
||||
# win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
|
||||
#
|
||||
# for w in tl_windows:
|
||||
# if w[1] == unique_name:
|
||||
self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number))
|
||||
self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0])
|
||||
# self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0])
|
||||
self.main_window.gdkhandle = self.main_window.window
|
||||
self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle)
|
||||
|
||||
style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE)
|
||||
style |= win32con.WS_CLIPCHILDREN
|
||||
win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style)
|
||||
break
|
||||
# break
|
||||
|
||||
window.set_title(real_name)
|
||||
# window.set_title(real_name)
|
||||
|
||||
class Stat_Window:
|
||||
|
||||
|
@ -445,10 +445,10 @@ class Stat_Window:
|
|||
|
||||
Stats.do_tip(e_box[r][c], 'stuff')
|
||||
if usegtkframes:
|
||||
grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
|
||||
grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = game.xpad, ypadding = game.ypad)
|
||||
self.frame[r][c].add(e_box[r][c])
|
||||
else:
|
||||
grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0)
|
||||
grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = game.xpad, ypadding = game.ypad)
|
||||
label[r].append( gtk.Label('xxx') )
|
||||
|
||||
if usegtkframes:
|
||||
|
@ -473,6 +473,7 @@ class Popup_window:
|
|||
def __init__(self, parent, stat_window):
|
||||
self.sb_click = 0
|
||||
self.stat_window = stat_window
|
||||
self.parent = parent
|
||||
|
||||
# create the popup window
|
||||
self.window = gtk.Window()
|
||||
|
@ -532,11 +533,15 @@ class Popup_window:
|
|||
# db_connection.close_connection()
|
||||
stat_dict = stat_window.parent.stat_dict
|
||||
pu_text = ""
|
||||
mo_text = ""
|
||||
for s in stat_list:
|
||||
number = Stats.do_stat(stat_dict, player = int(stat_window.player_id), stat = s)
|
||||
mo_text += number[5] + " " + number[4] + "\n"
|
||||
pu_text += number[3] + "\n"
|
||||
|
||||
|
||||
self.lab.set_text(pu_text)
|
||||
Stats.do_tip(self.lab, mo_text)
|
||||
self.window.show_all()
|
||||
|
||||
self.window.set_transient_for(stat_window.window)
|
||||
|
@ -572,25 +577,25 @@ class Popup_window:
|
|||
def topify_window(self, window):
|
||||
"""Set the specified gtk window to stayontop in MS Windows."""
|
||||
|
||||
def windowEnumerationHandler(hwnd, resultList):
|
||||
'''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
||||
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
||||
# def windowEnumerationHandler(hwnd, resultList):
|
||||
# '''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
||||
# resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
||||
|
||||
unique_name = 'unique name for finding this window'
|
||||
real_name = window.get_title()
|
||||
window.set_title(unique_name)
|
||||
tl_windows = []
|
||||
win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
|
||||
# unique_name = 'unique name for finding this window'
|
||||
# real_name = window.get_title()
|
||||
# window.set_title(unique_name)
|
||||
# tl_windows = []
|
||||
# win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
|
||||
|
||||
for w in tl_windows:
|
||||
if w[1] == unique_name:
|
||||
# for w in tl_windows:
|
||||
# if w[1] == unique_name:
|
||||
window.set_transient_for(self.parent.main_window)
|
||||
style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE)
|
||||
style |= win32con.WS_CLIPCHILDREN
|
||||
win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style)
|
||||
break
|
||||
# break
|
||||
|
||||
window.set_title(real_name)
|
||||
# window.set_title(real_name)
|
||||
|
||||
if __name__== "__main__":
|
||||
main_window = gtk.Window()
|
||||
|
|
237
pyfpdb/Mucked.py
237
pyfpdb/Mucked.py
|
@ -37,27 +37,18 @@ import Configuration
|
|||
import Database
|
||||
import Card
|
||||
|
||||
class Aux_Window:
|
||||
class Aux_Window(object):
|
||||
def __init__(self, hud, params, config):
|
||||
self.hud = hud
|
||||
self.params = params
|
||||
self.config = config
|
||||
|
||||
def update_data(self, *args):
|
||||
pass
|
||||
|
||||
def update_gui(self, *args):
|
||||
pass
|
||||
|
||||
def create(self, *args):
|
||||
pass
|
||||
|
||||
def relocate(self, *args):
|
||||
pass
|
||||
|
||||
def save_layout(self, *args):
|
||||
pass
|
||||
|
||||
# Override these methods as needed
|
||||
def update_data(self, *args): pass
|
||||
def update_gui(self, *args): pass
|
||||
def create(self, *args): pass
|
||||
def relocate(self, *args): pass
|
||||
def save_layout(self, *args): pass
|
||||
def destroy(self):
|
||||
try:
|
||||
self.container.destroy()
|
||||
|
@ -89,14 +80,19 @@ class Aux_Window:
|
|||
pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0)
|
||||
return temp_pb
|
||||
|
||||
def split_cards(self, card):
|
||||
if card == 'xx': return ('B', 'S')
|
||||
return (card[0], card[1].upper())
|
||||
|
||||
def has_cards(self, cards):
|
||||
"""Returns the number of cards in the list."""
|
||||
n = 0
|
||||
for c in cards:
|
||||
if c in set('shdc'): return True
|
||||
return False
|
||||
if c != None and c > 0: n = n + 1
|
||||
return n
|
||||
|
||||
def get_id_from_seat(self, seat):
|
||||
"""Determine player id from seat number, given stat_dict."""
|
||||
for id, dict in self.hud.stat_dict.iteritems():
|
||||
if seat == dict['seat']:
|
||||
return id
|
||||
return None
|
||||
|
||||
class Stud_mucked(Aux_Window):
|
||||
def __init__(self, hud, config, params):
|
||||
|
@ -329,87 +325,152 @@ class Stud_cards:
|
|||
self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[0])
|
||||
self.eb[(c, r)].set_tooltip_text('')
|
||||
|
||||
class Flop_Mucked(Aux_Window):
|
||||
"""Aux_Window class for displaying mucked cards for flop games."""
|
||||
class Seat_Window(gtk.Window):
|
||||
"""Subclass gtk.Window for the seat windows."""
|
||||
|
||||
class Aux_Seats(Aux_Window):
|
||||
"""A super class to display an aux_window at each seat."""
|
||||
|
||||
def __init__(self, hud, config, params):
|
||||
self.hud = hud # hud object that this aux window supports
|
||||
self.config = config # configuration object for this aux window to use
|
||||
self.params = params # dict aux params from config
|
||||
self.positions = {} # dict of window positions
|
||||
# self.rel_positions = {} # dict of window positions, relative to the table origin
|
||||
self.displayed_cards = False
|
||||
self.displayed = False # the seat windows are displayed
|
||||
self.uses_timer = False # the Aux_seats object uses a timer to control hiding
|
||||
self.timer_on = False # bool = Ture if the timeout for removing the cards is on
|
||||
self.card_images = self.get_card_images()
|
||||
|
||||
# placeholders that should be overridden--so we don't throw errors
|
||||
def create_contents(self): pass
|
||||
def update_contents(self): pass
|
||||
|
||||
def create(self):
|
||||
self.adj = self.hud.adj_seats(0, self.config)
|
||||
self.adj = self.hud.adj_seats(0, self.config) # move adj_seats to aux and get rid of it in Hud.py
|
||||
loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max))
|
||||
|
||||
self.m_windows = {} # windows to put the card images in
|
||||
self.eb = {} # event boxes so we can interact with the mucked cards
|
||||
self.seen_cards = {} # image objects to stash the cards in
|
||||
|
||||
for i in (range(1, self.hud.max + 1) + ['common']):
|
||||
if i == 'common':
|
||||
(x, y) = self.params['layout'][self.hud.max].common
|
||||
else:
|
||||
(x, y) = loc[self.adj[i]]
|
||||
self.m_windows[i] = gtk.Window()
|
||||
self.m_windows[i] = Seat_Window()
|
||||
self.m_windows[i].set_decorated(False)
|
||||
self.m_windows[i].set_property("skip-taskbar-hint", True)
|
||||
self.m_windows[i].set_transient_for(self.hud.main_window)
|
||||
self.m_windows[i].set_focus_on_map(False)
|
||||
self.eb[i] = gtk.EventBox()
|
||||
self.eb[i].connect("button_press_event", self.button_press_cb)
|
||||
self.m_windows[i].connect("configure_event", self.configure_event_cb, i)
|
||||
self.m_windows[i].add(self.eb[i])
|
||||
self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[('B', 'H')])
|
||||
self.eb[i].add(self.seen_cards[i])
|
||||
self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y)
|
||||
# self.rel_positions[i] = (int(x), int(y))
|
||||
self.m_windows[i].move(self.positions[i][0], self.positions[i][1])
|
||||
if self.params.has_key('opacity'):
|
||||
self.m_windows[i].set_opacity(float(self.params['opacity']))
|
||||
|
||||
# the create_contents method is supplied by the subclass
|
||||
self.create_contents(self.m_windows[i], i)
|
||||
|
||||
self.m_windows[i].show_all()
|
||||
if self.uses_timer:
|
||||
self.m_windows[i].hide()
|
||||
|
||||
def update_gui(self, new_hand_id):
|
||||
"""Prepare and show the mucked cards."""
|
||||
if self.displayed_cards:
|
||||
self.hide_mucked_cards()
|
||||
self.displayed_cards = False
|
||||
for (i, cards) in self.hud.cards.iteritems():
|
||||
if self.has_cards(cards):
|
||||
"""Update the gui, LDO."""
|
||||
for i in self.m_windows.keys():
|
||||
self.update_contents(self.m_windows[i], i)
|
||||
|
||||
# Methods likely to be of use for any Seat_Window implementation
|
||||
def destroy(self):
|
||||
"""Destroy all of the seat windows."""
|
||||
for i in self.m_windows.keys():
|
||||
self.m_windows[i].destroy()
|
||||
del(self.m_windows[i])
|
||||
|
||||
# Methods likely to be useful for mucked card windows (or similar) only
|
||||
def hide(self):
|
||||
"""Hide the seat windows."""
|
||||
for (i, w) in self.m_windows.iteritems():
|
||||
w.hide()
|
||||
self.displayed = False
|
||||
|
||||
def save_layout(self, *args):
|
||||
"""Save new layout back to the aux element in the config file."""
|
||||
new_locs = {}
|
||||
# print "adj =", self.adj
|
||||
for (i, pos) in self.positions.iteritems():
|
||||
if i != 'common':
|
||||
new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y)
|
||||
else:
|
||||
new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y)
|
||||
self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs)
|
||||
|
||||
def configure_event_cb(self, widget, event, i, *args):
|
||||
self.positions[i] = widget.get_position()
|
||||
# self.rel_positions[i] = (self.positions[i][0] - self.hud.table.x, self.positions[i][1] - self.hud.table.y)
|
||||
|
||||
class Flop_Mucked(Aux_Seats):
|
||||
"""Aux_Window class for displaying mucked cards for flop games."""
|
||||
|
||||
def __init__(self, hud, config, params):
|
||||
super(Flop_Mucked, self).__init__(hud, config, params)
|
||||
self.card_images = self.get_card_images()
|
||||
self.uses_timer = True # this Aux_seats object uses a timer to control hiding
|
||||
|
||||
def create_contents(self, container, i):
|
||||
"""Create the widgets for showing the contents of the Aux_seats window."""
|
||||
container.eb = gtk.EventBox()
|
||||
container.eb.connect("button_press_event", self.button_press_cb)
|
||||
container.add(container.eb)
|
||||
container.seen_cards = gtk.image_new_from_pixbuf(self.card_images[0])
|
||||
container.eb.add(container.seen_cards)
|
||||
|
||||
def update_contents(self, container, i):
|
||||
if not self.hud.cards.has_key(i): return
|
||||
cards = self.hud.cards[i]
|
||||
n_cards = self.has_cards(cards)
|
||||
if n_cards > 1:
|
||||
|
||||
# scratch is a working pixbuf, used to assemble the image
|
||||
scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8,
|
||||
int(self.params['card_wd'])*len(cards)/2,
|
||||
int(self.params['card_wd'])*n_cards,
|
||||
int(self.params['card_ht']))
|
||||
x = 0 # x coord where the next card starts in scratch
|
||||
for card in [cards[k:k+2] for k in xrange(0, len(cards), 2)]:
|
||||
for card in cards:
|
||||
# concatenate each card image to scratch
|
||||
self.card_images[self.split_cards(card)].copy_area(0, 0,
|
||||
if card == None or card ==0:
|
||||
break
|
||||
self.card_images[card].copy_area(0, 0,
|
||||
int(self.params['card_wd']), int(self.params['card_ht']),
|
||||
scratch, x, 0)
|
||||
x = x + int(self.params['card_wd'])
|
||||
self.seen_cards[i].set_from_pixbuf(scratch)
|
||||
# self.m_windows[i].show_all()
|
||||
self.m_windows[i].resize(1,1)
|
||||
self.m_windows[i].show()
|
||||
self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back
|
||||
self.displayed_cards = True
|
||||
container.seen_cards.set_from_pixbuf(scratch)
|
||||
container.resize(1,1)
|
||||
container.show()
|
||||
container.move(self.positions[i][0], self.positions[i][1]) # here is where I move back
|
||||
self.displayed = True
|
||||
if i != "common":
|
||||
id = self.get_id_from_seat(i)
|
||||
self.m_windows[i].eb.set_tooltip_text(self.hud.stat_dict[id]['screen_name'])
|
||||
|
||||
for stats in self.hud.stat_dict.itervalues():
|
||||
self.eb[stats['seat']].set_tooltip_text(stats['screen_name'])
|
||||
def update_gui(self, new_hand_id):
|
||||
"""Prepare and show the mucked cards."""
|
||||
if self.displayed: self.hide()
|
||||
|
||||
if self.displayed_cards and float(self.params['timeout']) > 0:
|
||||
# See how many players showed a hand. Skip if only 1 shows (= hero)
|
||||
n_sd = 0
|
||||
for (i, cards) in self.hud.cards.iteritems():
|
||||
n_cards = self.has_cards(cards)
|
||||
if n_cards > 0 and i != 'common':
|
||||
n_sd = n_sd + 1
|
||||
if n_sd < 2:
|
||||
print "skipping, n_sd =", n_sd
|
||||
return
|
||||
|
||||
super(Flop_Mucked, self).update_gui(new_hand_id)
|
||||
|
||||
if self.displayed and float(self.params['timeout']) > 0:
|
||||
self.timer_on = True
|
||||
gobject.timeout_add(int(1000*float(self.params['timeout'])), self.timed_out)
|
||||
|
||||
def destroy(self):
|
||||
"""Destroy all of the mucked windows."""
|
||||
for w in self.m_windows.values():
|
||||
w.destroy()
|
||||
|
||||
def timed_out(self):
|
||||
# this is the callback from the timeout
|
||||
|
||||
|
@ -418,15 +479,9 @@ class Flop_Mucked(Aux_Window):
|
|||
if not self.timer_on:
|
||||
return False
|
||||
else:
|
||||
self.hide_mucked_cards()
|
||||
self.hide()
|
||||
return False
|
||||
|
||||
def hide_mucked_cards(self):
|
||||
"""Hide the mucked card windows."""
|
||||
for (i, w) in self.m_windows.iteritems():
|
||||
w.hide()
|
||||
self.displayed_cards = False
|
||||
|
||||
def button_press_cb(self, widget, event, *args):
|
||||
"""Handle button clicks in the event boxes."""
|
||||
|
||||
|
@ -444,58 +499,14 @@ class Flop_Mucked(Aux_Window):
|
|||
self.timer_on = False
|
||||
else:
|
||||
self.timer_on = False
|
||||
self.hide_mucked_cards()
|
||||
self.hide()
|
||||
|
||||
elif event.button == 1: # left button event
|
||||
window = widget.get_parent()
|
||||
window.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time)
|
||||
|
||||
def configure_event_cb(self, widget, event, i, *args):
|
||||
self.positions[i] = widget.get_position()
|
||||
# self.rel_positions[i] = (self.positions[i][0] - self.hud.table.x, self.positions[i][1] - self.hud.table.y)
|
||||
|
||||
def expose_all(self):
|
||||
for (i, cards) in self.hud.cards.iteritems():
|
||||
self.m_windows[i].show()
|
||||
self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) # here is where I move back
|
||||
self.displayed_cards = True
|
||||
|
||||
def save_layout(self, *args):
|
||||
"""Save new layout back to the aux element in the config file."""
|
||||
new_locs = {}
|
||||
# print "adj =", self.adj
|
||||
for (i, pos) in self.positions.iteritems():
|
||||
if i != 'common':
|
||||
new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y)
|
||||
else:
|
||||
new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y)
|
||||
self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs)
|
||||
|
||||
# This test program doesn't work
|
||||
|
||||
#if __name__== "__main__":
|
||||
#
|
||||
# def destroy(*args): # call back for terminating the main eventloop
|
||||
# gtk.main_quit() # used only for testing
|
||||
#
|
||||
# def process_new_hand(source, condition, db_connection): #callback from stdin watch -- testing only
|
||||
## there is a new hand_id to be processed
|
||||
## just read it and pass it to update
|
||||
# new_hand_id = sys.stdin.readline()
|
||||
# new_hand_id = new_hand_id.rstrip() # remove trailing whitespace
|
||||
# m.update_data(new_hand_id, db_connection)
|
||||
# m.update_gui(new_hand_id)
|
||||
# return(True)
|
||||
#
|
||||
# config = Configuration.Config()
|
||||
# db_connection = Database.Database(config, 'fpdbTEST', '')
|
||||
# main_window = gtk.Window()
|
||||
# main_window.set_keep_above(True)
|
||||
# main_window.connect("destroy", destroy)
|
||||
#
|
||||
# aux_to_call = "stud_mucked"
|
||||
# aux_params = config.get_aux_parameters(aux_to_call)
|
||||
# m = eval("%s(None, config, aux_params)" % aux_params['class'])
|
||||
#
|
||||
# s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand, db_connection)
|
||||
# gtk.main()
|
||||
self.displayed = True
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
########################################################################
|
||||
|
||||
# TODO: straighten out discards for draw games
|
||||
import sys
|
||||
from HandHistoryConverter import *
|
||||
|
||||
|
@ -25,16 +26,35 @@ from HandHistoryConverter import *
|
|||
|
||||
class PokerStars(HandHistoryConverter):
|
||||
|
||||
############################################################
|
||||
# Class Variables
|
||||
|
||||
# Static regexes
|
||||
re_GameInfo = re.compile("PokerStars Game #(?P<HID>[0-9]+):\s+(HORSE)? \(?(?P<GAME>Hold\'em|Razz|7 Card Stud|7 Card Stud Hi/Lo|Omaha|Omaha Hi/Lo|Badugi) (?P<LIMIT>No Limit|Limit|Pot Limit),? \(?(?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\) - (?P<DATETIME>.*$)", re.MULTILINE)
|
||||
re_GameInfo = re.compile("""PokerStars\sGame\s\#(?P<HID>[0-9]+):\s+
|
||||
(Tournament\s\#(?P<TOURNO>\d+),\s(?P<BUYIN>[\$\+\d\.]+)\s)?
|
||||
(?P<MIXED>HORSE|8\-Game|HOSE)?\s?\(?
|
||||
(?P<GAME>Hold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s
|
||||
(?P<LIMIT>No\sLimit|Limit|Pot\sLimit)\)?,?\s
|
||||
(-\sLevel\s(?P<LEVEL>[IVXLC]+)\s)?\(?
|
||||
(?P<CURRENCY>\$|)?
|
||||
(?P<SB>[.0-9]+)/\$?
|
||||
(?P<BB>[.0-9]+)\)\s-\s
|
||||
(?P<DATETIME>.*$)""",
|
||||
re.MULTILINE|re.VERBOSE)
|
||||
re_SplitHands = re.compile('\n\n+')
|
||||
re_TailSplitHands = re.compile('(\n\n\n+)')
|
||||
re_HandInfo = re.compile("^Table \'(?P<TABLE>[- a-zA-Z]+)\'(?P<TABLEATTRIBUTES>.+?$)?", re.MULTILINE)
|
||||
re_HandInfo = re.compile("""^Table\s\'(?P<TABLE>[-\ a-zA-Z\d]+)\'\s
|
||||
((?P<MAX>\d+)-max\s)?
|
||||
(?P<PLAY>\(Play\sMoney\)\s)?
|
||||
(Seat\s\#(?P<BUTTON>\d+)\sis\sthe\sbutton)?""",
|
||||
re.MULTILINE|re.VERBOSE)
|
||||
re_Button = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE)
|
||||
re_PlayerInfo = re.compile('^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[.0-9]+) in chips\)', re.MULTILINE)
|
||||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
# self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
|
||||
|
||||
mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'}
|
||||
|
||||
def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True):
|
||||
"""\
|
||||
in_path (default '-' = sys.stdin)
|
||||
|
@ -53,6 +73,9 @@ follow : whether to tail -f the input"""
|
|||
players = set([player[1] for player in hand.players])
|
||||
if not players <= self.compiledPlayers: # x <= y means 'x is subset of y'
|
||||
# we need to recompile the player regexs.
|
||||
# TODO: should probably rename re_HeroCards and corresponding method,
|
||||
# since they are used to find all cards on lines starting with "Dealt to:"
|
||||
# They still identify the hero.
|
||||
self.compiledPlayers = players
|
||||
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
|
||||
logging.debug("player_re: " + player_re)
|
||||
|
@ -62,32 +85,43 @@ follow : whether to tail -f the input"""
|
|||
self.re_BringIn = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_PostBoth = re.compile(r"^%s: posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||
self.re_HeroCards = re.compile(r"^Dealt to %s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE)
|
||||
self.re_Action = re.compile(r"^%s:(?P<ATYPE> bets| checks| raises| calls| folds| discards| stands pat)( \$(?P<BET>[.\d]+))?( to \$(?P<BETTO>[.\d]+))?( (?P<NODISCARDED>\d) cards?( \[(?P<DISCARDED>.+?)\])?)?" % player_re, re.MULTILINE)
|
||||
self.re_Action = re.compile(r"""^%s:(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat)
|
||||
(\s\$?(?P<BET>[.\d]+))?(\sto\s\$?(?P<BETTO>[.\d]+))? # the number discarded goes in <BET>
|
||||
(\scards?(\s\[(?P<DISCARDED>.+?)\])?)?"""
|
||||
% player_re, re.MULTILINE|re.VERBOSE)
|
||||
self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
|
||||
self.re_CollectPot = re.compile(r"Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*|)" % player_re, re.MULTILINE)
|
||||
self.re_CollectPot = re.compile(r"Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$?(?P<POT>[.\d]+)\)(, mucked| with.*|)" % player_re, re.MULTILINE)
|
||||
self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE)
|
||||
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s \(.*\) showed \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
|
||||
|
||||
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
|
||||
|
||||
def readSupportedGames(self):
|
||||
return [["ring", "hold", "nl"],
|
||||
["ring", "hold", "pl"],
|
||||
["ring", "hold", "fl"],
|
||||
|
||||
["ring", "stud", "fl"],
|
||||
#["ring", "draw", "fl"],
|
||||
["ring", "omaha", "pl"]
|
||||
|
||||
["ring", "draw", "fl"],
|
||||
|
||||
["tour", "hold", "nl"],
|
||||
["tour", "hold", "pl"],
|
||||
["tour", "hold", "fl"],
|
||||
|
||||
["tour", "stud", "fl"],
|
||||
]
|
||||
|
||||
def determineGameType(self, handText):
|
||||
info = {'type':'ring'}
|
||||
# inspect the handText and return the gametype dict
|
||||
# gametype dict is:
|
||||
# {'limitType': xxx, 'base': xxx, 'category': xxx}
|
||||
|
||||
info = {}
|
||||
m = self.re_GameInfo.search(handText)
|
||||
if not m:
|
||||
return None
|
||||
|
||||
mg = m.groupdict()
|
||||
|
||||
# translations from captured groups to our info strings
|
||||
# translations from captured groups to fpdb info strings
|
||||
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' }
|
||||
games = { # base, category
|
||||
"Hold'em" : ('hold','holdem'),
|
||||
|
@ -96,9 +130,14 @@ follow : whether to tail -f the input"""
|
|||
'Razz' : ('stud','razz'),
|
||||
'7 Card Stud' : ('stud','studhi'),
|
||||
'7 Card Stud Hi/Lo' : ('stud','studhilo'),
|
||||
'Badugi' : ('draw','badugi')
|
||||
'Badugi' : ('draw','badugi'),
|
||||
'Triple Draw 2-7 Lowball' : ('draw','27_3draw'),
|
||||
}
|
||||
currencies = { u'€':'EUR', '$':'USD', '':'T$' }
|
||||
# I don't think this is doing what we think. mg will always have all
|
||||
# the expected keys, but the ones that didn't match in the regex will
|
||||
# have a value of None. It is OK if it throws an exception when it
|
||||
# runs across an unknown game or limit or whatever.
|
||||
if 'LIMIT' in mg:
|
||||
info['limitType'] = limits[mg['LIMIT']]
|
||||
if 'GAME' in mg:
|
||||
|
@ -109,8 +148,13 @@ follow : whether to tail -f the input"""
|
|||
info['bb'] = mg['BB']
|
||||
if 'CURRENCY' in mg:
|
||||
info['currency'] = currencies[mg['CURRENCY']]
|
||||
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
|
||||
|
||||
if 'TOURNO' in mg and mg['TOURNO'] == None:
|
||||
info['type'] = 'ring'
|
||||
else:
|
||||
info['type'] = 'tour'
|
||||
|
||||
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
|
||||
return info
|
||||
|
||||
|
||||
|
@ -119,14 +163,13 @@ follow : whether to tail -f the input"""
|
|||
m = self.re_HandInfo.search(hand.handText,re.DOTALL)
|
||||
if m:
|
||||
info.update(m.groupdict())
|
||||
# TODO: Be less lazy and parse maxseats from the HandInfo regex
|
||||
if m.group('TABLEATTRIBUTES'):
|
||||
m2 = re.search("\s*(\d+)-max", m.group('TABLEATTRIBUTES'))
|
||||
hand.maxseats = int(m2.group(1))
|
||||
# hand.maxseats = int(m2.group(1))
|
||||
else:
|
||||
pass # throw an exception here, eh?
|
||||
m = self.re_GameInfo.search(hand.handText)
|
||||
if m: info.update(m.groupdict())
|
||||
m = self.re_Button.search(hand.handText)
|
||||
if m: info.update(m.groupdict())
|
||||
# m = self.re_Button.search(hand.handText)
|
||||
# if m: info.update(m.groupdict())
|
||||
# TODO : I rather like the idea of just having this dict as hand.info
|
||||
logging.debug("readHandInfo: %s" % info)
|
||||
for key in info:
|
||||
|
@ -143,6 +186,22 @@ follow : whether to tail -f the input"""
|
|||
hand.tablename = info[key]
|
||||
if key == 'BUTTON':
|
||||
hand.buttonpos = info[key]
|
||||
if key == 'MAX':
|
||||
hand.maxseats = int(info[key])
|
||||
|
||||
if key == 'MIXED':
|
||||
if info[key] == None: hand.mixed = None
|
||||
else: hand.mixed = self.mixes[info[key]]
|
||||
|
||||
if key == 'TOURNO':
|
||||
hand.tourNo = info[key]
|
||||
if key == 'BUYIN':
|
||||
hand.buyin = info[key]
|
||||
if key == 'LEVEL':
|
||||
hand.level = info[key]
|
||||
if key == 'PLAY' and info['PLAY'] != None:
|
||||
# hand.currency = 'play' # overrides previously set value
|
||||
hand.gametype['currency'] = 'play'
|
||||
|
||||
def readButton(self, hand):
|
||||
m = self.re_Button.search(hand.handText)
|
||||
|
@ -211,78 +270,115 @@ follow : whether to tail -f the input"""
|
|||
for a in self.re_PostBoth.finditer(hand.handText):
|
||||
hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB'))
|
||||
|
||||
# def readHeroCards(self, hand):
|
||||
# m = self.re_HeroCards.search(hand.handText)
|
||||
# if(m == None):
|
||||
# #Not involved in hand
|
||||
# hand.involved = False
|
||||
# else:
|
||||
# hand.hero = m.group('PNAME')
|
||||
# # "2c, qh" -> set(["2c","qc"])
|
||||
# # Also works with Omaha hands.
|
||||
# cards = m.group('NEWCARDS')
|
||||
# cards = set(cards.split(' '))
|
||||
# hand.addHoleCards(cards, m.group('PNAME'), shown=False, mucked=False, dealt=True)
|
||||
|
||||
def readHeroCards(self, hand):
|
||||
m = self.re_HeroCards.search(hand.handText)
|
||||
if(m == None):
|
||||
#Not involved in hand
|
||||
hand.involved = False
|
||||
else:
|
||||
hand.hero = m.group('PNAME')
|
||||
# "2c, qh" -> set(["2c","qc"])
|
||||
# Also works with Omaha hands.
|
||||
cards = m.group('NEWCARDS')
|
||||
cards = set(cards.split(' '))
|
||||
hand.addHoleCards(cards, m.group('PNAME'))
|
||||
|
||||
def readDrawCards(self, hand, street):
|
||||
logging.debug("readDrawCards")
|
||||
# streets PREFLOP, PREDRAW, and THIRD are special cases beacause
|
||||
# we need to grab hero's cards
|
||||
for street in ('PREFLOP', 'DEAL'):
|
||||
if street in hand.streets.keys():
|
||||
m = self.re_HeroCards.finditer(hand.streets[street])
|
||||
if m == None:
|
||||
hand.involved = False
|
||||
else:
|
||||
for player in m:
|
||||
hand.hero = player.group('PNAME') # Only really need to do this once
|
||||
newcards = player.group('NEWCARDS')
|
||||
oldcards = player.group('OLDCARDS')
|
||||
if newcards == None:
|
||||
newcards = set()
|
||||
else:
|
||||
newcards = set(newcards.split(' '))
|
||||
if oldcards == None:
|
||||
oldcards = set()
|
||||
else:
|
||||
oldcards = set(oldcards.split(' '))
|
||||
hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street)
|
||||
for found in m:
|
||||
# if m == None:
|
||||
# hand.involved = False
|
||||
# else:
|
||||
hand.hero = found.group('PNAME')
|
||||
newcards = found.group('NEWCARDS').split(' ')
|
||||
hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True)
|
||||
|
||||
|
||||
def readStudPlayerCards(self, hand, street):
|
||||
# See comments of reference implementation in FullTiltToFpdb.py
|
||||
logging.debug("readStudPlayerCards")
|
||||
for street, text in hand.streets.iteritems():
|
||||
if street in ('PREFLOP', 'DEAL'): continue # already done these
|
||||
m = self.re_HeroCards.finditer(hand.streets[street])
|
||||
for player in m:
|
||||
#~ logging.debug(player.groupdict())
|
||||
(pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS'))
|
||||
if oldcards:
|
||||
oldcards = [c.strip() for c in oldcards.split(' ')]
|
||||
if newcards:
|
||||
newcards = [c.strip() for c in newcards.split(' ')]
|
||||
if street=='ANTES':
|
||||
return
|
||||
elif street=='THIRD':
|
||||
# we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS'
|
||||
# hero: [xx][o]
|
||||
# others: [o]
|
||||
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards)
|
||||
elif street in ('FOURTH', 'FIFTH', 'SIXTH'):
|
||||
# 4th:
|
||||
# hero: [xxo] [o]
|
||||
# others: [o] [o]
|
||||
# 5th:
|
||||
# hero: [xxoo] [o]
|
||||
# others: [oo] [o]
|
||||
# 6th:
|
||||
# hero: [xxooo] [o]
|
||||
# others: [ooo] [o]
|
||||
hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards)
|
||||
# we may additionally want to check the earlier streets tally with what we have but lets trust it for now.
|
||||
elif street=='SEVENTH' and newcards:
|
||||
# hero: [xxoooo] [x]
|
||||
# others: not reported.
|
||||
hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards)
|
||||
for found in m:
|
||||
player = found.group('PNAME')
|
||||
if found.group('NEWCARDS') == None:
|
||||
newcards = []
|
||||
else:
|
||||
newcards = found.group('NEWCARDS').split(' ')
|
||||
if found.group('OLDCARDS') == None:
|
||||
oldcards = []
|
||||
else:
|
||||
oldcards = found.group('OLDCARDS').split(' ')
|
||||
|
||||
if street == 'THIRD' and len(newcards) == 3: # hero in stud game
|
||||
hand.hero = player
|
||||
hand.dealt.add(player) # need this for stud??
|
||||
hand.addHoleCards(street, player, closed=newcards[0:2], open=[newcards[2]], shown=False, mucked=False, dealt=False)
|
||||
else:
|
||||
hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False)
|
||||
|
||||
|
||||
# def readDrawCards(self, hand, street):
|
||||
# logging.debug("readDrawCards")
|
||||
# m = self.re_HeroCards.finditer(hand.streets[street])
|
||||
# if m == None:
|
||||
# hand.involved = False
|
||||
# else:
|
||||
# for player in m:
|
||||
# hand.hero = player.group('PNAME') # Only really need to do this once
|
||||
# newcards = player.group('NEWCARDS')
|
||||
# oldcards = player.group('OLDCARDS')
|
||||
# if newcards == None:
|
||||
# newcards = set()
|
||||
# else:
|
||||
# newcards = set(newcards.split(' '))
|
||||
# if oldcards == None:
|
||||
# oldcards = set()
|
||||
# else:
|
||||
# oldcards = set(oldcards.split(' '))
|
||||
# hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street)
|
||||
|
||||
|
||||
# def readStudPlayerCards(self, hand, street):
|
||||
# # See comments of reference implementation in FullTiltToFpdb.py
|
||||
# logging.debug("readStudPlayerCards")
|
||||
# m = self.re_HeroCards.finditer(hand.streets[street])
|
||||
# for player in m:
|
||||
# #~ logging.debug(player.groupdict())
|
||||
# (pname, oldcards, newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS'))
|
||||
# if oldcards:
|
||||
# oldcards = [c.strip() for c in oldcards.split(' ')]
|
||||
# if newcards:
|
||||
# newcards = [c.strip() for c in newcards.split(' ')]
|
||||
# if street=='ANTES':
|
||||
# return
|
||||
# elif street=='THIRD':
|
||||
# # we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS'
|
||||
# # hero: [xx][o]
|
||||
# # others: [o]
|
||||
# hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = oldcards, open = newcards)
|
||||
# elif street in ('FOURTH', 'FIFTH', 'SIXTH'):
|
||||
# # 4th:
|
||||
# # hero: [xxo] [o]
|
||||
# # others: [o] [o]
|
||||
# # 5th:
|
||||
# # hero: [xxoo] [o]
|
||||
# # others: [oo] [o]
|
||||
# # 6th:
|
||||
# # hero: [xxooo] [o]
|
||||
# # others: [ooo] [o]
|
||||
# hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards)
|
||||
# # we may additionally want to check the earlier streets tally with what we have but lets trust it for now.
|
||||
# elif street=='SEVENTH' and newcards:
|
||||
# # hero: [xxoooo] [x]
|
||||
# # others: not reported.
|
||||
# hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards)
|
||||
|
||||
def readAction(self, hand, street):
|
||||
m = self.re_Action.finditer(hand.streets[street])
|
||||
for action in m:
|
||||
acts = action.groupdict()
|
||||
if action.group('ATYPE') == ' raises':
|
||||
hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') )
|
||||
elif action.group('ATYPE') == ' calls':
|
||||
|
@ -294,7 +390,7 @@ follow : whether to tail -f the input"""
|
|||
elif action.group('ATYPE') == ' checks':
|
||||
hand.addCheck( street, action.group('PNAME'))
|
||||
elif action.group('ATYPE') == ' discards':
|
||||
hand.addDiscard(street, action.group('PNAME'), action.group('NODISCARDED'), action.group('DISCARDED'))
|
||||
hand.addDiscard(street, action.group('PNAME'), action.group('BET'), action.group('DISCARDED'))
|
||||
elif action.group('ATYPE') == ' stands pat':
|
||||
hand.addStandsPat( street, action.group('PNAME'))
|
||||
else:
|
||||
|
@ -302,9 +398,9 @@ follow : whether to tail -f the input"""
|
|||
|
||||
|
||||
def readShowdownActions(self, hand):
|
||||
# TODO: pick up mucks also
|
||||
for shows in self.re_ShowdownAction.finditer(hand.handText):
|
||||
cards = shows.group('CARDS')
|
||||
cards = set(cards.split(' '))
|
||||
cards = shows.group('CARDS').split(' ')
|
||||
hand.addShownCards(cards, shows.group('PNAME'))
|
||||
|
||||
def readCollectPot(self,hand):
|
||||
|
@ -315,8 +411,13 @@ follow : whether to tail -f the input"""
|
|||
for m in self.re_ShownCards.finditer(hand.handText):
|
||||
if m.group('CARDS') is not None:
|
||||
cards = m.group('CARDS')
|
||||
cards = set(cards.split(' '))
|
||||
hand.addShownCards(cards=cards, player=m.group('PNAME'))
|
||||
cards = cards.split(' ') # needs to be a list, not a set--stud needs the order
|
||||
|
||||
(shown, mucked) = (False, False)
|
||||
if m.group('SHOWED') == "showed": shown = True
|
||||
elif m.group('SHOWED') == "mucked": mucked = True
|
||||
|
||||
hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked)
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = OptionParser()
|
||||
|
|
|
@ -542,18 +542,13 @@ class Sql:
|
|||
|
||||
self.query['get_common_cards'] = """
|
||||
select
|
||||
card1Value AS card1value,
|
||||
card1Suit AS card1suit,
|
||||
card2Value AS card2value,
|
||||
card2Suit AS card2suit,
|
||||
card3Value AS card3value,
|
||||
card3Suit AS card3suit,
|
||||
card4Value AS card4value,
|
||||
card4Suit AS card4suit,
|
||||
card5Value AS card5value,
|
||||
card5Suit AS card5suit
|
||||
from BoardCards
|
||||
where handId = %s
|
||||
boardcard1,
|
||||
boardcard2,
|
||||
boardcard3,
|
||||
boardcard4,
|
||||
boardcard5
|
||||
from Hands
|
||||
where Id = %s
|
||||
"""
|
||||
|
||||
self.query['get_action_from_hand'] = """
|
||||
|
|
|
@ -231,7 +231,7 @@ def discover_nt_by_name(c, tablename):
|
|||
titles = {}
|
||||
win32gui.EnumWindows(win_enum_handler, titles)
|
||||
for hwnd in titles:
|
||||
print "Tbales.py: tablename =", tablename, "title =", titles[hwnd]
|
||||
#print "Tables.py: tablename =", tablename, "title =", titles[hwnd]
|
||||
try:
|
||||
# this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html
|
||||
if not tablename in titles[hwnd]: continue
|
||||
|
@ -314,6 +314,10 @@ def get_site_from_exe(c, exe):
|
|||
return params['site_name']
|
||||
return None
|
||||
|
||||
def everleaf_decode_table(tw):
|
||||
# 2 - Tournament ID: 573256 - NL Hold'em - 150/300 blinds - Good luck <username>! - [Connection is ...]
|
||||
pass
|
||||
|
||||
def pokerstars_decode_table(tw):
|
||||
# Extract poker information from the window title. This is not needed for
|
||||
# fpdb, since all that information is available in the db via new_hand_number.
|
||||
|
@ -365,7 +369,7 @@ def clean_title(name):
|
|||
for pattern in [' \(6 max\)', ' \(heads up\)', ' \(deep\)',
|
||||
' \(deep hu\)', ' \(deep 6\)', ' \(2\)',
|
||||
' \(edu\)', ' \(edu, 6 max\)', ' \(6\)',
|
||||
' \(speed\)',
|
||||
' \(speed\)', 'special', 'newVPP',
|
||||
' no all-in', ' fast', ',', ' 50BB min', '50bb min', '\s+$']:
|
||||
name = re.sub(pattern, '', name)
|
||||
name = name.rstrip()
|
||||
|
|
|
@ -92,6 +92,8 @@ if __name__=="__main__":
|
|||
print "game =", table.get_game()
|
||||
|
||||
fake = fake_hud(table)
|
||||
print "fake =", fake
|
||||
gobject.timeout_add(100, check_on_table, table, fake)
|
||||
print "calling main"
|
||||
gtk.main()
|
||||
|
||||
|
|
|
@ -65,8 +65,11 @@ class Table(Table_Window):
|
|||
print "x = %s y = %s width = %s height = %s" % (x, y, width, height)
|
||||
self.x = int(x) + b_width
|
||||
self.y = int(y) + tb_height
|
||||
self.height = int(height) - b_width - tb_height
|
||||
self.width = int(width) - 2*b_width
|
||||
self.width = width - x
|
||||
self.height = height - y
|
||||
print "x = %s y = %s width = %s height = %s" % (self.x, self.y, self.width, self.height)
|
||||
#self.height = int(height) - b_width - tb_height
|
||||
#self.width = int(width) - 2*b_width
|
||||
|
||||
self.exe = self.get_nt_exe(hwnd)
|
||||
self.title = titles[hwnd]
|
||||
|
@ -76,12 +79,13 @@ class Table(Table_Window):
|
|||
self.gdkhandle = gtk.gdk.window_foreign_new(long(self.window))
|
||||
|
||||
def get_geometry(self):
|
||||
|
||||
if not win32gui.IsWindow(self.window): # window closed
|
||||
if not win32gui.IsWindow(self.number): # window closed
|
||||
return None
|
||||
|
||||
try:
|
||||
(x, y, width, height) = win32gui.GetWindowRect(hwnd)
|
||||
(x, y, width, height) = win32gui.GetWindowRect(self.number)
|
||||
width = width - x
|
||||
height = height - y
|
||||
return {'x' : int(x) + b_width,
|
||||
'y' : int(y) + tb_height,
|
||||
'width' : int(height) - b_width - tb_height,
|
||||
|
@ -116,27 +120,32 @@ class Table(Table_Window):
|
|||
def topify(self, hud):
|
||||
"""Set the specified gtk window to stayontop in MS Windows."""
|
||||
|
||||
def windowEnumerationHandler(hwnd, resultList):
|
||||
'''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
||||
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
||||
|
||||
unique_name = 'unique name for finding this window'
|
||||
real_name = hud.main_window.get_title()
|
||||
hud.main_window.set_title(unique_name)
|
||||
tl_windows = []
|
||||
win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
|
||||
|
||||
for w in tl_windows:
|
||||
if w[1] == unique_name:
|
||||
hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0])
|
||||
# def windowEnumerationHandler(hwnd, resultList):
|
||||
# '''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
||||
# resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
||||
#
|
||||
# unique_name = 'unique name for finding this window'
|
||||
# real_name = hud.main_window.get_title()
|
||||
# hud.main_window.set_title(unique_name)
|
||||
# tl_windows = []
|
||||
# win32gui.EnumWindows(windowEnumerationHandler, tl_windows)
|
||||
#
|
||||
# for w in tl_windows:
|
||||
# if w[1] == unique_name:
|
||||
# hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0])
|
||||
hud.main_window.gdkhandle = hud.main_window.window
|
||||
hud.main_window.gdkhandle.set_transient_for(self.gdkhandle)
|
||||
rect = self.gdkhandle.get_frame_extents()
|
||||
(innerx, innery) = self.gdkhandle.get_origin()
|
||||
b_width = rect.x - innerx
|
||||
tb_height = rect.y - innery
|
||||
#
|
||||
# style = win32gui.GetWindowLong(self.number, win32con.GWL_EXSTYLE)
|
||||
# style |= win32con.WS_CLIPCHILDREN
|
||||
# win32gui.SetWindowLong(self.number, win32con.GWL_EXSTYLE, style)
|
||||
break
|
||||
# break
|
||||
|
||||
hud.main_window.set_title(real_name)
|
||||
# hud.main_window.set_title(real_name)
|
||||
|
||||
def win_enum_handler(hwnd, titles):
|
||||
titles[hwnd] = win32gui.GetWindowText(hwnd)
|
||||
|
|
101
pyfpdb/fpdb.py
101
pyfpdb/fpdb.py
|
@ -33,7 +33,7 @@ import pygtk
|
|||
pygtk.require('2.0')
|
||||
import gtk
|
||||
|
||||
import fpdb_db
|
||||
|
||||
import fpdb_simple
|
||||
import GuiBulkImport
|
||||
import GuiPlayerStats
|
||||
|
@ -42,6 +42,8 @@ import GuiTableViewer
|
|||
import GuiAutoImport
|
||||
import GuiGraphViewer
|
||||
import GuiSessionViewer
|
||||
import SQL
|
||||
import Database
|
||||
import FpdbSQLQueries
|
||||
import Configuration
|
||||
|
||||
|
@ -179,20 +181,21 @@ class fpdb:
|
|||
def dia_load_profile(self, widget, data=None):
|
||||
"""Dialogue to select a file to load a profile from"""
|
||||
if self.obtain_global_lock() == 0: # returns 0 if successful
|
||||
try:
|
||||
chooser = gtk.FileChooserDialog(title="Please select a profile file to load",
|
||||
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
||||
chooser.set_filename(self.profile)
|
||||
#try:
|
||||
# chooser = gtk.FileChooserDialog(title="Please select a profile file to load",
|
||||
# action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
# buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
||||
# chooser.set_filename(self.profile)
|
||||
|
||||
response = chooser.run()
|
||||
chooser.destroy()
|
||||
if response == gtk.RESPONSE_OK:
|
||||
self.load_profile(chooser.get_filename())
|
||||
elif response == gtk.RESPONSE_CANCEL:
|
||||
print 'User cancelled loading profile'
|
||||
except:
|
||||
pass
|
||||
# response = chooser.run()
|
||||
# chooser.destroy()
|
||||
# if response == gtk.RESPONSE_OK:
|
||||
# self.load_profile(chooser.get_filename())
|
||||
# elif response == gtk.RESPONSE_CANCEL:
|
||||
# print 'User cancelled loading profile'
|
||||
#except:
|
||||
# pass
|
||||
self.load_profile()
|
||||
self.release_global_lock()
|
||||
#end def dia_load_profile
|
||||
|
||||
|
@ -204,22 +207,23 @@ class fpdb:
|
|||
try:
|
||||
dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING,
|
||||
buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables")
|
||||
diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted."
|
||||
diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database " \
|
||||
+self.db.fdb.database+" on "+self.db.fdb.host+" they will be deleted."
|
||||
dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted
|
||||
|
||||
response = dia_confirm.run()
|
||||
dia_confirm.destroy()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
if self.db.backend == self.fdb_lock.MYSQL_INNODB:
|
||||
if self.db.fdb.backend == self.fdb_lock.fdb.MYSQL_INNODB:
|
||||
# mysql requires locks on all tables or none - easier to release this lock
|
||||
# than lock all the other tables
|
||||
# ToDo: lock all other tables so that lock doesn't have to be released
|
||||
self.release_global_lock()
|
||||
lock_released = True
|
||||
self.db.recreate_tables()
|
||||
self.db.fdb.recreate_tables()
|
||||
else:
|
||||
# for other dbs use same connection as holds global lock
|
||||
self.fdb_lock.recreate_tables()
|
||||
self.fdb_lock.fdb.recreate_tables()
|
||||
elif response == gtk.RESPONSE_NO:
|
||||
print 'User cancelled recreating tables'
|
||||
except:
|
||||
|
@ -347,6 +351,7 @@ class fpdb:
|
|||
|
||||
def load_profile(self):
|
||||
"""Loads profile from the provided path name."""
|
||||
self.config = Configuration.Config(file=options.config, dbname=options.dbname)
|
||||
self.settings = {}
|
||||
if (os.sep=="/"):
|
||||
self.settings['os']="linuxmac"
|
||||
|
@ -359,17 +364,13 @@ class fpdb:
|
|||
self.settings.update(self.config.get_import_parameters())
|
||||
self.settings.update(self.config.get_default_paths())
|
||||
|
||||
if self.db!=None:
|
||||
if self.db != None and self.db.fdb != None:
|
||||
self.db.disconnect()
|
||||
|
||||
self.db = fpdb_db.fpdb_db()
|
||||
#print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName']
|
||||
self.db.connect(self.settings['db-backend'],
|
||||
self.settings['db-host'],
|
||||
self.settings['db-databaseName'],
|
||||
self.settings['db-user'],
|
||||
self.settings['db-password'])
|
||||
if self.db.wrongDbVersion:
|
||||
self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server'])
|
||||
self.db = Database.Database(self.config, sql = self.sql)
|
||||
|
||||
if self.db.fdb.wrongDbVersion:
|
||||
diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
|
||||
|
||||
label = gtk.Label("An invalid DB version or missing tables have been detected.")
|
||||
|
@ -387,9 +388,16 @@ class fpdb:
|
|||
response = diaDbVersionWarning.run()
|
||||
diaDbVersionWarning.destroy()
|
||||
|
||||
if self.status_bar == None:
|
||||
self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host))
|
||||
self.main_vbox.pack_end(self.status_bar, False, True, 0)
|
||||
self.status_bar.show()
|
||||
else:
|
||||
self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host))
|
||||
|
||||
# Database connected to successfully, load queries to pass on to other classes
|
||||
self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name())
|
||||
self.db.db.rollback()
|
||||
self.db.connection.rollback()
|
||||
#end def load_profile
|
||||
|
||||
def not_implemented(self, widget, data=None):
|
||||
|
@ -398,13 +406,9 @@ class fpdb:
|
|||
|
||||
def obtain_global_lock(self):
|
||||
print "\nTaking global lock ..."
|
||||
self.fdb_lock = fpdb_db.fpdb_db()
|
||||
self.fdb_lock.connect(self.settings['db-backend'],
|
||||
self.settings['db-host'],
|
||||
self.settings['db-databaseName'],
|
||||
self.settings['db-user'],
|
||||
self.settings['db-password'])
|
||||
return self.fdb_lock.get_global_lock()
|
||||
self.fdb_lock = Database.Database(self.config, sql = self.sql)
|
||||
self.fdb_lock.do_connect(self.config)
|
||||
return self.fdb_lock.fdb.get_global_lock()
|
||||
#end def obtain_global_lock
|
||||
|
||||
def quit(self, widget, data=None):
|
||||
|
@ -415,9 +419,9 @@ class fpdb:
|
|||
#end def quit_cliecked
|
||||
|
||||
def release_global_lock(self):
|
||||
self.fdb_lock.db.rollback()
|
||||
self.fdb_lock.disconnect()
|
||||
print "Global lock released."
|
||||
self.fdb_lock.fdb.db.rollback()
|
||||
self.fdb_lock.fdb.disconnect()
|
||||
print "Global lock released.\n"
|
||||
#end def release_global_lock
|
||||
|
||||
def tab_abbreviations(self, widget, data=None):
|
||||
|
@ -466,7 +470,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
|||
def tab_table_viewer(self, widget, data=None):
|
||||
"""opens a table viewer tab"""
|
||||
#print "start of tab_table_viewer"
|
||||
new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings)
|
||||
new_tv_thread=GuiTableViewer.GuiTableViewer(self.db.fdb, self.settings)
|
||||
self.threads.append(new_tv_thread)
|
||||
tv_tab=new_tv_thread.get_vbox()
|
||||
self.add_and_display_tab(tv_tab, "Table Viewer")
|
||||
|
@ -475,22 +479,16 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
|||
def tabGraphViewer(self, widget, data=None):
|
||||
"""opens a graph viewer tab"""
|
||||
#print "start of tabGraphViewer"
|
||||
new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config)
|
||||
new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.querydict, self.config)
|
||||
self.threads.append(new_gv_thread)
|
||||
gv_tab=new_gv_thread.get_vbox()
|
||||
self.add_and_display_tab(gv_tab, "Graphs")
|
||||
#end def tabGraphViewer
|
||||
|
||||
def __init__(self):
|
||||
LOG_FILENAME = './logging.out'
|
||||
LOG_FORMAT = "%(asctime)-15s %(levelname)-8s %(message)s"
|
||||
logging.basicConfig(filename=LOG_FILENAME,level=10,format=LOG_FORMAT)
|
||||
logging.info("Fpdb started")
|
||||
|
||||
self.threads=[]
|
||||
self.db=None
|
||||
self.config = Configuration.Config(file=options.config, dbname=options.dbname)
|
||||
self.load_profile()
|
||||
self.threads = []
|
||||
self.db = None
|
||||
self.status_bar = None
|
||||
|
||||
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
self.window.connect("delete_event", self.delete_event)
|
||||
|
@ -525,11 +523,8 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
|||
|
||||
self.tab_main_help(None, None)
|
||||
|
||||
self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host))
|
||||
self.main_vbox.pack_end(self.status_bar, False, True, 0)
|
||||
self.status_bar.show()
|
||||
|
||||
self.window.show()
|
||||
self.load_profile()
|
||||
sys.stderr.write("fpdb starting ...")
|
||||
#end def __init__
|
||||
|
||||
|
|
|
@ -255,7 +255,6 @@ class fpdb_db:
|
|||
self.cursor.execute(self.sql.query['createPlayersTable'])
|
||||
self.cursor.execute(self.sql.query['createAutoratesTable'])
|
||||
self.cursor.execute(self.sql.query['createHandsTable'])
|
||||
self.cursor.execute(self.sql.query['createBoardCardsTable'])
|
||||
self.cursor.execute(self.sql.query['createTourneyTypesTable'])
|
||||
self.cursor.execute(self.sql.query['createTourneysTable'])
|
||||
self.cursor.execute(self.sql.query['createTourneysPlayersTable'])
|
||||
|
@ -587,17 +586,18 @@ class fpdb_db:
|
|||
print "analyze took", atime, "seconds"
|
||||
#end def analyzeDB
|
||||
|
||||
# Currently uses an exclusive lock on the Hands table as a global lock
|
||||
# Currently uses an exclusive lock on the Players table as a global lock
|
||||
# ( Changed because Hands is used in Database.init() )
|
||||
# Return values are Unix style, 0 for success, positive integers for errors
|
||||
# 1 = generic error
|
||||
# 2 = hands table does not exist (error message is suppressed)
|
||||
# 2 = players table does not exist (error message is suppressed)
|
||||
def get_global_lock(self):
|
||||
if self.backend == self.MYSQL_INNODB:
|
||||
try:
|
||||
self.cursor.execute( "lock tables Hands write" )
|
||||
self.cursor.execute( "lock tables Players write" )
|
||||
except:
|
||||
# Table 'fpdb.hands' doesn't exist
|
||||
if str(sys.exc_value).find(".Hands' doesn't exist") >= 0:
|
||||
# Table 'fpdb.players' doesn't exist
|
||||
if str(sys.exc_value).find(".Players' doesn't exist") >= 0:
|
||||
return(2)
|
||||
print "Error! failed to obtain global lock. Close all programs accessing " \
|
||||
+ "database (including fpdb) and try again (%s)." \
|
||||
|
@ -605,11 +605,11 @@ class fpdb_db:
|
|||
return(1)
|
||||
elif self.backend == self.PGSQL:
|
||||
try:
|
||||
self.cursor.execute( "lock table Hands in exclusive mode nowait" )
|
||||
self.cursor.execute( "lock table Players in exclusive mode nowait" )
|
||||
#print "... after lock table, status =", self.cursor.statusmessage
|
||||
except:
|
||||
# relation "hands" does not exist
|
||||
if str(sys.exc_value).find('relation "hands" does not exist') >= 0:
|
||||
# relation "players" does not exist
|
||||
if str(sys.exc_value).find('relation "players" does not exist') >= 0:
|
||||
return(2)
|
||||
print "Error! failed to obtain global lock. Close all programs accessing " \
|
||||
+ "database (including fpdb) and try again (%s)." \
|
||||
|
|
|
@ -32,6 +32,7 @@ import re
|
|||
|
||||
import fpdb_simple
|
||||
import fpdb_db
|
||||
import Database
|
||||
import fpdb_parse_logic
|
||||
import Configuration
|
||||
|
||||
|
@ -58,7 +59,8 @@ class Importer:
|
|||
self.settings = settings
|
||||
self.caller = caller
|
||||
self.config = config
|
||||
self.fdb = None
|
||||
self.database = None # database will be the main db interface eventually
|
||||
self.fdb = None # fdb may disappear or just hold the simple db connection
|
||||
self.cursor = None
|
||||
self.filelist = {}
|
||||
self.dirlist = {}
|
||||
|
@ -76,6 +78,7 @@ class Importer:
|
|||
self.settings.setdefault("minPrint", 30)
|
||||
self.settings.setdefault("handCount", 0)
|
||||
|
||||
self.database = Database.Database(self.config) # includes .connection and .sql variables
|
||||
self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
|
||||
self.fdb.do_connect(self.config)
|
||||
self.fdb.db.rollback()
|
||||
|
@ -393,8 +396,9 @@ class Importer:
|
|||
self.hand=hand
|
||||
|
||||
try:
|
||||
handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb
|
||||
, self.siteIds[site], category, hand, self.config)
|
||||
handsId = fpdb_parse_logic.mainParser( self.settings, self.fdb
|
||||
, self.siteIds[site], category, hand
|
||||
, self.config, self.database )
|
||||
self.fdb.db.commit()
|
||||
|
||||
stored += 1
|
||||
|
|
|
@ -21,10 +21,13 @@ import fpdb_simple
|
|||
import Database
|
||||
|
||||
#parses a holdem hand
|
||||
def mainParser(settings, fdb, siteID, category, hand, config):
|
||||
def mainParser(settings, fdb, siteID, category, hand, config, db = None):
|
||||
backend = settings['db-backend']
|
||||
#This is redundant - hopefully fdb will be a Database object in an interation soon
|
||||
db = Database.Database(config, 'fpdb', '')
|
||||
if db == None:
|
||||
#This is redundant - hopefully fdb will be a Database object in an iteration soon
|
||||
db = Database.Database(c = config, sql = None)
|
||||
else:
|
||||
db = db
|
||||
category = fpdb_simple.recogniseCategory(hand[0])
|
||||
|
||||
base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud"
|
||||
|
|
|
@ -1136,16 +1136,6 @@ def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, ac
|
|||
cursor.executemany("INSERT INTO HandsActions (handsPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", inserts)
|
||||
#end def storeActions
|
||||
|
||||
def store_board_cards(cursor, hands_id, board_values, board_suits):
|
||||
#stores into table board_cards
|
||||
cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit,
|
||||
card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit,
|
||||
card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
|
||||
(hands_id, board_values[0], board_suits[0], board_values[1], board_suits[1],
|
||||
board_values[2], board_suits[2], board_values[3], board_suits[3],
|
||||
board_values[4], board_suits[4]))
|
||||
#end def store_board_cards
|
||||
|
||||
def storeHands(backend, conn, cursor, site_hand_no, gametype_id
|
||||
,hand_start_time, names, tableName, maxSeats, hudCache,
|
||||
board_values, board_suits):
|
||||
|
|
Loading…
Reference in New Issue
Block a user