sqlcoder initial updates
This commit is contained in:
		
							parent
							
								
									5884f2f66b
								
							
						
					
					
						commit
						a824814c0a
					
				
							
								
								
									
										0
									
								
								pyfpdb/CliFpdb.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								pyfpdb/CliFpdb.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										1219
									
								
								pyfpdb/Configuration.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										1219
									
								
								pyfpdb/Configuration.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -601,7 +601,34 @@ class FpdbSQLQueries: | |||
| 					WHERE Players.name = %s AND Players.siteId = %s AND (tourneysPlayersId IS NULL) | ||||
| 					ORDER BY handStart""" | ||||
| 
 | ||||
| 		# Returns the profit for a given ring game handId, Total pot - money invested by playerId | ||||
| 		# Returns the profit for all hands, Total pot - money invested by playerId | ||||
| 		if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): | ||||
| 			self.query['getRingProfitAllHandsPlayerIdSite'] = """  | ||||
|                                         SELECT hp.handId, hp.winnings, SUM(ha.amount) costs, hp.winnings - SUM(ha.amount) profit | ||||
|                                         FROM HandsPlayers hp | ||||
|                                         INNER JOIN Players pl      ON hp.playerId     = pl.id | ||||
|                                         INNER JOIN Hands h         ON h.id            = hp.handId | ||||
|                                         INNER JOIN HandsActions ha ON ha.handPlayerId = hp.id | ||||
|                                         WHERE pl.name   = %s | ||||
|                                         AND   pl.siteId = %s | ||||
|                                         AND   hp.tourneysPlayersId IS NULL | ||||
|                                         group by hp.handId, hp.winnings, h.handStart | ||||
|                                         ORDER BY h.handStart""" | ||||
| 		elif(self.dbname == 'SQLite'): | ||||
| 			#May not work. | ||||
| 			self.query['getRingProfitAllHandsPlayerIdSite'] = """  | ||||
|                                         SELECT hp.handId, hp.winnings, SUM(ha.amount) costs, hp.winnings - SUM(ha.amount) profit | ||||
|                                         FROM HandsPlayers hp | ||||
|                                         INNER JOIN Players pl      ON hp.playerId     = pl.id | ||||
|                                         INNER JOIN Hands h         ON h.id            = hp.handId | ||||
|                                         INNER JOIN HandsActions ha ON ha.handPlayerId = hp.id | ||||
|                                         WHERE pl.name   = %s | ||||
|                                         AND   pl.siteId = %s | ||||
|                                         AND   hp.tourneysPlayersId IS NULL | ||||
|                                         group by hp.handId, hp.winnings, h.handStart | ||||
|                                         ORDER BY h.handStart""" | ||||
| 
 | ||||
| 		# Returns the profit for a given ring game handId, Total pot - money invested by playerId - WRONG, returns players costs | ||||
| 		if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL'): | ||||
| 			self.query['getRingProfitFromHandId'] = """SELECT SUM(amount) FROM HandsActions | ||||
| 					INNER JOIN HandsPlayers ON HandsActions.handPlayerId = HandsPlayers.id | ||||
|  |  | |||
|  | @ -1,216 +1,211 @@ | |||
| #!/usr/bin/python | ||||
| 
 | ||||
| #Copyright 2008 Steffen Jobbagy-Felso | ||||
| #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 in the docs folder of the package. | ||||
| 
 | ||||
| import threading | ||||
| import subprocess | ||||
| 
 | ||||
| import pygtk | ||||
| pygtk.require('2.0') | ||||
| import gtk | ||||
| import gobject | ||||
| import os | ||||
| import time | ||||
| import fpdb_import | ||||
| 
 | ||||
| class GuiAutoImport (threading.Thread): | ||||
| 	def starsBrowseClicked(self, widget, data): | ||||
| 		"""runs when user clicks browse on auto import tab""" | ||||
| 		#print "start of GuiAutoImport.starsBrowseClicked" | ||||
| 		current_path=self.starsDirPath.get_text() | ||||
| 		 | ||||
| 		dia_chooser = gtk.FileChooserDialog(title="Please choose the path that you want to auto import", | ||||
| 				action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, | ||||
| 				buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) | ||||
| 		#dia_chooser.set_current_folder(pathname) | ||||
| 		dia_chooser.set_filename(current_path) | ||||
| 		#dia_chooser.set_select_multiple(select_multiple) #not in tv, but want this in bulk import | ||||
| 
 | ||||
| 		response = dia_chooser.run() | ||||
| 		if response == gtk.RESPONSE_OK: | ||||
| 			#print dia_chooser.get_filename(), 'selected' | ||||
| 			self.starsDirPath.set_text(dia_chooser.get_filename()) | ||||
| 		elif response == gtk.RESPONSE_CANCEL: | ||||
| 			print 'Closed, no files selected' | ||||
| 		dia_chooser.destroy()		 | ||||
| 	#end def GuiAutoImport.starsBrowseClicked | ||||
| 
 | ||||
| 	def tiltBrowseClicked(self, widget, data): | ||||
| 		"""runs when user clicks browse on auto import tab""" | ||||
| 		#print "start of GuiAutoImport.tiltBrowseClicked" | ||||
| 		current_path=self.tiltDirPath.get_text() | ||||
| 
 | ||||
| 		dia_chooser = gtk.FileChooserDialog(title="Please choose the path that you want to auto import", | ||||
| 				action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, | ||||
| 				buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) | ||||
| 		#dia_chooser.set_current_folder(pathname) | ||||
| 		dia_chooser.set_filename(current_path) | ||||
| 		#dia_chooser.set_select_multiple(select_multiple) #not in tv, but want this in bulk import | ||||
| 
 | ||||
| 		response = dia_chooser.run() | ||||
| 		if response == gtk.RESPONSE_OK: | ||||
| 			#print dia_chooser.get_filename(), 'selected' | ||||
| 			self.tiltDirPath.set_text(dia_chooser.get_filename()) | ||||
| 		elif response == gtk.RESPONSE_CANCEL: | ||||
| 			print 'Closed, no files selected' | ||||
| 		dia_chooser.destroy() | ||||
| 	#end def GuiAutoImport.tiltBrowseClicked | ||||
| 
 | ||||
| 	def do_import(self): | ||||
| 		"""Callback for timer to do an import iteration.""" | ||||
| 		self.importer.runUpdated() | ||||
| 		print "GuiAutoImport.import_dir done" | ||||
| 		return True | ||||
| 
 | ||||
| 	def startClicked(self, widget, data): | ||||
| 		"""runs when user clicks start on auto import tab""" | ||||
| 
 | ||||
| #	Check to see if we have an open file handle to the HUD and open one if we do not. | ||||
| #	bufsize = 1 means unbuffered | ||||
| #	We need to close this file handle sometime. | ||||
| 
 | ||||
| #	TODO:  Allow for importing from multiple dirs - REB 29AUG2008 | ||||
| #	As presently written this function does nothing if there is already a pipe open. | ||||
| #	That is not correct.  It should open another dir for importing while piping the | ||||
| #	results to the same pipe.  This means that self.path should be a a list of dirs | ||||
| #	to watch. | ||||
| 		try:      #uhhh, I don't this this is the best way to check for the existence of an attr | ||||
| 			getattr(self, "pipe_to_hud") | ||||
| 		except AttributeError: | ||||
| 			if os.name == 'nt': | ||||
| 				command = "python HUD_main.py" + " %s" % (self.database) | ||||
| 				bs = 0    # windows is not happy with line buffing here | ||||
| 				self.pipe_to_hud = subprocess.Popen(command, bufsize = bs, stdin = subprocess.PIPE,  | ||||
| 											    universal_newlines=True) | ||||
| 			else: | ||||
| 				cwd = os.getcwd() | ||||
| 				command = os.path.join(cwd, 'HUD_main.py') | ||||
| 				bs = 1 | ||||
| 				self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE,  | ||||
| 											    universal_newlines=True) | ||||
| #			self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE,  | ||||
| #											    universal_newlines=True) | ||||
| #			command = command + " %s" % (self.database) | ||||
| #			print "command = ", command | ||||
| #			self.pipe_to_hud = os.popen(command, 'w') | ||||
| 			self.starspath=self.starsDirPath.get_text() | ||||
| 			self.tiltpath=self.tiltDirPath.get_text() | ||||
| 
 | ||||
| #			Add directory to importer object. | ||||
| 			self.importer.addImportDirectory(self.starspath, True, "PokerStars", "passthrough") | ||||
| 			self.importer.addImportDirectory(self.tiltpath, True, "FullTilt", "passthrough") | ||||
| 			self.do_import() | ||||
| 		 | ||||
| 			interval=int(self.intervalEntry.get_text()) | ||||
| 			gobject.timeout_add(interval*1000, self.do_import) | ||||
| 	#end def GuiAutoImport.startClicked | ||||
| 
 | ||||
| 	def get_vbox(self): | ||||
| 		"""returns the vbox of this thread""" | ||||
| 		return self.mainVBox | ||||
| 	#end def get_vbox | ||||
| 	 | ||||
| 	def __init__(self, settings, config, debug=True): | ||||
| 		"""Constructor for GuiAutoImport""" | ||||
| 		self.settings=settings | ||||
| 		self.config=config | ||||
| 		self.importer = fpdb_import.Importer(self,self.settings) | ||||
| 		self.importer.setCallHud(True) | ||||
| 		self.importer.setMinPrint(30) | ||||
| 		self.importer.setQuiet(False) | ||||
| 		self.importer.setFailOnError(False) | ||||
| 		self.importer.setHandCount(0) | ||||
| #		self.importer.setWatchTime() | ||||
| 		 | ||||
| 		self.server=settings['db-host'] | ||||
| 		self.user=settings['db-user'] | ||||
| 		self.password=settings['db-password'] | ||||
| 		self.database=settings['db-databaseName'] | ||||
| 		 | ||||
| 		self.mainVBox=gtk.VBox(False,1) | ||||
| 		self.mainVBox.show() | ||||
| 		 | ||||
| 		self.settingsHBox = gtk.HBox(False, 0) | ||||
| 		self.mainVBox.pack_start(self.settingsHBox, False, True, 0) | ||||
| 		self.settingsHBox.show() | ||||
| 		 | ||||
| 		self.intervalLabel = gtk.Label("Interval (ie. break) between imports in seconds:") | ||||
| 		self.settingsHBox.pack_start(self.intervalLabel) | ||||
| 		self.intervalLabel.show() | ||||
| 		 | ||||
| 		self.intervalEntry=gtk.Entry() | ||||
| 		self.intervalEntry.set_text(str(self.settings['hud-defaultInterval'])) | ||||
| 		self.settingsHBox.pack_start(self.intervalEntry) | ||||
| 		self.intervalEntry.show() | ||||
| 		 | ||||
| 		self.pathHBox = gtk.HBox(False, 0) | ||||
| 		self.mainVBox.pack_start(self.pathHBox, False, True, 0) | ||||
| 		self.pathHBox.show() | ||||
| 		 | ||||
| 		self.pathStarsLabel = gtk.Label("Path to PokerStars auto-import:") | ||||
| 		self.pathHBox.pack_start(self.pathStarsLabel, False, False, 0) | ||||
| 		self.pathStarsLabel.show() | ||||
| 		 | ||||
| 		self.starsDirPath=gtk.Entry() | ||||
| 		paths = self.config.get_default_paths("PokerStars") | ||||
| 		self.starsDirPath.set_text(paths['hud-defaultPath']) | ||||
| 		self.pathHBox.pack_start(self.starsDirPath, False, True, 0) | ||||
| 		self.starsDirPath.show() | ||||
| 
 | ||||
| 		self.browseButton=gtk.Button("Browse...") | ||||
| 		self.browseButton.connect("clicked", self.starsBrowseClicked, "Browse clicked") | ||||
| 		self.pathHBox.pack_start(self.browseButton, False, False, 0) | ||||
|  		self.browseButton.show() | ||||
| 		 | ||||
| 		self.pathTiltLabel = gtk.Label("Path to Full Tilt auto-import:") | ||||
| 		self.pathHBox.pack_start(self.pathTiltLabel, False, False, 0) | ||||
| 		self.pathTiltLabel.show() | ||||
| 
 | ||||
| 		self.tiltDirPath=gtk.Entry() | ||||
| 		paths = self.config.get_default_paths("Full Tilt") | ||||
| 		self.tiltDirPath.set_text(paths['hud-defaultPath']) | ||||
| 		self.pathHBox.pack_start(self.tiltDirPath, False, True, 0) | ||||
| 		self.tiltDirPath.show() | ||||
| 
 | ||||
| 		self.browseButton=gtk.Button("Browse...") | ||||
| 		self.browseButton.connect("clicked", self.tiltBrowseClicked, "Browse clicked") | ||||
| 		self.pathHBox.pack_start(self.browseButton, False, False, 0) | ||||
|  		self.browseButton.show() | ||||
| 
 | ||||
| 		self.startButton=gtk.Button("Start Autoimport") | ||||
| 		self.startButton.connect("clicked", self.startClicked, "start clicked") | ||||
| 		self.mainVBox.add(self.startButton) | ||||
|  		self.startButton.show() | ||||
| 	#end of GuiAutoImport.__init__ | ||||
| if __name__== "__main__": | ||||
|     def destroy(*args):             # call back for terminating the main eventloop | ||||
|         gtk.main_quit() | ||||
| 
 | ||||
|     settings = {} | ||||
|     settings['db-host'] = "192.168.1.100" | ||||
|     settings['db-user'] = "mythtv" | ||||
|     settings['db-password'] = "mythtv" | ||||
|     settings['db-databaseName'] = "fpdb" | ||||
|     settings['hud-defaultInterval'] = 10 | ||||
|     settings['hud-defaultPath'] = 'C:/Program Files/PokerStars/HandHistory/nutOmatic' | ||||
|     settings['imp-callFpdbHud'] = True | ||||
| 
 | ||||
|     i = GuiAutoImport(settings) | ||||
|     main_window = gtk.Window() | ||||
|     main_window.connect("destroy", destroy) | ||||
|     main_window.add(i.mainVBox) | ||||
|     main_window.show() | ||||
|     gtk.main() | ||||
| #!/usr/bin/python | ||||
| 
 | ||||
| #Copyright 2008 Steffen Jobbagy-Felso | ||||
| #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 in the docs folder of the package. | ||||
| 
 | ||||
| import threading | ||||
| import subprocess | ||||
| 
 | ||||
| import pygtk | ||||
| pygtk.require('2.0') | ||||
| import gtk | ||||
| import gobject | ||||
| import os | ||||
| import time | ||||
| import fpdb_import | ||||
| 
 | ||||
| 
 | ||||
| class GuiAutoImport (threading.Thread): | ||||
|         def __init__(self, settings, config): | ||||
|                 """Constructor for GuiAutoImport""" | ||||
|                 self.settings=settings | ||||
|                 self.config=config | ||||
| 
 | ||||
|                 imp = self.config.get_import_parameters() | ||||
| 
 | ||||
|                 print "Import parameters" | ||||
|                 print imp | ||||
| 
 | ||||
|                 self.input_settings = {} | ||||
| 
 | ||||
|                 self.importer = fpdb_import.Importer(self, self.settings, self.config) | ||||
|                 self.importer.setCallHud(True) | ||||
|                 self.importer.setMinPrint(30) | ||||
|                 self.importer.setQuiet(False) | ||||
|                 self.importer.setFailOnError(False) | ||||
|                 self.importer.setHandCount(0) | ||||
| #               self.importer.setWatchTime() | ||||
|                  | ||||
|                 self.server=settings['db-host'] | ||||
|                 self.user=settings['db-user'] | ||||
|                 self.password=settings['db-password'] | ||||
|                 self.database=settings['db-databaseName'] | ||||
| 
 | ||||
|                 self.mainVBox=gtk.VBox(False,1) | ||||
|                 self.mainVBox.show() | ||||
| 
 | ||||
|                 self.settingsHBox = gtk.HBox(False, 0) | ||||
|                 self.mainVBox.pack_start(self.settingsHBox, False, True, 0) | ||||
|                 self.settingsHBox.show() | ||||
| 
 | ||||
|                 self.intervalLabel = gtk.Label("Time between imports in seconds:") | ||||
|                 self.settingsHBox.pack_start(self.intervalLabel) | ||||
|                 self.intervalLabel.show() | ||||
| 
 | ||||
|                 self.intervalEntry=gtk.Entry() | ||||
|                 self.intervalEntry.set_text(str(self.config.get_import_parameters().get("interval"))) | ||||
|                 self.settingsHBox.pack_start(self.intervalEntry) | ||||
|                 self.intervalEntry.show() | ||||
| 
 | ||||
|                 self.addSites(self.mainVBox) | ||||
| 
 | ||||
|                 self.startButton=gtk.Button("Start Autoimport") | ||||
|                 self.startButton.connect("clicked", self.startClicked, "start clicked") | ||||
|                 self.mainVBox.add(self.startButton) | ||||
|                 self.startButton.show() | ||||
| 
 | ||||
| 
 | ||||
|         #end of GuiAutoImport.__init__ | ||||
|         def browseClicked(self, widget, data): | ||||
|                 """runs when user clicks one of the browse buttons in the auto import tab""" | ||||
|                 current_path=data[1].get_text() | ||||
| 
 | ||||
