You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
410 lines
18 KiB
410 lines
18 KiB
#!/usr/bin/env python |
|
# -*- coding: utf-8 -*- |
|
|
|
#Copyright 2008-2011 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() |
|
|
|
# Standard Library modules |
|
import os |
|
import sys |
|
from time import time |
|
from optparse import OptionParser |
|
import traceback |
|
|
|
# pyGTK modules |
|
import pygtk |
|
pygtk.require('2.0') |
|
import gtk |
|
import gobject |
|
|
|
# fpdb/FreePokerTools modules |
|
import fpdb_import |
|
import Configuration |
|
import Exceptions |
|
|
|
|
|
class GuiBulkImport(): |
|
|
|
# CONFIGURATION - update these as preferred: |
|
allowThreads = True # set to True to try out the threads field |
|
|
|
def dopulse(self): |
|
self.progressbar.pulse() |
|
return True |
|
|
|
def load_clicked(self, widget, data=None): |
|
stored = None |
|
dups = None |
|
partial = None |
|
errs = None |
|
ttime = None |
|
# Does the lock acquisition need to be more sophisticated for multiple dirs? |
|
# (see comment above about what to do if pipe already open) |
|
if self.settings['global_lock'].acquire(wait=False, source="GuiBulkImport"): # returns false immediately if lock not acquired |
|
#try: |
|
print _("\nGlobal lock taken ...") |
|
self.progressbar.set_text(_("Importing...")) |
|
self.progressbar.pulse() |
|
while gtk.events_pending(): # see http://faq.pygtk.org/index.py?req=index for more hints (3.7) |
|
gtk.main_iteration(False) |
|
self.timer = gobject.timeout_add(100, self.dopulse) |
|
|
|
# get the dir to import from the chooser |
|
selected = self.chooser.get_filenames() |
|
|
|
# get the import settings from the gui and save in the importer |
|
self.importer.setHandCount(int(self.spin_hands.get_text())) |
|
self.importer.setQuiet(self.chk_st_st.get_active()) |
|
self.importer.setThreads(int(self.spin_threads.get_text())) |
|
self.importer.setHandsInDB(self.n_hands_in_db) |
|
cb_model = self.cb_dropindexes.get_model() |
|
cb_index = self.cb_dropindexes.get_active() |
|
cb_hmodel = self.cb_drophudcache.get_model() |
|
cb_hindex = self.cb_drophudcache.get_active() |
|
|
|
#self.lab_info.set_markup('<span foreground="blue">Importing ...</span>') # uses pango markup! |
|
|
|
if cb_index: |
|
self.importer.setDropIndexes(cb_model[cb_index][0]) |
|
else: |
|
self.importer.setDropIndexes("auto") |
|
if cb_hindex: |
|
self.importer.setDropHudCache(cb_hmodel[cb_hindex][0]) |
|
else: |
|
self.importer.setDropHudCache("auto") |
|
sitename = self.cbfilter.get_model()[self.cbfilter.get_active()][0] |
|
#self.importer.setFailOnError(self.chk_fail.get_active()) |
|
if self.is_archive.get_active(): |
|
if sitename == "PokerStars": |
|
self.importer.setStarsArchive(True) |
|
if sitename == "Full Tilt Poker": |
|
self.importer.setFTPArchive(True) |
|
|
|
for selection in selected: |
|
self.importer.addBulkImportImportFileOrDir(selection, site = sitename) |
|
self.importer.setCallHud(self.cb_testmode.get_active()) |
|
self.importer.bHudTest = self.cb_testmode.get_active() |
|
starttime = time() |
|
# try: |
|
(stored, dups, partial, errs, ttime) = self.importer.runImport() |
|
# except: |
|
# print "*** EXCEPTION DURING BULKIMPORT!!!" |
|
# raise Exceptions.FpdbError |
|
# finally: |
|
gobject.source_remove(self.timer) |
|
|
|
ttime = time() - starttime |
|
if ttime == 0: |
|
ttime = 1 |
|
print _('GuiBulkImport.load done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec')\ |
|
% (stored, dups, partial, errs, ttime, (stored+0.0) / ttime) |
|
self.importer.clearFileList() |
|
# This file should really be 'logging' |
|
#log.info('GuiBulkImport.load done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec'\ |
|
# % (stored, dups, partial, errs, ttime, (stored+0.0) / ttime)) |
|
if self.n_hands_in_db == 0 and stored > 0: |
|
self.cb_dropindexes.set_sensitive(True) |
|
self.cb_dropindexes.set_active(0) |
|
self.lab_drop.set_sensitive(True) |
|
self.cb_drophudcache.set_sensitive(True) |
|
self.cb_drophudcache.set_active(0) |
|
self.lab_hdrop.set_sensitive(True) |
|
|
|
self.progressbar.set_text(_("Import Complete")) |
|
self.progressbar.set_fraction(0) |
|
#except: |
|
#err = traceback.extract_tb(sys.exc_info()[2])[-1] |
|
#print "*** BulkImport Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) |
|
#self.settings['global_lock'].release() |
|
self.settings['global_lock'].release() |
|
else: |
|
print _("bulk import aborted - global lock not available") |
|
|
|
def get_vbox(self): |
|
"""returns the vbox of this thread""" |
|
return self.vbox |
|
|
|
def __init__(self, settings, config, sql = None, parent = None): |
|
self.settings = settings |
|
self.config = config |
|
self.parent = parent |
|
|
|
self.importer = fpdb_import.Importer(self, self.settings, config, sql, parent) |
|
|
|
self.vbox = gtk.VBox(False, 0) |
|
self.vbox.show() |
|
|
|
self.chooser = gtk.FileChooserWidget() |
|
self.chooser.set_filename(self.settings['bulkImport-defaultPath']) |
|
self.chooser.set_select_multiple(True) |
|
self.vbox.add(self.chooser) |
|
self.chooser.show() |
|
|
|
# Table widget to hold the settings |
|
self.table = gtk.Table(rows=5, columns=5, homogeneous=False) |
|
self.vbox.add(self.table) |
|
self.table.show() |
|
|
|
# checkbox - print start/stop? |
|
self.chk_st_st = gtk.CheckButton(_('Print Start/Stop Info')) |
|
self.table.attach(self.chk_st_st, 0, 1, 0, 1, xpadding=10, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.chk_st_st.show() |
|
self.chk_st_st.set_active(True) |
|
|
|
# label - status |
|
self.lab_status = gtk.Label(_("Hands/status print:")) |
|
self.table.attach(self.lab_status, 1, 2, 0, 1, xpadding=0, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.lab_status.show() |
|
self.lab_status.set_justify(gtk.JUSTIFY_RIGHT) |
|
self.lab_status.set_alignment(1.0, 0.5) |
|
|
|
# spin button - status |
|
status_adj = gtk.Adjustment(value=100, lower=0, upper=300, step_incr=10, |
|
page_incr=1, page_size=0) #not sure what upper value should be! |
|
self.spin_status = gtk.SpinButton(adjustment=status_adj, climb_rate=0.0, |
|
digits=0) |
|
self.table.attach(self.spin_status, 2, 3, 0, 1, xpadding=10, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.spin_status.show() |
|
|
|
# label - threads |
|
self.lab_threads = gtk.Label(_("Number of threads:")) |
|
self.table.attach(self.lab_threads, 3, 4, 0, 1, xpadding=0, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.lab_threads.show() |
|
if not self.allowThreads: |
|
self.lab_threads.set_sensitive(False) |
|
self.lab_threads.set_justify(gtk.JUSTIFY_RIGHT) |
|
self.lab_threads.set_alignment(1.0, 0.5) |
|
|
|
# spin button - threads |
|
threads_adj = gtk.Adjustment(value=0, lower=0, upper=32, step_incr=1, |
|
page_incr=1, page_size=0) #not sure what upper value should be! |
|
self.spin_threads = gtk.SpinButton(adjustment=threads_adj, climb_rate=0.0, digits=0) |
|
self.table.attach(self.spin_threads, 4, 5, 0, 1, xpadding=10, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.spin_threads.show() |
|
if not self.allowThreads: |
|
self.spin_threads.set_sensitive(False) |
|
|
|
# checkbox - archive file? |
|
self.is_archive = gtk.CheckButton(_('Archive File')) |
|
self.table.attach(self.is_archive, 0, 1, 1, 2, xpadding=10, ypadding=0, yoptions=gtk.SHRINK) |
|
self.is_archive.show() |
|
|
|
# label - hands |
|
self.lab_hands = gtk.Label(_("Hands/file:")) |
|
self.table.attach(self.lab_hands, 1, 2, 1, 2, xpadding=0, ypadding=0, yoptions=gtk.SHRINK) |
|
self.lab_hands.show() |
|
self.lab_hands.set_justify(gtk.JUSTIFY_RIGHT) |
|
self.lab_hands.set_alignment(1.0, 0.5) |
|
|
|
# spin button - hands to import |
|
hands_adj = gtk.Adjustment(value=0, lower=0, upper=10, step_incr=1, |
|
page_incr=1, page_size=0) #not sure what upper value should be! |
|
self.spin_hands = gtk.SpinButton(adjustment=hands_adj, climb_rate=0.0, digits=0) |
|
self.table.attach(self.spin_hands, 2, 3, 1, 2, xpadding=10, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.spin_hands.show() |
|
|
|
# label - drop indexes |
|
self.lab_drop = gtk.Label(_("Drop indexes:")) |
|
self.table.attach(self.lab_drop, 3, 4, 1, 2, xpadding=0, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.lab_drop.show() |
|
self.lab_drop.set_justify(gtk.JUSTIFY_RIGHT) |
|
self.lab_drop.set_alignment(1.0, 0.5) |
|
|
|
# ComboBox - drop indexes |
|
self.cb_dropindexes = gtk.combo_box_new_text() |
|
self.cb_dropindexes.append_text(_('auto')) |
|
self.cb_dropindexes.append_text(_("don't drop")) |
|
self.cb_dropindexes.append_text(_('drop')) |
|
self.cb_dropindexes.set_active(0) |
|
self.table.attach(self.cb_dropindexes, 4, 5, 1, 2, xpadding=10, |
|
ypadding=0, yoptions=gtk.SHRINK) |
|
self.cb_dropindexes.show() |
|
|
|
self.cb_testmode = gtk.CheckButton(_('HUD Test mode')) |
|
self.table.attach(self.cb_testmode, 0, 1, 2, 3, xpadding=10, ypadding=0, yoptions=gtk.SHRINK) |
|
self.cb_testmode.show() |
|
|
|
# label - filter |
|
self.lab_filter = gtk.Label(_("Site filter:")) |
|
self.table.attach(self.lab_filter, 1, 2, 2, 3, xpadding=0, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.lab_filter.show() |
|
self.lab_filter.set_justify(gtk.JUSTIFY_RIGHT) |
|
self.lab_filter.set_alignment(1.0, 0.5) |
|
|
|
# ComboBox - filter |
|
self.cbfilter = gtk.combo_box_new_text() |
|
disabled_sites = [] # move disabled sites to bottom of list |
|
for w in self.config.hhcs: |
|
try: |
|
if self.config.supported_sites[w].enabled: # include enabled ones first |
|
print w |
|
self.cbfilter.append_text(w) |
|
else: |
|
disabled_sites.append(w) |
|
except: # self.supported_sites[w] may not exist if hud_config is bad |
|
disabled_sites.append(w) |
|
for w in disabled_sites: # then disabled ones |
|
print w |
|
self.cbfilter.append_text(w) |
|
self.cbfilter.set_active(0) |
|
self.table.attach(self.cbfilter, 2, 3, 2, 3, xpadding=10, ypadding=1, |
|
yoptions=gtk.SHRINK) |
|
self.cbfilter.show() |
|
|
|
# label - drop hudcache |
|
self.lab_hdrop = gtk.Label(_("Drop HudCache:")) |
|
self.table.attach(self.lab_hdrop, 3, 4, 2, 3, xpadding=0, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.lab_hdrop.show() |
|
self.lab_hdrop.set_justify(gtk.JUSTIFY_RIGHT) |
|
self.lab_hdrop.set_alignment(1.0, 0.5) |
|
|
|
# ComboBox - drop hudcache |
|
self.cb_drophudcache = gtk.combo_box_new_text() |
|
self.cb_drophudcache.append_text(_('auto')) |
|
self.cb_drophudcache.append_text(_("don't drop")) |
|
self.cb_drophudcache.append_text(_('drop')) |
|
self.cb_drophudcache.set_active(0) |
|
self.table.attach(self.cb_drophudcache, 4, 5, 2, 3, xpadding=10, |
|
ypadding=0, yoptions=gtk.SHRINK) |
|
self.cb_drophudcache.show() |
|
|
|
# button - Import |
|
self.load_button = gtk.Button(_('_Bulk Import')) # todo: rename variables to import too |
|
self.load_button.connect('clicked', self.load_clicked, |
|
_('Import clicked')) |
|
self.table.attach(self.load_button, 2, 3, 4, 5, xpadding=0, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.load_button.show() |
|
|
|
# label - spacer (keeps rows 3 & 5 apart) |
|
self.lab_spacer = gtk.Label() |
|
self.table.attach(self.lab_spacer, 3, 5, 3, 4, xpadding=0, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.lab_spacer.show() |
|
|
|
# label - info |
|
# self.lab_info = gtk.Label() |
|
# self.table.attach(self.lab_info, 3, 5, 4, 5, xpadding = 0, ypadding = 0, yoptions=gtk.SHRINK) |
|
# self.lab_info.show() |
|
self.progressbar = gtk.ProgressBar() |
|
self.table.attach(self.progressbar, 3, 5, 4, 5, xpadding=0, ypadding=0, |
|
yoptions=gtk.SHRINK) |
|
self.progressbar.set_text(_("Waiting...")) |
|
self.progressbar.set_fraction(0) |
|
self.progressbar.show() |
|
|
|
# see how many hands are in the db and adjust accordingly |
|
tcursor = self.importer.database.cursor |
|
tcursor.execute("Select count(1) from Hands") |
|
row = tcursor.fetchone() |
|
tcursor.close() |
|
self.importer.database.rollback() |
|
self.n_hands_in_db = row[0] |
|
if self.n_hands_in_db == 0: |
|
self.cb_dropindexes.set_active(2) |
|
self.cb_dropindexes.set_sensitive(False) |
|
self.lab_drop.set_sensitive(False) |
|
self.cb_drophudcache.set_active(2) |
|
self.cb_drophudcache.set_sensitive(False) |
|
self.lab_hdrop.set_sensitive(False) |
|
|
|
def main(argv=None): |
|
"""main can also be called in the python interpreter, by supplying the command line as the argument.""" |
|
if argv is None: |
|
argv = sys.argv[1:] |
|
|
|
def destroy(*args): # call back for terminating the main eventloop |
|
gtk.main_quit() |
|
|
|
parser = OptionParser() |
|
parser.add_option("-f", "--file", dest="filename", metavar="FILE", default=None, |
|
help=_("Input file")) |
|
parser.add_option("-c", "--convert", dest="filtername", default=None, metavar="FILTER", |
|
help=_("Conversion filter (*Full Tilt Poker, PokerStars, Everleaf, Absolute)")) |
|
parser.add_option("-x", "--failOnError", action="store_true", default=False, |
|
help=_("If this option is passed it quits when it encounters any error")) |
|
parser.add_option("-u", "--usage", action="store_true", dest="usage", default=False, |
|
help=_("Print some useful one liners")) |
|
parser.add_option("-s", "--starsarchive", action="store_true", dest="starsArchive", default=False, |
|
help=_("Do the required conversion for Stars Archive format (ie. as provided by support")) |
|
parser.add_option("-F", "--ftparchive", action="store_true", dest="ftpArchive", default=False, |
|
help=_("Do the required conversion for FTP Archive format (ie. as provided by support")) |
|
parser.add_option("-t", "--testdata", action="store_true", dest="testData", default=False, |
|
help=_("Output the pprinted version of the HandsPlayer hash for regresion testing")) |
|
(options, argv) = parser.parse_args(args = argv) |
|
|
|
if options.usage == True: |
|
#Print usage examples and exit |
|
print _("USAGE:") |
|
print _('PokerStars converter: ./GuiBulkImport.py -c PokerStars -f filename') |
|
print _('Full Tilt converter: ./GuiBulkImport.py -c "Full Tilt Poker" -f filename') |
|
print _("Everleaf converter: ./GuiBulkImport.py -c Everleaf -f filename") |
|
print _("Absolute converter: ./GuiBulkImport.py -c Absolute -f filename") |
|
print _("PartyPoker converter: ./GuiBulkImport.py -c PartyPoker -f filename") |
|
sys.exit(0) |
|
|
|
config = Configuration.Config() |
|
|
|
settings = {} |
|
if os.name == 'nt': settings['os'] = 'windows' |
|
else: settings['os'] = 'linuxmac' |
|
|
|
settings.update(config.get_db_parameters()) |
|
settings.update(config.get_import_parameters()) |
|
settings.update(config.get_default_paths()) |
|
|
|
if not options.filename: |
|
i = GuiBulkImport(settings, config, None) |
|
main_window = gtk.Window() |
|
main_window.connect('destroy', destroy) |
|
main_window.add(i.vbox) |
|
main_window.show() |
|
gtk.main() |
|
else: |
|
if not options.filtername: |
|
print _("You have to select a site with the -c parameter. E.g.:"), "Everleaf converter: ./GuiBulkImport.py -c Everleaf -f filename" |
|
#Do something useful |
|
importer = fpdb_import.Importer(False,settings, config, None) |
|
# importer.setDropIndexes("auto") |
|
importer.setDropIndexes(_("don't drop")) |
|
importer.setFailOnError(options.failOnError) |
|
importer.setThreads(-1) |
|
importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername) |
|
importer.setCallHud(False) |
|
if options.starsArchive: |
|
importer.setStarsArchive(True) |
|
if options.ftpArchive: |
|
importer.setFTPArchive(True) |
|
if options.testData: |
|
importer.setPrintTestData(True) |
|
(stored, dups, partial, errs, ttime) = importer.runImport() |
|
importer.clearFileList() |
|
print _('GuiBulkImport done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec')\ |
|
% (stored, dups, partial, errs, ttime, (stored+0.0) / ttime) |
|
|
|
|
|
if __name__ == '__main__': |
|
sys.exit(main())
|
|
|