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

This commit is contained in:
Eratosthenes 2010-11-30 12:14:58 -05:00
commit 0d79fe8f09
17 changed files with 840 additions and 138 deletions

View File

@ -133,8 +133,9 @@ or None if we fail to get the info """
self.info = {} self.info = {}
mg = m.groupdict() mg = m.groupdict()
print mg
limits = { 'No Limit':'nl', 'Limit':'fl' } limits = { 'No Limit':'nl', 'No Limit ':'nl', 'Limit':'fl' }
games = { # base, category games = { # base, category
'Holdem' : ('hold','holdem'), 'Holdem' : ('hold','holdem'),
'Holdem Tournament' : ('hold','holdem') } 'Holdem Tournament' : ('hold','holdem') }

View File

@ -73,7 +73,7 @@ except ImportError:
use_numpy = False use_numpy = False
DB_VERSION = 144 DB_VERSION = 145
# Variance created as sqlite has a bunch of undefined aggregate functions. # Variance created as sqlite has a bunch of undefined aggregate functions.
@ -255,6 +255,11 @@ class Database:
self.database = db_params['db-databaseName'] self.database = db_params['db-databaseName']
self.host = db_params['db-host'] self.host = db_params['db-host']
self.db_path = '' self.db_path = ''
gen = c.get_general_params()
self.day_start = 0
if 'day_start' in gen:
self.day_start = float(gen['day_start'])
# where possible avoid creating new SQL instance by using the global one passed in # where possible avoid creating new SQL instance by using the global one passed in
if sql is None: if sql is None:
@ -291,8 +296,8 @@ class Database:
# vars for hand ids or dates fetched according to above config: # vars for hand ids or dates fetched according to above config:
self.hand_1day_ago = 0 # max hand id more than 24 hrs earlier than now self.hand_1day_ago = 0 # max hand id more than 24 hrs earlier than now
self.date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) self.date_ndays_ago = 'd00000000' # date N days ago ('d' + YYMMDD)
self.h_date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) for hero self.h_date_ndays_ago = 'd00000000' # date N days ago ('d' + YYMMDD) for hero
self.date_nhands_ago = {} # dates N hands ago per player - not used yet self.date_nhands_ago = {} # dates N hands ago per player - not used yet
self.saveActions = False if self.import_options['saveActions'] == False else True self.saveActions = False if self.import_options['saveActions'] == False else True
@ -690,20 +695,24 @@ class Database:
if row and row[0]: if row and row[0]:
self.hand_1day_ago = int(row[0]) self.hand_1day_ago = int(row[0])
d = timedelta(days=hud_days) tz = datetime.utcnow() - datetime.today()
now = datetime.utcnow() - d tz_offset = tz.seconds/3600
self.date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day) tz_day_start_offset = self.day_start + tz_offset
d = timedelta(days=h_hud_days) d = timedelta(days=hud_days, hours=tz_day_start_offset)
now = datetime.utcnow() - d now = datetime.utcnow() - d
self.h_date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day) self.date_ndays_ago = "d%02d%02d%02d%02d" % (now.year - 2000, now.month, now.day, tz_day_start_offset)
d = timedelta(days=h_hud_days, hours=tz_day_start_offset)
now = datetime.utcnow() - d
self.h_date_ndays_ago = "d%02d%02d%02d%02d" % (now.year - 2000, now.month, now.day, tz_day_start_offset)
def init_player_hud_stat_vars(self, playerid): def init_player_hud_stat_vars(self, playerid):
# not sure if this is workable, to be continued ... # not sure if this is workable, to be continued ...
try: try:
# self.date_nhands_ago is used for fetching stats for last n hands (hud_style = 'H') # self.date_nhands_ago is used for fetching stats for last n hands (hud_style = 'H')
# This option not used yet - needs to be called for each player :-( # This option not used yet - needs to be called for each player :-(
self.date_nhands_ago[str(playerid)] = 'd000000' self.date_nhands_ago[str(playerid)] = 'd00000000'
# should use aggregated version of query if appropriate # should use aggregated version of query if appropriate
c.execute(self.sql.query['get_date_nhands_ago'], (self.hud_hands, playerid)) c.execute(self.sql.query['get_date_nhands_ago'], (self.hud_hands, playerid))
@ -771,11 +780,11 @@ class Database:
if hud_style == 'T': if hud_style == 'T':
stylekey = self.date_ndays_ago stylekey = self.date_ndays_ago
elif hud_style == 'A': elif hud_style == 'A':
stylekey = '0000000' # all stylekey values should be higher than this stylekey = '000000000' # all stylekey values should be higher than this
elif hud_style == 'S': elif hud_style == 'S':
stylekey = 'zzzzzzz' # all stylekey values should be lower than this stylekey = 'zzzzzzzzz' # all stylekey values should be lower than this
else: else:
stylekey = '0000000' stylekey = '000000000'
log.info('hud_style: %s' % hud_style) log.info('hud_style: %s' % hud_style)
#elif hud_style == 'H': #elif hud_style == 'H':
@ -784,11 +793,11 @@ class Database:
if h_hud_style == 'T': if h_hud_style == 'T':
h_stylekey = self.h_date_ndays_ago h_stylekey = self.h_date_ndays_ago
elif h_hud_style == 'A': elif h_hud_style == 'A':
h_stylekey = '0000000' # all stylekey values should be higher than this h_stylekey = '000000000' # all stylekey values should be higher than this
elif h_hud_style == 'S': elif h_hud_style == 'S':
h_stylekey = 'zzzzzzz' # all stylekey values should be lower than this h_stylekey = 'zzzzzzzzz' # all stylekey values should be lower than this
else: else:
h_stylekey = '000000' h_stylekey = '00000000'
log.info('h_hud_style: %s' % h_hud_style) log.info('h_hud_style: %s' % h_hud_style)
#elif h_hud_style == 'H': #elif h_hud_style == 'H':
@ -1824,11 +1833,11 @@ class Database:
"""Update cached statistics. If update fails because no record exists, do an insert.""" """Update cached statistics. If update fails because no record exists, do an insert."""
if self.use_date_in_hudcache: if self.use_date_in_hudcache:
styleKey = datetime.strftime(starttime, 'd%y%m%d') styleKey = datetime.strftime(starttime, 'd%y%m%d%H')
#styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) #styleKey = "d%02d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day, hand_start_time.hour)
else: else:
# hard-code styleKey as 'A000000' (all-time cache, no key) for now # hard-code styleKey as 'A00000000' (all-time cache, no key) for now
styleKey = 'A000000' styleKey = 'A00000000'
update_hudcache = self.sql.query['update_hudcache'] update_hudcache = self.sql.query['update_hudcache']
update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder']) update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder'])

View File

@ -50,11 +50,14 @@ import Database
import Filters import Filters
import Charset import Charset
DEBUG = False
class GuiSessionViewer (threading.Thread): class GuiSessionViewer (threading.Thread):
def __init__(self, config, querylist, mainwin, debug=True): def __init__(self, config, querylist, mainwin, debug=True):
self.debug = debug self.debug = debug
self.conf = config self.conf = config
self.sql = querylist self.sql = querylist
self.window = mainwin
self.liststore = None self.liststore = None
@ -153,6 +156,28 @@ class GuiSessionViewer (threading.Thread):
# make sure Hand column is not displayed # make sure Hand column is not displayed
#[x for x in self.columns if x[0] == 'hand'][0][1] = False #[x for x in self.columns if x[0] == 'hand'][0][1] = False
if DEBUG == False:
warning_string = """
Session Viewer is proof of concept code only, and contains many bugs.
Feel free to use the viewer, but there is no guarantee that the data is accurate.
If you are interested in developing the code further please contact us via the usual channels.
Thankyou
"""
self.warning_box(warning_string)
def warning_box(self, str, diatitle=_("FPDB WARNING")):
diaWarning = gtk.Dialog(title=diatitle, parent=self.window, flags=gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
label = gtk.Label(str)
diaWarning.vbox.add(label)
label.show()
response = diaWarning.run()
diaWarning.destroy()
return response
def get_vbox(self): def get_vbox(self):
"""returns the vbox of this thread""" """returns the vbox of this thread"""

218
pyfpdb/GuiStove.py Normal file
View File

@ -0,0 +1,218 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Copyright 2008-2010 Steffen Schaumburg
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, version 3 of the License.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU Affero General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>.
#In the "official" distribution you can find the license in agpl-3.0.txt.
import L10n
_ = L10n.get_translation()
import pygtk
pygtk.require('2.0')
import gtk
import os
import sys
import Charset
DEBUG = False
class GuiStove():
def __init__(self, config, parent, debug=True):
"""Constructor for GraphViewer"""
self.conf = config
self.parent = parent
self.mainHBox = gtk.HBox(False, 0)
# hierarchy: self.mainHBox / self.notebook
self.notebook = gtk.Notebook()
self.notebook.set_tab_pos(gtk.POS_TOP)
self.notebook.set_show_tabs(True)
self.notebook.set_show_border(True)
self.createFlopTab()
self.createStudTab()
self.createDrawTab()
self.mainHBox.add(self.notebook)
self.mainHBox.show_all()
if DEBUG == False:
warning_string = """
Stove is a GUI mockup of a EV calculation page, and completely non functional.
Unless you are interested in developing this feature, please ignore this page.
If you are interested in developing the code further see GuiStove.py and Stove.py
Thankyou
"""
self.warning_box(warning_string)
def warning_box(self, str, diatitle=_("FPDB WARNING")):
diaWarning = gtk.Dialog(title=diatitle, parent=self.parent, flags=gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
label = gtk.Label(str)
diaWarning.vbox.add(label)
label.show()
response = diaWarning.run()
diaWarning.destroy()
return response
def get_active_text(combobox):
model = combobox.get_model()
active = combobox.get_active()
if active < 0:
return None
return model[active][0]
def create_combo_box(self, strings):
combobox = gtk.combo_box_new_text()
for label in strings:
combobox.append_text(label)
combobox.set_active(0)
return combobox
def createDrawTab(self):
tab_title = "Draw"
label = gtk.Label(tab_title)
ddbox = gtk.VBox(False, 0)
self.notebook.append_page(ddbox, label)
def createStudTab(self):
tab_title = "Stud"
label = gtk.Label(tab_title)
ddbox = gtk.VBox(False, 0)
self.notebook.append_page(ddbox, label)
def createFlopTab(self):
# hierarchy: hbox / ddbox / ddhbox / Label + flop_games_cb | label + players_cb
# / gamehbox / in_frame / table /
# / out_frame
tab_title = "Flop"
label = gtk.Label(tab_title)
ddbox = gtk.VBox(False, 0)
self.notebook.append_page(ddbox, label)
ddhbox = gtk.HBox(False, 0)
gamehbox = gtk.HBox(False, 0)
ddbox.add(ddhbox)
ddbox.add(gamehbox)
# Combo boxes in the top row
games = [ "Holdem", "Omaha", "Omaha 8", ]
players = [ "2", "3", "4", "5", "6", "7", "8", "9", "10" ]
flop_games_cb = self.create_combo_box(games)
players_cb = self.create_combo_box(players)
label = gtk.Label("Gametype:")
ddhbox.add(label)
ddhbox.add(flop_games_cb)
label = gtk.Label("Players:")
ddhbox.add(label)
ddhbox.add(players_cb)
# Frames for Stove input and output
in_frame = gtk.Frame("Input:")
out_frame = gtk.Frame("Output:")
gamehbox.add(in_frame)
gamehbox.add(out_frame)
outstring = """
No board given. Using Monte-Carlo simulation...
Enumerated 2053443 possible plays.
Your hand: (Ad Ac)
Against the range: {
AhAd, AhAs, AdAs, KhKd, KhKs,
KhKc, KdKs, KdKc, KsKc, QhQd,
QhQs, QhQc, QdQs, QdQc, QsQc,
JhJd, JhJs, JhJc, JdJs, JdJc,
JsJc
}
Win Lose Tie
69.91% 15.83% 14.26%
"""
label = gtk.Label(outstring)
out_frame.add(label)
# Input Frame
table = gtk.Table(4, 4, True)
label = gtk.Label("Board:")
board = gtk.Entry()
#board.connect("changed", self._some_function, arg)
btn1 = gtk.Button()
btn1.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
#btn.connect('clicked', self._some_function, arg)
table.attach(label, 0, 1, 0, 1, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
table.attach(board, 1, 2, 0, 1, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
table.attach(btn1, 2, 3, 0, 1, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
label = gtk.Label("Player1:")
board = gtk.Entry()
#board.connect("changed", self._some_function, arg)
btn2 = gtk.Button()
btn2.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
#btn.connect('clicked', self._some_function, arg)
btn3 = gtk.Button()
btn3.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
#btn.connect('clicked', self._some_function, arg)
table.attach(label, 0, 1, 1, 2, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
table.attach(board, 1, 2, 1, 2, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
table.attach(btn2, 2, 3, 1, 2, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
table.attach(btn3, 3, 4, 1, 2, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
label = gtk.Label("Player2:")
board = gtk.Entry()
#board.connect("changed", self._some_function, arg)
btn4 = gtk.Button()
btn4.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
#btn.connect('clicked', self._some_function, arg)
btn5 = gtk.Button()
btn5.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON))
#btn.connect('clicked', self._some_function, arg)
table.attach(label, 0, 1, 2, 3, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
table.attach(board, 1, 2, 2, 3, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
table.attach(btn4, 2, 3, 2, 3, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
table.attach(btn5, 3, 4, 2, 3, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
#table.attach(label, i, i+1, j, j+1,)
in_frame.add(table)
def get_vbox(self):
"""returns the vbox of this thread"""
return self.mainHBox
#end def get_vbox

View File

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#Copyright 2010 Chaz Littlejohn #Copyright 2010 Chaz Littlejohn
@ -28,18 +28,21 @@ import Configuration
import Database import Database
__ARCHIVE_PRE_HEADER_REGEX='^Hand #(\d+)\s*$|\*{20}\s#\s\d+\s\*+\s+' __ARCHIVE_PRE_HEADER_REGEX='^Hand #(\d+)\s*$|\*{20}\s#\s\d+\s\*+\s+'
re_SplitArchive = re.compile(__ARCHIVE_PRE_HEADER_REGEX) re_SplitArchive = re.compile(__ARCHIVE_PRE_HEADER_REGEX, re.MULTILINE)
class IdentifySite: class IdentifySite:
def __init__(self, config, in_path = '-'): def __init__(self, config, in_path = '-'):
self.in_path = in_path self.in_path = in_path
self.config = config self.config = config
self.db = Database.Database(config) self.db = Database.Database(self.config)
self.sitelist = {} self.sitelist = {}
self.filelist = {} self.filelist = {}
self.generateSiteList() self.generateSiteList()
self.walkDirectory(self.in_path, self.sitelist) if os.path.isdir(self.in_path):
self.walkDirectory(self.in_path, self.sitelist)
else:
self.idSite(self.in_path, self.sitelist)
def generateSiteList(self): def generateSiteList(self):
"""Generates a ordered dictionary of site, filter and filter name for each site in hhcs""" """Generates a ordered dictionary of site, filter and filter name for each site in hhcs"""
@ -80,7 +83,7 @@ class IdentifySite:
for kodec in self.__listof(obj.codepage): for kodec in self.__listof(obj.codepage):
try: try:
in_fh = codecs.open(file, 'r', kodec) in_fh = codecs.open(file, 'r', kodec)
whole_file = in_fh.read() whole_file = in_fh.read(2000)
in_fh.close() in_fh.close()
if info[2] in ('OnGame', 'Winamax'): if info[2] in ('OnGame', 'Winamax'):
@ -94,7 +97,7 @@ class IdentifySite:
if re_SplitArchive.search(whole_file): if re_SplitArchive.search(whole_file):
archive = True archive = True
if m: if m:
self.filelist[file] = [info[0]] + [info[1]] + [kodec] + [archive] self.filelist[file] = [info[1]] + [kodec] + [archive]
break break
except: except:
pass pass

View File

@ -59,6 +59,8 @@ def fpdb_options():
help=_("File to be split is a PokerStars or Full Tilt Poker archive file")) help=_("File to be split is a PokerStars or Full Tilt Poker archive file"))
parser.add_option("-n", "--numhands", dest="hands", default="100", type="int", parser.add_option("-n", "--numhands", dest="hands", default="100", type="int",
help=_("How many hands do you want saved to each file. Default is 100")) help=_("How many hands do you want saved to each file. Default is 100"))
parser.add_option("-w", "--workerid", dest="workerid", default="0", type="int",
help=_("Specifies the worker id running the script"))
(options, argv) = parser.parse_args() (options, argv) = parser.parse_args()

View File

@ -298,7 +298,7 @@ class PokerStars(HandHistoryConverter):
if key == 'BUTTON': if key == 'BUTTON':
hand.buttonpos = info[key] hand.buttonpos = info[key]
if key == 'MAX': if key == 'MAX':
hand.maxseats = int(info[key]) if info[key]: hand.maxseats = int(info[key])
if key == 'MIXED': if key == 'MIXED':
hand.mixed = self.mixes[info[key]] if info[key] is not None else None hand.mixed = self.mixes[info[key]] if info[key] is not None else None

View File

@ -1064,7 +1064,7 @@ class Sql:
activeSeats SMALLINT NOT NULL, activeSeats SMALLINT NOT NULL,
position CHAR(1), position CHAR(1),
tourneyTypeId SMALLINT UNSIGNED, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), tourneyTypeId SMALLINT UNSIGNED, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */ styleKey CHAR(9) NOT NULL, /* 1st char is style (A/T/H/S), other 8 are the key */
HDs INT NOT NULL, HDs INT NOT NULL,
wonWhenSeenStreet1 FLOAT, wonWhenSeenStreet1 FLOAT,
@ -1165,7 +1165,7 @@ class Sql:
activeSeats SMALLINT, activeSeats SMALLINT,
position CHAR(1), position CHAR(1),
tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */ styleKey CHAR(9) NOT NULL, /* 1st char is style (A/T/H/S), other 8 are the key */
HDs INT, HDs INT,
wonWhenSeenStreet1 FLOAT, wonWhenSeenStreet1 FLOAT,
@ -2047,7 +2047,7 @@ class Sql:
# gets a date, would need to use handsplayers (not hudcache) to get exact hand Id # gets a date, would need to use handsplayers (not hudcache) to get exact hand Id
if db_server == 'mysql': if db_server == 'mysql':
self.query['get_date_nhands_ago'] = """ self.query['get_date_nhands_ago'] = """
select concat( 'd', date_format(max(h.startTime), '%Y%m%d') ) select concat( 'd', date_format(max(h.startTime), '%Y%m%d%H') )
from (select hp.playerId from (select hp.playerId
,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx ,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx
from HandsPlayers hp from HandsPlayers hp
@ -2059,7 +2059,7 @@ class Sql:
""" """
elif db_server == 'postgresql': elif db_server == 'postgresql':
self.query['get_date_nhands_ago'] = """ self.query['get_date_nhands_ago'] = """
select 'd' || to_char(max(h3.startTime), 'YYMMDD') select 'd' || to_char(max(h3.startTime), 'YYMMDDHH')
from (select hp.playerId from (select hp.playerId
,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx ,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx
from HandsPlayers hp from HandsPlayers hp
@ -2071,7 +2071,7 @@ class Sql:
""" """
elif db_server == 'sqlite': # untested guess at query: elif db_server == 'sqlite': # untested guess at query:
self.query['get_date_nhands_ago'] = """ self.query['get_date_nhands_ago'] = """
select 'd' || strftime(max(h3.startTime), 'YYMMDD') select 'd' || strftime(max(h3.startTime), 'YYMMDDHH')
from (select hp.playerId from (select hp.playerId
,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx ,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx
from HandsPlayers hp from HandsPlayers hp
@ -3290,7 +3290,7 @@ class Sql:
else 'E' else 'E'
end AS hc_position end AS hc_position
<tourney_select_clause> <tourney_select_clause>
,date_format(h.startTime, 'd%y%m%d') ,date_format(h.startTime, 'd%y%m%d%H')
,count(1) ,count(1)
,sum(wonWhenSeenStreet1) ,sum(wonWhenSeenStreet1)
,sum(wonWhenSeenStreet2) ,sum(wonWhenSeenStreet2)
@ -3379,7 +3379,7 @@ class Sql:
,h.seats ,h.seats
,hc_position ,hc_position
<tourney_group_clause> <tourney_group_clause>
,date_format(h.startTime, 'd%y%m%d') ,date_format(h.startTime, 'd%y%m%d%H')
""" """
elif db_server == 'postgresql': elif db_server == 'postgresql':
self.query['rebuildHudCache'] = """ self.query['rebuildHudCache'] = """
@ -3488,7 +3488,7 @@ class Sql:
else 'E' else 'E'
end AS hc_position end AS hc_position
<tourney_select_clause> <tourney_select_clause>
,'d' || to_char(h.startTime, 'YYMMDD') ,'d' || to_char(h.startTime, 'YYMMDDHH')
,count(1) ,count(1)
,sum(wonWhenSeenStreet1) ,sum(wonWhenSeenStreet1)
,sum(wonWhenSeenStreet2) ,sum(wonWhenSeenStreet2)
@ -3577,7 +3577,7 @@ class Sql:
,h.seats ,h.seats
,hc_position ,hc_position
<tourney_group_clause> <tourney_group_clause>
,to_char(h.startTime, 'YYMMDD') ,to_char(h.startTime, 'YYMMDDHH')
""" """
else: # assume sqlite else: # assume sqlite
self.query['rebuildHudCache'] = """ self.query['rebuildHudCache'] = """
@ -3686,7 +3686,7 @@ class Sql:
else 'E' else 'E'
end AS hc_position end AS hc_position
<tourney_select_clause> <tourney_select_clause>
,'d' || substr(strftime('%Y%m%d', h.startTime),3,7) ,'d' || substr(strftime('%Y%m%d%H', h.startTime),3,9)
,count(1) ,count(1)
,sum(wonWhenSeenStreet1) ,sum(wonWhenSeenStreet1)
,sum(wonWhenSeenStreet2) ,sum(wonWhenSeenStreet2)
@ -3775,7 +3775,7 @@ class Sql:
,h.seats ,h.seats
,hc_position ,hc_position
<tourney_group_clause> <tourney_group_clause>
,'d' || substr(strftime('%Y%m%d', h.startTime),3,7) ,'d' || substr(strftime('%Y%m%d%H', h.startTime),3,9)
""" """
self.query['insert_hudcache'] = """ self.query['insert_hudcache'] = """

View File

@ -1,19 +1,22 @@
#!/usr/bin/python #!/usr/bin/env python
# -*- coding: utf-8 -*-
#Copyright 2010 Chaz Littlejohn # Copyright 2010, Chaz Littlejohn
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, version 3 of the License.
# #
#This program is distributed in the hope that it will be useful, # This program is free software; you can redistribute it and/or modify
#but WITHOUT ANY WARRANTY; without even the implied warranty of # it under the terms of the GNU General Public License as published by
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # the Free Software Foundation; either version 2 of the License, or
#GNU General Public License for more details. # (at your option) any later version.
# #
#You should have received a copy of the GNU Affero General Public License # This program is distributed in the hope that it will be useful,
#along with this program. If not, see <http://www.gnu.org/licenses/>. # but WITHOUT ANY WARRANTY; without even the implied warranty of
#In the "official" distribution you can find the license in agpl-3.0.txt. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
########################################################################
import L10n import L10n
_ = L10n.get_translation() _ = L10n.get_translation()
@ -28,6 +31,7 @@ import Options
import Configuration import Configuration
from Exceptions import * from Exceptions import *
from cStringIO import StringIO from cStringIO import StringIO
import time
(options, argv) = Options.fpdb_options() (options, argv) = Options.fpdb_options()
@ -37,7 +41,7 @@ codepage = ["utf-16", "utf-8", "cp1252"]
class SplitHandHistory: class SplitHandHistory:
def __init__(self, config, in_path = '-', out_path = None, hands = 100, filter = "PokerStarsToFpdb", archive = False): def __init__(self, config, in_path = '-', out_path = None, hands = 100, filter = "PokerStarsToFpdb", archive = False, workerid = 0):
self.config = config self.config = config
self.in_path = in_path self.in_path = in_path
self.out_path = out_path self.out_path = out_path
@ -50,22 +54,25 @@ class SplitHandHistory:
self.line_addendum = None self.line_addendum = None
self.filedone = False self.filedone = False
self.timestamp = str(time.time())
self.workerid = '%02d' % workerid
#Acquire re_SplitHands for this hh #Acquire re_SplitHands for this hh
filter_name = filter.replace("ToFpdb", "") self.filter_name = filter.replace("ToFpdb", "")
mod = __import__(filter) mod = __import__(filter)
obj = getattr(mod, filter_name, None) obj = getattr(mod, self.filter_name, None)
self.re_SplitHands = obj.re_SplitHands self.re_SplitHands = obj.re_SplitHands
#Determine line delimiter type if any #Determine line delimiter type if any
if self.re_SplitHands.match('\n\n'):
self.line_delimiter = '\n\n'
if self.re_SplitHands.match('\n\n\n'): if self.re_SplitHands.match('\n\n\n'):
self.line_delimiter = '\n\n\n' self.line_delimiter = '\n\n\n'
if self.re_SplitHands.match('\n\n'):
self.line_delimiter = '\n\n'
#Add new line addendum for sites which match SplitHand to next line as well #Add new line addendum for sites which match SplitHand to next line as well
if filter_name == 'OnGame': if self.filter_name == 'OnGame':
self.line_addendum = '*' self.line_addendum = '*'
if filter_name == 'Carbon': if self.filter_name == 'Carbon':
self.line_addendum = '<game' self.line_addendum = '<game'
#Open the gargantuan file #Open the gargantuan file
@ -75,6 +82,7 @@ class SplitHandHistory:
except IOError: except IOError:
print _('File not found') print _('File not found')
sys.exit(2) sys.exit(2)
self.kodec = kodec
#Split with do_hands_per_file if archive and paragraphs if a regular hh #Split with do_hands_per_file if archive and paragraphs if a regular hh
if self.archive: if self.archive:
@ -105,9 +113,10 @@ class SplitHandHistory:
print _('Nope, will not work (fileno=%d)' % fileno) print _('Nope, will not work (fileno=%d)' % fileno)
sys.exit(2) sys.exit(2)
basename = os.path.splitext(os.path.basename(self.in_path))[0] basename = os.path.splitext(os.path.basename(self.in_path))[0]
name = os.path.join(self.out_path, basename+'-%06d.txt' % fileno) name = os.path.join(self.out_path, self.filter_name+'-'+basename+'_'+self.workerid+'_'+self.timestamp+'_%06d.txt' % fileno)
print '-> %s' % name print '-> %s' % name
newfile = file(name, 'w') newfile = file(name, 'w')
os.chmod(name, 0775)
return newfile return newfile
#Archive Hand Splitter #Archive Hand Splitter
@ -122,8 +131,11 @@ class SplitHandHistory:
except FpdbEndOfFile: except FpdbEndOfFile:
done = True done = True
break break
except UnicodeEncodeError:
print _('Absurd character done messed you up')
sys.exit(2)
except: except:
print _("Unexpected error processing file") print _('Unexpected error processing file')
sys.exit(2) sys.exit(2)
n += 1 n += 1
outfile.close() outfile.close()
@ -174,7 +186,7 @@ class SplitHandHistory:
l = infile.readline() l = infile.readline()
l = l.replace('\r\n', '\n') l = l.replace('\r\n', '\n')
outfile.write(l) outfile.write(l)
l = infile.readline() l = infile.readline().encode(self.kodec)
while len(l) < 3: while len(l) < 3:
l = infile.readline() l = infile.readline()
@ -182,7 +194,7 @@ class SplitHandHistory:
while len(l) > 2: while len(l) > 2:
l = l.replace('\r\n', '\n') l = l.replace('\r\n', '\n')
outfile.write(l) outfile.write(l)
l = infile.readline() l = infile.readline().encode(self.kodec)
outfile.write(self.line_delimiter) outfile.write(self.line_delimiter)
return infile return infile
@ -196,12 +208,18 @@ def main(argv=None):
if argv is None: if argv is None:
argv = sys.argv[1:] argv = sys.argv[1:]
if not options.filename:
options.filename = sys.argv[1]
if not options.config: if not options.config:
options.config = Configuration.Config(file = "HUD_config.test.xml") options.config = sys.argv[2]
if sys.argv[3] == "True":
options.archive = True
if options.filename: if options.filename:
SplitHH = SplitHandHistory(options.config, options.filename, options.outpath, options.hands, SplitHH = SplitHandHistory(options.config, options.filename, options.outpath, options.hands,
options.hhc, options.archive) options.hhc, options.archive, options.workerid)
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

View File

@ -22,14 +22,57 @@ OFFSUIT = 2
ev = pokereval.PokerEval() ev = pokereval.PokerEval()
holder = None
class Holder: class Stove:
def __init__(self): def __init__(self):
self.hand = None self.hand = None
self.board = None self.board = None
self.range = None self.range = None
def set_board_with_list(self, board):
pass
def set_board_string(self, string):
board = Board()
# Board
b = string.strip().split()
if len(b) > 4:
board.b5 = b[4]
if len(b) > 3:
board.b4 = b[3]
if len(b) > 2:
board.b1 = b[0]
board.b2 = b[1]
board.b3 = b[2]
self.board = board
def set_hero_cards_string(self, string):
# Our pocket cards
cc = string.strip().split()
c1 = cc[0]
c2 = cc[1]
pocket_cards = Cards(c1, c2)
self.hand = pocket_cards
def set_villain_range_string(self, string):
# Villain's range
range = Range()
hands_in_range = string.strip().split(',')
for h in hands_in_range:
_h = h.strip()
if len(_h) > 3:
cc = _h.split()
r1 = cc[0]
r2 = cc[1]
vp = Cards(r1, r2)
range.add(vp)
else:
range.expand(expand_hands(_h, pocket_cards, board))
self.range = range
class Cards: class Cards:
def __init__(self, c1, c2): def __init__(self, c1, c2):
@ -177,50 +220,15 @@ def expand_hands(abbrev, hand, board):
return range return range
def parse_args(args, container): def parse_args(args, container):
# args[0] is the path being executed; need 3 more args # args[0] is the path being executed; need 3 more args
if len(args) < 4: if len(args) < 4:
return False return False
board = Board() container.set_board_string(args[1])
container.set_hero_cards_string(args[2])
container.set_villain_range_string(args[3])
# Board
b = args[1].strip().split()
if len(b) > 4:
board.b5 = b[4]
if len(b) > 3:
board.b4 = b[3]
if len(b) > 2:
board.b1 = b[0]
board.b2 = b[1]
board.b3 = b[2]
# Our pocket cards
cc = args[2].strip().split()
c1 = cc[0]
c2 = cc[1]
pocket_cards = Cards(c1, c2)
# Villain's range
range = Range()
hands_in_range = args[3].strip().split(',')
for h in hands_in_range:
_h = h.strip()
if len(_h) > 3:
cc = _h.split()
r1 = cc[0]
r2 = cc[1]
vp = Cards(r1, r2)
range.add(vp)
else:
range.expand(expand_hands(_h, pocket_cards, board))
holder.hand = pocket_cards
holder.range = range
holder.board = board
return True return True
@ -284,26 +292,12 @@ def odds_for_range(holder):
sev.show(holder.hand, holder.range.get()) sev.show(holder.hand, holder.range.get())
def main(argv=None):
stove = Stove()
if not parse_args(sys.argv, stove):
usage(sys.argv[0])
sys.exit(2)
odds_for_range(stove)
if __name__ == '__main__':
holder = Holder() sys.exit(main())
if not parse_args(sys.argv, holder):
usage(sys.argv[0])
sys.exit(2)
odds_for_range(holder)
# debugs
#print '%s, %s' % ( holder.hand.c1, holder.hand.c2)
#print '%s %s %s %s %s' % (holder.board.b1, holder.board.b2,
# holder.board.b3, holder.board.b4, holder.board.b5)
#while True:
# try:
# vl = holder.range.get()
# v = vl.pop()
# print '\t%s %s' % (v.c1, v.c2)
# except IndexError:
# break

View File

@ -201,6 +201,7 @@ def main(argv=None):
walk_testfiles("regression-test-files/cash/iPoker/", compare, importer, iPokerErrors, "iPoker") walk_testfiles("regression-test-files/cash/iPoker/", compare, importer, iPokerErrors, "iPoker")
if sites['Winamax'] == True: if sites['Winamax'] == True:
walk_testfiles("regression-test-files/cash/Winamax/", compare, importer, WinamaxErrors, "Winamax") walk_testfiles("regression-test-files/cash/Winamax/", compare, importer, WinamaxErrors, "Winamax")
walk_testfiles("regression-test-files/tour/Winamax/", compare, importer, WinamaxErrors, "Winamax")
if sites['Win2day'] == True: if sites['Win2day'] == True:
walk_testfiles("regression-test-files/cash/Win2day/", compare, importer, Win2dayErrors, "Win2day") walk_testfiles("regression-test-files/cash/Win2day/", compare, importer, Win2dayErrors, "Win2day")

View File

@ -82,15 +82,26 @@ class Winamax(HandHistoryConverter):
# Winamax Poker - CashGame - HandId: #279823-223-1285031451 - Holdem no limit (0.02€/0.05€) - 2010/09/21 03:10:51 UTC # Winamax Poker - CashGame - HandId: #279823-223-1285031451 - Holdem no limit (0.02€/0.05€) - 2010/09/21 03:10:51 UTC
# Table: 'Charenton-le-Pont' 9-max (real money) Seat #5 is the button # Table: 'Charenton-le-Pont' 9-max (real money) Seat #5 is the button
re_HandInfo = re.compile(u""" re_HandInfo = re.compile(u"""
\s*Winamax\sPoker\s-\sCashGame\s-\sHandId:\s\#(?P<HID1>\d+)-(?P<HID2>\d+)-(?P<HID3>\d+).*\s \s*Winamax\sPoker\s-\s
(?P<RING>CashGame)?
(?P<TOUR>Tournament\s
(?P<TOURNAME>.+)?\s
buyIn:\s(?P<BUYIN>(?P<BIAMT>[%(LS)s\d\,]+)?\s\+?\s(?P<BIRAKE>[%(LS)s\d\,]+)?\+?(?P<BOUNTY>[%(LS)s\d\.]+)?\s?(?P<TOUR_ISO>%(LEGAL_ISO)s)?|Gratuit|Ticket\suniquement)?\s
(level:\s(?P<LEVEL>\d+))?
.*)?
\s-\sHandId:\s\#(?P<HID1>\d+)-(?P<HID2>\d+)-(?P<HID3>\d+).*\s
(?P<GAME>Holdem|Omaha)\s (?P<GAME>Holdem|Omaha)\s
(?P<LIMIT>no\slimit|pot\slimit)\s (?P<LIMIT>no\slimit|pot\slimit)\s
\( \(
(((%(LS)s)?(?P<ANTE>[.0-9]+)(%(LS)s)?)/)?
((%(LS)s)?(?P<SB>[.0-9]+)(%(LS)s)?)/ ((%(LS)s)?(?P<SB>[.0-9]+)(%(LS)s)?)/
((%(LS)s)?(?P<BB>[.0-9]+)(%(LS)s)?) ((%(LS)s)?(?P<BB>[.0-9]+)(%(LS)s)?)
\)\s-\s \)\s-\s
(?P<DATETIME>.*) (?P<DATETIME>.*)
Table:\s\'(?P<TABLE>[^']+)\'\s(?P<MAXPLAYER>\d+)\-max Table:\s\'(?P<TABLE>[^(]+)
(.(?P<TOURNO>\d+).\#(?P<TABLENO>\d+))?.*
\'
\s(?P<MAXPLAYER>\d+)\-max
""" % substitutions, re.MULTILINE|re.DOTALL|re.VERBOSE) """ % substitutions, re.MULTILINE|re.DOTALL|re.VERBOSE)
re_TailSplitHands = re.compile(r'\n\s*\n') re_TailSplitHands = re.compile(r'\n\s*\n')
@ -126,8 +137,8 @@ class Winamax(HandHistoryConverter):
self.re_PostSB = re.compile('%(PLYR)s posts small blind (%(CUR)s)?(?P<SB>[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE) self.re_PostSB = re.compile('%(PLYR)s posts small blind (%(CUR)s)?(?P<SB>[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE)
self.re_PostBB = re.compile('%(PLYR)s posts big blind (%(CUR)s)?(?P<BB>[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE) self.re_PostBB = re.compile('%(PLYR)s posts big blind (%(CUR)s)?(?P<BB>[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE)
self.re_DenySB = re.compile('(?P<PNAME>.*) deny SB' % subst, re.MULTILINE) self.re_DenySB = re.compile('(?P<PNAME>.*) deny SB' % subst, re.MULTILINE)
self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante (%(CUR)s)?(?P<ANTE>[\.0-9]+)(%(CUR)s)?" % subst, re.MULTILINE) self.re_Antes = re.compile(r"^%(PLYR)s posts ante (%(CUR)s)?(?P<ANTE>[\.0-9]+)(%(CUR)s)?" % subst, re.MULTILINE)
self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for (%(CUR)s)?(?P<BRINGIN>[\.0-9]+(%(CUR)s)?)" % subst, re.MULTILINE) self.re_BringIn = re.compile(r"^%(PLYR)s brings[- ]in( low|) for (%(CUR)s)?(?P<BRINGIN>[\.0-9]+(%(CUR)s)?)" % subst, re.MULTILINE)
self.re_PostBoth = re.compile('(?P<PNAME>.*): posts small \& big blind \( (%(CUR)s)?(?P<SBBB>[\.0-9]+)(%(CUR)s)?\)' % subst) self.re_PostBoth = re.compile('(?P<PNAME>.*): posts small \& big blind \( (%(CUR)s)?(?P<SBBB>[\.0-9]+)(%(CUR)s)?\)' % subst)
self.re_PostDead = re.compile('(?P<PNAME>.*) posts dead blind \((%(CUR)s)?(?P<DEAD>[\.0-9]+)(%(CUR)s)?\)' % subst, re.MULTILINE) self.re_PostDead = re.compile('(?P<PNAME>.*) posts dead blind \((%(CUR)s)?(?P<DEAD>[\.0-9]+)(%(CUR)s)?\)' % subst, re.MULTILINE)
self.re_HeroCards = re.compile('Dealt\sto\s%(PLYR)s\s\[(?P<CARDS>.*)\]' % subst) self.re_HeroCards = re.compile('Dealt\sto\s%(PLYR)s\s\[(?P<CARDS>.*)\]' % subst)
@ -144,6 +155,9 @@ class Winamax(HandHistoryConverter):
["ring", "hold", "fl"], ["ring", "hold", "fl"],
["ring", "hold", "nl"], ["ring", "hold", "nl"],
["ring", "hold", "pl"], ["ring", "hold", "pl"],
["tour", "hold", "fl"],
["tour", "hold", "nl"],
["tour", "hold", "pl"],
] ]
def determineGameType(self, handText): def determineGameType(self, handText):
@ -160,7 +174,11 @@ class Winamax(HandHistoryConverter):
mg = m.groupdict() mg = m.groupdict()
info['type'] = 'ring' if mg.get('TOUR'):
info['type'] = 'tour'
elif mg.get('RING'):
info['type'] = 'ring'
info['currency'] = 'EUR' info['currency'] = 'EUR'
if 'LIMIT' in mg: if 'LIMIT' in mg:
@ -202,11 +220,62 @@ class Winamax(HandHistoryConverter):
hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET" hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET"
hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, "CET", "UTC") hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, "CET", "UTC")
if key == 'HID1': if key == 'HID1':
hand.handid = "1%.4d%s%s"%(int(info['HID2']),info['HID1'],info['HID3'])
# Need to remove non-alphanumerics for MySQL # Need to remove non-alphanumerics for MySQL
hand.handid = "1%.9d%s%s"%(int(info['HID2']),info['HID1'],info['HID3'])
if key == 'TOURNO':
hand.tourNo = info[key]
if key == 'TABLE': if key == 'TABLE':
hand.tablename = info[key] hand.tablename = info[key]
if key == 'BUYIN':
if hand.tourNo!=None:
#print "DEBUG: info['BUYIN']: %s" % info['BUYIN']
#print "DEBUG: info['BIAMT']: %s" % info['BIAMT']
#print "DEBUG: info['BIRAKE']: %s" % info['BIRAKE']
#print "DEBUG: info['BOUNTY']: %s" % info['BOUNTY']
for k in ['BIAMT','BIRAKE']:
if k in info.keys() and info[k]:
info[k] = info[k].replace(',','.')
if info[key] == 'Freeroll':
hand.buyin = 0
hand.fee = 0
hand.buyinCurrency = "FREE"
else:
if info[key].find("$")!=-1:
hand.buyinCurrency="USD"
elif info[key].find(u"")!=-1:
hand.buyinCurrency="EUR"
elif info[key].find("FPP")!=-1:
hand.buyinCurrency="PSFP"
else:
#FIXME: handle other currencies, FPP, play money
raise FpdbParseError(_("failed to detect currency"))
info['BIAMT'] = info['BIAMT'].strip(u'$€FPP')
if hand.buyinCurrency!="PSFP":
if info['BOUNTY'] != None:
# There is a bounty, Which means we need to switch BOUNTY and BIRAKE values
tmp = info['BOUNTY']
info['BOUNTY'] = info['BIRAKE']
info['BIRAKE'] = tmp
info['BOUNTY'] = info['BOUNTY'].strip(u'$€') # Strip here where it isn't 'None'
hand.koBounty = int(100*Decimal(info['BOUNTY']))
hand.isKO = True
else:
hand.isKO = False
info['BIRAKE'] = info['BIRAKE'].strip(u'$€')
hand.buyin = int(100*Decimal(info['BIAMT']))
hand.fee = int(100*Decimal(info['BIRAKE']))
else:
hand.buyin = int(Decimal(info['BIAMT']))
hand.fee = 0
if key == 'LEVEL':
hand.level = info[key]
# TODO: These # TODO: These
hand.buttonpos = 1 hand.buttonpos = 1
hand.maxseats = 10 # Set to None - Hand.py will guessMaxSeats() hand.maxseats = 10 # Set to None - Hand.py will guessMaxSeats()

View File

@ -116,6 +116,7 @@ import GuiAutoImport
import GuiGraphViewer import GuiGraphViewer
import GuiTourneyGraphViewer import GuiTourneyGraphViewer
import GuiSessionViewer import GuiSessionViewer
import GuiStove
import SQL import SQL
import Database import Database
import Configuration import Configuration
@ -778,6 +779,7 @@ class fpdb:
<menuitem action="tourneyviewer"/> <menuitem action="tourneyviewer"/>
<menuitem action="posnstats"/> <menuitem action="posnstats"/>
<menuitem action="sessionstats"/> <menuitem action="sessionstats"/>
<menuitem action="stove"/>
</menu> </menu>
<menu action="database"> <menu action="database">
<menuitem action="maintaindbs"/> <menuitem action="maintaindbs"/>
@ -814,6 +816,7 @@ class fpdb:
('hudConfigurator', None, _('_HUD Configurator'), _('<control>H'), 'HUD Configurator', self.diaHudConfigurator), ('hudConfigurator', None, _('_HUD Configurator'), _('<control>H'), 'HUD Configurator', self.diaHudConfigurator),
('graphs', None, _('_Graphs'), _('<control>G'), 'Graphs', self.tabGraphViewer), ('graphs', None, _('_Graphs'), _('<control>G'), 'Graphs', self.tabGraphViewer),
('tourneygraphs', None, _('Tourney Graphs'), None, 'TourneyGraphs', self.tabTourneyGraphViewer), ('tourneygraphs', None, _('Tourney Graphs'), None, 'TourneyGraphs', self.tabTourneyGraphViewer),
('stove', None, _('Stove'), None, 'Stove', self.tabStove),
('ringplayerstats', None, _('Ring _Player Stats (tabulated view, not on pgsql)'), _('<control>P'), 'Ring Player Stats (tabulated view, not on pgsql)', self.tab_ring_player_stats), ('ringplayerstats', None, _('Ring _Player Stats (tabulated view, not on pgsql)'), _('<control>P'), 'Ring Player Stats (tabulated view, not on pgsql)', self.tab_ring_player_stats),
('tourneyplayerstats', None, _('_Tourney Stats (tabulated view, not on pgsql)'), _('<control>T'), 'Tourney Stats (tabulated view, not on pgsql)', self.tab_tourney_player_stats), ('tourneyplayerstats', None, _('_Tourney Stats (tabulated view, not on pgsql)'), _('<control>T'), 'Tourney Stats (tabulated view, not on pgsql)', self.tab_tourney_player_stats),
('tourneyviewer', None, _('Tourney _Viewer'), None, 'Tourney Viewer)', self.tab_tourney_viewer_stats), ('tourneyviewer', None, _('Tourney _Viewer'), None, 'Tourney Viewer)', self.tab_tourney_viewer_stats),
@ -1000,7 +1003,7 @@ class fpdb:
self.add_and_display_tab(bulk_tab, _("Bulk Import")) self.add_and_display_tab(bulk_tab, _("Bulk Import"))
def tab_tourney_import(self, widget, data=None): def tab_tourney_import(self, widget, data=None):
"""opens a tab for bulk importing""" """opens a tab for bulk importing tournament summaries"""
new_import_thread = GuiTourneyImport.GuiTourneyImport(self.settings, self.config, self.sql, self.window) new_import_thread = GuiTourneyImport.GuiTourneyImport(self.settings, self.config, self.sql, self.window)
self.threads.append(new_import_thread) self.threads.append(new_import_thread)
bulk_tab=new_import_thread.get_vbox() bulk_tab=new_import_thread.get_vbox()
@ -1078,6 +1081,13 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an
gv_tab = new_gv_thread.get_vbox() gv_tab = new_gv_thread.get_vbox()
self.add_and_display_tab(gv_tab, _("Tourney Graphs")) self.add_and_display_tab(gv_tab, _("Tourney Graphs"))
def tabStove(self, widget, data=None):
"""opens a tab for bulk importing tournament summaries"""
thread = GuiStove.GuiStove(self.config, self.window)
self.threads.append(thread)
tab = thread.get_vbox()
self.add_and_display_tab(tab, _("Stove"))
def __init__(self): def __init__(self):
# no more than 1 process can this lock at a time: # no more than 1 process can this lock at a time:
self.lock = interlocks.InterProcessLock(name="fpdb_global_lock") self.lock = interlocks.InterProcessLock(name="fpdb_global_lock")

2
pyfpdb/interlocks.py Executable file → Normal file
View File

@ -108,7 +108,7 @@ class InterProcessLockFcntl(InterProcessLockBase):
self.lockfd = 0 self.lockfd = 0
try: try:
os.unlink(self.lock_file_name) os.unlink(self.lock_file_name)
except IOError: except OSError:
# We don't care about the existence of the file too much here. It's the flock() we care about, # We don't care about the existence of the file too much here. It's the flock() we care about,
# And that should just go away magically. # And that should just go away magically.
pass pass

View File

@ -0,0 +1,42 @@
PokerStars Game #2428142447: Hold'em Limit ($1/$2 USD) - 2005/08/26 16:12:22 ET
Table 'Teucer II' Seat #5 is the button
Seat 1: Frankson34 ($24 in chips)
Seat 2: webb22 ($64 in chips)
Seat 3: eric_mtx ($26 in chips)
Seat 4: sososolid ($147.75 in chips)
Seat 5: DRILHER ($48.25 in chips)
Seat 6: Naughtychic ($60 in chips)
Seat 7: Terps78 ($71.50 in chips)
Seat 8: ChazDazzle ($69.25 in chips)
Seat 9: alekos ($55 in chips)
Seat 10: BigNards84 ($64.25 in chips)
Naughtychic: posts small blind $0.50
Terps78: posts big blind $1
*** HOLE CARDS ***
Dealt to ChazDazzle [8c Kd]
ChazDazzle: folds
alekos: folds
BigNards84: raises $1 to $2
Frankson34: folds
webb22: folds
eric_mtx: folds
ChazDazzle leaves the table
sososolid: folds
DRILHER: folds
cdhender joins the table at seat #8
Naughtychic: folds
Terps78: folds
BigNards84 collected $2.50 from pot
BigNards84: doesn't show hand
*** SUMMARY ***
Total pot $2.50 | Rake $0
Seat 1: Frankson34 folded before Flop (didn't bet)
Seat 2: webb22 folded before Flop (didn't bet)
Seat 3: eric_mtx folded before Flop (didn't bet)
Seat 4: sososolid folded before Flop (didn't bet)
Seat 5: DRILHER (button) folded before Flop (didn't bet)
Seat 6: Naughtychic (small blind) folded before Flop
Seat 7: Terps78 (big blind) folded before Flop
Seat 8: ChazDazzle folded before Flop (didn't bet)
Seat 9: alekos folded before Flop (didn't bet)
Seat 10: BigNards84 collected ($2.50)

View File

@ -0,0 +1,310 @@
Winamax Poker - Tournament "No Limit Hold'em" buyIn: 0,90€ + 0,10€ level: 0 - HandId: #7959970263859201-1-1288800933 - Holdem no limit (10/20) - 2010/11/03 17:15:33 UTC
Table: 'No Limit Hold'em(1853325)#0' 10-max (real money) Seat #3 is the button
Seat 1: Player6 (1500)
Seat 2: Player3 (1500)
Seat 3: Player9 (1500)
Seat 4: Player1 (1500)
Seat 5: Player0 (1500)
Seat 6: Player7 (1500)
Seat 7: Player4 (1500)
Seat 8: Player2 (1500)
Seat 9: Player5 (1500)
Seat 10: Player8 (1500)
*** ANTE/BLINDS ***
Player1 posts small blind 10
Player0 posts big blind 20
Dealt to Player6 [Jd 7h]
*** PRE-FLOP ***
Player7 folds
Player4 folds
Player2 folds
Player5 calls 20
Player8 folds
Player6 calls 20
Player3 calls 20
Player9 calls 20
Player1 calls 10
Player0 checks
*** FLOP *** [Td 4c 5h]
Player1 checks
Player0 checks
Player5 checks
Player6 bets 80
Player3 calls 80
Player9 folds
Player1 folds
Player0 calls 80
Player5 folds
*** TURN *** [Td 4c 5h][3h]
Player0 checks
Player6 checks
Player3 checks
*** RIVER *** [Td 4c 5h 3h][Kc]
Player0 checks
Player6 bets 240
Player3 calls 240
Player0 folds
*** SHOW DOWN ***
Player6 shows [Jd 7h] (High card : King)
Player3 shows [Kd 4d] (Two pairs : Kings and 4)
Player3 collected 840 from pot
*** SUMMARY ***
Total pot 840 | No rake
Board: [Td 4c 5h 3h Kc]
Seat 1: Player6 showed [Jd 7h] and lost with High card : King
Seat 2: Player3 showed [Kd 4d] and won 840 with Two pairs : Kings and 4
Seat 3: Player9 (button) folded on the flop
Seat 4: Player1 (small blind) folded on the flop
Seat 5: Player0 (big blind) folded on the river
Seat 6: Player7 folded on the pre-flop
Seat 7: Player4 folded
Seat 8: Player2 folded on the pre-flop
Seat 9: Player5 folded on the flop
Seat 10: Player8 folded on the pre-flop
Winamax Poker - Tournament "No Limit Hold'em" buyIn: 0,90€ + 0,10€ level: 0 - HandId: #7959970263859201-2-1288801071 - Holdem no limit (10/20) - 2010/11/03 17:17:51 UTC
Table: 'No Limit Hold'em(1853325)#0' 10-max (real money) Seat #4 is the button
Seat 1: Player6 (1160)
Seat 2: Player3 (2000)
Seat 3: Player9 (1480)
Seat 4: Player1 (1480)
Seat 5: Player0 (1400)
Seat 6: Player7 (1500)
Seat 7: Player4 (1500)
Seat 8: Player2 (1500)
Seat 9: Player5 (1480)
Seat 10: Player8 (1500)
*** ANTE/BLINDS ***
Player0 posts small blind 10
Player7 posts big blind 20
Dealt to Player6 [7h 3s]
*** PRE-FLOP ***
Player4 folds
Player2 folds
Player5 calls 20
Player8 calls 20
Player6 folds
Player3 calls 20
Player9 folds
Player1 calls 20
Player0 calls 10
Player7 checks
*** FLOP *** [Jh 6h Qd]
Player0 checks
Player7 bets 20
Player5 calls 20
Player8 calls 20
Player3 folds
Player1 calls 20
Player0 calls 20
*** TURN *** [Jh 6h Qd][5s]
Player0 checks
Player7 checks
Player5 bets 220
Player8 folds
Player1 folds
Player0 folds
Player7 calls 220
*** RIVER *** [Jh 6h Qd 5s][3c]
Player7 checks
Player5 bets 660
Player7 folds
Player5 collected 1320 from pot
*** SUMMARY ***
Total pot 1.32k | No rake
Board: [Jh 6h Qd 5s 3c]
Seat 1: Player6 folded on the pre-flop
Seat 2: Player3 folded on the flop
Seat 3: Player9 folded on the pre-flop
Seat 4: Player1 (button) folded on the turn
Seat 5: Player0 (small blind) folded on the turn
Seat 6: Player7 (big blind) folded on the river
Seat 7: Player4 folded on the pre-flop
Seat 8: Player2 folded on the pre-flop
Seat 9: Player5 won 1320
Seat 10: Player8 folded on the turn
Winamax Poker - Tournament "No Limit Hold'em" buyIn: 0,90€ + 0,10€ level: 0 - HandId: #7959970263859201-3-1288801160 - Holdem no limit (10/20) - 2010/11/03 17:19:20 UTC
Table: 'No Limit Hold'em(1853325)#0' 10-max (real money) Seat #5 is the button
Seat 1: Player6 (1160)
Seat 2: Player3 (1980)
Seat 3: Player9 (1480)
Seat 4: Player1 (1440)
Seat 5: Player0 (1360)
Seat 6: Player7 (1240)
Seat 7: Player4 (1500)
Seat 8: Player2 (1500)
Seat 9: Player5 (1880)
Seat 10: Player8 (1460)
*** ANTE/BLINDS ***
Player7 posts small blind 10
Player4 posts big blind 20
Dealt to Player6 [4h 3d]
*** PRE-FLOP ***
Player2 folds
Player5 calls 20
Player8 calls 20
Player6 folds
Player3 folds
Player9 folds
Player1 calls 20
Player0 folds
Player7 raises 20 to 40
Player4 folds
Player5 calls 20
Player8 calls 20
Player1 calls 20
*** FLOP *** [Qd Kh 4s]
Player7 bets 1200 and is all-in
Player5 folds
Player8 folds
Player1 folds
Player7 collected 1380 from pot
*** SUMMARY ***
Total pot 1.38k | No rake
Board: [Qd Kh 4s]
Seat 1: Player6 folded on the pre-flop
Seat 2: Player3 folded on the pre-flop
Seat 3: Player9 folded on the pre-flop
Seat 4: Player1 folded on the flop
Seat 5: Player0 (button) folded on the pre-flop
Seat 6: Player7 (small blind) won 1380
Seat 7: Player4 (big blind) folded on the pre-flop
Seat 8: Player2 folded on the pre-flop
Seat 9: Player5 folded on the flop
Seat 10: Player8 folded on the flop
Winamax Poker - Tournament "No Limit Hold'em" buyIn: 0,90€ + 0,10€ level: 0 - HandId: #7959970263859201-4-1288801277 - Holdem no limit (10/20) - 2010/11/03 17:21:17 UTC
Table: 'No Limit Hold'em(1853325)#0' 10-max (real money) Seat #6 is the button
Seat 1: Player6 (1160)
Seat 2: Player3 (1980)
Seat 3: Player9 (1480)
Seat 4: Player1 (1400)
Seat 5: Player0 (1360)
Seat 6: Player7 (1380)
Seat 7: Player4 (1480)
Seat 8: Player2 (1500)
Seat 9: Player5 (1840)
Seat 10: Player8 (1420)
*** ANTE/BLINDS ***
Player4 posts small blind 10
Player2 posts big blind 20
Dealt to Player6 [Qc 7d]
*** PRE-FLOP ***
Player5 calls 20
Player8 folds
Player6 folds
Player3 folds
Player9 folds
Player1 calls 20
Player0 folds
Player7 calls 20
Player4 calls 10
Player2 checks
*** FLOP *** [9s 7h 5h]
Player4 checks
Player2 checks
Player5 checks
Player1 checks
Player7 checks
*** TURN *** [9s 7h 5h][Ts]
Player4 checks
Player2 checks
Player5 checks
Player1 checks
Player7 bets 20
Player4 calls 20
Player2 folds
Player5 folds
Player1 calls 20
*** RIVER *** [9s 7h 5h Ts][7s]
Player4 checks
Player1 checks
Player7 bets 160
Player4 folds
Player1 calls 160
*** SHOW DOWN ***
Player1 shows [4c 4d] (Two pairs : 7 and 4)
Player7 shows [4s As] (Flush Ace high)
Player7 collected 480 from pot
*** SUMMARY ***
Total pot 480 | No rake
Board: [9s 7h 5h Ts 7s]
Seat 1: Player6 folded on the pre-flop
Seat 2: Player3 folded on the pre-flop
Seat 3: Player9 folded on the pre-flop
Seat 4: Player1 showed [4c 4d] and lost with Two pairs : 7 and 4
Seat 5: Player0 folded on the pre-flop
Seat 6: Player7 (button) showed [4s As] and won 480 with Flush Ace high
Seat 7: Player4 (small blind) folded on the river
Seat 8: Player2 (big blind) folded on the turn
Seat 9: Player5 folded on the turn
Seat 10: Player8 folded on the pre-flop
Winamax Poker - Tournament "No Limit Hold'em" buyIn: 0,90€ + 0,10€ level: 1 - HandId: #7959970263859201-5-1288801360 - Holdem no limit (10/20) - 2010/11/03 17:22:40 UTC
Table: 'No Limit Hold'em(1853325)#0' 10-max (real money) Seat #7 is the button
Seat 1: Player6 (1160)
Seat 2: Player3 (1980)
Seat 3: Player9 (1480)
Seat 4: Player1 (1200)
Seat 5: Player0 (1360)
Seat 6: Player7 (1660)
Seat 7: Player4 (1440)
Seat 8: Player2 (1480)
Seat 9: Player5 (1820)
Seat 10: Player8 (1420)
*** ANTE/BLINDS ***
Player2 posts small blind 10
Player5 posts big blind 20
Dealt to Player6 [Kd Ah]
*** PRE-FLOP ***
Player8 calls 20
Player6 raises 70 to 90
Player3 folds
Player9 calls 90
Player1 calls 90
Player0 calls 90
Player7 calls 90
Player4 calls 90
Player2 folds
Player5 calls 70
Player8 calls 70
*** FLOP *** [2s 5h 3h]
Player5 checks
Player8 checks
Player6 bets 365
Player9 folds
Player1 folds
Player0 folds
Player7 calls 365
Player4 folds
Player5 folds
Player8 folds
*** TURN *** [2s 5h 3h][6d]
Player6 bets 705 and is all-in
Player7 calls 705
*** RIVER *** [2s 5h 3h 6d][5s]
*** SHOW DOWN ***
Player6 shows [Kd Ah] (One pair : 5)
Player7 shows [7d 7h] (Two pairs : 7 and 5)
Player7 collected 2870 from pot
*** SUMMARY ***
Total pot 2.87k | No rake
Board: [2s 5h 3h 6d 5s]
Seat 1: Player6 showed [Kd Ah] and lost with One pair : 5
Seat 2: Player3 folded on the pre-flop
Seat 3: Player9 folded on the flop
Seat 4: Player1 folded on the flop
Seat 5: Player0 folded on the flop
Seat 6: Player7 showed [7d 7h] and won 2870 with Two pairs : 7 and 5
Seat 7: Player4 (button) folded on the flop
Seat 8: Player2 (small blind) folded on the pre-flop
Seat 9: Player5 (big blind) folded on the flop
Seat 10: Player8 folded on the flop