|                 dia_chooser = gtk.FileChooserDialog(title="Please choose the path that you want to auto import", | ||||
|                                 action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, | ||||
|                                 buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) | ||||
|                 #dia_chooser.set_current_folder(pathname) | ||||
|                 dia_chooser.set_filename(current_path) | ||||
|                 #dia_chooser.set_select_multiple(select_multiple) #not in tv, but want this in bulk import | ||||
| 
 | ||||
|                 response = dia_chooser.run() | ||||
|                 if response == gtk.RESPONSE_OK: | ||||
|                         #print dia_chooser.get_filename(), 'selected' | ||||
|                         data[1].set_text(dia_chooser.get_filename()) | ||||
|                         self.input_settings[data[0]][0] = dia_chooser.get_filename() | ||||
|                 elif response == gtk.RESPONSE_CANCEL: | ||||
|                         print 'Closed, no files selected' | ||||
|                 dia_chooser.destroy() | ||||
|         #end def GuiAutoImport.browseClicked | ||||
| 
 | ||||
|         def do_import(self): | ||||
|                 """Callback for timer to do an import iteration.""" | ||||
|                 self.importer.runUpdated() | ||||
|                 print "GuiAutoImport.import_dir done" | ||||
|                 return True | ||||
| 
 | ||||
|         def startClicked(self, widget, data): | ||||
|                 """runs when user clicks start on auto import tab""" | ||||
| 
 | ||||
| #       Check to see if we have an open file handle to the HUD and open one if we do not. | ||||
| #       bufsize = 1 means unbuffered | ||||
| #       We need to close this file handle sometime. | ||||
| 
 | ||||
| #       TODO:  Allow for importing from multiple dirs - REB 29AUG2008 | ||||
| #       As presently written this function does nothing if there is already a pipe open. | ||||
| #       That is not correct.  It should open another dir for importing while piping the | ||||
| #       results to the same pipe.  This means that self.path should be a a list of dirs | ||||
| #       to watch. | ||||
|                 try:      #uhhh, I don't this this is the best way to check for the existence of an attr | ||||
|                         getattr(self, "pipe_to_hud") | ||||
|                 except AttributeError: | ||||
|                         if os.name == 'nt': | ||||
|                                 command = "python HUD_main.py" + " %s" % (self.database) | ||||
|                                 bs = 0    # windows is not happy with line buffing here | ||||
|                                 self.pipe_to_hud = subprocess.Popen(command, bufsize = bs, stdin = subprocess.PIPE, | ||||
|                                                                                             universal_newlines=True) | ||||
|                         else: | ||||
|                                 cwd = os.getcwd() | ||||
|                                 command = os.path.join(cwd, 'HUD_main.py') | ||||
|                                 bs = 1 | ||||
|                                 self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, | ||||
|                                                                                             universal_newlines=True) | ||||
| #                       self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, | ||||
| #                                                                                           universal_newlines=True) | ||||
| #                       command = command + " %s" % (self.database) | ||||
| #                       print "command = ", command | ||||
| #                       self.pipe_to_hud = os.popen(command, 'w') | ||||
| 
 | ||||
| #                       Add directories to importer object. | ||||
|                         for site in self.input_settings: | ||||
|                                 self.importer.addImportDirectory(self.input_settings[site][0], True, site, self.input_settings[site][1]) | ||||
|                                 print "Adding import directories - Site: " + site + " dir: "+ str(self.input_settings[site][0]) | ||||
|                         self.do_import() | ||||
|                 | ||||
|                         interval=int(self.intervalEntry.get_text()) | ||||
|                         gobject.timeout_add(interval*1000, self.do_import) | ||||
|         #end def GuiAutoImport.startClicked | ||||
| 
 | ||||
|         def get_vbox(self): | ||||
|                 """returns the vbox of this thread""" | ||||
|                 return self.mainVBox | ||||
|         #end def get_vbox | ||||
| 
 | ||||
|         #Create the site line given required info and setup callbacks | ||||
|         #enabling and disabling sites from this interface not possible | ||||
|         #expects a box to layout the line horizontally | ||||
|         def createSiteLine(self, hbox, site, iconpath, hhpath, filter_name, active = True): | ||||
|                 label = gtk.Label(site + " auto-import:") | ||||
|                 hbox.pack_start(label, False, False, 0) | ||||
|                 label.show() | ||||
| 
 | ||||
|                 dirPath=gtk.Entry() | ||||
|                 dirPath.set_text(hhpath) | ||||
|                 hbox.pack_start(dirPath, False, True, 0) | ||||
|                 dirPath.show() | ||||
| 
 | ||||
|                 browseButton=gtk.Button("Browse...") | ||||
|                 browseButton.connect("clicked", self.browseClicked, [site] + [dirPath]) | ||||
|                 hbox.pack_start(browseButton, False, False, 0) | ||||
|                 browseButton.show() | ||||
| 
 | ||||
|                 label = gtk.Label(site + " filter:") | ||||
|                 hbox.pack_start(label, False, False, 0) | ||||
|                 label.show() | ||||
| 
 | ||||
|                 filter=gtk.Entry() | ||||
|                 filter.set_text(filter_name) | ||||
|                 hbox.pack_start(filter, False, True, 0) | ||||
|                 filter.show() | ||||
| 
 | ||||
|         def addSites(self, vbox): | ||||
|                 for site in self.config.supported_sites.keys(): | ||||
|                         pathHBox = gtk.HBox(False, 0) | ||||
|                         vbox.pack_start(pathHBox, False, True, 0) | ||||
|                         pathHBox.show() | ||||
| 
 | ||||
|                         paths = self.config.get_default_paths(site) | ||||
|                         params = self.config.get_site_parameters(site) | ||||
|                         self.createSiteLine(pathHBox, site, False, paths['hud-defaultPath'], params['converter'], params['enabled']) | ||||
|                         self.input_settings[site] = [paths['hud-defaultPath']] + [params['converter']] | ||||
| 
 | ||||
| if __name__== "__main__": | ||||
|     def destroy(*args):             # call back for terminating the main eventloop | ||||
|         gtk.main_quit() | ||||
| 
 | ||||
|     settings = {} | ||||
|     settings['db-host'] = "192.168.1.100" | ||||
|     settings['db-user'] = "mythtv" | ||||
|     settings['db-password'] = "mythtv" | ||||
|     settings['db-databaseName'] = "fpdb" | ||||
|     settings['hud-defaultInterval'] = 10 | ||||
|     settings['hud-defaultPath'] = 'C:/Program Files/PokerStars/HandHistory/nutOmatic' | ||||
|     settings['callFpdbHud'] = True | ||||
| 
 | ||||
|     i = GuiAutoImport(settings) | ||||
|     main_window = gtk.Window() | ||||
|     main_window.connect("destroy", destroy) | ||||
|     main_window.add(i.mainVBox) | ||||
|     main_window.show() | ||||
|     gtk.main() | ||||
|  |  | |||
|  | @ -87,16 +87,20 @@ class GuiGraphViewer (threading.Thread): | |||
| 	#end of def showClicked | ||||
| 
 | ||||
| 	def getRingProfitGraph(self, name, site): | ||||
|                 self.cursor.execute(self.sql.query['getRingWinningsAllGamesPlayerIdSite'], (name, site)) | ||||
|                 #self.cursor.execute(self.sql.query['getRingWinningsAllGamesPlayerIdSite'], (name, site)) | ||||
|                 self.cursor.execute(self.sql.query['getRingProfitAllHandsPlayerIdSite'], (name, site)) | ||||
|                 # returns (HandId,Winnings,Costs,Profit) | ||||
|                 winnings = self.db.cursor.fetchall() | ||||
| 
 | ||||
|                 profit=range(len(winnings)) | ||||
|                 for i in profit: | ||||
|                         self.cursor.execute(self.sql.query['getRingProfitFromHandId'], (name, winnings[i][0], site)) | ||||
|                         spent = self.db.cursor.fetchone() | ||||
|                         profit[i]=(i, winnings[i][1]-spent[0]) | ||||
|                 #profit=range(len(winnings)) | ||||
|                 #for i in profit: | ||||
|                 #        self.cursor.execute(self.sql.query['getRingProfitFromHandId'], (name, winnings[i][0], site)) | ||||
|                 #        spent = self.db.cursor.fetchone() | ||||
|                 #        profit[i]=(i, winnings[i][1]-spent[0]) | ||||
|                  | ||||
|                 #y=map(lambda x:float(x[1]), profit) | ||||
|                 y=map(lambda x:float(x[3]), winnings) | ||||
| 
 | ||||
|                 y=map(lambda x:float(x[1]), profit) | ||||
|                 line = cumsum(y) | ||||
|                 return line/100 | ||||
|         #end of def getRingProfitGraph | ||||
|  |  | |||
							
								
								
									
										337
									
								
								pyfpdb/HUD_main.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										337
									
								
								pyfpdb/HUD_main.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -1,166 +1,171 @@ | |||
| #!/usr/bin/env python | ||||
| 
 | ||||
| """Hud_main.py | ||||
| 
 | ||||
| Main for FreePokerTools HUD. | ||||
| """ | ||||
| #    Copyright 2008, Ray E. Barker | ||||
| #     | ||||
| #    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 | ||||
| 
 | ||||
| ######################################################################## | ||||
| 
 | ||||
| #    to do kill window on my seat | ||||
| #    to do adjust for preferred seat | ||||
| #    to do allow window resizing | ||||
| #    to do hud to echo, but ignore non numbers | ||||
| #    to do no hud window for hero | ||||
| #    to do things to add to config.xml | ||||
| #    to do     font and size | ||||
| #    to do     opacity | ||||
| 
 | ||||
| #    Standard Library modules | ||||
| import sys | ||||
| import os | ||||
| import thread | ||||
| import time | ||||
| import string | ||||
| import re | ||||
| 
 | ||||
| errorfile = open('HUD-error.txt', 'w', 0) | ||||
| sys.stderr = errorfile | ||||
| 
 | ||||
| #    pyGTK modules | ||||
| import pygtk | ||||
| import gtk | ||||
| import gobject | ||||
| 
 | ||||
| #    FreePokerTools modules | ||||
| import Configuration | ||||
| import Database | ||||
| import Tables | ||||
| import Hud | ||||
| 
 | ||||
| #    global dict for keeping the huds | ||||
| hud_dict = {} | ||||
| 
 | ||||
| db_connection = 0; | ||||
| config = 0; | ||||
| 
 | ||||
| def destroy(*args):             # call back for terminating the main eventloop | ||||
|     gtk.main_quit() | ||||
| 
 | ||||
| def create_HUD(new_hand_id, table, db_name, table_name, max, poker_game, db_connection, config, stat_dict): | ||||
|     global hud_dict | ||||
|     def idle_func(): | ||||
|         global hud_dict | ||||
|         gtk.gdk.threads_enter() | ||||
|         try: | ||||
|             hud_dict[table_name] = Hud.Hud(table, max, poker_game, config, db_name) | ||||
|             hud_dict[table_name].create(new_hand_id, config) | ||||
|             hud_dict[table_name].update(new_hand_id, config, stat_dict) | ||||
|             hud_dict[table_name].reposition_windows() | ||||
|             return False | ||||
|         finally: | ||||
|             gtk.gdk.threads_leave() | ||||
|     gobject.idle_add(idle_func) | ||||
| 
 | ||||
| def update_HUD(new_hand_id, table_name, config, stat_dict): | ||||
|     global hud_dict | ||||
|     def idle_func(): | ||||
|         gtk.gdk.threads_enter() | ||||
|         try: | ||||
|             hud_dict[table_name].update(new_hand_id, config, stat_dict) | ||||
|             return False | ||||
|         finally: | ||||
|             gtk.gdk.threads_leave() | ||||
|     gobject.idle_add(idle_func) | ||||
| 
 | ||||
| def read_stdin():            # This is the thread function | ||||
|     global hud_dict | ||||
| 
 | ||||
|     db_connection = Database.Database(config, db_name, 'temp') | ||||
| #    tourny_finder = re.compile('(\d+) (\d+)') | ||||
| 
 | ||||
|     while True: # wait for a new hand number on stdin | ||||
|         new_hand_id = sys.stdin.readline() | ||||
|         new_hand_id = string.rstrip(new_hand_id) | ||||
|         if new_hand_id == "":           # blank line means quit | ||||
|             destroy() | ||||
| 
 | ||||
| #    delete hud_dict entries for any HUD destroyed since last iteration | ||||
|         for h in hud_dict.keys(): | ||||
|             if hud_dict[h].deleted: | ||||
|                 del(hud_dict[h]) | ||||
| 
 | ||||
| #    get basic info about the new hand from the db | ||||
|         (table_name, max, poker_game) = db_connection.get_table_name(new_hand_id) | ||||
| 
 | ||||
| #    find out if this hand is from a tournament | ||||
|         is_tournament = False | ||||
| #        (t_number, s_number) = (0, 0) | ||||
| #        mat_obj = tourny_finder(table_name) | ||||
| #        if len(mat_obj.groups) == 2: | ||||
| #            is_tournament = True | ||||
| #            (t_number, s_number) = mat_obj.group(1, 2) | ||||
|              | ||||
|         stat_dict = db_connection.get_stats_from_hand(new_hand_id) | ||||
| 
 | ||||
| #    if a hud for this CASH table exists, just update it | ||||
|         if hud_dict.has_key(table_name): | ||||
|             update_HUD(new_hand_id, table_name, config, stat_dict) | ||||
| #    if a hud for this TOURNAMENT table exists, just update it | ||||
| #        elif hud_dict.has_key(t_number): | ||||
| #            update_HUD(new_hand_id, t_number, config, stat_dict) | ||||
| #        otherwise create a new hud | ||||
|         else: | ||||
|             if is_tournament: | ||||
|                 tablewindow = Tables.discover_tournament_table(config, t_number, s_number) | ||||
|                 if tablewindow == None: | ||||
|                     sys.stderr.write("table name "+table_name+" not found\n") | ||||
|                 else: | ||||
|                     create_HUD(new_hand_id, tablewindow, db_name, t_number, max, poker_game, db_connection, config, stat_dict) | ||||
|             else: | ||||
|                 tablewindow = Tables.discover_table_by_name(config, table_name) | ||||
|                 if tablewindow == None: | ||||
|                     sys.stderr.write("table name "+table_name+" not found\n") | ||||
|                 else: | ||||
|                     create_HUD(new_hand_id, tablewindow, db_name, table_name, max, poker_game, db_connection, config, stat_dict) | ||||
| 
 | ||||
| if __name__== "__main__": | ||||
|     sys.stderr.write("HUD_main starting\n") | ||||
| 
 | ||||
|     try: | ||||
|         db_name = sys.argv[1] | ||||
|     except: | ||||
|         db_name = 'fpdb' | ||||
|     sys.stderr.write("Using db name = %s\n" % (db_name)) | ||||
| 
 | ||||
|     config = Configuration.Config() | ||||
| 
 | ||||
|     gobject.threads_init()                # this is required | ||||
|     thread.start_new_thread(read_stdin, ()) # starts the thread | ||||
| 
 | ||||
|     main_window = gtk.Window() | ||||
|     main_window.connect("destroy", destroy) | ||||
|     eb = gtk.EventBox() | ||||
|     label = gtk.Label('Closing this window will exit from the HUD.') | ||||
|     eb.add(label) | ||||
|     main_window.add(eb) | ||||
|     main_window.set_title("HUD Main Window") | ||||
|     main_window.show_all() | ||||
|      | ||||
|     gtk.main() | ||||
| 
 | ||||
| #!/usr/bin/env python | ||||
| 
 | ||||
| """Hud_main.py | ||||
| 
 | ||||
| Main for FreePokerTools HUD. | ||||
| """ | ||||
| #    Copyright 2008, Ray E. Barker | ||||
| #    | ||||
| #    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 | ||||
| 
 | ||||
| ######################################################################## | ||||
| 
 | ||||
| #    to do kill window on my seat | ||||
| #    to do adjust for preferred seat | ||||
| #    to do allow window resizing | ||||
| #    to do hud to echo, but ignore non numbers | ||||
| #    to do no hud window for hero | ||||
| #    to do things to add to config.xml | ||||
| #    to do     font and size | ||||
| #    to do     opacity | ||||
| 
 | ||||
| #    Standard Library modules | ||||
| import sys | ||||
| import os | ||||
| import thread | ||||
| import time | ||||
| import string | ||||
| import re | ||||
| 
 | ||||
| errorfile = open('HUD-error.txt', 'w', 0) | ||||
| sys.stderr = errorfile | ||||
| 
 | ||||
| #    pyGTK modules | ||||
| import pygtk | ||||
| import gtk | ||||
| import gobject | ||||
| 
 | ||||
| #    FreePokerTools modules | ||||
| import Configuration | ||||
| import Database | ||||
| import Tables | ||||
| import Hud | ||||
| 
 | ||||
| #    global dict for keeping the huds | ||||
| hud_dict = {} | ||||
| 
 | ||||
| db_connection = 0; | ||||
| config = 0; | ||||
| 
 | ||||
| def destroy(*args):             # call back for terminating the main eventloop | ||||
|     gtk.main_quit() | ||||
| 
 | ||||
| def create_HUD(new_hand_id, table, db_name, table_name, max, poker_game, db_connection, config, stat_dict): | ||||
|     global hud_dict | ||||
|     def idle_func(): | ||||
|         global hud_dict | ||||
|         gtk.gdk.threads_enter() | ||||
|         try: | ||||
|             hud_dict[table_name] = Hud.Hud(table, max, poker_game, config, db_name) | ||||
|             hud_dict[table_name].create(new_hand_id, config) | ||||
|             hud_dict[table_name].update(new_hand_id, config, stat_dict) | ||||
|             hud_dict[table_name].reposition_windows() | ||||
|             return False | ||||
|         finally: | ||||
|             gtk.gdk.threads_leave() | ||||
|     gobject.idle_add(idle_func) | ||||
| 
 | ||||
