diff --git a/pyfpdb/CarbonToFpdb.py b/pyfpdb/CarbonToFpdb.py
index 1a1541ee..a2d2f56f 100644
--- a/pyfpdb/CarbonToFpdb.py
+++ b/pyfpdb/CarbonToFpdb.py
@@ -133,8 +133,9 @@ or None if we fail to get the info """
self.info = {}
mg = m.groupdict()
+ print mg
- limits = { 'No Limit':'nl', 'Limit':'fl' }
+ limits = { 'No Limit':'nl', 'No Limit ':'nl', 'Limit':'fl' }
games = { # base, category
'Holdem' : ('hold','holdem'),
'Holdem Tournament' : ('hold','holdem') }
diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py
index 0647baf2..99d1322d 100644
--- a/pyfpdb/Database.py
+++ b/pyfpdb/Database.py
@@ -73,7 +73,7 @@ except ImportError:
use_numpy = False
-DB_VERSION = 144
+DB_VERSION = 145
# Variance created as sqlite has a bunch of undefined aggregate functions.
@@ -255,6 +255,11 @@ class Database:
self.database = db_params['db-databaseName']
self.host = db_params['db-host']
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
if sql is None:
@@ -291,8 +296,8 @@ class Database:
# 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.date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD)
- self.h_date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) for hero
+ self.date_ndays_ago = 'd00000000' # date N days ago ('d' + YYMMDD)
+ 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.saveActions = False if self.import_options['saveActions'] == False else True
@@ -689,21 +694,25 @@ class Database:
else:
if row and row[0]:
self.hand_1day_ago = int(row[0])
-
- d = timedelta(days=hud_days)
+
+ tz = datetime.utcnow() - datetime.today()
+ tz_offset = tz.seconds/3600
+ tz_day_start_offset = self.day_start + tz_offset
+
+ d = timedelta(days=hud_days, hours=tz_day_start_offset)
now = datetime.utcnow() - d
- self.date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day)
-
- d = timedelta(days=h_hud_days)
+ 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" % (now.year - 2000, now.month, now.day)
+ 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):
# not sure if this is workable, to be continued ...
try:
# 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 :-(
- self.date_nhands_ago[str(playerid)] = 'd000000'
+ self.date_nhands_ago[str(playerid)] = 'd00000000'
# should use aggregated version of query if appropriate
c.execute(self.sql.query['get_date_nhands_ago'], (self.hud_hands, playerid))
@@ -771,11 +780,11 @@ class Database:
if hud_style == 'T':
stylekey = self.date_ndays_ago
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':
- stylekey = 'zzzzzzz' # all stylekey values should be lower than this
+ stylekey = 'zzzzzzzzz' # all stylekey values should be lower than this
else:
- stylekey = '0000000'
+ stylekey = '000000000'
log.info('hud_style: %s' % hud_style)
#elif hud_style == 'H':
@@ -784,11 +793,11 @@ class Database:
if h_hud_style == 'T':
h_stylekey = self.h_date_ndays_ago
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':
- h_stylekey = 'zzzzzzz' # all stylekey values should be lower than this
+ h_stylekey = 'zzzzzzzzz' # all stylekey values should be lower than this
else:
- h_stylekey = '000000'
+ h_stylekey = '00000000'
log.info('h_hud_style: %s' % h_hud_style)
#elif h_hud_style == 'H':
@@ -1824,11 +1833,11 @@ class Database:
"""Update cached statistics. If update fails because no record exists, do an insert."""
if self.use_date_in_hudcache:
- styleKey = datetime.strftime(starttime, 'd%y%m%d')
- #styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day)
+ styleKey = datetime.strftime(starttime, 'd%y%m%d%H')
+ #styleKey = "d%02d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day, hand_start_time.hour)
else:
- # hard-code styleKey as 'A000000' (all-time cache, no key) for now
- styleKey = 'A000000'
+ # hard-code styleKey as 'A00000000' (all-time cache, no key) for now
+ styleKey = 'A00000000'
update_hudcache = self.sql.query['update_hudcache']
update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder'])
diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py
index d12f1d10..6f0fd269 100644
--- a/pyfpdb/GuiSessionViewer.py
+++ b/pyfpdb/GuiSessionViewer.py
@@ -50,11 +50,14 @@ import Database
import Filters
import Charset
+DEBUG = False
+
class GuiSessionViewer (threading.Thread):
def __init__(self, config, querylist, mainwin, debug=True):
self.debug = debug
self.conf = config
self.sql = querylist
+ self.window = mainwin
self.liststore = None
@@ -153,6 +156,28 @@ class GuiSessionViewer (threading.Thread):
# make sure Hand column is not displayed
#[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):
"""returns the vbox of this thread"""
diff --git a/pyfpdb/GuiStove.py b/pyfpdb/GuiStove.py
new file mode 100644
index 00000000..7ff0820e
--- /dev/null
+++ b/pyfpdb/GuiStove.py
@@ -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 .
+#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
diff --git a/pyfpdb/IdentifySite.py b/pyfpdb/IdentifySite.py
index b4f1a8a7..723991f3 100644
--- a/pyfpdb/IdentifySite.py
+++ b/pyfpdb/IdentifySite.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Copyright 2010 Chaz Littlejohn
@@ -28,18 +28,21 @@ import Configuration
import Database
__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:
def __init__(self, config, in_path = '-'):
self.in_path = in_path
self.config = config
- self.db = Database.Database(config)
+ self.db = Database.Database(self.config)
self.sitelist = {}
self.filelist = {}
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):
"""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):
try:
in_fh = codecs.open(file, 'r', kodec)
- whole_file = in_fh.read()
+ whole_file = in_fh.read(2000)
in_fh.close()
if info[2] in ('OnGame', 'Winamax'):
@@ -94,7 +97,7 @@ class IdentifySite:
if re_SplitArchive.search(whole_file):
archive = True
if m:
- self.filelist[file] = [info[0]] + [info[1]] + [kodec] + [archive]
+ self.filelist[file] = [info[1]] + [kodec] + [archive]
break
except:
pass
diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py
index b8be3d2a..6369b485 100644
--- a/pyfpdb/Options.py
+++ b/pyfpdb/Options.py
@@ -59,6 +59,8 @@ def fpdb_options():
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",
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()
diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py
index 16c4091e..3817ae3f 100644
--- a/pyfpdb/PokerStarsToFpdb.py
+++ b/pyfpdb/PokerStarsToFpdb.py
@@ -298,7 +298,7 @@ class PokerStars(HandHistoryConverter):
if key == 'BUTTON':
hand.buttonpos = info[key]
if key == 'MAX':
- hand.maxseats = int(info[key])
+ if info[key]: hand.maxseats = int(info[key])
if key == 'MIXED':
hand.mixed = self.mixes[info[key]] if info[key] is not None else None
diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py
index d45ccd38..6a505eae 100644
--- a/pyfpdb/SQL.py
+++ b/pyfpdb/SQL.py
@@ -1064,7 +1064,7 @@ class Sql:
activeSeats SMALLINT NOT NULL,
position CHAR(1),
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,
wonWhenSeenStreet1 FLOAT,
@@ -1165,7 +1165,7 @@ class Sql:
activeSeats SMALLINT,
position CHAR(1),
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,
wonWhenSeenStreet1 FLOAT,
@@ -2047,7 +2047,7 @@ class Sql:
# gets a date, would need to use handsplayers (not hudcache) to get exact hand Id
if db_server == 'mysql':
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
,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx
from HandsPlayers hp
@@ -2059,7 +2059,7 @@ class Sql:
"""
elif db_server == 'postgresql':
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
,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx
from HandsPlayers hp
@@ -2071,7 +2071,7 @@ class Sql:
"""
elif db_server == 'sqlite': # untested guess at query:
self.query['get_date_nhands_ago'] = """
- select 'd' || strftime(max(h3.startTime), 'YYMMDD')
+ select 'd' || strftime(max(h3.startTime), 'YYMMDDHH')
from (select hp.playerId
,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx
from HandsPlayers hp
@@ -3290,7 +3290,7 @@ class Sql:
else 'E'
end AS hc_position
- ,date_format(h.startTime, 'd%y%m%d')
+ ,date_format(h.startTime, 'd%y%m%d%H')
,count(1)
,sum(wonWhenSeenStreet1)
,sum(wonWhenSeenStreet2)
@@ -3379,7 +3379,7 @@ class Sql:
,h.seats
,hc_position
- ,date_format(h.startTime, 'd%y%m%d')
+ ,date_format(h.startTime, 'd%y%m%d%H')
"""
elif db_server == 'postgresql':
self.query['rebuildHudCache'] = """
@@ -3488,7 +3488,7 @@ class Sql:
else 'E'
end AS hc_position
- ,'d' || to_char(h.startTime, 'YYMMDD')
+ ,'d' || to_char(h.startTime, 'YYMMDDHH')
,count(1)
,sum(wonWhenSeenStreet1)
,sum(wonWhenSeenStreet2)
@@ -3577,7 +3577,7 @@ class Sql:
,h.seats
,hc_position
- ,to_char(h.startTime, 'YYMMDD')
+ ,to_char(h.startTime, 'YYMMDDHH')
"""
else: # assume sqlite
self.query['rebuildHudCache'] = """
@@ -3686,7 +3686,7 @@ class Sql:
else 'E'
end AS hc_position
- ,'d' || substr(strftime('%Y%m%d', h.startTime),3,7)
+ ,'d' || substr(strftime('%Y%m%d%H', h.startTime),3,9)
,count(1)
,sum(wonWhenSeenStreet1)
,sum(wonWhenSeenStreet2)
@@ -3775,7 +3775,7 @@ class Sql:
,h.seats
,hc_position
- ,'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'] = """
diff --git a/pyfpdb/SplitHandHistory.py b/pyfpdb/SplitHandHistory.py
index 52c1d340..c996f903 100644
--- a/pyfpdb/SplitHandHistory.py
+++ b/pyfpdb/SplitHandHistory.py
@@ -1,19 +1,22 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
+#!/usr/bin/env python
-#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,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU General Public License for more details.
-#
-#You should have received a copy of the GNU Affero General Public License
-#along with this program. If not, see .
-#In the "official" distribution you can find the license in agpl-3.0.txt.
+# Copyright 2010, Chaz Littlejohn
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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 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
_ = L10n.get_translation()
@@ -28,6 +31,7 @@ import Options
import Configuration
from Exceptions import *
from cStringIO import StringIO
+import time
(options, argv) = Options.fpdb_options()
@@ -37,7 +41,7 @@ codepage = ["utf-16", "utf-8", "cp1252"]
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.in_path = in_path
self.out_path = out_path
@@ -50,22 +54,25 @@ class SplitHandHistory:
self.line_addendum = None
self.filedone = False
+ self.timestamp = str(time.time())
+ self.workerid = '%02d' % workerid
+
#Acquire re_SplitHands for this hh
- filter_name = filter.replace("ToFpdb", "")
+ self.filter_name = filter.replace("ToFpdb", "")
mod = __import__(filter)
- obj = getattr(mod, filter_name, None)
+ obj = getattr(mod, self.filter_name, None)
self.re_SplitHands = obj.re_SplitHands
#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'):
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
- if filter_name == 'OnGame':
+ if self.filter_name == 'OnGame':
self.line_addendum = '*'
- if filter_name == 'Carbon':
+ if self.filter_name == 'Carbon':
self.line_addendum = ' %s' % name
newfile = file(name, 'w')
+ os.chmod(name, 0775)
return newfile
#Archive Hand Splitter
@@ -122,8 +131,11 @@ class SplitHandHistory:
except FpdbEndOfFile:
done = True
break
+ except UnicodeEncodeError:
+ print _('Absurd character done messed you up')
+ sys.exit(2)
except:
- print _("Unexpected error processing file")
+ print _('Unexpected error processing file')
sys.exit(2)
n += 1
outfile.close()
@@ -174,7 +186,7 @@ class SplitHandHistory:
l = infile.readline()
l = l.replace('\r\n', '\n')
outfile.write(l)
- l = infile.readline()
+ l = infile.readline().encode(self.kodec)
while len(l) < 3:
l = infile.readline()
@@ -182,7 +194,7 @@ class SplitHandHistory:
while len(l) > 2:
l = l.replace('\r\n', '\n')
outfile.write(l)
- l = infile.readline()
+ l = infile.readline().encode(self.kodec)
outfile.write(self.line_delimiter)
return infile
@@ -195,13 +207,19 @@ class SplitHandHistory:
def main(argv=None):
if argv is None:
argv = sys.argv[1:]
+
+ if not options.filename:
+ options.filename = sys.argv[1]
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:
SplitHH = SplitHandHistory(options.config, options.filename, options.outpath, options.hands,
- options.hhc, options.archive)
+ options.hhc, options.archive, options.workerid)
if __name__ == '__main__':
sys.exit(main())
diff --git a/pyfpdb/Stove.py b/pyfpdb/Stove.py
index eb939c0f..2e2a6ef1 100755
--- a/pyfpdb/Stove.py
+++ b/pyfpdb/Stove.py
@@ -22,14 +22,57 @@ OFFSUIT = 2
ev = pokereval.PokerEval()
-holder = None
-class Holder:
+class Stove:
def __init__(self):
self.hand = None
self.board = 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:
def __init__(self, c1, c2):
@@ -177,50 +220,15 @@ def expand_hands(abbrev, hand, board):
return range
-
-
-
def parse_args(args, container):
# args[0] is the path being executed; need 3 more args
if len(args) < 4:
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
@@ -283,27 +291,13 @@ def odds_for_range(holder):
sev.add(e)
sev.show(holder.hand, holder.range.get())
-
-
-
-holder = Holder()
-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
-
-
+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__':
+ sys.exit(main())
diff --git a/pyfpdb/TestHandsPlayers.py b/pyfpdb/TestHandsPlayers.py
index ee3be1e9..e0013ecc 100755
--- a/pyfpdb/TestHandsPlayers.py
+++ b/pyfpdb/TestHandsPlayers.py
@@ -201,6 +201,7 @@ def main(argv=None):
walk_testfiles("regression-test-files/cash/iPoker/", compare, importer, iPokerErrors, "iPoker")
if sites['Winamax'] == True:
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:
walk_testfiles("regression-test-files/cash/Win2day/", compare, importer, Win2dayErrors, "Win2day")
diff --git a/pyfpdb/WinamaxToFpdb.py b/pyfpdb/WinamaxToFpdb.py
index c49f4e09..47721515 100644
--- a/pyfpdb/WinamaxToFpdb.py
+++ b/pyfpdb/WinamaxToFpdb.py
@@ -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
# Table: 'Charenton-le-Pont' 9-max (real money) Seat #5 is the button
re_HandInfo = re.compile(u"""
- \s*Winamax\sPoker\s-\sCashGame\s-\sHandId:\s\#(?P\d+)-(?P\d+)-(?P\d+).*\s
+ \s*Winamax\sPoker\s-\s
+ (?PCashGame)?
+ (?PTournament\s
+ (?P.+)?\s
+ buyIn:\s(?P(?P[%(LS)s\d\,]+)?\s\+?\s(?P[%(LS)s\d\,]+)?\+?(?P[%(LS)s\d\.]+)?\s?(?P%(LEGAL_ISO)s)?|Gratuit|Ticket\suniquement)?\s
+ (level:\s(?P\d+))?
+ .*)?
+ \s-\sHandId:\s\#(?P\d+)-(?P\d+)-(?P\d+).*\s
(?PHoldem|Omaha)\s
(?Pno\slimit|pot\slimit)\s
\(
+ (((%(LS)s)?(?P[.0-9]+)(%(LS)s)?)/)?
((%(LS)s)?(?P[.0-9]+)(%(LS)s)?)/
((%(LS)s)?(?P[.0-9]+)(%(LS)s)?)
\)\s-\s
(?P.*)
- Table:\s\'(?P[^']+)\'\s(?P\d+)\-max
+ Table:\s\'(?P[^(]+)
+ (.(?P\d+).\#(?P\d+))?.*
+ \'
+ \s(?P\d+)\-max
""" % substitutions, re.MULTILINE|re.DOTALL|re.VERBOSE)
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[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE)
self.re_PostBB = re.compile('%(PLYR)s posts big blind (%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE)
self.re_DenySB = re.compile('(?P.*) deny SB' % subst, re.MULTILINE)
- self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante (%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?" % subst, re.MULTILINE)
- self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for (%(CUR)s)?(?P[\.0-9]+(%(CUR)s)?)" % subst, re.MULTILINE)
+ self.re_Antes = re.compile(r"^%(PLYR)s posts ante (%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?" % subst, re.MULTILINE)
+ self.re_BringIn = re.compile(r"^%(PLYR)s brings[- ]in( low|) for (%(CUR)s)?(?P[\.0-9]+(%(CUR)s)?)" % subst, re.MULTILINE)
self.re_PostBoth = re.compile('(?P.*): posts small \& big blind \( (%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?\)' % subst)
self.re_PostDead = re.compile('(?P.*) posts dead blind \((%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?\)' % subst, re.MULTILINE)
self.re_HeroCards = re.compile('Dealt\sto\s%(PLYR)s\s\[(?P.*)\]' % subst)
@@ -144,6 +155,9 @@ class Winamax(HandHistoryConverter):
["ring", "hold", "fl"],
["ring", "hold", "nl"],
["ring", "hold", "pl"],
+ ["tour", "hold", "fl"],
+ ["tour", "hold", "nl"],
+ ["tour", "hold", "pl"],
]
def determineGameType(self, handText):
@@ -160,7 +174,11 @@ class Winamax(HandHistoryConverter):
mg = m.groupdict()
- info['type'] = 'ring'
+ if mg.get('TOUR'):
+ info['type'] = 'tour'
+ elif mg.get('RING'):
+ info['type'] = 'ring'
+
info['currency'] = 'EUR'
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 = HandHistoryConverter.changeTimezone(hand.startTime, "CET", "UTC")
if key == 'HID1':
- hand.handid = "1%.4d%s%s"%(int(info['HID2']),info['HID1'],info['HID3'])
# 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':
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
hand.buttonpos = 1
hand.maxseats = 10 # Set to None - Hand.py will guessMaxSeats()
diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw
index 91a0ebef..3660dd57 100755
--- a/pyfpdb/fpdb.pyw
+++ b/pyfpdb/fpdb.pyw
@@ -116,6 +116,7 @@ import GuiAutoImport
import GuiGraphViewer
import GuiTourneyGraphViewer
import GuiSessionViewer
+import GuiStove
import SQL
import Database
import Configuration
@@ -778,6 +779,7 @@ class fpdb:
+