2 # -*- coding: utf-8 -*-
4 #Copyright 2008-2011 Steffen Schaumburg
5 #This program is free software: you can redistribute it and/or modify
6 #it under the terms of the GNU Affero General Public License as published by
7 #the Free Software Foundation, version 3 of the License.
9 #This program is distributed in the hope that it will be useful,
10 #but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 #GNU General Public License for more details.
14 #You should have received a copy of the GNU Affero General Public License
15 #along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #In the "official" distribution you can find the license in agpl-3.0.txt.
19 _
= L10n
.get_translation()
21 # Standard Library modules
25 from optparse
import OptionParser
34 # fpdb/FreePokerTools modules
40 # logging has been set up in fpdb.py or HUD_main.py, use their settings:
41 log
= logging
.getLogger("importer")
43 class GuiBulkImport():
45 # CONFIGURATION - update these as preferred:
46 allowThreads
= False # set to True to try out the threads field
49 self
.progressbar
.pulse()
52 def load_clicked(self
, widget
, data
=None):
53 if self
.cbfilter
.get_model()[self
.cbfilter
.get_active()][0] == (_("Please select site")):
54 self
.progressbar
.set_text(_("Please select site"))
61 # Does the lock acquisition need to be more sophisticated for multiple dirs?
62 # (see comment above about what to do if pipe already open)
63 if self
.settings
['global_lock'].acquire(wait
=False, source
="GuiBulkImport"): # returns false immediately if lock not acquired
65 print _("\nGlobal lock taken ...")
66 self
.progressbar
.set_text(_("Importing..."))
67 self
.progressbar
.pulse()
68 while gtk
.events_pending(): # see http://faq.pygtk.org/index.py?req=index for more hints (3.7)
69 gtk
.main_iteration(False)
70 self
.timer
= gobject
.timeout_add(100, self
.dopulse
)
72 # get the dir to import from the chooser
73 selected
= self
.chooser
.get_filenames()
75 # get the import settings from the gui and save in the importer
76 self
.importer
.setHandCount(int(self
.spin_hands
.get_text()))
77 self
.importer
.setQuiet(self
.chk_st_st
.get_active())
78 self
.importer
.setThreads(int(self
.spin_threads
.get_text()))
79 self
.importer
.setHandsInDB(self
.n_hands_in_db
)
80 cb_model
= self
.cb_dropindexes
.get_model()
81 cb_index
= self
.cb_dropindexes
.get_active()
82 cb_hmodel
= self
.cb_drophudcache
.get_model()
83 cb_hindex
= self
.cb_drophudcache
.get_active()
85 #self.lab_info.set_markup('<span foreground="blue">Importing ...</span>') # uses pango markup!
88 self
.importer
.setDropIndexes(cb_model
[cb_index
][0])
90 self
.importer
.setDropIndexes("auto")
92 self
.importer
.setDropHudCache(cb_hmodel
[cb_hindex
][0])
94 self
.importer
.setDropHudCache("auto")
95 sitename
= self
.cbfilter
.get_model()[self
.cbfilter
.get_active()][0]
96 #self.importer.setFailOnError(self.chk_fail.get_active())
97 if self
.is_archive
.get_active():
98 if sitename
== "PokerStars":
99 self
.importer
.setStarsArchive(True)
100 if sitename
== "Full Tilt Poker":
101 self
.importer
.setFTPArchive(True)
103 for selection
in selected
:
104 self
.importer
.addBulkImportImportFileOrDir(selection
, site
= sitename
)
105 self
.importer
.setCallHud(self
.cb_testmode
.get_active())
106 self
.importer
.bHudTest
= self
.cb_testmode
.get_active()
109 (stored
, dups
, partial
, errs
, ttime
) = self
.importer
.runImport()
111 # print "*** EXCEPTION DURING BULKIMPORT!!!"
112 # raise Exceptions.FpdbError
114 gobject
.source_remove(self
.timer
)
116 ttime
= time() - starttime
120 completionMessage
= _('Bulk import done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec')\
121 % (stored
, dups
, partial
, errs
, ttime
, (stored
+0.0) / ttime
)
122 print completionMessage
123 log
.info(completionMessage
)
125 self
.importer
.clearFileList()
127 if self
.n_hands_in_db
== 0 and stored
> 0:
128 self
.cb_dropindexes
.set_sensitive(True)
129 self
.cb_dropindexes
.set_active(0)
130 self
.lab_drop
.set_sensitive(True)
131 self
.cb_drophudcache
.set_sensitive(True)
132 self
.cb_drophudcache
.set_active(0)
133 self
.lab_hdrop
.set_sensitive(True)
135 self
.progressbar
.set_text(_("Import Complete"))
136 self
.progressbar
.set_fraction(0)
138 #err = traceback.extract_tb(sys.exc_info()[2])[-1]
139 #print "*** BulkImport Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
140 #self.settings['global_lock'].release()
141 self
.settings
['global_lock'].release()
143 print _("bulk import aborted - global lock not available")
146 """returns the vbox of this thread"""
149 def __init__(self
, settings
, config
, sql
= None, parent
= None):
150 self
.settings
= settings
154 self
.importer
= fpdb_import
.Importer(self
, self
.settings
, config
, sql
, parent
)
156 self
.vbox
= gtk
.VBox(False, 0)
159 self
.chooser
= gtk
.FileChooserWidget()
160 self
.chooser
.set_filename(self
.settings
['bulkImport-defaultPath'])
161 self
.chooser
.set_select_multiple(True)
162 self
.vbox
.add(self
.chooser
)
165 # Table widget to hold the settings
166 self
.table
= gtk
.Table(rows
=5, columns
=5, homogeneous
=False)
167 self
.vbox
.add(self
.table
)
170 # checkbox - print start/stop?
171 self
.chk_st_st
= gtk
.CheckButton(_('Print Start/Stop Info'))
172 self
.table
.attach(self
.chk_st_st
, 0, 1, 0, 1, xpadding
=10, ypadding
=0,
174 self
.chk_st_st
.show()
175 self
.chk_st_st
.set_active(True)
178 self
.lab_status
= gtk
.Label(_("Hands/status print:"))
179 self
.table
.attach(self
.lab_status
, 1, 2, 0, 1, xpadding
=0, ypadding
=0,
181 self
.lab_status
.show()
182 self
.lab_status
.set_justify(gtk
.JUSTIFY_RIGHT
)
183 self
.lab_status
.set_alignment(1.0, 0.5)
185 # spin button - status
186 status_adj
= gtk
.Adjustment(value
=100, lower
=0, upper
=300, step_incr
=10,
187 page_incr
=1, page_size
=0) #not sure what upper value should be!
188 self
.spin_status
= gtk
.SpinButton(adjustment
=status_adj
, climb_rate
=0.0,
190 self
.table
.attach(self
.spin_status
, 2, 3, 0, 1, xpadding
=10, ypadding
=0,
192 self
.spin_status
.show()
195 self
.lab_threads
= gtk
.Label(_("Number of threads:"))
196 self
.table
.attach(self
.lab_threads
, 3, 4, 0, 1, xpadding
=0, ypadding
=0,
198 self
.lab_threads
.show()
199 if not self
.allowThreads
:
200 self
.lab_threads
.set_sensitive(False)
201 self
.lab_threads
.set_justify(gtk
.JUSTIFY_RIGHT
)
202 self
.lab_threads
.set_alignment(1.0, 0.5)
204 # spin button - threads
205 threads_adj
= gtk
.Adjustment(value
=0, lower
=0, upper
=32, step_incr
=1,
206 page_incr
=1, page_size
=0) #not sure what upper value should be!
207 self
.spin_threads
= gtk
.SpinButton(adjustment
=threads_adj
, climb_rate
=0.0, digits
=0)
208 self
.table
.attach(self
.spin_threads
, 4, 5, 0, 1, xpadding
=10, ypadding
=0,
210 self
.spin_threads
.show()
211 if not self
.allowThreads
:
212 self
.spin_threads
.set_sensitive(False)
214 # checkbox - archive file?
215 self
.is_archive
= gtk
.CheckButton(_('Archive File'))
216 self
.table
.attach(self
.is_archive
, 0, 1, 1, 2, xpadding
=10, ypadding
=0, yoptions
=gtk
.SHRINK
)
217 self
.is_archive
.show()
220 self
.lab_hands
= gtk
.Label(_("Hands/file:"))
221 self
.table
.attach(self
.lab_hands
, 1, 2, 1, 2, xpadding
=0, ypadding
=0, yoptions
=gtk
.SHRINK
)
222 self
.lab_hands
.show()
223 self
.lab_hands
.set_justify(gtk
.JUSTIFY_RIGHT
)
224 self
.lab_hands
.set_alignment(1.0, 0.5)
226 # spin button - hands to import
227 hands_adj
= gtk
.Adjustment(value
=0, lower
=0, upper
=10, step_incr
=1,
228 page_incr
=1, page_size
=0) #not sure what upper value should be!
229 self
.spin_hands
= gtk
.SpinButton(adjustment
=hands_adj
, climb_rate
=0.0, digits
=0)
230 self
.table
.attach(self
.spin_hands
, 2, 3, 1, 2, xpadding
=10, ypadding
=0,
232 self
.spin_hands
.show()
234 # label - drop indexes
235 self
.lab_drop
= gtk
.Label(_("Drop indexes:"))
236 self
.table
.attach(self
.lab_drop
, 3, 4, 1, 2, xpadding
=0, ypadding
=0,
239 self
.lab_drop
.set_justify(gtk
.JUSTIFY_RIGHT
)
240 self
.lab_drop
.set_alignment(1.0, 0.5)
242 # ComboBox - drop indexes
243 self
.cb_dropindexes
= gtk
.combo_box_new_text()
244 self
.cb_dropindexes
.append_text(_('auto'))
245 self
.cb_dropindexes
.append_text(_("don't drop"))
246 self
.cb_dropindexes
.append_text(_('drop'))
247 self
.cb_dropindexes
.set_active(0)
248 self
.table
.attach(self
.cb_dropindexes
, 4, 5, 1, 2, xpadding
=10,
249 ypadding
=0, yoptions
=gtk
.SHRINK
)
250 self
.cb_dropindexes
.show()
252 self
.cb_testmode
= gtk
.CheckButton(_('HUD Test mode'))
253 self
.table
.attach(self
.cb_testmode
, 0, 1, 2, 3, xpadding
=10, ypadding
=0, yoptions
=gtk
.SHRINK
)
254 self
.cb_testmode
.show()
257 self
.lab_filter
= gtk
.Label(_("Site filter:"))
258 self
.table
.attach(self
.lab_filter
, 1, 2, 2, 3, xpadding
=0, ypadding
=0,
260 self
.lab_filter
.show()
261 self
.lab_filter
.set_justify(gtk
.JUSTIFY_RIGHT
)
262 self
.lab_filter
.set_alignment(1.0, 0.5)
265 self
.cbfilter
= gtk
.combo_box_new_text()
266 disabled_sites
= [] # move disabled sites to bottom of list
267 self
.cbfilter
.append_text(_("Please select site"))
268 for w
in self
.config
.hhcs
:
270 if self
.config
.supported_sites
[w
].enabled
: # include enabled ones first
272 self
.cbfilter
.append_text(w
)
274 disabled_sites
.append(w
)
275 except: # self.supported_sites[w] may not exist if hud_config is bad
276 disabled_sites
.append(w
)
277 for w
in disabled_sites
: # then disabled ones
279 self
.cbfilter
.append_text(w
)
280 self
.cbfilter
.set_active(0)
281 self
.table
.attach(self
.cbfilter
, 2, 3, 2, 3, xpadding
=10, ypadding
=1,
285 # label - drop hudcache
286 self
.lab_hdrop
= gtk
.Label(_("Drop HudCache:"))
287 self
.table
.attach(self
.lab_hdrop
, 3, 4, 2, 3, xpadding
=0, ypadding
=0,
289 self
.lab_hdrop
.show()
290 self
.lab_hdrop
.set_justify(gtk
.JUSTIFY_RIGHT
)
291 self
.lab_hdrop
.set_alignment(1.0, 0.5)
293 # ComboBox - drop hudcache
294 self
.cb_drophudcache
= gtk
.combo_box_new_text()
295 self
.cb_drophudcache
.append_text(_('auto'))
296 self
.cb_drophudcache
.append_text(_("don't drop"))
297 self
.cb_drophudcache
.append_text(_('drop'))
298 self
.cb_drophudcache
.set_active(0)
299 self
.table
.attach(self
.cb_drophudcache
, 4, 5, 2, 3, xpadding
=10,
300 ypadding
=0, yoptions
=gtk
.SHRINK
)
301 self
.cb_drophudcache
.show()
304 self
.load_button
= gtk
.Button(_('_Bulk Import')) # todo: rename variables to import too
305 self
.load_button
.connect('clicked', self
.load_clicked
,
307 self
.table
.attach(self
.load_button
, 2, 3, 4, 5, xpadding
=0, ypadding
=0,
309 self
.load_button
.show()
311 # label - spacer (keeps rows 3 & 5 apart)
312 self
.lab_spacer
= gtk
.Label()
313 self
.table
.attach(self
.lab_spacer
, 3, 5, 3, 4, xpadding
=0, ypadding
=0,
315 self
.lab_spacer
.show()
318 # self.lab_info = gtk.Label()
319 # self.table.attach(self.lab_info, 3, 5, 4, 5, xpadding = 0, ypadding = 0, yoptions=gtk.SHRINK)
320 # self.lab_info.show()
321 self
.progressbar
= gtk
.ProgressBar()
322 self
.table
.attach(self
.progressbar
, 3, 5, 4, 5, xpadding
=0, ypadding
=0,
324 self
.progressbar
.set_text(_("Waiting..."))
325 self
.progressbar
.set_fraction(0)
326 self
.progressbar
.show()
328 # see how many hands are in the db and adjust accordingly
329 tcursor
= self
.importer
.database
.cursor
330 tcursor
.execute("Select count(1) from Hands")
331 row
= tcursor
.fetchone()
333 self
.importer
.database
.rollback()
334 self
.n_hands_in_db
= row
[0]
335 if self
.n_hands_in_db
== 0:
336 self
.cb_dropindexes
.set_active(2)
337 self
.cb_dropindexes
.set_sensitive(False)
338 self
.lab_drop
.set_sensitive(False)
339 self
.cb_drophudcache
.set_active(2)
340 self
.cb_drophudcache
.set_sensitive(False)
341 self
.lab_hdrop
.set_sensitive(False)
344 """main can also be called in the python interpreter, by supplying the command line as the argument."""
348 def destroy(*args
): # call back for terminating the main eventloop
351 parser
= OptionParser()
352 parser
.add_option("-f", "--file", dest
="filename", metavar
="FILE", default
=None,
353 help=_("Input file"))
354 parser
.add_option("-c", "--convert", dest
="filtername", default
=None, metavar
="FILTER",
355 help=_("Site")+ " (Absolute, Carbon, Everleaf, Full Tilt Poker, PokerStars, ...)") #TODO: dynamically generate list
356 parser
.add_option("-x", "--failOnError", action
="store_true", default
=False,
357 help=_("If this option is used it quits with an extended error message if it encounters any error"))
358 parser
.add_option("-u", "--usage", action
="store_true", dest
="usage", default
=False,
359 help=_("Print some useful one liners"))
360 parser
.add_option("-s", "--starsarchive", action
="store_true", dest
="starsArchive", default
=False,
361 help=_("Do the required conversion for %s archive format (ie. as provided by support)") % "PokerStars")
362 parser
.add_option("-F", "--ftparchive", action
="store_true", dest
="ftpArchive", default
=False,
363 help=_("Do the required conversion for %s archive format (ie. as provided by support)") % "Full Tilt Poker")
364 parser
.add_option("-t", "--testdata", action
="store_true", dest
="testData", default
=False,
365 help=_("Generate and print test data for regression testing"))
366 (options
, argv
) = parser
.parse_args(args
= argv
)
368 if options
.usage
== True:
369 #Print usage examples and exit
371 print ('PokerStars ' + _('converter') + ': ./GuiBulkImport.py -c PokerStars -f filename')
372 print ('Full Tilt ' + _('converter') + ': ./GuiBulkImport.py -c "Full Tilt Poker" -f filename')
373 print ('Everleaf ' + _('converter') + ': ./GuiBulkImport.py -c Everleaf -f filename')
374 print ('Absolute ' + _('converter') + ': ./GuiBulkImport.py -c Absolute -f filename')
375 print ('PartyPoker ' + _('converter') + ': ./GuiBulkImport.py -c PartyPoker -f filename')
378 config
= Configuration
.Config()
381 if os
.name
== 'nt': settings
['os'] = 'windows'
382 else: settings
['os'] = 'linuxmac'
384 settings
.update(config
.get_db_parameters())
385 settings
.update(config
.get_import_parameters())
386 settings
.update(config
.get_default_paths())
388 if not options
.filename
:
389 i
= GuiBulkImport(settings
, config
, None)
390 main_window
= gtk
.Window()
391 main_window
.connect('destroy', destroy
)
392 main_window
.add(i
.vbox
)
396 if not options
.filtername
:
397 print _("You have to select a site with the -c parameter. E.g.:"), "Everleaf converter: ./GuiBulkImport.py -c Everleaf -f filename"
399 importer
= fpdb_import
.Importer(False,settings
, config
, None)
400 # importer.setDropIndexes("auto")
401 importer
.setDropIndexes(_("don't drop"))
402 importer
.setFailOnError(options
.failOnError
)
403 importer
.setThreads(-1)
404 importer
.addBulkImportImportFileOrDir(os
.path
.expanduser(options
.filename
), site
=options
.filtername
)
405 importer
.setCallHud(False)
406 if options
.starsArchive
:
407 importer
.setStarsArchive(True)
408 if options
.ftpArchive
:
409 importer
.setFTPArchive(True)
411 importer
.setPrintTestData(True)
412 (stored
, dups
, partial
, errs
, ttime
) = importer
.runImport()
413 importer
.clearFileList()
414 print _('Bulk import done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d in %s seconds - %.0f/sec')\
415 % (stored
, dups
, partial
, errs
, ttime
, (stored
+0.0) / ttime
)
418 if __name__
== '__main__':