| def update_HUD(new_hand_id, table_name, config, stat_dict): | ||||
|     global hud_dict | ||||
|     def idle_func(): | ||||
|         gtk.gdk.threads_enter() | ||||
|         try: | ||||
|             hud_dict[table_name].update(new_hand_id, config, stat_dict) | ||||
|             for m in hud_dict[table_name].aux_windows: | ||||
|                 m.update_gui(new_hand_id) | ||||
|             return False | ||||
|         finally: | ||||
|             gtk.gdk.threads_leave() | ||||
|     gobject.idle_add(idle_func) | ||||
| 
 | ||||
| def read_stdin():            # This is the thread function | ||||
|     global hud_dict | ||||
| 
 | ||||
|     db_connection = Database.Database(config, db_name, 'temp') | ||||
|     tourny_finder = re.compile('(\d+) (\d+)') | ||||
| 
 | ||||
|     while True: # wait for a new hand number on stdin | ||||
|         new_hand_id = sys.stdin.readline() | ||||
|         new_hand_id = string.rstrip(new_hand_id) | ||||
|         if new_hand_id == "":           # blank line means quit | ||||
|             destroy() | ||||
| 
 | ||||
| #    delete hud_dict entries for any HUD destroyed since last iteration | ||||
|         for h in hud_dict.keys(): | ||||
|             if hud_dict[h].deleted: | ||||
|                 del(hud_dict[h]) | ||||
| 
 | ||||
| #    get basic info about the new hand from the db | ||||
|         (table_name, max, poker_game) = db_connection.get_table_name(new_hand_id) | ||||
| 
 | ||||
| #    find out if this hand is from a tournament | ||||
|         is_tournament = False | ||||
|         (tour_number, tab_number) = (0, 0) | ||||
|         mat_obj = tourny_finder.search(table_name) | ||||
| #        if len(mat_obj.groups) == 2: | ||||
|         if mat_obj: | ||||
|             is_tournament = True | ||||
|             (tour_number, tab_number) = mat_obj.group(1, 2) | ||||
|             | ||||
|         stat_dict = db_connection.get_stats_from_hand(new_hand_id) | ||||
| 
 | ||||
| #    if a hud for this CASH table exists, just update it | ||||
|         if hud_dict.has_key(table_name): | ||||
| #    update the data for the aux_windows | ||||
|             for aw in hud_dict[table_name].aux_windows: | ||||
|                 aw.update_data(new_hand_id) | ||||
|             update_HUD(new_hand_id, table_name, config, stat_dict) | ||||
| #    if a hud for this TOURNAMENT table exists, just update it | ||||
|         elif hud_dict.has_key(tour_number): | ||||
|             update_HUD(new_hand_id, tour_number, config, stat_dict) | ||||
| #    otherwise create a new hud | ||||
|         else: | ||||
|             if is_tournament: | ||||
|                 tablewindow = Tables.discover_tournament_table(config, tour_number, tab_number) | ||||
|                 if tablewindow == None: | ||||
|                     sys.stderr.write("tournament %s,  table %s not found\n" % (tour_number, tab_number)) | ||||
|                 else: | ||||
|                     create_HUD(new_hand_id, tablewindow, db_name, tour_number, max, poker_game, db_connection, config, stat_dict) | ||||
|             else: | ||||
|                 tablewindow = Tables.discover_table_by_name(config, table_name) | ||||
|                 if tablewindow == None: | ||||
|                     sys.stderr.write("table name "+table_name+" not found\n") | ||||
|                 else: | ||||
|                     create_HUD(new_hand_id, tablewindow, db_name, table_name, max, poker_game, db_connection, config, stat_dict) | ||||
| 
 | ||||
| if __name__== "__main__": | ||||
|     sys.stderr.write("HUD_main starting\n") | ||||
| 
 | ||||
|     try: | ||||
|         db_name = sys.argv[1] | ||||
|     except: | ||||
|         db_name = 'fpdb' | ||||
|     sys.stderr.write("Using db name = %s\n" % (db_name)) | ||||
| 
 | ||||
|     config = Configuration.Config() | ||||
| 
 | ||||
|     gobject.threads_init()                # this is required | ||||
|     thread.start_new_thread(read_stdin, ()) # starts the thread | ||||
| 
 | ||||
|     main_window = gtk.Window() | ||||
|     main_window.connect("destroy", destroy) | ||||
|     eb = gtk.EventBox() | ||||
|     label = gtk.Label('Closing this window will exit from the HUD.') | ||||
|     eb.add(label) | ||||
|     main_window.add(eb) | ||||
|     main_window.set_title("HUD Main Window") | ||||
|     main_window.show_all() | ||||
|     | ||||
|     gtk.main() | ||||
|  |  | |||
							
								
								
									
										1140
									
								
								pyfpdb/Hud.py
									
									
									
									
									
								
							
							
						
						
									
										1140
									
								
								pyfpdb/Hud.py
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -229,14 +229,21 @@ class Sql: | |||
|                         sum(street3CheckCallRaiseDone)   AS ccr_3, | ||||
|                         sum(street4CheckCallRaiseChance) AS ccr_opp_4, | ||||
|                         sum(street4CheckCallRaiseDone)   AS ccr_4 | ||||
|                     FROM HudCache, Hands | ||||
|                     WHERE HudCache.PlayerId in  | ||||
|                         (SELECT PlayerId FROM HandsPlayers  | ||||
|                         WHERE handId = %s) | ||||
|                     AND   Hands.id = %s | ||||
|                     AND   Hands.gametypeId = HudCache.gametypeId | ||||
|                     FROM Hands | ||||
|                          INNER JOIN HandsPlayers ON (HandsPlayers.handId = %s) | ||||
|                          INNER JOIN HudCache ON (    HudCache.PlayerId = HandsPlayers.PlayerId+0 | ||||
|                                                  AND HudCache.gametypeId+0 = Hands.gametypeId+0) | ||||
|                     WHERE Hands.id = %s | ||||
|                     GROUP BY HudCache.PlayerId | ||||
|                 """ | ||||
| 
 | ||||
| #                    FROM HudCache, Hands | ||||
| #                    WHERE HudCache.PlayerId in  | ||||
| #                        (SELECT PlayerId FROM HandsPlayers  | ||||
| #                        WHERE handId = %s) | ||||
| #                    AND   Hands.id = %s | ||||
| #                    AND   Hands.gametypeId = HudCache.gametypeId | ||||
| 
 | ||||
| #                    AND   PlayerId LIKE %s | ||||
| #                        HudCache.gametypeId              AS gametypeId, | ||||
| #                        activeSeats                      AS n_active, | ||||
|  |  | |||
							
								
								
									
										110
									
								
								pyfpdb/Stats.py
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								pyfpdb/Stats.py
									
									
									
									
									
								
							|  | @ -71,6 +71,7 @@ def do_stat(stat_dict, player = 24, stat = 'vpip'): | |||
| #    functions that return individual stats | ||||
| 
 | ||||
| def playername(stat_dict, player): | ||||
|     """    Player Name.""" | ||||
|     return (stat_dict[player]['screen_name'], | ||||
|             stat_dict[player]['screen_name'], | ||||
|             stat_dict[player]['screen_name'], | ||||
|  | @ -98,6 +99,26 @@ def vpip(stat_dict, player): | |||
|                     'wtsd' | ||||
|                     ) | ||||
| 
 | ||||
| def vpip_0(stat_dict, player): | ||||
|     """    Voluntarily put $ in the pot (no decimals).""" | ||||
|     stat = 0.0 | ||||
|     try: | ||||
|         stat = float(stat_dict[player]['vpip'])/float(stat_dict[player]['n']) | ||||
|         return (stat,  | ||||
|                 '%2.0f'      % (100*stat) + '%',  | ||||
|                 'v=%2.0f'    % (100*stat) + '%',  | ||||
|                 'vpip=%2.0f' % (100*stat) + '%',  | ||||
|                 '(%d/%d)'    % (stat_dict[player]['vpip'], stat_dict[player]['n']), | ||||
|                 'vpip' | ||||
|                 ) | ||||
|     except: return (stat,  | ||||
|                     '%2.0f'      % (0) + '%',  | ||||
|                     'w=%2.0f'    % (0) + '%',  | ||||
|                     'wtsd=%2.0f' % (0) + '%',  | ||||
|                     '(%d/%d)'    % (0, 0), | ||||
|                     'wtsd' | ||||
|                     ) | ||||
| 
 | ||||
| def pfr(stat_dict, player): | ||||
|     """    Preflop (3rd street) raise.""" | ||||
|     stat = 0.0 | ||||
|  | @ -119,6 +140,27 @@ def pfr(stat_dict, player): | |||
|                 'pfr' | ||||
|                 ) | ||||
| 
 | ||||
| def pfr_0(stat_dict, player): | ||||
|     """    Preflop (3rd street) raise (no decimals).""" | ||||
|     stat = 0.0 | ||||
|     try: | ||||
|         stat = float(stat_dict[player]['pfr'])/float(stat_dict[player]['n']) | ||||
|         return (stat,  | ||||
|                 '%2.0f'      % (100*stat) + '%',  | ||||
|                 'p=%2.0f'    % (100*stat) + '%',  | ||||
|                 'pfr=%2.0f'  % (100*stat) + '%',  | ||||
|                 '(%d/%d)'    % (stat_dict[player]['pfr'], stat_dict[player]['n']), | ||||
|                 'pfr' | ||||
|                 ) | ||||
|     except:  | ||||
|         return (stat,  | ||||
|                 '%2.0f'      % (0) + '%',  | ||||
|                 'p=%2.0f'    % (0) + '%',  | ||||
|                 'pfr=%2.0f' % (0) + '%',  | ||||
|                 '(%d/%d)'    % (0, 0), | ||||
|                 'pfr' | ||||
|                 ) | ||||
| 
 | ||||
| def wtsd(stat_dict, player): | ||||
|     """    Went to SD when saw flop/4th.""" | ||||
|     stat = 0.0 | ||||
|  | @ -149,7 +191,7 @@ def wmsd(stat_dict, player): | |||
|                 '%3.1f'      % (100*stat) + '%',  | ||||
|                 'w=%3.1f'    % (100*stat) + '%',  | ||||
|                 'wmsd=%3.1f' % (100*stat) + '%',  | ||||
|                 '(%f5.0/%d)'    % (stat_dict[player]['wmsd'], stat_dict[player]['sd']), | ||||
|                 '(%5.1f/%d)'    % (float(stat_dict[player]['wmsd']), stat_dict[player]['sd']), | ||||
|                 '% won money at showdown' | ||||
|                 ) | ||||
|     except: | ||||
|  | @ -414,6 +456,61 @@ def a_freq_4(stat_dict, player): | |||
|                 '(%d/%d)'      % (0, 0), | ||||
|                 'Aggression Freq flop/4th' | ||||
|                 ) | ||||
| 
 | ||||
| def a_freq_123(stat_dict, player): | ||||
|     """    Post-Flop aggression frequency.""" | ||||
|     stat = 0.0 | ||||
|     try: | ||||
|         stat = float(  stat_dict[player]['aggr_1'] + stat_dict[player]['aggr_2'] + stat_dict[player]['aggr_3'] | ||||
|                     ) / float(  stat_dict[player]['saw_1'] + stat_dict[player]['saw_2'] + stat_dict[player]['saw_3']); | ||||
|         return (stat, | ||||
|                 '%3.1f'             % (100*stat) + '%',  | ||||
|                 'afq=%3.1f'         % (100*stat) + '%',  | ||||
|                 'postf_aggfq=%3.1f' % (100*stat) + '%',  | ||||
|                 '(%d/%d)'           % (  stat_dict[player]['aggr_1'] | ||||
|                                        + stat_dict[player]['aggr_2'] | ||||
|                                        + stat_dict[player]['aggr_3'] | ||||
|                                       ,  stat_dict[player]['saw_1'] | ||||
|                                        + stat_dict[player]['saw_2'] | ||||
|                                        + stat_dict[player]['saw_3'] | ||||
|                                       ), | ||||
|                 'Post-Flop Aggression Freq' | ||||
|                 ) | ||||
|     except: | ||||
|         return (stat, | ||||
|                 '%2.0f'        % (0) + '%',  | ||||
|                 'a3=%2.0f'     % (0) + '%',  | ||||
|                 'a_fq_3=%2.0f' % (0) + '%',  | ||||
|                 '(%d/%d)'      % (0, 0), | ||||
|                 'Post-Flop Aggression Freq' | ||||
|                 ) | ||||
| 
 | ||||
| def a_freq_123_0(stat_dict, player): | ||||
|     """    Post-Flop aggression frequency (no decimals).""" | ||||
|     stat = 0.0 | ||||
|     try: | ||||
|         stat = float(  stat_dict[player]['aggr_1'] + stat_dict[player]['aggr_2'] + stat_dict[player]['aggr_3']) / float(  stat_dict[player]['saw_1'] + stat_dict[player]['saw_2'] + stat_dict[player]['saw_3']); | ||||
|         return (stat, | ||||
|                 '%2.0f'             % (100*stat) + '%',  | ||||
|                 'afq=%2.0f'         % (100*stat) + '%',  | ||||
|                 'postf_aggfq=%2.0f' % (100*stat) + '%',  | ||||
|                 '(%d/%d)'           % (  stat_dict[player]['aggr_1'] | ||||
|                                        + stat_dict[player]['aggr_2'] | ||||
|                                        + stat_dict[player]['aggr_3'] | ||||
|                                       ,  stat_dict[player]['saw_1'] | ||||
|                                        + stat_dict[player]['saw_2'] | ||||
|                                        + stat_dict[player]['saw_3'] | ||||
|                                       ), | ||||
|                 'Post-Flop Aggression Freq' | ||||
|                 ) | ||||
|     except: | ||||
|         return (stat, | ||||
|                 '%2.0f'        % (0) + '%',  | ||||
|                 'a3=%2.0f'     % (0) + '%',  | ||||
|                 'a_fq_3=%2.0f' % (0) + '%',  | ||||
|                 '(%d/%d)'      % (0, 0), | ||||
|                 'Post-Flop Aggression Freq' | ||||
|                 ) | ||||
|      | ||||
| def cb_1(stat_dict, player): | ||||
|     """    Flop continuation bet.""" | ||||
|  | @ -591,7 +688,9 @@ if __name__== "__main__": | |||
|      | ||||
|     for player in stat_dict.keys(): | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'vpip_0')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'pfr')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'pfr_0')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'wtsd')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'saw_f')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'n')  | ||||
|  | @ -606,6 +705,8 @@ if __name__== "__main__": | |||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_2')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_3')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_4')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_123')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'a_freq_123_0')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_1')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_2')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'cb_3')  | ||||
|  | @ -613,7 +714,8 @@ if __name__== "__main__": | |||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_1')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_2')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_3')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_4')  | ||||
|         print "player = ", player, do_stat(stat_dict, player = player, stat = 'ffreq_4') | ||||
|         print "\n"  | ||||
| 
 | ||||
|     print "\n\nLegal stats:" | ||||
|     for attr in dir(): | ||||
|  | @ -621,8 +723,8 @@ if __name__== "__main__": | |||
|         if attr in ("Configuration", "Database", "GInitiallyUnowned", "gtk", "pygtk", | ||||
|                     "player", "c", "db_connection", "do_stat", "do_tip", "stat_dict", | ||||
|                     "h"): continue | ||||
|         print attr, eval("%s.__doc__" % (attr)) | ||||
|         print "%-14s %s" % (attr, eval("%s.__doc__" % (attr))) | ||||
| #        print "            <pu_stat pu_stat_name = \"%s\"> </pu_stat>" % (attr) | ||||
| 
 | ||||
|     db_connection.close | ||||
|     db_connection.close_connection | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										898
									
								
								pyfpdb/fpdb.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										898
									
								
								pyfpdb/fpdb.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -1,449 +1,449 @@ | |||
| #!/usr/bin/python | ||||
| 
 | ||||
| #Copyright 2008 Steffen Jobbagy-Felso | ||||
| #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 in the docs folder of the package. | ||||
| 
 | ||||
| import os | ||||
| import sys | ||||
| from optparse import OptionParser | ||||
| 
 | ||||
| 
 | ||||
| parser = OptionParser() | ||||
| parser.add_option("-x", "--errorsToConsole", action="store_true", | ||||
| 				help="If passed error output will go to the console rather than .") | ||||
| (options, sys.argv) = parser.parse_args() | ||||
| 
 | ||||
| if not options.errorsToConsole: | ||||
| 	print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_." | ||||
| 	errorFile = open('fpdb-error-log.txt', 'w', 0) | ||||
| 	sys.stderr = errorFile | ||||
| 
 | ||||
| import pygtk | ||||
| pygtk.require('2.0') | ||||
| import gtk | ||||
| 
 | ||||
| import fpdb_db | ||||
| import fpdb_simple | ||||
| import GuiBulkImport | ||||
| import GuiTableViewer | ||||
| import GuiAutoImport | ||||
| import GuiGraphViewer | ||||
| import FpdbSQLQueries | ||||
| import Configuration | ||||
| 
 | ||||
| class fpdb: | ||||
| 	def tab_clicked(self, widget, tab_name): | ||||
| 		"""called when a tab button is clicked to activate that tab""" | ||||
| 		#print "start of tab_clicked" | ||||
| 		self.display_tab(tab_name) | ||||
| 	#end def tab_clicked | ||||
| 		 | ||||
| 	def add_and_display_tab(self, new_tab, new_tab_name): | ||||
| 		"""just calls the component methods""" | ||||
| 		self.add_tab(new_tab, new_tab_name) | ||||
| 		self.display_tab(new_tab_name) | ||||
| 	#end def add_and_display_tab | ||||
| 	 | ||||
| 	def add_tab(self, new_tab, new_tab_name): | ||||
| 		"""adds a tab, namely creates the button and displays it and appends all the relevant arrays""" | ||||
| 		#print "start of add_tab" | ||||
| 		for i in self.tab_names: #todo: check this is valid | ||||
| 			if i==new_tab_name: | ||||
| 				raise fpdb_simple.FpdbError("duplicate tab_name not permitted") | ||||
| 		 | ||||
| 		self.tabs.append(new_tab) | ||||
| 		self.tab_names.append(new_tab_name) | ||||
| 		 | ||||
| 		new_tab_sel_button=gtk.ToggleButton(new_tab_name) | ||||
| 		new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name) | ||||
| 		self.tab_box.add(new_tab_sel_button) | ||||
| 		new_tab_sel_button.show() | ||||
| 		self.tab_buttons.append(new_tab_sel_button) | ||||
| 	#end def add_tab | ||||
| 	 | ||||
| 	def display_tab(self, new_tab_name): | ||||
| 		"""displays the indicated tab""" | ||||
| 		#print "start of display_tab, len(self.tab_names):",len(self.tab_names) | ||||
| 		tab_no=-1 | ||||
| 		#if len(self.tab_names)>1: | ||||
| 		for i in range(len(self.tab_names)): | ||||
| 			#print "display_tab, new_tab_name:",new_tab_name,"  self.tab_names[i]:", self.tab_names[i] | ||||
| 			if (new_tab_name==self.tab_names[i]): | ||||
| 				tab_no=i | ||||
| 				#self.tab_buttons[i].set_active(False) | ||||
| 		#else: | ||||
| 		#	tab_no=0 | ||||
| 		 | ||||
| 		#current_tab_no=-1 | ||||
| 		for i in range(len(self.tab_names)): | ||||
| 			if self.current_tab==self.tabs[i]: | ||||
| 				#self.tab_buttons[i].set_active(False) | ||||
| 				pass | ||||
| 		 | ||||
| 		if tab_no==-1: | ||||
| 			raise fpdb_simple.FpdbError("invalid tab_no") | ||||
| 		else: | ||||
| 			self.main_vbox.remove(self.current_tab) | ||||
| 			#self.current_tab.destroy() | ||||
| 			self.current_tab=self.tabs[tab_no] | ||||
| 			self.main_vbox.add(self.current_tab) | ||||
| 			self.tab_buttons[tab_no].set_active(True) | ||||
| 			self.current_tab.show() | ||||
| 	#end def display_tab | ||||
| 	 | ||||
| 	def delete_event(self, widget, event, data=None): | ||||
| 		return False | ||||
| 	#end def delete_event | ||||
| 
 | ||||
| 	def destroy(self, widget, data=None): | ||||
| 		self.quit(widget, data) | ||||
| 	#end def destroy | ||||
| 	 | ||||
| 	def dia_about(self, widget, data): | ||||
| 		print "todo: implement dia_about" | ||||
| 	#end def dia_about | ||||
| 	 | ||||
| 	def dia_create_del_database(self, widget, data): | ||||
| 		print "todo: implement dia_create_del_database" | ||||
| 		obtain_global_lock() | ||||
| 	#end def dia_create_del_database | ||||
| 	 | ||||
| 	def dia_create_del_user(self, widget, data): | ||||
| 		print "todo: implement dia_create_del_user" | ||||
| 		obtain_global_lock() | ||||
| 	#end def dia_create_del_user | ||||
| 	 | ||||
| 	def dia_database_stats(self, widget, data): | ||||
| 		print "todo: implement dia_database_stats" | ||||
| 		#string=fpdb_db.getDbStats(db, cursor) | ||||
| 	#end def dia_database_stats | ||||
| 	 | ||||
| 	def dia_delete_db_parts(self, widget, data): | ||||
| 		print "todo: implement dia_delete_db_parts" | ||||
| 		obtain_global_lock() | ||||
| 	#end def dia_delete_db_parts | ||||
| 	 | ||||
| 	def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None): | ||||
| 		print "todo: implement dia_edit_profile" | ||||
| 		obtain_global_lock() | ||||
| 	#end def dia_edit_profile | ||||
| 
 | ||||
| 	def dia_export_db(self, widget, data): | ||||
| 		print "todo: implement dia_export_db" | ||||
| 		obtain_global_lock() | ||||
| 	#end def dia_export_db | ||||
| 	 | ||||
| 	def dia_get_db_root_credentials(self): | ||||
| 		"""obtains db root credentials from user""" | ||||
| 		print "todo: implement dia_get_db_root_credentials" | ||||
| #		user, pw=None, None | ||||
| #		 | ||||
| #		dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0, | ||||
| #				buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,"Connect and recreate",gtk.RESPONSE_OK)) | ||||
| #		 | ||||
| #		label_warning1=gtk.Label("Please enter credentials for a database user for "+self.host+" that has permissions to create a database.") | ||||
| #		 | ||||
| #		 | ||||
| #		label_user=gtk.Label("Username") | ||||
| #		dialog.vbox.add(label_user) | ||||
| #		label_user.show() | ||||
| #		 | ||||
| #		response=dialog.run() | ||||
| #		dialog.destroy() | ||||
| #		return (user, pw, response) | ||||
| 	#end def dia_get_db_root_credentials | ||||
| 	 | ||||
| 	def dia_import_db(self, widget, data): | ||||
| 		print "todo: implement dia_import_db" | ||||
| 		obtain_global_lock() | ||||
| 	#end def dia_import_db | ||||
| 	 | ||||
| 	def dia_licensing(self, widget, data): | ||||
| 		print "todo: implement dia_licensing" | ||||
| 	#end def dia_licensing | ||||
| 	 | ||||
| 	def dia_load_profile(self, widget, data): | ||||
| 		"""Dialogue to select a file to load a profile from""" | ||||
| 		self.obtain_global_lock() | ||||
| 		chooser = gtk.FileChooserDialog(title="Please select a profile file to load", | ||||
| 				action=gtk.FILE_CHOOSER_ACTION_OPEN, | ||||
| 				buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) | ||||
| 		chooser.set_filename(self.profile) | ||||
| 		 | ||||
| 		response = chooser.run() | ||||
| 		chooser.destroy()	 | ||||
| 		if response == gtk.RESPONSE_OK: | ||||
| 			self.load_profile(chooser.get_filename()) | ||||
| 		elif response == gtk.RESPONSE_CANCEL: | ||||
| 			print 'User cancelled loading profile' | ||||
| 	#end def dia_load_profile | ||||
| 	 | ||||
| 	def dia_recreate_tables(self, widget, data): | ||||
| 		"""Dialogue that asks user to confirm that he wants to delete and recreate the tables""" | ||||
| 		self.obtain_global_lock() | ||||
| 		dia_confirm=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, | ||||
| 				buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") | ||||
| 		diastring=("Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted.") | ||||
| 		dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted | ||||
| 
 | ||||
| 		response=dia_confirm.run() | ||||
| 		dia_confirm.destroy() | ||||
| 		if response == gtk.RESPONSE_YES: | ||||
| 			self.db.recreate_tables() | ||||
| 		elif response == gtk.RESPONSE_NO: | ||||
| 			print 'User cancelled recreating tables' | ||||
| 	#end def dia_recreate_tables | ||||
| 	 | ||||
| 	def dia_regression_test(self, widget, data): | ||||
| 		print "todo: implement dia_regression_test" | ||||
| 		self.obtain_global_lock() | ||||
| 	#end def dia_regression_test | ||||
| 	 | ||||
| 	def dia_save_profile(self, widget, data): | ||||
| 		print "todo: implement dia_save_profile" | ||||
| 	#end def dia_save_profile | ||||
| 	 | ||||
| 	def diaSetupWizard(self, path): | ||||
| 		print "todo: implement setup wizard" | ||||
| 		print "setup wizard not implemented - please create the default configuration file:", path	 | ||||
| 		diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK)) | ||||
| 
 | ||||
| 		label = gtk.Label("Please copy the config file from the docs folder to:") | ||||
| 		diaSetupWizard.vbox.add(label) | ||||
| 		label.show() | ||||
| 		 | ||||
| 		label = gtk.Label(path) | ||||
| 		diaSetupWizard.vbox.add(label) | ||||
| 		label.show() | ||||
| 		 | ||||
| 		label = gtk.Label("and edit it according to the install documentation at http://fpdb.sourceforge.net") | ||||
| 		diaSetupWizard.vbox.add(label) | ||||
| 		label.show() | ||||
| 
 | ||||
| 		response = diaSetupWizard.run() | ||||
| 		sys.exit(1) | ||||
| 	#end def diaSetupWizard | ||||
| 	 | ||||
| 	def get_menu(self, window): | ||||
| 		"""returns the menu for this program""" | ||||
| 		accel_group = gtk.AccelGroup() | ||||
| 		self.item_factory = gtk.ItemFactory(gtk.MenuBar, "<main>", accel_group) | ||||
| 		self.item_factory.create_items(self.menu_items) | ||||
| 		window.add_accel_group(accel_group) | ||||
| 		return self.item_factory.get_widget("<main>") | ||||
| 	#end def get_menu | ||||
| 	 | ||||
| 	def load_profile(self): | ||||
| 		"""Loads profile from the provided path name.""" | ||||
| 		self.settings = {} | ||||
| 		if (os.sep=="/"): | ||||
| 			self.settings['os']="linuxmac" | ||||
| 		else: | ||||
| 			self.settings['os']="windows" | ||||
| 
 | ||||
| 		self.settings.update(self.config.get_db_parameters()) | ||||
| 		self.settings.update(self.config.get_tv_parameters()) | ||||
| 		self.settings.update(self.config.get_import_parameters()) | ||||
| 		self.settings.update(self.config.get_default_paths()) | ||||
| 		 | ||||
| 		if self.db!=None: | ||||
| 			self.db.disconnect() | ||||
| 		 | ||||
| 		self.db = fpdb_db.fpdb_db() | ||||
| 		#print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] | ||||
| 		self.db.connect(self.settings['db-backend'], self.settings['db-host'], self.settings['db-databaseName'], self.settings['db-user'], self.settings['db-password']) | ||||
| 		if self.db.wrongDbVersion: | ||||
| 			diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) | ||||
| 
 | ||||
| 			label = gtk.Label("An invalid DB version or missing tables have been detected.") | ||||
| 			diaDbVersionWarning.vbox.add(label) | ||||
| 			label.show() | ||||
| 		 | ||||
| 			label = gtk.Label("This error is not necessarily fatal but it is strongly recommended that you recreate the tables by using the Database menu.") | ||||
| 			diaDbVersionWarning.vbox.add(label) | ||||
| 			label.show() | ||||
| 		 | ||||
| 			label = gtk.Label("Not doing this will likely lead to misbehaviour including fpdb crashes, corrupt data etc.") | ||||
| 			diaDbVersionWarning.vbox.add(label) | ||||
| 			label.show() | ||||
| 
 | ||||
| 			response = diaDbVersionWarning.run() | ||||
| 			diaDbVersionWarning.destroy() | ||||
| 
 | ||||
| 		# Database connected to successfully, load queries to pass on to other classes | ||||
|                 self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) | ||||
| 	#end def load_profile | ||||
| 	 | ||||
| 	def not_implemented(self): | ||||
| 		print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented | ||||
| 	#end def not_implemented | ||||
| 	 | ||||
| 	def obtain_global_lock(self): | ||||
| 		print "todo: implement obtain_global_lock (users: pls ignore this)" | ||||
| 	#end def obtain_global_lock | ||||
| 	 | ||||
| 	def quit(self, widget, data): | ||||
| 		print "Quitting normally" | ||||
| 		#check if current settings differ from profile, if so offer to save or abort | ||||
| 		self.db.disconnect() | ||||
| 		gtk.main_quit() | ||||
| 	#end def quit_cliecked | ||||
| 	 | ||||
| 	def release_global_lock(self): | ||||
| 		print "todo: implement release_global_lock" | ||||
| 	#end def release_global_lock | ||||
| 	 | ||||
| 	def tab_abbreviations(self, widget, data): | ||||
| 		print "todo: implement tab_abbreviations" | ||||
| 	#end def tab_abbreviations | ||||
| 	 | ||||
| 	def tab_auto_import(self, widget, data): | ||||
| 		"""opens the auto import tab""" | ||||
| 		new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config) | ||||
| 		self.threads.append(new_aimp_thread) | ||||
| 		aimp_tab=new_aimp_thread.get_vbox() | ||||
| 		self.add_and_display_tab(aimp_tab, "Auto Import") | ||||
| 	#end def tab_auto_import | ||||
| 
 | ||||
| 	def tab_bulk_import(self, widget, data): | ||||
| 		"""opens a tab for bulk importing""" | ||||
| 		#print "start of tab_bulk_import" | ||||
| 		new_import_thread=GuiBulkImport.GuiBulkImport(self.db, self.settings, self.config) | ||||
| 		self.threads.append(new_import_thread) | ||||
| 		bulk_tab=new_import_thread.get_vbox() | ||||
| 		self.add_and_display_tab(bulk_tab, "Bulk Import") | ||||
| 	#end def tab_bulk_import | ||||
| 
 | ||||
| 	def tab_main_help(self, widget, data): | ||||
| 		"""Displays a tab with the main fpdb help screen""" | ||||
| 		#print "start of tab_main_help" | ||||
| 		mh_tab=gtk.Label("""Welcome to Fpdb! | ||||
| For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder. | ||||
| Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml | ||||
| This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") | ||||
| 		self.add_and_display_tab(mh_tab, "Help") | ||||
| 	#end def tab_main_help | ||||
| 	 | ||||
| 	def tab_table_viewer(self, widget, data): | ||||
| 		"""opens a table viewer tab""" | ||||
| 		#print "start of tab_table_viewer" | ||||
| 		new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) | ||||
| 		self.threads.append(new_tv_thread) | ||||
| 		tv_tab=new_tv_thread.get_vbox() | ||||
| 		self.add_and_display_tab(tv_tab, "Table Viewer") | ||||
| 	#end def tab_table_viewer | ||||
| 
 | ||||
| 	def tabGraphViewer(self, widget, data): | ||||
| 		"""opens a graph viewer tab""" | ||||
| 		#print "start of tabGraphViewer" | ||||
| 		new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) | ||||
| 		self.threads.append(new_gv_thread) | ||||
| 		gv_tab=new_gv_thread.get_vbox() | ||||
| 		self.add_and_display_tab(gv_tab, "Graphs") | ||||
| 	#end def tabGraphViewer | ||||
| 
 | ||||
| 	def __init__(self): | ||||
| 		self.threads=[] | ||||
| 		self.db=None | ||||
| 		self.config = Configuration.Config() | ||||
| 		self.load_profile() | ||||
| 		 | ||||
| 		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) | ||||
| 		self.window.connect("delete_event", self.delete_event) | ||||
| 		self.window.connect("destroy", self.destroy) | ||||
| 		self.window.set_title("Free Poker DB - version: alpha9+, p143 or higher") | ||||
| 		self.window.set_border_width(1) | ||||
| 		self.window.set_size_request(1020,400) | ||||
| 		self.window.set_resizable(True) | ||||
| 		 | ||||
| 		self.menu_items = ( | ||||
| 				( "/_Main",                                 None,         None, 0, "<Branch>" ), | ||||
| 				( "/Main/_Load Profile (broken)",                    "<control>L", self.dia_load_profile, 0, None ), | ||||
| 				( "/Main/_Edit Profile (todo)",                    "<control>E", self.dia_edit_profile, 0, None ), | ||||
| 				( "/Main/_Save Profile (todo)",                    None,         self.dia_save_profile, 0, None ), | ||||
| 				("/Main/sep1", None, None, 0, "<Separator>" ), | ||||
| 				("/Main/_Quit", "<control>Q", self.quit, 0, None ), | ||||
| 				("/_Import",                               None,         None, 0, "<Branch>" ), | ||||
| 				("/Import/_Bulk Import",  "<control>B", self.tab_bulk_import, 0, None ), | ||||
| 				("/Import/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ), | ||||
| 				("/Import/Auto _Rating (todo)",                   "<control>R", self.not_implemented, 0, None ), | ||||
| 				("/_Viewers", None, None, 0, "<Branch>" ), | ||||
| 				("/_Viewers/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ), | ||||
| 				("/Viewers/_Graphs", "<control>G", self.tabGraphViewer, 0, None ), | ||||
| 				("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ), | ||||
| 				("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ), | ||||
| 				("/Viewers/_Player Stats (tabulated view) (todo)", None, self.not_implemented, 0, None ), | ||||
| 				("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ), | ||||
| 				("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ), | ||||
| 				("/Viewers/Poker_table Viewer (mostly obselete)", "<control>T", self.tab_table_viewer, 0, None ), | ||||
| 				#( "/Viewers/Tourney Replayer | ||||
| 				( "/_Database",                             None,         None, 0, "<Branch>" ), | ||||
| 				( "/Database/Create or Delete _Database (todo)",   None,         self.dia_create_del_database, 0, None ), | ||||
| 				( "/Database/Create or Delete _User (todo)",       None,         self.dia_create_del_user, 0, None ), | ||||
| 				( "/Database/Create or Recreate _Tables",   None,         self.dia_recreate_tables, 0, None ), | ||||
| 				( "/Database/_Statistics (todo)",                  None,         self.dia_database_stats, 0, None ), | ||||
| 				( "/D_ebugging",                            None,         None, 0, "<Branch>" ), | ||||
| 				( "/Debugging/_Delete Parts of Database (todo)",   None,         self.dia_delete_db_parts, 0, None ), | ||||
| 				( "/Debugging/_Export DB (todo)",                  None,         self.dia_export_db, 0, None ), | ||||
| 				( "/Debugging/_Import DB (todo)",                  None,         self.dia_import_db, 0, None ), | ||||
| 				( "/Debugging/_Regression test (todo)",            None,         self.dia_regression_test, 0, None ), | ||||
| 				( "/_Help",                                 None,         None, 0, "<LastBranch>" ), | ||||
| 				( "/Help/_Main Help",                       "<control>H", self.tab_main_help, 0, None ), | ||||
| 				( "/Help/_Abbrevations (todo)",                    None,         self.tab_abbreviations, 0, None ), | ||||
| 				( "/Help/sep1",                             None,         None, 0, "<Separator>" ), | ||||
| 				( "/Help/A_bout (todo)",                           None,         self.dia_about, 0, None ), | ||||
| 				( "/Help/_License and Copying (todo)",             None,         self.dia_licensing, 0, None ) | ||||
| 		) | ||||
| 		 | ||||
| 		self.main_vbox = gtk.VBox(False, 1) | ||||
| 		self.main_vbox.set_border_width(1) | ||||
| 		self.window.add(self.main_vbox) | ||||
| 		self.main_vbox.show() | ||||
| 		 | ||||
| 		menubar = self.get_menu(self.window) | ||||
| 		self.main_vbox.pack_start(menubar, False, True, 0) | ||||
| 		menubar.show() | ||||
| 		#done menubar | ||||
| 		 | ||||
| 		self.tabs=[] | ||||
| 		self.tab_names=[] | ||||
| 		self.tab_buttons=[] | ||||
| 		self.tab_box = gtk.HBox(False,1) | ||||
| 		self.main_vbox.pack_start(self.tab_box, False, True, 0) | ||||
| 		self.tab_box.show() | ||||
| 		#done tab bar | ||||
| 		 | ||||
| 		self.current_tab = gtk.VBox(False,1) | ||||
| 		self.current_tab.set_border_width(1) | ||||
| 		self.main_vbox.add(self.current_tab) | ||||
| 		self.current_tab.show() | ||||
| 		 | ||||
| 		self.tab_main_help(None, None) | ||||
| 		 | ||||
| 		self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host) | ||||
| 		self.main_vbox.pack_end(self.status_bar, False, True, 0) | ||||
| 		self.status_bar.show() | ||||
| 		 | ||||
| 		self.window.show() | ||||
| 	#end def __init__ | ||||
| 
 | ||||
| 	def main(self): | ||||
| 		gtk.main() | ||||
| 		return 0 | ||||
| 	#end def main | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
| 	me = fpdb() | ||||
| 	me.main() | ||||
| #!/usr/bin/python | ||||
| 
 | ||||
| #Copyright 2008 Steffen Jobbagy-Felso | ||||
| #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 in the docs folder of the package. | ||||
| 
 | ||||
| import os | ||||
| import sys | ||||
| from optparse import OptionParser | ||||
| 
 | ||||
| 
 | ||||
| parser = OptionParser() | ||||
| parser.add_option("-x", "--errorsToConsole", action="store_true", | ||||
|                                 help="If passed error output will go to the console rather than .") | ||||
| (options, sys.argv) = parser.parse_args() | ||||
| 
 | ||||
| if not options.errorsToConsole: | ||||
|         print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_." | ||||
|         errorFile = open('fpdb-error-log.txt', 'w', 0) | ||||
|         sys.stderr = errorFile | ||||
| 
 | ||||
| import pygtk | ||||
| pygtk.require('2.0') | ||||
| import gtk | ||||
| 
 | ||||
| import fpdb_db | ||||
| import fpdb_simple | ||||
| import GuiBulkImport | ||||
| import GuiTableViewer | ||||
| import GuiAutoImport | ||||
| import GuiGraphViewer | ||||
| import FpdbSQLQueries | ||||
| import Configuration | ||||
| 
 | ||||
| class fpdb: | ||||
|         def tab_clicked(self, widget, tab_name): | ||||
|                 """called when a tab button is clicked to activate that tab""" | ||||
|                 #print "start of tab_clicked" | ||||
|                 self.display_tab(tab_name) | ||||
|         #end def tab_clicked | ||||
|                  | ||||
|         def add_and_display_tab(self, new_tab, new_tab_name): | ||||
|                 """just calls the component methods""" | ||||
|                 self.add_tab(new_tab, new_tab_name) | ||||
|                 self.display_tab(new_tab_name) | ||||
|         #end def add_and_display_tab | ||||
|          | ||||
|         def add_tab(self, new_tab, new_tab_name): | ||||
|                 """adds a tab, namely creates the button and displays it and appends all the relevant arrays""" | ||||
|                 #print "start of add_tab" | ||||
|                 for i in self.tab_names: #todo: check this is valid | ||||
|                         if i==new_tab_name: | ||||
|                                 raise fpdb_simple.FpdbError("duplicate tab_name not permitted") | ||||
|                 | ||||
|                 self.tabs.append(new_tab) | ||||
|                 self.tab_names.append(new_tab_name) | ||||
|                 | ||||
|                 new_tab_sel_button=gtk.ToggleButton(new_tab_name) | ||||
|                 new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name) | ||||
|                 self.tab_box.add(new_tab_sel_button) | ||||
|                 new_tab_sel_button.show() | ||||
|                 self.tab_buttons.append(new_tab_sel_button) | ||||
|         #end def add_tab | ||||
|          | ||||
|         def display_tab(self, new_tab_name): | ||||
|                 """displays the indicated tab""" | ||||
|                 #print "start of display_tab, len(self.tab_names):",len(self.tab_names) | ||||
|                 tab_no=-1 | ||||
|                 #if len(self.tab_names)>1: | ||||
|                 for i in range(len(self.tab_names)): | ||||
|                         #print "display_tab, new_tab_name:",new_tab_name,"  self.tab_names[i]:", self.tab_names[i] | ||||
|                         if (new_tab_name==self.tab_names[i]): | ||||
|                                 tab_no=i | ||||
|                                 #self.tab_buttons[i].set_active(False) | ||||
|                 #else: | ||||
|                 #       tab_no=0 | ||||
|                  | ||||
|                 #current_tab_no=-1 | ||||
|                 for i in range(len(self.tab_names)): | ||||
|                         if self.current_tab==self.tabs[i]: | ||||
|                                 #self.tab_buttons[i].set_active(False) | ||||
|                                 pass | ||||
|                 | ||||
|                 if tab_no==-1: | ||||
|                         raise fpdb_simple.FpdbError("invalid tab_no") | ||||
|                 else: | ||||
|                         self.main_vbox.remove(self.current_tab) | ||||
|                         #self.current_tab.destroy() | ||||
|                         self.current_tab=self.tabs[tab_no] | ||||
|                         self.main_vbox.add(self.current_tab) | ||||
|                         self.tab_buttons[tab_no].set_active(True) | ||||
|                         self.current_tab.show() | ||||
|         #end def display_tab | ||||
|          | ||||
|         def delete_event(self, widget, event, data=None): | ||||
|                 return False | ||||
|         #end def delete_event | ||||
| 
 | ||||
|         def destroy(self, widget, data=None): | ||||
|                 self.quit(widget, data) | ||||
|         #end def destroy | ||||
|          | ||||
|         def dia_about(self, widget, data): | ||||
|                 print "todo: implement dia_about" | ||||
|         #end def dia_about | ||||
|          | ||||
|         def dia_create_del_database(self, widget, data): | ||||
|                 print "todo: implement dia_create_del_database" | ||||
|                 obtain_global_lock() | ||||
|         #end def dia_create_del_database | ||||
|          | ||||
|         def dia_create_del_user(self, widget, data): | ||||
|                 print "todo: implement dia_create_del_user" | ||||
|                 obtain_global_lock() | ||||
|         #end def dia_create_del_user | ||||
|          | ||||
|         def dia_database_stats(self, widget, data): | ||||
|                 print "todo: implement dia_database_stats" | ||||
|                 #string=fpdb_db.getDbStats(db, cursor) | ||||
|         #end def dia_database_stats | ||||
|          | ||||
|         def dia_delete_db_parts(self, widget, data): | ||||
|                 print "todo: implement dia_delete_db_parts" | ||||
|                 obtain_global_lock() | ||||
|         #end def dia_delete_db_parts | ||||
|          | ||||
|         def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None): | ||||
|                 print "todo: implement dia_edit_profile" | ||||
|                 obtain_global_lock() | ||||
|         #end def dia_edit_profile | ||||
| 
 | ||||
|         def dia_export_db(self, widget, data): | ||||
|                 print "todo: implement dia_export_db" | ||||
|                 obtain_global_lock() | ||||
|         #end def dia_export_db | ||||
|          | ||||
|         def dia_get_db_root_credentials(self): | ||||
|                 """obtains db root credentials from user""" | ||||
|                 print "todo: implement dia_get_db_root_credentials" | ||||
| #               user, pw=None, None | ||||
| #                | ||||
| #               dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0, | ||||
| #                               buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,"Connect and recreate",gtk.RESPONSE_OK)) | ||||
| #                | ||||
| #               label_warning1=gtk.Label("Please enter credentials for a database user for "+self.host+" that has permissions to create a database.") | ||||
| #                | ||||
| #                | ||||
| #               label_user=gtk.Label("Username") | ||||
| #               dialog.vbox.add(label_user) | ||||
| #               label_user.show() | ||||
| #                | ||||
| #               response=dialog.run() | ||||
| #               dialog.destroy() | ||||
| #               return (user, pw, response) | ||||
|         #end def dia_get_db_root_credentials | ||||
|          | ||||
|         def dia_import_db(self, widget, data): | ||||
|                 print "todo: implement dia_import_db" | ||||
|                 obtain_global_lock() | ||||
|         #end def dia_import_db | ||||
|          | ||||
|         def dia_licensing(self, widget, data): | ||||
|                 print "todo: implement dia_licensing" | ||||
|         #end def dia_licensing | ||||
|          | ||||
|         def dia_load_profile(self, widget, data): | ||||
|                 """Dialogue to select a file to load a profile from""" | ||||
|                 self.obtain_global_lock() | ||||
|                 chooser = gtk.FileChooserDialog(title="Please select a profile file to load", | ||||
|                                 action=gtk.FILE_CHOOSER_ACTION_OPEN, | ||||
|                                 buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) | ||||
|                 chooser.set_filename(self.profile) | ||||
|                 | ||||
|                 response = chooser.run() | ||||
|                 chooser.destroy()        | ||||
|                 if response == gtk.RESPONSE_OK: | ||||
|                         self.load_profile(chooser.get_filename()) | ||||
|                 elif response == gtk.RESPONSE_CANCEL: | ||||
|                         print 'User cancelled loading profile' | ||||
|         #end def dia_load_profile | ||||
|          | ||||
|         def dia_recreate_tables(self, widget, data): | ||||
|                 """Dialogue that asks user to confirm that he wants to delete and recreate the tables""" | ||||
|                 self.obtain_global_lock() | ||||
|                 dia_confirm=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, | ||||
|                                 buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") | ||||
|                 diastring=("Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted.") | ||||
|                 dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted | ||||
| 
 | ||||
|                 response=dia_confirm.run() | ||||
|                 dia_confirm.destroy() | ||||
|                 if response == gtk.RESPONSE_YES: | ||||
|                         self.db.recreate_tables() | ||||
|                 elif response == gtk.RESPONSE_NO: | ||||
|                         print 'User cancelled recreating tables' | ||||
|         #end def dia_recreate_tables | ||||
|          | ||||
|         def dia_regression_test(self, widget, data): | ||||
|                 print "todo: implement dia_regression_test" | ||||
|                 self.obtain_global_lock() | ||||
|         #end def dia_regression_test | ||||
|          | ||||
|         def dia_save_profile(self, widget, data): | ||||
|                 print "todo: implement dia_save_profile" | ||||
|         #end def dia_save_profile | ||||
|          | ||||
|         def diaSetupWizard(self, path): | ||||
|                 print "todo: implement setup wizard" | ||||
|                 print "setup wizard not implemented - please create the default configuration file:", path      | ||||
|                 diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK)) | ||||
| 
 | ||||
|                 label = gtk.Label("Please copy the config file from the docs folder to:") | ||||
|                 diaSetupWizard.vbox.add(label) | ||||
|                 label.show() | ||||
|                 | ||||
|                 label = gtk.Label(path) | ||||
|                 diaSetupWizard.vbox.add(label) | ||||
|                 label.show() | ||||
|                 | ||||
|                 label = gtk.Label("and edit it according to the install documentation at http://fpdb.sourceforge.net") | ||||
|                 diaSetupWizard.vbox.add(label) | ||||
|                 label.show() | ||||
| 
 | ||||
|                 response = diaSetupWizard.run() | ||||
|                 sys.exit(1) | ||||
|         #end def diaSetupWizard | ||||
|          | ||||
|         def get_menu(self, window): | ||||
|                 """returns the menu for this program""" | ||||
|                 accel_group = gtk.AccelGroup() | ||||
|                 self.item_factory = gtk.ItemFactory(gtk.MenuBar, "<main>", accel_group) | ||||
|                 self.item_factory.create_items(self.menu_items) | ||||
|                 window.add_accel_group(accel_group) | ||||
|                 return self.item_factory.get_widget("<main>") | ||||
|         #end def get_menu | ||||
|          | ||||
|         def load_profile(self): | ||||
|                 """Loads profile from the provided path name.""" | ||||
|                 self.settings = {} | ||||
|                 if (os.sep=="/"): | ||||
|                         self.settings['os']="linuxmac" | ||||
|                 else: | ||||
|                         self.settings['os']="windows" | ||||
| 
 | ||||
|                 self.settings.update(self.config.get_db_parameters()) | ||||
|                 self.settings.update(self.config.get_tv_parameters()) | ||||
|                 self.settings.update(self.config.get_import_parameters()) | ||||
|                 self.settings.update(self.config.get_default_paths()) | ||||
|                 | ||||
|                 if self.db!=None: | ||||
|                         self.db.disconnect() | ||||
|                 | ||||
|                 self.db = fpdb_db.fpdb_db() | ||||
|                 #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] | ||||
|                 self.db.connect(self.settings['db-backend'], self.settings['db-host'], self.settings['db-databaseName'], self.settings['db-user'], self.settings['db-password']) | ||||
|                 if self.db.wrongDbVersion: | ||||
|                         diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) | ||||
| 
 | ||||
|                         label = gtk.Label("An invalid DB version or missing tables have been detected.") | ||||
|                         diaDbVersionWarning.vbox.add(label) | ||||
|                         label.show() | ||||
|                 | ||||
|                         label = gtk.Label("This error is not necessarily fatal but it is strongly recommended that you recreate the tables by using the Database menu.") | ||||
|                         diaDbVersionWarning.vbox.add(label) | ||||
|                         label.show() | ||||
|                 | ||||
|                         label = gtk.Label("Not doing this will likely lead to misbehaviour including fpdb crashes, corrupt data etc.") | ||||
|                         diaDbVersionWarning.vbox.add(label) | ||||
|                         label.show() | ||||
| 
 | ||||
|                         response = diaDbVersionWarning.run() | ||||
|                         diaDbVersionWarning.destroy() | ||||
| 
 | ||||
|                 # Database connected to successfully, load queries to pass on to other classes | ||||
|                 self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) | ||||
|         #end def load_profile | ||||
|          | ||||
|         def not_implemented(self): | ||||
|                 print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented | ||||
|         #end def not_implemented | ||||
|          | ||||
|         def obtain_global_lock(self): | ||||
|                 print "todo: implement obtain_global_lock (users: pls ignore this)" | ||||
|         #end def obtain_global_lock | ||||
|          | ||||
|         def quit(self, widget, data): | ||||
|                 print "Quitting normally" | ||||
|                 #check if current settings differ from profile, if so offer to save or abort | ||||
|                 self.db.disconnect() | ||||
|                 gtk.main_quit() | ||||
|         #end def quit_cliecked | ||||
|          | ||||
|         def release_global_lock(self): | ||||
|                 print "todo: implement release_global_lock" | ||||
|         #end def release_global_lock | ||||
|          | ||||
|         def tab_abbreviations(self, widget, data): | ||||
|                 print "todo: implement tab_abbreviations" | ||||
|         #end def tab_abbreviations | ||||
|          | ||||
|         def tab_auto_import(self, widget, data): | ||||
|                 """opens the auto import tab""" | ||||
|                 new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config) | ||||
|                 self.threads.append(new_aimp_thread) | ||||
|                 aimp_tab=new_aimp_thread.get_vbox() | ||||
|                 self.add_and_display_tab(aimp_tab, "Auto Import") | ||||
|         #end def tab_auto_import | ||||
| 
 | ||||
|         def tab_bulk_import(self, widget, data): | ||||
|                 """opens a tab for bulk importing""" | ||||
|                 #print "start of tab_bulk_import" | ||||
|                 new_import_thread=GuiBulkImport.GuiBulkImport(self.db, self.settings, self.config) | ||||
|                 self.threads.append(new_import_thread) | ||||
|                 bulk_tab=new_import_thread.get_vbox() | ||||
|                 self.add_and_display_tab(bulk_tab, "Bulk Import") | ||||
|         #end def tab_bulk_import | ||||
| 
 | ||||
|         def tab_main_help(self, widget, data): | ||||
|                 """Displays a tab with the main fpdb help screen""" | ||||
|                 #print "start of tab_main_help" | ||||
|                 mh_tab=gtk.Label("""Welcome to Fpdb! | ||||
| For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder. | ||||
| Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml | ||||
| This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") | ||||
|                 self.add_and_display_tab(mh_tab, "Help") | ||||
|         #end def tab_main_help | ||||
|          | ||||
|         def tab_table_viewer(self, widget, data): | ||||
|                 """opens a table viewer tab""" | ||||
|                 #print "start of tab_table_viewer" | ||||
|                 new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) | ||||
|                 self.threads.append(new_tv_thread) | ||||
|                 tv_tab=new_tv_thread.get_vbox() | ||||
|                 self.add_and_display_tab(tv_tab, "Table Viewer") | ||||
|         #end def tab_table_viewer | ||||
| 
 | ||||
|         def tabGraphViewer(self, widget, data): | ||||
|                 """opens a graph viewer tab""" | ||||
|                 #print "start of tabGraphViewer" | ||||
|                 new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) | ||||
|                 self.threads.append(new_gv_thread) | ||||
|                 gv_tab=new_gv_thread.get_vbox() | ||||
|                 self.add_and_display_tab(gv_tab, "Graphs") | ||||
|         #end def tabGraphViewer | ||||
| 
 | ||||
|         def __init__(self): | ||||
|                 self.threads=[] | ||||
|                 self.db=None | ||||
|                 self.config = Configuration.Config() | ||||
|                 self.load_profile() | ||||
|                 | ||||
|                 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) | ||||
|                 self.window.connect("delete_event", self.delete_event) | ||||
|                 self.window.connect("destroy", self.destroy) | ||||
|                 self.window.set_title("Free Poker DB - version: alpha9+, p143 or higher") | ||||
|                 self.window.set_border_width(1) | ||||
|                 self.window.set_size_request(1020,400) | ||||
|                 self.window.set_resizable(True) | ||||
|                 | ||||
|                 self.menu_items = ( | ||||
|                                 ( "/_Main",                                 None,         None, 0, "<Branch>" ), | ||||
|                                 ( "/Main/_Load Profile (broken)",                    "<control>L", self.dia_load_profile, 0, None ), | ||||
|                                 ( "/Main/_Edit Profile (todo)",                    "<control>E", self.dia_edit_profile, 0, None ), | ||||
|                                 ( "/Main/_Save Profile (todo)",                    None,         self.dia_save_profile, 0, None ), | ||||
|                                 ("/Main/sep1", None, None, 0, "<Separator>" ), | ||||
|                                 ("/Main/_Quit", "<control>Q", self.quit, 0, None ), | ||||
|                                 ("/_Import",                               None,         None, 0, "<Branch>" ), | ||||
|                                 ("/Import/_Bulk Import",  "<control>B", self.tab_bulk_import, 0, None ), | ||||
|                                 ("/Import/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ), | ||||
|                                 ("/Import/Auto _Rating (todo)",                   "<control>R", self.not_implemented, 0, None ), | ||||
|                                 ("/_Viewers", None, None, 0, "<Branch>" ), | ||||
|                                 ("/_Viewers/_Auto Import and HUD", "<control>A", self.tab_auto_import, 0, None ), | ||||
|                                 ("/Viewers/_Graphs", "<control>G", self.tabGraphViewer, 0, None ), | ||||
|                                 ("/Viewers/Hand _Replayer (todo)", None, self.not_implemented, 0, None ), | ||||
|                                 ("/Viewers/Player _Details (todo)", None, self.not_implemented, 0, None ), | ||||
|                                 ("/Viewers/_Player Stats (tabulated view) (todo)", None, self.not_implemented, 0, None ), | ||||
|                                 ("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ), | ||||
|                                 ("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ), | ||||
|                                 ("/Viewers/Poker_table Viewer (mostly obselete)", "<control>T", self.tab_table_viewer, 0, None ), | ||||
|                                 #( "/Viewers/Tourney Replayer | ||||
|                                 ( "/_Database",                             None,         None, 0, "<Branch>" ), | ||||
|                                 ( "/Database/Create or Delete _Database (todo)",   None,         self.dia_create_del_database, 0, None ), | ||||
|                                 ( "/Database/Create or Delete _User (todo)",       None,         self.dia_create_del_user, 0, None ), | ||||
|                                 ( "/Database/Create or Recreate _Tables",   None,         self.dia_recreate_tables, 0, None ), | ||||
|                                 ( "/Database/_Statistics (todo)",                  None,         self.dia_database_stats, 0, None ), | ||||
|                                 ( "/D_ebugging",                            None,         None, 0, "<Branch>" ), | ||||
|                                 ( "/Debugging/_Delete Parts of Database (todo)",   None,         self.dia_delete_db_parts, 0, None ), | ||||
|                                 ( "/Debugging/_Export DB (todo)",                  None,         self.dia_export_db, 0, None ), | ||||
|                                 ( "/Debugging/_Import DB (todo)",                  None,         self.dia_import_db, 0, None ), | ||||
|                                 ( "/Debugging/_Regression test (todo)",            None,         self.dia_regression_test, 0, None ), | ||||
|                                 ( "/_Help",                                 None,         None, 0, "<LastBranch>" ), | ||||
|                                 ( "/Help/_Main Help",                       "<control>H", self.tab_main_help, 0, None ), | ||||
|                                 ( "/Help/_Abbrevations (todo)",                    None,         self.tab_abbreviations, 0, None ), | ||||
|                                 ( "/Help/sep1",                             None,         None, 0, "<Separator>" ), | ||||
|                                 ( "/Help/A_bout (todo)",                           None,         self.dia_about, 0, None ), | ||||
|                                 ( "/Help/_License and Copying (todo)",             None,         self.dia_licensing, 0, None ) | ||||
|                 ) | ||||
|                 | ||||
|                 self.main_vbox = gtk.VBox(False, 1) | ||||
|                 self.main_vbox.set_border_width(1) | ||||
|                 self.window.add(self.main_vbox) | ||||
|                 self.main_vbox.show() | ||||
|                 | ||||
|                 menubar = self.get_menu(self.window) | ||||
|                 self.main_vbox.pack_start(menubar, False, True, 0) | ||||
|                 menubar.show() | ||||
|                 #done menubar | ||||
|                  | ||||
|                 self.tabs=[] | ||||
|                 self.tab_names=[] | ||||
|                 self.tab_buttons=[] | ||||
|                 self.tab_box = gtk.HBox(False,1) | ||||
|                 self.main_vbox.pack_start(self.tab_box, False, True, 0) | ||||
|                 self.tab_box.show() | ||||
|                 #done tab bar | ||||
|                  | ||||
|                 self.current_tab = gtk.VBox(False,1) | ||||
|                 self.current_tab.set_border_width(1) | ||||
|                 self.main_vbox.add(self.current_tab) | ||||
|                 self.current_tab.show() | ||||
|                 | ||||
|                 self.tab_main_help(None, None) | ||||
|                 | ||||
|                 self.status_bar = gtk.Label("Status: Connected to "+self.db.get_backend_name()+" database named "+self.db.database+" on host "+self.db.host) | ||||
|                 self.main_vbox.pack_end(self.status_bar, False, True, 0) | ||||
|                 self.status_bar.show() | ||||
|                 | ||||
|                 self.window.show() | ||||
|         #end def __init__ | ||||
| 
 | ||||
|         def main(self): | ||||
|                 gtk.main() | ||||
|                 return 0 | ||||
|         #end def main | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|         me = fpdb() | ||||
|         me.main() | ||||
|  |  | |||
							
								
								
									
										0
									
								
								pyfpdb/fpdb_db.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								pyfpdb/fpdb_db.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										608
									
								
								pyfpdb/fpdb_import.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										608
									
								
								pyfpdb/fpdb_import.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -1,298 +1,310 @@ | |||
| #!/usr/bin/python | ||||
| 
 | ||||
| #Copyright 2008 Steffen Jobbagy-Felso | ||||
| #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 in the docs folder of the package. | ||||
| 
 | ||||
| #see status.txt for site/games support info | ||||
| 
 | ||||
| import sys | ||||
| 
 | ||||
| try: | ||||
| 	import MySQLdb | ||||
| 	mysqlLibFound=True | ||||
| except: | ||||
| 	pass | ||||
| 	 | ||||
| try: | ||||
| 	import psycopg2 | ||||
| 	pgsqlLibFound=True | ||||
| except: | ||||
| 	pass | ||||
| 
 | ||||
| import math | ||||
| import os | ||||
| import datetime | ||||
| import re | ||||
| import fpdb_simple | ||||
| import fpdb_parse_logic | ||||
| from time import time | ||||
| 
 | ||||
| class Importer: | ||||
| 
 | ||||
| 	def __init__(self, caller, settings): | ||||
| 		"""Constructor""" | ||||
| 		self.settings=settings | ||||
| 		self.caller=caller | ||||
| 		self.db = None | ||||
| 		self.cursor = None | ||||
| 		self.filelist = {} | ||||
| 		self.dirlist = {} | ||||
| 		self.monitor = False | ||||
| 		self.updated = {}		#Time last import was run {file:mtime} | ||||
| 		self.callHud = False | ||||
| 		self.lines = None | ||||
| 		self.faobs = None		#File as one big string | ||||
| 		self.pos_in_file = {} # dict to remember how far we have read in the file | ||||
| 		#Set defaults | ||||
| 		if not self.settings.has_key('imp-callFpdbHud'): | ||||
| 			self.settings['imp-callFpdbHud'] = False | ||||
| 		if not self.settings.has_key('minPrint'): | ||||
| 			self.settings['minPrint'] = 30 | ||||
| 		self.dbConnect() | ||||
| 
 | ||||
| 	def dbConnect(self): | ||||
| 		#connect to DB | ||||
| 		if self.settings['db-backend'] == 2: | ||||
| 			if not mysqlLibFound: | ||||
| 				raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file") | ||||
| 			self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'], | ||||
| 							self.settings['db-password'], self.settings['db-databaseName']) | ||||
| 		elif self.settings['db-backend'] == 3: | ||||
| 			if not pgsqlLibFound: | ||||
| 				raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file") | ||||
| 			print self.settings | ||||
| 			self.db = psycopg2.connect(host = self.settings['db-host'], | ||||
| 									   user = self.settings['db-user'], | ||||
| 									   password = self.settings['db-password'], | ||||
| 									   database = self.settings['db-databaseName']) | ||||
| 		elif self.settings['db-backend'] == 4: | ||||
| 			pass | ||||
| 		else: | ||||
| 			pass | ||||
| 		self.cursor = self.db.cursor() | ||||
| 
 | ||||
| 	#Set functions | ||||
| 	def setCallHud(self, value): | ||||
| 		self.callHud = value | ||||
| 
 | ||||
| 	def setMinPrint(self, value): | ||||
| 		self.settings['minPrint'] = int(value) | ||||
| 
 | ||||
| 	def setHandCount(self, value): | ||||
| 		self.settings['handCount'] = int(value) | ||||
| 
 | ||||
| 	def setQuiet(self, value): | ||||
| 		self.settings['quiet'] = value | ||||
| 
 | ||||
| 	def setFailOnError(self, value): | ||||
| 		self.settings['failOnError'] = value | ||||
| 
 | ||||
| #	def setWatchTime(self): | ||||
| #		self.updated = time() | ||||
| 
 | ||||
| 	def clearFileList(self): | ||||
| 		self.filelist = {} | ||||
| 
 | ||||
| 	#Add an individual file to filelist | ||||
| 	def addImportFile(self, filename, site = "default", filter = "passthrough"): | ||||
| 		#TODO: test it is a valid file | ||||
| 		self.filelist[filename] = [site] + [filter] | ||||
| 
 | ||||
| 	#Add a directory of files to filelist | ||||
| 	#Only one import directory per site supported. | ||||
| 	#dirlist is a hash of lists: | ||||
| 	#dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] } | ||||
| 	def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"): | ||||
| 		if os.path.isdir(dir): | ||||
| 			if monitor == True: | ||||
| 				self.monitor = True | ||||
| 				self.dirlist[site] = [dir] + [filter] | ||||
| 
 | ||||
| 			for file in os.listdir(dir): | ||||
| 				self.addImportFile(os.path.join(dir, file), site, filter) | ||||
| 		else: | ||||
| 			print "Warning: Attempted to add: '" + str(dir) + "' as an import directory" | ||||
| 
 | ||||
| 	#Run full import on filelist | ||||
| 	def runImport(self): | ||||
| 		for file in self.filelist: | ||||
| 			self.import_file_dict(file) | ||||
| 
 | ||||
| 	#Run import on updated files, then store latest update time. | ||||
| 	def runUpdated(self): | ||||
| 		#Check for new files in directory | ||||
| 		#todo: make efficient - always checks for new file, should be able to use mtime of directory | ||||
| 		# ^^ May not work on windows | ||||
| 		for site in self.dirlist: | ||||
| 			self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1]) | ||||
| 
 | ||||
| 		for file in self.filelist: | ||||
| 			stat_info = os.stat(file) | ||||
| 			try:  | ||||
| 				lastupdate = self.updated[file] | ||||
| 				if stat_info.st_mtime > lastupdate: | ||||
| 					self.import_file_dict(file) | ||||
| 					self.updated[file] = time() | ||||
| 			except: | ||||
| 				self.updated[file] = time() | ||||
| 				# This codepath only runs first time the file is found, if modified in the last | ||||
| 				# minute run an immediate import. | ||||
| 				if (time() - stat_info.st_mtime) < 60: | ||||
| 					self.import_file_dict(file) | ||||
| 
 | ||||
| 	# This is now an internal function that should not be called directly. | ||||
| 	def import_file_dict(self, file): | ||||
| 		starttime = time() | ||||
| 		last_read_hand=0 | ||||
| 		loc = 0 | ||||
| 		if (file=="stdin"): | ||||
| 			inputFile=sys.stdin | ||||
| 		else: | ||||
| 			inputFile=open(file, "rU") | ||||
| 			try: loc = self.pos_in_file[file] | ||||
| 			except: pass | ||||
| 
 | ||||
| 		# Read input file into class and close file | ||||
| 		inputFile.seek(loc) | ||||
| 		self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines()) | ||||
| 		self.pos_in_file[file] = inputFile.tell() | ||||
| 		inputFile.close() | ||||
| 
 | ||||
| 		firstline = self.lines[0] | ||||
| 
 | ||||
| 		if firstline.find("Tournament Summary")!=-1: | ||||
| 			print "TODO: implement importing tournament summaries" | ||||
| 			#self.faobs = readfile(inputFile) | ||||
| 			#self.parseTourneyHistory() | ||||
| 			return 0 | ||||
| 		 | ||||
| 		site=fpdb_simple.recogniseSite(firstline) | ||||
| 		category=fpdb_simple.recogniseCategory(firstline) | ||||
| 
 | ||||
| 		startpos=0 | ||||
| 		stored=0 #counter | ||||
| 		duplicates=0 #counter | ||||
| 		partial=0 #counter | ||||
| 		errors=0 #counter | ||||
| 
 | ||||
| 		for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method | ||||
| 			if (len(self.lines[i])<2): | ||||
| 				endpos=i | ||||
| 				hand=self.lines[startpos:endpos] | ||||
| 		 | ||||
| 				if (len(hand[0])<2): | ||||
| 					hand=hand[1:] | ||||
| 		 | ||||
| 				cancelled=False | ||||
| 				damaged=False | ||||
| 				if (site=="ftp"): | ||||
| 					for i in range (len(hand)): | ||||
| 						if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right? | ||||
| 							cancelled=True | ||||
| 						 | ||||
| 						seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line | ||||
| 						if (seat1!=-1): | ||||
| 							if (hand[i].find("Seat ", seat1+3)!=-1): | ||||
| 								damaged=True | ||||
| 				 | ||||
| 				if (len(hand)<3): | ||||
| 					pass | ||||
| 					#todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work. | ||||
| 				elif (hand[0].endswith(" (partial)")): #partial hand - do nothing | ||||
| 					partial+=1 | ||||
| 				elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and? | ||||
| 					partial+=1 | ||||
| 				elif (cancelled or damaged): | ||||
| 					partial+=1 | ||||
| 				else: #normal processing | ||||
| 					isTourney=fpdb_simple.isTourney(hand[0]) | ||||
| 					if not isTourney: | ||||
| 						fpdb_simple.filterAnteBlindFold(site,hand) | ||||
| 					hand=fpdb_simple.filterCrap(site, hand, isTourney) | ||||
| 					self.hand=hand | ||||
| 					 | ||||
| 					try: | ||||
| 						handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand) | ||||
| 						self.db.commit() | ||||
| 						 | ||||
| 						stored+=1 | ||||
| 						self.db.commit() | ||||
| #						if settings['imp-callFpdbHud'] and self.callHud and os.sep=='/': | ||||
| 						if self.settings['imp-callFpdbHud'] and self.callHud: | ||||
| 							#print "call to HUD here. handsId:",handsId | ||||
| 							#pipe the Hands.id out to the HUD | ||||
| 							self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) | ||||
| 					except fpdb_simple.DuplicateError: | ||||
| 						duplicates+=1 | ||||
| 					except (ValueError), fe: | ||||
| 						errors+=1 | ||||
| 						self.printEmailErrorMessage(errors, file, hand[0]) | ||||
| 				 | ||||
| 						if (self.settings['failOnError']): | ||||
| 							self.db.commit() #dont remove this, in case hand processing was cancelled. | ||||
| 							raise | ||||
| 					except (fpdb_simple.FpdbError), fe: | ||||
| 						errors+=1 | ||||
| 						self.printEmailErrorMessage(errors, file, hand[0]) | ||||
| 
 | ||||
| 						#fe.printStackTrace() #todo: get stacktrace | ||||
| 						self.db.rollback() | ||||
| 						 | ||||
| 						if (self.settings['failOnError']): | ||||
| 							self.db.commit() #dont remove this, in case hand processing was cancelled. | ||||
| 							raise | ||||
| 					if (self.settings['minPrint']!=0): | ||||
| 						if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0): | ||||
| 							print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors | ||||
| 			 | ||||
| 					if (self.settings['handCount']!=0): | ||||
| 						if ((stored+duplicates+partial+errors)>=self.settings['handCount']): | ||||
| 							if (not self.settings['quiet']): | ||||
| 								print "quitting due to reaching the amount of hands to be imported" | ||||
| 								print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime) | ||||
| 							sys.exit(0) | ||||
| 				startpos=endpos | ||||
| 		print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", (time() - starttime) | ||||
| 		 | ||||
| 		if stored==0: | ||||
| 			if duplicates>0: | ||||
| 				for line_no in range(len(self.lines)): | ||||
| 					if self.lines[line_no].find("Game #")!=-1: | ||||
| 						final_game_line=self.lines[line_no] | ||||
| 				handsId=fpdb_simple.parseSiteHandNo(final_game_line) | ||||
| 			else: | ||||
| 				print "failed to read a single hand from file:", inputFile | ||||
| 				handsId=0 | ||||
| 			#todo: this will cause return of an unstored hand number if the last hand was error or partial | ||||
| 		self.db.commit() | ||||
| 		self.handsId=handsId | ||||
| 		return handsId | ||||
| #end def import_file_dict | ||||
| 
 | ||||
| 	def parseTourneyHistory(self): | ||||
| 		print "Tourney history parser stub" | ||||
| 		#Find tournament boundaries. | ||||
| 		#print self.foabs | ||||
| 		 | ||||
| 
 | ||||
| 	def printEmailErrorMessage(self, errors, filename, line): | ||||
| 		print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it." | ||||
| 		print "Filename:", filename | ||||
| 		print "Here is the first line so you can identify it. Please mention that the error was a ValueError:" | ||||
| 		print self.hand[0] | ||||
| 	 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
| 	print "CLI for fpdb_import is now available as CliFpdb.py" | ||||
| #!/usr/bin/python | ||||
| 
 | ||||
| #Copyright 2008 Steffen Jobbagy-Felso | ||||
| #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 in the docs folder of the package. | ||||
| 
 | ||||
| #see status.txt for site/games support info | ||||
| 
 | ||||
| import sys | ||||
| 
 | ||||
| try: | ||||
|         import MySQLdb | ||||
|         mysqlLibFound=True | ||||
| except: | ||||
|         pass | ||||
|         | ||||
| try: | ||||
|         import psycopg2 | ||||
|         pgsqlLibFound=True | ||||
| except: | ||||
|         pass | ||||
| 
 | ||||
| import math | ||||
| import os | ||||
| import datetime | ||||
| import re | ||||
| import fpdb_simple | ||||
| import fpdb_parse_logic | ||||
| from time import time | ||||
| 
 | ||||
| class Importer: | ||||
| 
 | ||||
|         def __init__(self, caller, settings, config): | ||||
|                 """Constructor""" | ||||
|                 self.settings=settings | ||||
|                 self.caller=caller | ||||
|                 self.config = config | ||||
|                 self.db = None | ||||
|                 self.cursor = None | ||||
|                 self.filelist = {} | ||||
|                 self.dirlist = {} | ||||
|                 self.monitor = False | ||||
|                 self.updated = {}               #Time last import was run {file:mtime} | ||||
|                 self.lines = None | ||||
|                 self.faobs = None               #File as one big string | ||||
|                 self.pos_in_file = {} # dict to remember how far we have read in the file | ||||
|                 #Set defaults | ||||
|                 self.callHud = self.config.get_import_parameters().get("callFpdbHud") | ||||
|                 if not self.settings.has_key('minPrint'): | ||||
|                         self.settings['minPrint'] = 30 | ||||
|                 self.dbConnect() | ||||
| 
 | ||||
|         def dbConnect(self): | ||||
|                 #connect to DB | ||||
|                 if self.settings['db-backend'] == 2: | ||||
|                         if not mysqlLibFound: | ||||
|                                 raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file") | ||||
|                         self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'], | ||||
|                                                         self.settings['db-password'], self.settings['db-databaseName']) | ||||
|                 elif self.settings['db-backend'] == 3: | ||||
|                         if not pgsqlLibFound: | ||||
|                                 raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file") | ||||
|                         print self.settings | ||||
|                         self.db = psycopg2.connect(host = self.settings['db-host'], | ||||
|                                                                            user = self.settings['db-user'], | ||||
|                                                                            password = self.settings['db-password'], | ||||
|                                                                            database = self.settings['db-databaseName']) | ||||
|                 elif self.settings['db-backend'] == 4: | ||||
|                         pass | ||||
|                 else: | ||||
|                         pass | ||||
|                 self.cursor = self.db.cursor() | ||||
| 
 | ||||
|         #Set functions | ||||
|         def setCallHud(self, value): | ||||
|                 self.callHud = value | ||||
| 
 | ||||
|         def setMinPrint(self, value): | ||||
|                 self.settings['minPrint'] = int(value) | ||||
| 
 | ||||
|         def setHandCount(self, value): | ||||
|                 self.settings['handCount'] = int(value) | ||||
| 
 | ||||
|         def setQuiet(self, value): | ||||
|                 self.settings['quiet'] = value | ||||
| 
 | ||||
|         def setFailOnError(self, value): | ||||
|                 self.settings['failOnError'] = value | ||||
| 
 | ||||
| #       def setWatchTime(self): | ||||
| #               self.updated = time() | ||||
| 
 | ||||
|         def clearFileList(self): | ||||
|                 self.filelist = {} | ||||
| 
 | ||||
|         #Add an individual file to filelist | ||||
|         def addImportFile(self, filename, site = "default", filter = "passthrough"): | ||||
|                 #TODO: test it is a valid file | ||||
|                 self.filelist[filename] = [site] + [filter] | ||||
| 
 | ||||
|         #Add a directory of files to filelist | ||||
|         #Only one import directory per site supported. | ||||
|         #dirlist is a hash of lists: | ||||
|         #dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] } | ||||
|         def addImportDirectory(self, dir, monitor = False, site = "default", filter = "passthrough"): | ||||
|             if dir != "/dev/null" and dir.lower() != "none": | ||||
|                 if os.path.isdir(dir): | ||||
|                     if monitor == True: | ||||
|                         self.monitor = True | ||||
|                         self.dirlist[site] = [dir] + [filter] | ||||
| 
 | ||||
|                     for file in os.listdir(dir): | ||||
|                         self.addImportFile(os.path.join(dir, file), site, filter) | ||||
|                 else: | ||||
|                     print "Warning: Attempted to add: '" + str(dir) + "' as an import directory\n" | ||||
| 
 | ||||
|         #Run full import on filelist | ||||
|         def runImport(self): | ||||
|                 for file in self.filelist: | ||||
|                         self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) | ||||
| 
 | ||||
|         #Run import on updated files, then store latest update time. | ||||
|         def runUpdated(self): | ||||
|                 #Check for new files in directory | ||||
|                 #todo: make efficient - always checks for new file, should be able to use mtime of directory | ||||
|                 # ^^ May not work on windows | ||||
|                 for site in self.dirlist: | ||||
|                         self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1]) | ||||
| 
 | ||||
|                 for file in self.filelist: | ||||
|                         stat_info = os.stat(file) | ||||
|                         try: | ||||
|                                 lastupdate = self.updated[file] | ||||
|                                 if stat_info.st_mtime > lastupdate: | ||||
|                                         self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) | ||||
|                                         self.updated[file] = time() | ||||
|                         except: | ||||
|                                 self.updated[file] = time() | ||||
|                                 # This codepath only runs first time the file is found, if modified in the last | ||||
|                                 # minute run an immediate import. | ||||
|                                 if (time() - stat_info.st_mtime) < 60: | ||||
|                                         self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1]) | ||||
| 
 | ||||
|         # This is now an internal function that should not be called directly. | ||||
|         def import_file_dict(self, file, site, filter): | ||||
|                 if(filter == "passthrough"): | ||||
|                         self.import_fpdb_file(file, site) | ||||
|                 else: | ||||
|                         #Load filter, and run filtered file though main importer | ||||
|                         self.import_fpdb_file(file, site) | ||||
| 
 | ||||
| 
 | ||||
|         def import_fpdb_file(self, file, site): | ||||
|                 starttime = time() | ||||
|                 last_read_hand=0 | ||||
|                 loc = 0 | ||||
|                 if (file=="stdin"): | ||||
|                         inputFile=sys.stdin | ||||
|                 else: | ||||
|                         inputFile=open(file, "rU") | ||||
|                         try: loc = self.pos_in_file[file] | ||||
|                         except: pass | ||||
| 
 | ||||
|                 # Read input file into class and close file | ||||
|                 inputFile.seek(loc) | ||||
|                 self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines()) | ||||
|                 self.pos_in_file[file] = inputFile.tell() | ||||
|                 inputFile.close() | ||||
| 
 | ||||
|                 try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return. | ||||
|                         firstline = self.lines[0] | ||||
|                 except: | ||||
| #                       print "import_fpdb_file", file, site, self.lines, "\n" | ||||
|                         return | ||||
| 
 | ||||
|                 if firstline.find("Tournament Summary")!=-1: | ||||
|                         print "TODO: implement importing tournament summaries" | ||||
|                         #self.faobs = readfile(inputFile) | ||||
|                         #self.parseTourneyHistory() | ||||
|                         return 0 | ||||
|                 | ||||
|                 site=fpdb_simple.recogniseSite(firstline) | ||||
|                 category=fpdb_simple.recogniseCategory(firstline) | ||||
| 
 | ||||
|                 startpos=0 | ||||
|                 stored=0 #counter | ||||
|                 duplicates=0 #counter | ||||
|                 partial=0 #counter | ||||
|                 errors=0 #counter | ||||
| 
 | ||||
|                 for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method | ||||
|                         if (len(self.lines[i])<2): | ||||
|                                 endpos=i | ||||
|                                 hand=self.lines[startpos:endpos] | ||||
|                 | ||||
|                                 if (len(hand[0])<2): | ||||
|                                         hand=hand[1:] | ||||
|                 | ||||
|                                 cancelled=False | ||||
|                                 damaged=False | ||||
|                                 if (site=="ftp"): | ||||
|                                         for i in range (len(hand)): | ||||
|                                                 if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right? | ||||
|                                                         cancelled=True | ||||
|                                                 | ||||
|                                                 seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line | ||||
|                                                 if (seat1!=-1): | ||||
|                                                         if (hand[i].find("Seat ", seat1+3)!=-1): | ||||
|                                                                 damaged=True | ||||
|                                 | ||||
|                                 if (len(hand)<3): | ||||
|                                         pass | ||||
|                                         #todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work. | ||||
|                                 elif (hand[0].endswith(" (partial)")): #partial hand - do nothing | ||||
|                                         partial+=1 | ||||
|                                 elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and? | ||||
|                                         partial+=1 | ||||
|                                 elif (cancelled or damaged): | ||||
|                                         partial+=1 | ||||
|                                 else: #normal processing | ||||
|                                         isTourney=fpdb_simple.isTourney(hand[0]) | ||||
|                                         if not isTourney: | ||||
|                                                 fpdb_simple.filterAnteBlindFold(site,hand) | ||||
|                                         hand=fpdb_simple.filterCrap(site, hand, isTourney) | ||||
|                                         self.hand=hand | ||||
|                                         | ||||
|                                         try: | ||||
|                                                 handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand) | ||||
|                                                 self.db.commit() | ||||
|                                                 | ||||
|                                                 stored+=1 | ||||
|                                                 self.db.commit() | ||||
|                                                 if self.callHud: | ||||
|                                                         #print "call to HUD here. handsId:",handsId | ||||
|                                                         #pipe the Hands.id out to the HUD | ||||
|                                                         self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep) | ||||
|                                         except fpdb_simple.DuplicateError: | ||||
|                                                 duplicates+=1 | ||||
|                                         except (ValueError), fe: | ||||
|                                                 errors+=1 | ||||
|                                                 self.printEmailErrorMessage(errors, file, hand[0]) | ||||
|                                 | ||||
|                                                 if (self.settings['failOnError']): | ||||
|                                                         self.db.commit() #dont remove this, in case hand processing was cancelled. | ||||
|                                                         raise | ||||
|                                         except (fpdb_simple.FpdbError), fe: | ||||
|                                                 errors+=1 | ||||
|                                                 self.printEmailErrorMessage(errors, file, hand[0]) | ||||
| 
 | ||||
|                                                 #fe.printStackTrace() #todo: get stacktrace | ||||
|                                                 self.db.rollback() | ||||
|                                                 | ||||
|                                                 if (self.settings['failOnError']): | ||||
|                                                         self.db.commit() #dont remove this, in case hand processing was cancelled. | ||||
|                                                         raise | ||||
|                                         if (self.settings['minPrint']!=0): | ||||
|                                                 if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0): | ||||
|                                                         print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors | ||||
|                         | ||||
|                                         if (self.settings['handCount']!=0): | ||||
|                                                 if ((stored+duplicates+partial+errors)>=self.settings['handCount']): | ||||
|                                                         if (not self.settings['quiet']): | ||||
|                                                                 print "quitting due to reaching the amount of hands to be imported" | ||||
|                                                                 print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:",  | ||||
|                                                                 partial, "errors:", errors, " time: %5.3f" % (time() - starttime) | ||||
|                                                         sys.exit(0) | ||||
|                                 startpos=endpos | ||||
|                 print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time: %5.3f" % (time() - starttime) | ||||
|                 | ||||
|                 if stored==0: | ||||
|                         if duplicates>0: | ||||
|                                 for line_no in range(len(self.lines)): | ||||
|                                         if self.lines[line_no].find("Game #")!=-1: | ||||
|                                                 final_game_line=self.lines[line_no] | ||||
|                                 handsId=fpdb_simple.parseSiteHandNo(final_game_line) | ||||
|                         else: | ||||
|                                 print "failed to read a single hand from file:", inputFile | ||||
|                                 handsId=0 | ||||
|                         #todo: this will cause return of an unstored hand number if the last hand was error or partial | ||||
|                 self.db.commit() | ||||
|                 self.handsId=handsId | ||||
|                 return handsId | ||||
| #end def import_file_dict | ||||
| 
 | ||||
|         def parseTourneyHistory(self): | ||||
|                 print "Tourney history parser stub" | ||||
|                 #Find tournament boundaries. | ||||
|                 #print self.foabs | ||||
|                  | ||||
| 
 | ||||
|         def printEmailErrorMessage(self, errors, filename, line): | ||||
|                 print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it." | ||||
|                 print "Filename:", filename | ||||
|                 print "Here is the first line so you can identify it. Please mention that the error was a ValueError:" | ||||
|                 print self.hand[0] | ||||
|         | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|         print "CLI for fpdb_import is now available as CliFpdb.py" | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ def mainParser(db, cursor, site, category, hand): | |||
| 			#print "found small blind line:",smallBlindLine | ||||
| 			break | ||||
| 	#print "small blind line:",smallBlindLine | ||||
| 	gametypeID=fpdb_simple.recogniseGametypeID(cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) | ||||
| 	gametypeID=fpdb_simple.recogniseGametypeID(db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) | ||||
| 	if isTourney: | ||||
| 		if site!="ps": | ||||
| 			raise fpdb_simple.FpdbError("tourneys are only supported on PS right now") | ||||
|  | @ -142,18 +142,18 @@ def mainParser(db, cursor, site, category, hand): | |||
| 		payin_amounts=fpdb_simple.calcPayin(len(names), buyin, fee) | ||||
| 		 | ||||
| 		if base=="hold": | ||||
| 			result = fpdb_save_to_db.tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, | ||||
| 			result = fpdb_save_to_db.tourney_holdem_omaha(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, | ||||
| 					siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) | ||||
| 		elif base=="stud": | ||||
| 			result = fpdb_save_to_db.tourney_stud(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, | ||||
| 			result = fpdb_save_to_db.tourney_stud(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, | ||||
| 					siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) | ||||
| 		else: | ||||
| 			raise fpdb_simple.FpdbError ("unrecognised category") | ||||
| 	else: | ||||
| 		if base=="hold": | ||||
| 			result = fpdb_save_to_db.ring_holdem_omaha(cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) | ||||
| 			result = fpdb_save_to_db.ring_holdem_omaha(db, cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) | ||||
| 		elif base=="stud": | ||||
| 			result = fpdb_save_to_db.ring_stud(cursor, base, category, siteHandNo, gametypeID,  | ||||
| 			result = fpdb_save_to_db.ring_stud(db, cursor, base, category, siteHandNo, gametypeID,  | ||||
| 					handStartTime, names, playerIDs, startCashes, antes, cardValues,  | ||||
| 					cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) | ||||
| 		else: | ||||
|  |  | |||
|  | @ -21,13 +21,13 @@ | |||
| import fpdb_simple | ||||
| 
 | ||||
| #stores a stud/razz hand into the database | ||||
| def ring_stud(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): | ||||
| def ring_stud(db, cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): | ||||
| 	fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) | ||||
| 	 | ||||
| 	hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) | ||||
| 	hands_id=fpdb_simple.storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) | ||||
| 	 | ||||
| 	#print "before calling store_hands_players_stud, antes:", antes | ||||
| 	hands_players_ids=fpdb_simple.store_hands_players_stud(cursor, hands_id, player_ids,  | ||||
| 	hands_players_ids=fpdb_simple.store_hands_players_stud(db, cursor, hands_id, player_ids,  | ||||
| 				start_cashes, antes, card_values, card_suits, winnings, rakes, seatNos) | ||||
| 	 | ||||
| 	fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) | ||||
|  | @ -36,14 +36,14 @@ def ring_stud(cursor, base, category, site_hand_no, gametype_id, hand_start_time | |||
| 	return hands_id | ||||
| #end def ring_stud | ||||
| 
 | ||||
| def ring_holdem_omaha(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): | ||||
| def ring_holdem_omaha(db, cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): | ||||
| 	"""stores a holdem/omaha hand into the database""" | ||||
| 	fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) | ||||
| 	fpdb_simple.fill_board_cards(board_values, board_suits) | ||||
| 
 | ||||
| 	hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) | ||||
| 	hands_id=fpdb_simple.storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) | ||||
| 	 | ||||
| 	hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos) | ||||
| 	hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos) | ||||
| 				 | ||||
| 	fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) | ||||
| 	 | ||||
|  | @ -53,7 +53,7 @@ def ring_holdem_omaha(cursor, base, category, site_hand_no, gametype_id, hand_st | |||
| 	return hands_id | ||||
| #end def ring_holdem_omaha | ||||
| 
 | ||||
| def tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId, siteId, #end of tourney specific params | ||||
| def tourney_holdem_omaha(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId, siteId, #end of tourney specific params | ||||
| 			site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): | ||||
| 	"""stores a tourney holdem/omaha hand into the database""" | ||||
| 	fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) | ||||
|  | @ -62,9 +62,9 @@ def tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knoc | |||
| 	tourney_id=fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) | ||||
| 	tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings) | ||||
| 	 | ||||
| 	hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) | ||||
| 	hands_id=fpdb_simple.storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) | ||||
| 	 | ||||
| 	hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha_tourney(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) | ||||
| 	hands_players_ids=fpdb_simple.store_hands_players_holdem_omaha_tourney(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) | ||||
| 	 | ||||
| 	fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) | ||||
| 	 | ||||
|  | @ -74,7 +74,7 @@ def tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knoc | |||
| 	return hands_id | ||||
| #end def tourney_holdem_omaha | ||||
| 
 | ||||
| def tourney_stud(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId, | ||||
| def tourney_stud(db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId, | ||||
| 					siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos): | ||||
| #stores a tourney stud/razz hand into the database | ||||
| 	fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) | ||||
|  | @ -83,9 +83,9 @@ def tourney_stud(cursor, base, category, siteTourneyNo, buyin, fee, knockout, en | |||
| 	 | ||||
| 	tourneys_players_ids=fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings) | ||||
| 	 | ||||
| 	hands_id=fpdb_simple.storeHands(cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) | ||||
| 	hands_id=fpdb_simple.storeHands(db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) | ||||
| 	 | ||||
| 	hands_players_ids=fpdb_simple.store_hands_players_stud_tourney(cursor, hands_id, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, seatNos, tourneys_players_ids) | ||||
| 	hands_players_ids=fpdb_simple.store_hands_players_stud_tourney(db, cursor, hands_id, playerIds, startCashes, antes, cardValues, cardSuits, winnings, rakes, seatNos, tourneys_players_ids) | ||||
| 	 | ||||
| 	fpdb_simple.storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData) | ||||
| 	 | ||||
|  |  | |||
|  | @ -484,7 +484,8 @@ def isActionLine(line): | |||
| 
 | ||||
| #returns whether this is a duplicate | ||||
| def isAlreadyInDB(cursor, gametypeID, siteHandNo): | ||||
| 	cursor.execute ("SELECT id FROM Hands WHERE gametypeId=%s AND siteHandNo=%s", (gametypeID, siteHandNo)) | ||||
| 	#print "isAlreadyInDB gtid,shand:",gametypeID, siteHandNo | ||||
|         cursor.execute ("SELECT id FROM Hands WHERE gametypeId=%s AND siteHandNo=%s", (gametypeID, siteHandNo)) | ||||
| 	result=cursor.fetchall() | ||||
| 	if (len(result)>=1): | ||||
| 		raise DuplicateError ("dupl") | ||||
|  | @ -1021,7 +1022,7 @@ def recogniseCategory(line): | |||
| #end def recogniseCategory | ||||
| 
 | ||||
| #returns the int for the gametype_id for the given line | ||||
| def recogniseGametypeID(cursor, topline, smallBlindLine, site_id, category, isTourney):#todo: this method is messy | ||||
| def recogniseGametypeID(db, cursor, topline, smallBlindLine, site_id, category, isTourney):#todo: this method is messy | ||||
| 	#if (topline.find("HORSE")!=-1): | ||||
| 	#	raise FpdbError("recogniseGametypeID: HORSE is not yet supported.") | ||||
| 	 | ||||
|  | @ -1072,7 +1073,10 @@ def recogniseGametypeID(cursor, topline, smallBlindLine, site_id, category, isTo | |||
| 	else: | ||||
| 		cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s AND limitType=%s AND smallBlind=%s AND bigBlind=%s", (site_id, type, category, limit_type, small_bet, big_bet)) | ||||
| 	result=cursor.fetchone() | ||||
| 	#print "tried SELECTing gametypes.id, result:",result | ||||
| 	#print "recgt1 result=",result | ||||
|         #ret=result[0] | ||||
|         #print "recgt1 ret=",ret | ||||
|         #print "tried SELECTing gametypes.id, result:",result | ||||
| 	 | ||||
| 	try: | ||||
| 		len(result) | ||||
|  | @ -1105,17 +1109,19 @@ def recogniseGametypeID(cursor, topline, smallBlindLine, site_id, category, isTo | |||
| 			cursor.execute("""INSERT INTO Gametypes | ||||
| 			(siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) | ||||
| 			VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (site_id, type, base, category, limit_type, hiLo, small_blind, big_blind, small_bet, big_bet)) | ||||
| 			cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s AND limitType=%s AND smallBet=%s AND bigBet=%s", (site_id, type, category, limit_type, small_bet, big_bet)) | ||||
| 			#cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s AND limitType=%s AND smallBet=%s AND bigBet=%s", (site_id, type, category, limit_type, small_bet, big_bet)) | ||||
| 		else: | ||||
| 			cursor.execute("""INSERT INTO Gametypes | ||||
| 			(siteId, type, base, category, limitType, hiLo, smallBlind, bigBlind, smallBet, bigBet) | ||||
| 			VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (site_id, type, base, category, limit_type, hiLo, small_bet, big_bet, 0, 0))#remember, for these bet means blind | ||||
| 			cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s AND limitType=%s AND smallBlind=%s AND bigBlind=%s", (site_id, type, category, limit_type, small_bet, big_bet)) | ||||
| 			#cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s AND limitType=%s AND smallBlind=%s AND bigBlind=%s", (site_id, type, category, limit_type, small_bet, big_bet)) | ||||
| 
 | ||||
| 		result=cursor.fetchone() | ||||
| 		result=(db.insert_id(),) | ||||
| 		#print "recgt2 result=",result | ||||
| 		#print "created new gametypes.id:",result | ||||
| 	 | ||||
| 	return result[0] | ||||
| 	#print "recgt3: result=", result | ||||
|         return result[0] | ||||
| #end def recogniseGametypeID | ||||
| 
 | ||||
| def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon): | ||||
|  | @ -1248,15 +1254,16 @@ def store_board_cards(cursor, hands_id, board_values, board_suits): | |||
| 	board_values[4], board_suits[4])) | ||||
| #end def store_board_cards | ||||
| 
 | ||||
| def storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats): | ||||
| def storeHands(db, cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats): | ||||
| #stores into table hands | ||||
| 	cursor.execute ("INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats) VALUES (%s, %s, %s, %s, %s, %s, %s)", (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats)) | ||||
| 	#todo: find a better way of doing this... | ||||
| 	cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id)) | ||||
| 	return cursor.fetchall()[0][0] | ||||
| 	#cursor.execute("SELECT id FROM Hands WHERE siteHandNo=%s AND gametypeId=%s", (site_hand_no, gametype_id)) | ||||
| 	#return cursor.fetchall()[0][0] | ||||
| 	return db.insert_id()  # mysql only | ||||
| #end def storeHands | ||||
| 
 | ||||
| def store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos): | ||||
| def store_hands_players_holdem_omaha(db, cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos): | ||||
| 	result=[] | ||||
| 	if (category=="holdem"): | ||||
| 		for i in range (len(player_ids)): | ||||
|  | @ -1268,8 +1275,9 @@ def store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, sta | |||
| 			(hands_id, player_ids[i], start_cashes[i], positions[i], | ||||
| 			card_values[i][0], card_suits[i][0], card_values[i][1],	card_suits[i][1], | ||||
| 			winnings[i], rakes[i], seatNos[i])) | ||||
| 			cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) | ||||
| 			result.append(cursor.fetchall()[0][0]) | ||||
| 			#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) | ||||
| 			#result.append(cursor.fetchall()[0][0]) | ||||
| 			result.append( db.insert_id() )  # mysql only | ||||
| 	elif (category=="omahahi" or category=="omahahilo"): | ||||
| 		for i in range (len(player_ids)): | ||||
| 			cursor.execute ("""INSERT INTO HandsPlayers  | ||||
|  | @ -1281,14 +1289,15 @@ def store_hands_players_holdem_omaha(cursor, category, hands_id, player_ids, sta | |||
| 			card_values[i][0], card_suits[i][0], card_values[i][1],	card_suits[i][1], | ||||
| 			card_values[i][2], card_suits[i][2], card_values[i][3],	card_suits[i][3], | ||||
| 			winnings[i], rakes[i], seatNos[i])) | ||||
| 			cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) | ||||
| 			result.append(cursor.fetchall()[0][0]) | ||||
| 			#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) | ||||
| 			#result.append(cursor.fetchall()[0][0]) | ||||
| 			result.append( db.insert_id() )  # mysql only | ||||
| 	else: | ||||
| 		raise FpdbError("invalid category") | ||||
| 	return result | ||||
| #end def store_hands_players_holdem_omaha | ||||
| 
 | ||||
| def store_hands_players_stud(cursor, hands_id, player_ids, start_cashes, antes, | ||||
| def store_hands_players_stud(db, cursor, hands_id, player_ids, start_cashes, antes, | ||||
| 			card_values, card_suits, winnings, rakes, seatNos): | ||||
| #stores hands_players rows for stud/razz games. returns an array of the resulting IDs | ||||
| 	result=[] | ||||
|  | @ -1307,12 +1316,14 @@ def store_hands_players_stud(cursor, hands_id, player_ids, start_cashes, antes, | |||
| 		card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], | ||||
| 		card_values[i][4], card_suits[i][4], card_values[i][5], card_suits[i][5], | ||||
| 		card_values[i][6], card_suits[i][6], winnings[i], rakes[i], seatNos[i])) | ||||
| 		cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) | ||||
| 		result.append(cursor.fetchall()[0][0]) | ||||
| 		#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) | ||||
| 		#result.append(cursor.fetchall()[0][0]) | ||||
| 		result.append( db.insert_id() )  # mysql only | ||||
| 	return result | ||||
| #end def store_hands_players_stud | ||||
| 
 | ||||
| def store_hands_players_holdem_omaha_tourney(cursor, category, hands_id, player_ids, start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): | ||||
| def store_hands_players_holdem_omaha_tourney(db, cursor, category, hands_id, player_ids,  | ||||
|           start_cashes, positions, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): | ||||
| #stores hands_players for tourney holdem/omaha hands | ||||
| 	result=[] | ||||
| 	for i in range (len(player_ids)): | ||||
|  | @ -1338,13 +1349,14 @@ def store_hands_players_holdem_omaha_tourney(cursor, category, hands_id, player_ | |||
| 			winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) | ||||
| 		else: | ||||
| 			raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) | ||||
| 		cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) | ||||
| 		result.append(cursor.fetchall()[0][0]) | ||||
| 		#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) | ||||
| 		#result.append(cursor.fetchall()[0][0]) | ||||
| 		result.append( db.insert_id() )  # mysql only | ||||
| 	 | ||||
| 	return result | ||||
| #end def store_hands_players_holdem_omaha_tourney | ||||
| 
 | ||||
| def store_hands_players_stud_tourney(cursor, hands_id, player_ids, start_cashes, | ||||
| def store_hands_players_stud_tourney(db, cursor, hands_id, player_ids, start_cashes, | ||||
| 			antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids): | ||||
| #stores hands_players for tourney stud/razz hands | ||||
| 	result=[] | ||||
|  | @ -1362,8 +1374,9 @@ def store_hands_players_stud_tourney(cursor, hands_id, player_ids, start_cashes, | |||
| 		card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], | ||||
| 		card_values[i][4], card_suits[i][4], card_values[i][5], card_suits[i][5], | ||||
| 		card_values[i][6], card_suits[i][6], winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i])) | ||||
| 		cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId=%s", (hands_id, player_ids[i])) | ||||
| 		result.append(cursor.fetchall()[0][0]) | ||||
| 		#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) | ||||
| 		#result.append(cursor.fetchall()[0][0]) | ||||
| 		result.append( db.insert_id() )  # mysql only | ||||
| 	return result | ||||
| #end def store_hands_players_stud_tourney | ||||
| 
 | ||||
|  | @ -1949,9 +1962,9 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): | |||
| 		 | ||||
| 		for player in range (len(playerIds)): | ||||
| 			if base=="hold": | ||||
| 				cursor.execute("SELECT * FROM HudCache WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) | ||||
| 				cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s AND position=%s", (gametypeId, playerIds[player], len(playerIds), hudImportData['position'][player])) | ||||
| 			else: | ||||
| 				cursor.execute("SELECT * FROM HudCache WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s", (gametypeId, playerIds[player], len(playerIds))) | ||||
| 				cursor.execute("SELECT * FROM HudCache WHERE gametypeId+0=%s AND playerId=%s AND activeSeats=%s", (gametypeId, playerIds[player], len(playerIds))) | ||||
| 			row=cursor.fetchone() | ||||
| 			#print "gametypeId:", gametypeId, "playerIds[player]",playerIds[player], "len(playerIds):",len(playerIds), "row:",row | ||||
| 			 | ||||
|  | @ -2097,7 +2110,7 @@ def storeHudCache(cursor, base, category, gametypeId, playerIds, hudImportData): | |||
| #end def storeHudCache | ||||
| 
 | ||||
| def store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): | ||||
| 	cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId=%s", (siteTourneyNo, tourneyTypeId)) | ||||
| 	cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) | ||||
| 	tmp=cursor.fetchone() | ||||
| 	#print "tried SELECTing tourneys.id, result:",tmp | ||||
| 	 | ||||
|  | @ -2107,7 +2120,7 @@ def store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, sta | |||
| 		cursor.execute("""INSERT INTO Tourneys | ||||
| 		(tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) | ||||
| 		VALUES (%s, %s, %s, %s, %s)""", (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) | ||||
| 		cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId=%s", (siteTourneyNo, tourneyTypeId)) | ||||
| 		cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) | ||||
| 		tmp=cursor.fetchone() | ||||
| 		#print "created new tourneys.id:",tmp | ||||
| 	return tmp[0] | ||||
|  | @ -2121,7 +2134,7 @@ def store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, | |||
| 	#print "ranks:",ranks | ||||
| 	#print "winnings:",winnings | ||||
| 	for i in range (len(player_ids)): | ||||
| 		cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId=%s", (tourney_id, player_ids[i])) | ||||
| 		cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", (tourney_id, player_ids[i])) | ||||
| 		tmp=cursor.fetchone() | ||||
| 		#print "tried SELECTing tourneys_players.id:",tmp | ||||
| 		 | ||||
|  | @ -2132,7 +2145,7 @@ def store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, | |||
| 			(tourneyId, playerId, payinAmount, rank, winnings) VALUES (%s, %s, %s, %s, %s)""", | ||||
| 			(tourney_id, player_ids[i], payin_amounts[i], ranks[i], winnings[i])) | ||||
| 			 | ||||
| 			cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId=%s", | ||||
| 			cursor.execute("SELECT id FROM TourneysPlayers WHERE tourneyId=%s AND playerId+0=%s", | ||||
| 						   (tourney_id, player_ids[i])) | ||||
| 			tmp=cursor.fetchone() | ||||
| 			#print "created new tourneys_players.id:",tmp | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user